LibreOffice Module oox (master)  1
graphichelper.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
21 
22 #include <com/sun/star/awt/Point.hpp>
23 #include <com/sun/star/awt/Size.hpp>
24 #include <com/sun/star/awt/XDevice.hpp>
25 #include <com/sun/star/awt/XUnitConversion.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/frame/Desktop.hpp>
28 #include <com/sun/star/graphic/GraphicProvider.hpp>
29 #include <com/sun/star/util/MeasureUnit.hpp>
30 #include <com/sun/star/graphic/GraphicMapper.hpp>
31 #include <osl/diagnose.h>
32 #include <sal/log.hxx>
33 #include <comphelper/seqstream.hxx>
34 #include <vcl/wmfexternal.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/outdev.hxx>
37 #include <tools/gen.hxx>
38 #include <tools/diagnose_ex.h>
39 #include <comphelper/sequence.hxx>
42 #include <oox/token/properties.hxx>
43 #include <oox/token/tokens.hxx>
44 
45 namespace oox {
46 
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::beans;
49 using namespace ::com::sun::star::frame;
50 using namespace ::com::sun::star::graphic;
51 using namespace ::com::sun::star::io;
52 using namespace ::com::sun::star::lang;
53 using namespace ::com::sun::star::uno;
54 
55 namespace {
56 
57 sal_Int32 lclConvertScreenPixelToHmm( double fPixel, double fPixelPerHmm )
58 {
59  return static_cast< sal_Int32 >( (fPixelPerHmm > 0.0) ? (fPixel / fPixelPerHmm + 0.5) : 0.0 );
60 }
61 
62 } // namespace
63 
64 GraphicHelper::GraphicHelper( const Reference< XComponentContext >& rxContext, const Reference< XFrame >& /*rxTargetFrame*/, const StorageRef& rxStorage ) :
65  mxContext( rxContext ),
66  mxStorage( rxStorage )
67 {
68  OSL_ENSURE( mxContext.is(), "GraphicHelper::GraphicHelper - missing component context" );
69  if( mxContext.is() )
70  mxGraphicProvider.set( graphic::GraphicProvider::create( mxContext ), uno::UNO_QUERY );
71 
73  maSystemPalette[ XML_3dDkShadow ] = Color(0x716F64);
74  maSystemPalette[ XML_3dLight ] = Color(0xF1EFE2);
75  maSystemPalette[ XML_activeBorder ] = Color(0xD4D0C8);
76  maSystemPalette[ XML_activeCaption ] = Color(0x0054E3);
77  maSystemPalette[ XML_appWorkspace ] = Color(0x808080);
78  maSystemPalette[ XML_background ] = Color(0x004E98);
79  maSystemPalette[ XML_btnFace ] = Color(0xECE9D8);
80  maSystemPalette[ XML_btnHighlight ] = Color(0xFFFFFF);
81  maSystemPalette[ XML_btnShadow ] = Color(0xACA899);
82  maSystemPalette[ XML_btnText ] = Color(0x000000);
83  maSystemPalette[ XML_captionText ] = Color(0xFFFFFF);
84  maSystemPalette[ XML_gradientActiveCaption ] = Color(0x3D95FF);
85  maSystemPalette[ XML_gradientInactiveCaption ] = Color(0xD8E4F8);
86  maSystemPalette[ XML_grayText ] = Color(0xACA899);
87  maSystemPalette[ XML_highlight ] = Color(0x316AC5);
88  maSystemPalette[ XML_highlightText ] = Color(0xFFFFFF);
89  maSystemPalette[ XML_hotLight ] = Color(0x000080);
90  maSystemPalette[ XML_inactiveBorder ] = Color(0xD4D0C8);
91  maSystemPalette[ XML_inactiveCaption ] = Color(0x7A96DF);
92  maSystemPalette[ XML_inactiveCaptionText ] = Color(0xD8E4F8);
93  maSystemPalette[ XML_infoBk ] = Color(0xFFFFE1);
94  maSystemPalette[ XML_infoText ] = Color(0x000000);
95  maSystemPalette[ XML_menu ] = Color(0xFFFFFF);
96  maSystemPalette[ XML_menuBar ] = Color(0xECE9D8);
97  maSystemPalette[ XML_menuHighlight ] = Color(0x316AC5);
98  maSystemPalette[ XML_menuText ] = Color(0x000000);
99  maSystemPalette[ XML_scrollBar ] = Color(0xD4D0C8);
100  maSystemPalette[ XML_window ] = Color(0xFFFFFF);
101  maSystemPalette[ XML_windowFrame ] = Color(0x000000);
102  maSystemPalette[ XML_windowText ] = Color(0x000000);
103 
104  // Note that we cannot try to get DeviceInfo from the current frame here,
105  // because there might not be a current frame yet
106  mxDefaultOutputDevice = Application::GetDefaultDevice();
107  maDeviceInfo = mxDefaultOutputDevice->GetDeviceInfo();
108  // 100 000 is 1 meter in MM100.
109  // various unit tests rely on these values being exactly this and not the "true" values
110  Size aDefault = mxDefaultOutputDevice->LogicToPixel(Size(100000, 100000), MapMode(MapUnit::Map100thMM));
111  maDeviceInfo.PixelPerMeterX = aDefault.Width();
112  maDeviceInfo.PixelPerMeterY = aDefault.Height();
113  mfPixelPerHmmX = maDeviceInfo.PixelPerMeterX / 100000.0;
114  mfPixelPerHmmY = maDeviceInfo.PixelPerMeterY / 100000.0;
115 }
116 
118 {
119 }
120 
121 // System colors and predefined colors ----------------------------------------
122 
123 ::Color GraphicHelper::getSystemColor( sal_Int32 nToken, ::Color nDefaultRgb ) const
124 {
125  return ContainerHelper::getMapElement( maSystemPalette, nToken, nDefaultRgb );
126 }
127 
128 ::Color GraphicHelper::getSchemeColor( sal_Int32 /*nToken*/ ) const
129 {
130  OSL_FAIL( "GraphicHelper::getSchemeColor - scheme colors not implemented" );
131  return API_RGB_TRANSPARENT;
132 }
133 
134 ::Color GraphicHelper::getPaletteColor( sal_Int32 /*nPaletteIdx*/ ) const
135 {
136  OSL_FAIL( "GraphicHelper::getPaletteColor - palette colors not implemented" );
137  return API_RGB_TRANSPARENT;
138 }
139 
141 {
142  return XML_solidFill;
143 }
144 
146 {
147  return XML_solidFill;
148 }
149 
151 {
152  // this value is what MSO 2016 writes fixing incomplete MSO 2010 documents (0.75 pt in emu)
153  return 9525;
154 }
155 
156 // Device info and device dependent unit conversion ---------------------------
157 
158 sal_Int32 GraphicHelper::convertScreenPixelXToHmm( double fPixelX ) const
159 {
160  return lclConvertScreenPixelToHmm( fPixelX, mfPixelPerHmmX );
161 }
162 
163 sal_Int32 GraphicHelper::convertScreenPixelYToHmm( double fPixelY ) const
164 {
165  return lclConvertScreenPixelToHmm( fPixelY, mfPixelPerHmmY );
166 }
167 
168 awt::Size GraphicHelper::convertScreenPixelToHmm( const awt::Size& rPixel ) const
169 {
170  return awt::Size( convertScreenPixelXToHmm( rPixel.Width ), convertScreenPixelYToHmm( rPixel.Height ) );
171 }
172 
173 double GraphicHelper::convertHmmToScreenPixelX( sal_Int32 nHmmX ) const
174 {
175  return nHmmX * mfPixelPerHmmX;
176 }
177 
178 double GraphicHelper::convertHmmToScreenPixelY( sal_Int32 nHmmY ) const
179 {
180  return nHmmY * mfPixelPerHmmY;
181 }
182 
183 awt::Point GraphicHelper::convertHmmToScreenPixel( const awt::Point& rHmm ) const
184 {
185  return awt::Point(
186  static_cast< sal_Int32 >( convertHmmToScreenPixelX( rHmm.X ) + 0.5 ),
187  static_cast< sal_Int32 >( convertHmmToScreenPixelY( rHmm.Y ) + 0.5 ) );
188 }
189 
190 awt::Size GraphicHelper::convertHmmToScreenPixel( const awt::Size& rHmm ) const
191 {
192  return awt::Size(
193  static_cast< sal_Int32 >( convertHmmToScreenPixelX( rHmm.Width ) + 0.5 ),
194  static_cast< sal_Int32 >( convertHmmToScreenPixelY( rHmm.Height ) + 0.5 ) );
195 }
196 
197 awt::Point GraphicHelper::convertHmmToAppFont( const awt::Point& rHmm ) const
198 {
199  try
200  {
201  awt::Point aPixel = convertHmmToScreenPixel( rHmm );
202  MapMode aMode(MapUnit::MapAppFont);
203  ::Point aVCLPoint(aPixel.X, aPixel.Y);
204  ::Point aDevPoint = mxDefaultOutputDevice->PixelToLogic(aVCLPoint, aMode );
205  return awt::Point(aDevPoint.X(), aDevPoint.Y());
206  }
207  catch( Exception& )
208  {
210  }
211  return awt::Point( 0, 0 );
212 }
213 
214 awt::Size GraphicHelper::convertHmmToAppFont( const awt::Size& rHmm ) const
215 {
216  try
217  {
218  awt::Size aPixel = convertHmmToScreenPixel( rHmm );
219  MapMode aMode(MapUnit::MapAppFont);
220  ::Size aVCLSize(aPixel.Width, aPixel.Height);
221  ::Size aDevSz = mxDefaultOutputDevice->PixelToLogic(aVCLSize, aMode );
222  return awt::Size(aDevSz.Width(), aDevSz.Height());
223  }
224  catch( Exception& )
225  {
227  }
228  return awt::Size( 0, 0 );
229 }
230 
231 
232 // Graphics and graphic objects ----------------------------------------------
233 
234 Reference< XGraphic > GraphicHelper::importGraphic( const Reference< XInputStream >& rxInStrm,
235  const WmfExternal* pExtHeader ) const
236 {
237  Reference< XGraphic > xGraphic;
238  if( rxInStrm.is() && mxGraphicProvider.is() ) try
239  {
240  Sequence< PropertyValue > aArgs( 2 );
241  aArgs[ 0 ].Name = "InputStream";
242  aArgs[ 0 ].Value <<= rxInStrm;
243  aArgs[ 1 ].Name = "LazyRead";
244  aArgs[ 1 ].Value <<= true;
245 
246  if ( pExtHeader && pExtHeader->mapMode > 0 )
247  {
248  aArgs.realloc( aArgs.getLength() + 1 );
249  Sequence< PropertyValue > aFilterData( 3 );
250  aFilterData[ 0 ].Name = "ExternalWidth";
251  aFilterData[ 0 ].Value <<= pExtHeader->xExt;
252  aFilterData[ 1 ].Name = "ExternalHeight";
253  aFilterData[ 1 ].Value <<= pExtHeader->yExt;
254  aFilterData[ 2 ].Name = "ExternalMapMode";
255  aFilterData[ 2 ].Value <<= pExtHeader->mapMode;
256  aArgs[ 2 ].Name = "FilterData";
257  aArgs[ 2 ].Value <<= aFilterData;
258  }
259 
260  xGraphic = mxGraphicProvider->queryGraphic( aArgs );
261  }
262  catch( Exception& )
263  {
264  }
265  return xGraphic;
266 }
267 
268 Reference< XGraphic > GraphicHelper::importGraphic( const StreamDataSequence& rGraphicData ) const
269 {
270  Reference< XGraphic > xGraphic;
271  if( rGraphicData.hasElements() )
272  {
273  Reference< XInputStream > xInStrm( new ::comphelper::SequenceInputStream( rGraphicData ) );
274  xGraphic = importGraphic( xInStrm );
275  }
276  return xGraphic;
277 }
278 
279 Reference< XGraphic > GraphicHelper::importEmbeddedGraphic( const OUString& rStreamName, const WmfExternal* pExtHeader ) const
280 {
281  Reference< XGraphic > xGraphic;
282  OSL_ENSURE( !rStreamName.isEmpty(), "GraphicHelper::importEmbeddedGraphic - empty stream name" );
283 
284  if( !rStreamName.isEmpty() )
285  {
287 
288  SAL_WARN_IF(!mxGraphicMapper.is(), "oox", "GraphicHelper::importEmbeddedGraphic - graphic mapper not available");
289 
290  xGraphic = mxGraphicMapper->findGraphic(rStreamName);
291  if (!xGraphic.is())
292  {
293  auto xStream = mxStorage->openInputStream(rStreamName);
294  xGraphic = importGraphic(xStream, pExtHeader);
295  if (xGraphic.is())
296  mxGraphicMapper->putGraphic(rStreamName, xGraphic);
297  }
298  }
299  return xGraphic;
300 }
301 
302 awt::Size GraphicHelper::getOriginalSize( const Reference< XGraphic >& xGraphic ) const
303 {
304  awt::Size aSizeHmm;
305  PropertySet aPropSet( xGraphic );
306  if( aPropSet.getProperty( aSizeHmm, PROP_Size100thMM ) && (aSizeHmm.Width == 0) && (aSizeHmm.Height == 0) ) // MAPMODE_PIXEL used?
307  {
308  awt::Size aSizePixel( 0, 0 );
309  if( aPropSet.getProperty( aSizePixel, PROP_SizePixel ) )
310  aSizeHmm = convertScreenPixelToHmm( aSizePixel );
311  }
312  return aSizeHmm;
313 }
314 
315 void GraphicHelper::setGraphicMapper(css::uno::Reference<css::graphic::XGraphicMapper> const & rGraphicMapper)
316 {
317  mxGraphicMapper = rGraphicMapper;
318 }
319 
321 {
322  if (!mxGraphicMapper.is())
323  {
324  auto* pNonConstThis = const_cast<GraphicHelper*>(this);
325  pNonConstThis->mxGraphicMapper = graphic::GraphicMapper::create(mxContext);
326  }
327 }
328 
329 } // namespace oox
330 
331 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Provides helper functions for colors, device measurement conversion, graphics, and graphic objects ha...
virtual ::Color getSchemeColor(sal_Int32 nToken) const
Derived classes may implement to resolve a scheme color from the passed XML token identifier...
css::uno::Reference< css::graphic::XGraphic > importEmbeddedGraphic(const OUString &rStreamName, const WmfExternal *pExtHeader=nullptr) const
Imports a graphic from the storage stream with the passed path and name.
css::uno::Reference< css::graphic::XGraphicProvider2 > mxGraphicProvider
const ::Color API_RGB_TRANSPARENT(ColorTransparency, 0xffffffff)
Transparent color for API calls.
double convertHmmToScreenPixelX(sal_Int32 nHmmX) const
Converts the passed value from 1/100 mm to horizontal screen pixels.
static sal_Int16 getDefaultChartAreaLineWidth()
Returns chartspace automatic default border width in Emu.
bool getProperty(Type &orValue, sal_Int32 nPropId) const
Gets the specified property from the property set.
Definition: propertyset.hxx:94
uno::Reference< uno::XComponentContext > mxContext
::Color getSystemColor(sal_Int32 nToken,::Color nDefaultRgb=API_RGB_TRANSPARENT) const
Returns a system color specified by the passed XML token identifier.
VclPtr< OutputDevice > mxDefaultOutputDevice
css::uno::Reference< css::uno::XComponentContext > mxContext
void initializeGraphicMapperIfNeeded() const
double mfPixelPerHmmX
Number of screen pixels per 1/100 mm in X direction.
std::shared_ptr< StorageBase > StorageRef
Definition: storagebase.hxx:42
css::awt::Point convertHmmToAppFont(const css::awt::Point &rHmm) const
Converts the passed point from 1/100 mm to AppFont units.
css::uno::Reference< css::graphic::XGraphicMapper > mxGraphicMapper
static OutputDevice * GetDefaultDevice()
constexpr tools::Long Width() const
css::awt::Point convertHmmToScreenPixel(const css::awt::Point &rHmm) const
Converts the passed point from 1/100 mm to screen pixels.
Reference< XInputStream > xStream
css::awt::Size convertScreenPixelToHmm(const css::awt::Size &rPixel) const
Converts the passed size from screen pixels to 1/100 mm.
static sal_Int32 getDefaultChartAreaLineStyle()
Returns chartspace automatic default border style.
Reference< XNameContainer > mxStorage
Definition: olestorage.cxx:75
double mfPixelPerHmmY
Number of screen pixels per 1/100 mm in Y direction.
sal_uInt16 mapMode
#define DBG_UNHANDLED_EXCEPTION(...)
css::uno::Sequence< sal_Int8 > StreamDataSequence
sal_Int32 convertScreenPixelXToHmm(double fPixelX) const
Converts the passed value from horizontal screen pixels to 1/100 mm.
void setGraphicMapper(css::uno::Reference< css::graphic::XGraphicMapper > const &rxGraphicMapper)
css::uno::Reference< css::graphic::XGraphic > importGraphic(const css::uno::Reference< css::io::XInputStream > &rxInStrm, const WmfExternal *pExtHeader=nullptr) const
Imports a graphic from the passed input stream.
::std::map< sal_Int32,::Color > maSystemPalette
Maps system colors (XML tokens) to RGB color values.
StorageRef mxStorage
Storage containing embedded graphics.
A wrapper for a UNO property set.
Definition: propertyset.hxx:57
GraphicHelper(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::frame::XFrame > &rxTargetFrame, const StorageRef &rxStorage)
double convertHmmToScreenPixelY(sal_Int32 nHmmY) const
Converts the passed value from 1/100 mm to vertical screen pixels.
sal_uInt16 xExt
virtual sal_Int32 getDefaultChartAreaFillStyle() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
virtual ::Color getPaletteColor(sal_Int32 nPaletteIdx) const
Derived classes may implement to resolve a palette index to an RGB color.
sal_Int32 convertScreenPixelYToHmm(double fPixelY) const
Converts the passed value from vertical screen pixels to 1/100 mm.
static const MapType::mapped_type * getMapElement(const MapType &rMap, const typename MapType::key_type &rKey)
Returns the pointer to an existing element of the passed map, or a null pointer, if an element with t...
sal_uInt16 yExt
#define SAL_WARN_IF(condition, area, stream)
constexpr tools::Long Height() const
css::awt::Size getOriginalSize(const css::uno::Reference< css::graphic::XGraphic > &rxGraphic) const
calculates the original size of a graphic which is necessary to be able to calculate cropping values ...