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/beans/XPropertySet.hpp>
25 #include <com/sun/star/graphic/GraphicProvider.hpp>
26 #include <com/sun/star/graphic/GraphicMapper.hpp>
27 #include <osl/diagnose.h>
28 #include <sal/log.hxx>
30 #include <comphelper/seqstream.hxx>
31 #include <vcl/wmfexternal.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/outdev.hxx>
34 #include <tools/gen.hxx>
35 #include <tools/diagnose_ex.h>
38 #include <oox/token/properties.hxx>
39 #include <oox/token/tokens.hxx>
40 
41 namespace oox {
42 
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::beans;
45 using namespace ::com::sun::star::frame;
46 using namespace ::com::sun::star::graphic;
47 using namespace ::com::sun::star::io;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::uno;
50 
51 namespace {
52 
53 sal_Int32 lclConvertScreenPixelToHmm( double fPixel, double fPixelPerHmm )
54 {
55  return static_cast< sal_Int32 >( (fPixelPerHmm > 0.0) ? (fPixel / fPixelPerHmm + 0.5) : 0.0 );
56 }
57 
58 } // namespace
59 
60 GraphicHelper::GraphicHelper( const Reference< XComponentContext >& rxContext, const Reference< XFrame >& /*rxTargetFrame*/, const StorageRef& rxStorage ) :
61  mxContext( rxContext ),
62  mxStorage( rxStorage )
63 {
64  OSL_ENSURE( mxContext.is(), "GraphicHelper::GraphicHelper - missing component context" );
65  if( mxContext.is() )
66  mxGraphicProvider.set( graphic::GraphicProvider::create( mxContext ), uno::UNO_QUERY );
67 
69  maSystemPalette[ XML_3dDkShadow ] = Color(0x716F64);
70  maSystemPalette[ XML_3dLight ] = Color(0xF1EFE2);
71  maSystemPalette[ XML_activeBorder ] = Color(0xD4D0C8);
72  maSystemPalette[ XML_activeCaption ] = Color(0x0054E3);
73  maSystemPalette[ XML_appWorkspace ] = Color(0x808080);
74  maSystemPalette[ XML_background ] = Color(0x004E98);
75  maSystemPalette[ XML_btnFace ] = Color(0xECE9D8);
76  maSystemPalette[ XML_btnHighlight ] = Color(0xFFFFFF);
77  maSystemPalette[ XML_btnShadow ] = Color(0xACA899);
78  maSystemPalette[ XML_btnText ] = Color(0x000000);
79  maSystemPalette[ XML_captionText ] = Color(0xFFFFFF);
80  maSystemPalette[ XML_gradientActiveCaption ] = Color(0x3D95FF);
81  maSystemPalette[ XML_gradientInactiveCaption ] = Color(0xD8E4F8);
82  maSystemPalette[ XML_grayText ] = Color(0xACA899);
83  maSystemPalette[ XML_highlight ] = Color(0x316AC5);
84  maSystemPalette[ XML_highlightText ] = Color(0xFFFFFF);
85  maSystemPalette[ XML_hotLight ] = Color(0x000080);
86  maSystemPalette[ XML_inactiveBorder ] = Color(0xD4D0C8);
87  maSystemPalette[ XML_inactiveCaption ] = Color(0x7A96DF);
88  maSystemPalette[ XML_inactiveCaptionText ] = Color(0xD8E4F8);
89  maSystemPalette[ XML_infoBk ] = Color(0xFFFFE1);
90  maSystemPalette[ XML_infoText ] = Color(0x000000);
91  maSystemPalette[ XML_menu ] = Color(0xFFFFFF);
92  maSystemPalette[ XML_menuBar ] = Color(0xECE9D8);
93  maSystemPalette[ XML_menuHighlight ] = Color(0x316AC5);
94  maSystemPalette[ XML_menuText ] = Color(0x000000);
95  maSystemPalette[ XML_scrollBar ] = Color(0xD4D0C8);
96  maSystemPalette[ XML_window ] = Color(0xFFFFFF);
97  maSystemPalette[ XML_windowFrame ] = Color(0x000000);
98  maSystemPalette[ XML_windowText ] = Color(0x000000);
99 
100  // Note that we cannot try to get DeviceInfo from the current frame here,
101  // because there might not be a current frame yet
102  mxDefaultOutputDevice = Application::GetDefaultDevice();
103  maDeviceInfo = mxDefaultOutputDevice->GetDeviceInfo();
104  // 100 000 is 1 meter in MM100.
105  // various unit tests rely on these values being exactly this and not the "true" values
106  Size aDefault = mxDefaultOutputDevice->LogicToPixel(Size(100000, 100000), MapMode(MapUnit::Map100thMM));
107  maDeviceInfo.PixelPerMeterX = aDefault.Width();
108  maDeviceInfo.PixelPerMeterY = aDefault.Height();
109  mfPixelPerHmmX = maDeviceInfo.PixelPerMeterX / 100000.0;
110  mfPixelPerHmmY = maDeviceInfo.PixelPerMeterY / 100000.0;
111 }
112 
114 {
115 }
116 
117 // System colors and predefined colors ----------------------------------------
118 
119 ::Color GraphicHelper::getSystemColor( sal_Int32 nToken, ::Color nDefaultRgb ) const
120 {
121  return ContainerHelper::getMapElement( maSystemPalette, nToken, nDefaultRgb );
122 }
123 
124 ::Color GraphicHelper::getSchemeColor( sal_Int32 /*nToken*/ ) const
125 {
126  OSL_FAIL( "GraphicHelper::getSchemeColor - scheme colors not implemented" );
127  return API_RGB_TRANSPARENT;
128 }
129 
130 ::Color GraphicHelper::getPaletteColor( sal_Int32 /*nPaletteIdx*/ ) const
131 {
132  OSL_FAIL( "GraphicHelper::getPaletteColor - palette colors not implemented" );
133  return API_RGB_TRANSPARENT;
134 }
135 
137 {
138  return XML_solidFill;
139 }
140 
142 {
143  return XML_solidFill;
144 }
145 
147 {
148  // this value is what MSO 2016 writes fixing incomplete MSO 2010 documents (0.75 pt in emu)
149  return 9525;
150 }
151 
152 // Device info and device dependent unit conversion ---------------------------
153 
154 sal_Int32 GraphicHelper::convertScreenPixelXToHmm( double fPixelX ) const
155 {
156  return lclConvertScreenPixelToHmm( fPixelX, mfPixelPerHmmX );
157 }
158 
159 sal_Int32 GraphicHelper::convertScreenPixelYToHmm( double fPixelY ) const
160 {
161  return lclConvertScreenPixelToHmm( fPixelY, mfPixelPerHmmY );
162 }
163 
164 awt::Size GraphicHelper::convertScreenPixelToHmm( const awt::Size& rPixel ) const
165 {
166  return awt::Size( convertScreenPixelXToHmm( rPixel.Width ), convertScreenPixelYToHmm( rPixel.Height ) );
167 }
168 
169 double GraphicHelper::convertHmmToScreenPixelX( sal_Int32 nHmmX ) const
170 {
171  return nHmmX * mfPixelPerHmmX;
172 }
173 
174 double GraphicHelper::convertHmmToScreenPixelY( sal_Int32 nHmmY ) const
175 {
176  return nHmmY * mfPixelPerHmmY;
177 }
178 
179 awt::Point GraphicHelper::convertHmmToScreenPixel( const awt::Point& rHmm ) const
180 {
181  return awt::Point(
182  static_cast< sal_Int32 >( convertHmmToScreenPixelX( rHmm.X ) + 0.5 ),
183  static_cast< sal_Int32 >( convertHmmToScreenPixelY( rHmm.Y ) + 0.5 ) );
184 }
185 
186 awt::Size GraphicHelper::convertHmmToScreenPixel( const awt::Size& rHmm ) const
187 {
188  return awt::Size(
189  static_cast< sal_Int32 >( convertHmmToScreenPixelX( rHmm.Width ) + 0.5 ),
190  static_cast< sal_Int32 >( convertHmmToScreenPixelY( rHmm.Height ) + 0.5 ) );
191 }
192 
193 awt::Point GraphicHelper::convertHmmToAppFont( const awt::Point& rHmm ) const
194 {
195  try
196  {
197  awt::Point aPixel = convertHmmToScreenPixel( rHmm );
198  MapMode aMode(MapUnit::MapAppFont);
199  ::Point aVCLPoint(aPixel.X, aPixel.Y);
200  ::Point aDevPoint = mxDefaultOutputDevice->PixelToLogic(aVCLPoint, aMode );
201  return awt::Point(aDevPoint.X(), aDevPoint.Y());
202  }
203  catch( Exception& )
204  {
206  }
207  return awt::Point( 0, 0 );
208 }
209 
210 awt::Size GraphicHelper::convertHmmToAppFont( const awt::Size& rHmm ) const
211 {
212  try
213  {
214  awt::Size aPixel = convertHmmToScreenPixel( rHmm );
215  MapMode aMode(MapUnit::MapAppFont);
216  ::Size aVCLSize(aPixel.Width, aPixel.Height);
217  ::Size aDevSz = mxDefaultOutputDevice->PixelToLogic(aVCLSize, aMode );
218  return awt::Size(aDevSz.Width(), aDevSz.Height());
219  }
220  catch( Exception& )
221  {
223  }
224  return awt::Size( 0, 0 );
225 }
226 
227 
228 // Graphics and graphic objects ----------------------------------------------
229 
230 Reference< XGraphic > GraphicHelper::importGraphic( const Reference< XInputStream >& rxInStrm,
231  const WmfExternal* pExtHeader ) const
232 {
233  Reference< XGraphic > xGraphic;
234  if( rxInStrm.is() && mxGraphicProvider.is() ) try
235  {
236  Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue("InputStream", rxInStrm),
237  comphelper::makePropertyValue("LazyRead", true) };
238 
239  if ( pExtHeader && pExtHeader->mapMode > 0 )
240  {
241  aArgs.realloc( aArgs.getLength() + 1 );
242  auto pArgs = aArgs.getArray();
243  Sequence< PropertyValue > aFilterData{
244  comphelper::makePropertyValue("ExternalWidth", pExtHeader->xExt),
245  comphelper::makePropertyValue("ExternalHeight", pExtHeader->yExt),
246  comphelper::makePropertyValue("ExternalMapMode", pExtHeader->mapMode)
247  };
248  pArgs[ 2 ].Name = "FilterData";
249  pArgs[ 2 ].Value <<= aFilterData;
250  }
251 
252  xGraphic = mxGraphicProvider->queryGraphic( aArgs );
253  }
254  catch( Exception& )
255  {
256  }
257  return xGraphic;
258 }
259 
260 Reference< XGraphic > GraphicHelper::importGraphic( const StreamDataSequence& rGraphicData ) const
261 {
262  Reference< XGraphic > xGraphic;
263  if( rGraphicData.hasElements() )
264  {
265  Reference< XInputStream > xInStrm( new ::comphelper::SequenceInputStream( rGraphicData ) );
266  xGraphic = importGraphic( xInStrm );
267  }
268  return xGraphic;
269 }
270 
271 Reference< XGraphic > GraphicHelper::importEmbeddedGraphic( const OUString& rStreamName, const WmfExternal* pExtHeader ) const
272 {
273  Reference< XGraphic > xGraphic;
274  OSL_ENSURE( !rStreamName.isEmpty(), "GraphicHelper::importEmbeddedGraphic - empty stream name" );
275 
276  if( !rStreamName.isEmpty() )
277  {
279 
280  SAL_WARN_IF(!mxGraphicMapper.is(), "oox", "GraphicHelper::importEmbeddedGraphic - graphic mapper not available");
281 
282  xGraphic = mxGraphicMapper->findGraphic(rStreamName);
283  if (!xGraphic.is())
284  {
285  auto xStream = mxStorage->openInputStream(rStreamName);
286  xGraphic = importGraphic(xStream, pExtHeader);
287  if (xGraphic.is())
288  mxGraphicMapper->putGraphic(rStreamName, xGraphic);
289  }
290  }
291  return xGraphic;
292 }
293 
294 awt::Size GraphicHelper::getOriginalSize( const Reference< XGraphic >& xGraphic ) const
295 {
296  awt::Size aSizeHmm;
297  PropertySet aPropSet( xGraphic );
298  if( aPropSet.getProperty( aSizeHmm, PROP_Size100thMM ) && (aSizeHmm.Width == 0) && (aSizeHmm.Height == 0) ) // MAPMODE_PIXEL used?
299  {
300  awt::Size aSizePixel( 0, 0 );
301  if( aPropSet.getProperty( aSizePixel, PROP_SizePixel ) )
302  aSizeHmm = convertScreenPixelToHmm( aSizePixel );
303  }
304  return aSizeHmm;
305 }
306 
307 void GraphicHelper::setGraphicMapper(css::uno::Reference<css::graphic::XGraphicMapper> const & rGraphicMapper)
308 {
309  mxGraphicMapper = rGraphicMapper;
310 }
311 
313 {
314  if (!mxGraphicMapper.is())
315  {
316  auto* pNonConstThis = const_cast<GraphicHelper*>(this);
317  pNonConstThis->mxGraphicMapper = graphic::GraphicMapper::create(mxContext);
318  }
319 }
320 
321 } // namespace oox
322 
323 /* 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::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
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 ...