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 
20 
21 #include "graphiccollector.hxx"
22 #include <com/sun/star/awt/XDevice.hpp>
23 #include <com/sun/star/frame/Desktop.hpp>
24 #include <com/sun/star/drawing/FillStyle.hpp>
25 #include <com/sun/star/drawing/BitmapMode.hpp>
26 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
27 #include <com/sun/star/presentation/XPresentationPage.hpp>
28 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
29 
30 using namespace ::com::sun::star;
31 using namespace ::com::sun::star::uno;
32 using namespace ::com::sun::star::awt;
33 using namespace ::com::sun::star::drawing;
34 using namespace ::com::sun::star::graphic;
35 using namespace ::com::sun::star::frame;
36 using namespace ::com::sun::star::beans;
37 using namespace ::com::sun::star::presentation;
38 
GetDeviceInfo(const Reference<XComponentContext> & rxFact)39 const DeviceInfo& GraphicCollector::GetDeviceInfo( const Reference< XComponentContext >& rxFact )
40 {
41     static DeviceInfo aDeviceInfo;
42     if( !aDeviceInfo.Width )
43     {
44         try
45         {
46             Reference< XDesktop2 > xDesktop = Desktop::create( rxFact );
47             Reference< XFrame > xFrame( xDesktop->getActiveFrame() );
48             Reference< XWindow > xWindow( xFrame->getContainerWindow() );
49             Reference< XDevice > xDevice( xWindow, UNO_QUERY_THROW );
50             aDeviceInfo = xDevice->getInfo();
51         }
52         catch( Exception& )
53         {
54         }
55     }
56     return aDeviceInfo;
57 }
58 
ImpAddEntity(std::vector<GraphicCollector::GraphicEntity> & rGraphicEntities,const GraphicSettings & rGraphicSettings,const GraphicCollector::GraphicUser & rUser)59 static void ImpAddEntity( std::vector< GraphicCollector::GraphicEntity >& rGraphicEntities, const GraphicSettings& rGraphicSettings, const GraphicCollector::GraphicUser& rUser )
60 {
61     if ( !rGraphicSettings.mbEmbedLinkedGraphics )
62         return;
63 
64     auto aIter = std::find_if(rGraphicEntities.begin(), rGraphicEntities.end(),
65         [&rUser](const GraphicCollector::GraphicEntity& rGraphicEntity) {
66             return rGraphicEntity.maUser[ 0 ].mxGraphic == rUser.mxGraphic;
67         });
68     if ( aIter == rGraphicEntities.end() )
69     {
70         GraphicCollector::GraphicEntity aEntity( rUser );
71         rGraphicEntities.push_back( aEntity );
72     }
73     else
74     {
75         if ( rUser.maLogicalSize.Width > aIter->maLogicalSize.Width )
76             aIter->maLogicalSize.Width = rUser.maLogicalSize.Width;
77         if ( rUser.maLogicalSize.Height > aIter->maLogicalSize.Height )
78             aIter->maLogicalSize.Height = rUser.maLogicalSize.Height;
79         aIter->maUser.push_back( rUser );
80     }
81 }
82 
ImpAddGraphicEntity(const Reference<XComponentContext> & rxMSF,Reference<XShape> const & rxShape,const GraphicSettings & rGraphicSettings,std::vector<GraphicCollector::GraphicEntity> & rGraphicEntities)83 static void ImpAddGraphicEntity( const Reference< XComponentContext >& rxMSF, Reference< XShape > const & rxShape, const GraphicSettings& rGraphicSettings, std::vector< GraphicCollector::GraphicEntity >& rGraphicEntities )
84 {
85     Reference< XGraphic > xGraphic;
86     Reference< XPropertySet > xShapePropertySet( rxShape, UNO_QUERY_THROW );
87     if ( !(xShapePropertySet->getPropertyValue( "Graphic" ) >>= xGraphic) )
88         return;
89 
90     text::GraphicCrop aGraphicCropLogic( 0, 0, 0, 0 );
91 
92     GraphicCollector::GraphicUser aUser;
93     aUser.mxShape = rxShape;
94     aUser.mbFillBitmap = false;
95     aUser.mxGraphic = xGraphic;
96     xShapePropertySet->getPropertyValue( "GraphicCrop" ) >>= aGraphicCropLogic;
97     awt::Size aLogicalSize( rxShape->getSize() );
98 
99     // calculating the logical size, as if there were no cropping
100     if ( aGraphicCropLogic.Left || aGraphicCropLogic.Right || aGraphicCropLogic.Top || aGraphicCropLogic.Bottom )
101     {
102         awt::Size aSize100thMM( GraphicCollector::GetOriginalSize( rxMSF, xGraphic ) );
103         if ( aSize100thMM.Width && aSize100thMM.Height )
104         {
105             awt::Size aCropSize( aSize100thMM.Width - ( aGraphicCropLogic.Left + aGraphicCropLogic.Right ),
106                                  aSize100thMM.Height - ( aGraphicCropLogic.Top + aGraphicCropLogic.Bottom ));
107             if ( aCropSize.Width && aCropSize.Height )
108             {
109                 awt::Size aNewLogSize( static_cast< sal_Int32 >( static_cast< double >( aSize100thMM.Width * aLogicalSize.Width ) / aCropSize.Width ),
110                     static_cast< sal_Int32 >( static_cast< double >( aSize100thMM.Height * aLogicalSize.Height ) / aCropSize.Height ) );
111                 aLogicalSize = aNewLogSize;
112             }
113         }
114     }
115     aUser.maGraphicCropLogic = aGraphicCropLogic;
116     aUser.maLogicalSize = aLogicalSize;
117     ImpAddEntity( rGraphicEntities, rGraphicSettings, aUser );
118 }
119 
ImpAddFillBitmapEntity(const Reference<XComponentContext> & rxMSF,const Reference<XPropertySet> & rxPropertySet,const awt::Size & rLogicalSize,std::vector<GraphicCollector::GraphicEntity> & rGraphicEntities,const GraphicSettings & rGraphicSettings,const Reference<XPropertySet> & rxPagePropertySet)120 static void ImpAddFillBitmapEntity( const Reference< XComponentContext >& rxMSF, const Reference< XPropertySet >& rxPropertySet, const awt::Size& rLogicalSize,
121     std::vector< GraphicCollector::GraphicEntity >& rGraphicEntities, const GraphicSettings& rGraphicSettings, const Reference< XPropertySet >& rxPagePropertySet )
122 {
123     try
124     {
125         FillStyle eFillStyle;
126         if ( rxPropertySet->getPropertyValue( "FillStyle" ) >>= eFillStyle )
127         {
128             if ( eFillStyle == FillStyle_BITMAP )
129             {
130                 Reference< XBitmap > xFillBitmap;
131                 if ( rxPropertySet->getPropertyValue( "FillBitmap" ) >>= xFillBitmap )
132                 {
133                     Reference< XGraphic > xGraphic( xFillBitmap, UNO_QUERY_THROW );
134                     awt::Size aLogicalSize( rLogicalSize );
135                     Reference< XPropertySetInfo > axPropSetInfo( rxPropertySet->getPropertySetInfo() );
136                     if ( axPropSetInfo.is() )
137                     {
138                         if ( axPropSetInfo->hasPropertyByName( "FillBitmapMode" ) )
139                         {
140                             BitmapMode eBitmapMode;
141                             if ( rxPropertySet->getPropertyValue( "FillBitmapMode" ) >>= eBitmapMode )
142                             {
143                                 if ( ( eBitmapMode == BitmapMode_REPEAT ) || ( eBitmapMode == BitmapMode_NO_REPEAT ) )
144                                 {
145                                     bool bLogicalSize = false;
146                                     awt::Size aSize( 0, 0 );
147                                     if ( ( rxPropertySet->getPropertyValue( "FillBitmapLogicalSize" ) >>= bLogicalSize )
148                                       && ( rxPropertySet->getPropertyValue( "FillBitmapSizeX" ) >>= aSize.Width )
149                                       && ( rxPropertySet->getPropertyValue( "FillBitmapSizeY" ) >>= aSize.Height ) )
150                                     {
151                                         if ( bLogicalSize )
152                                         {
153                                             if ( !aSize.Width || !aSize.Height )
154                                             {
155                                                 awt::Size aSize100thMM( GraphicCollector::GetOriginalSize( rxMSF, xGraphic ) );
156                                                 if ( aSize100thMM.Width && aSize100thMM.Height )
157                                                     aLogicalSize = aSize100thMM;
158                                             }
159                                             else
160                                                 aLogicalSize = aSize;
161                                         }
162                                         else
163                                         {
164                                             aLogicalSize.Width = sal::static_int_cast< sal_Int32 >( ( static_cast< double >( aLogicalSize.Width ) * aSize.Width ) / -100.0 );
165                                             aLogicalSize.Height = sal::static_int_cast< sal_Int32 >( ( static_cast< double >( aLogicalSize.Height ) * aSize.Height ) / -100.0 );
166                                         }
167                                     }
168                                 }
169                             }
170                         }
171                     }
172                     GraphicCollector::GraphicUser aUser;
173                     aUser.mxPropertySet = rxPropertySet;
174                     aUser.mxGraphic = xGraphic;
175                     aUser.mbFillBitmap = true;
176                     aUser.maLogicalSize = aLogicalSize;
177                     aUser.mxPagePropertySet = rxPagePropertySet;
178                     ImpAddEntity( rGraphicEntities, rGraphicSettings, aUser );
179                 }
180             }
181         }
182     }
183     catch( Exception& )
184     {
185     }
186 }
187 
ImpCollectBackgroundGraphic(const Reference<XComponentContext> & rxMSF,const Reference<XDrawPage> & rxDrawPage,const GraphicSettings & rGraphicSettings,std::vector<GraphicCollector::GraphicEntity> & rGraphicEntities)188 static void ImpCollectBackgroundGraphic( const Reference< XComponentContext >& rxMSF, const Reference< XDrawPage >& rxDrawPage, const GraphicSettings& rGraphicSettings, std::vector< GraphicCollector::GraphicEntity >& rGraphicEntities )
189 {
190     try
191     {
192         awt::Size aLogicalSize( 28000, 21000 );
193         Reference< XPropertySet > xPropertySet( rxDrawPage, UNO_QUERY_THROW );
194         xPropertySet->getPropertyValue( "Width" ) >>= aLogicalSize.Width;
195         xPropertySet->getPropertyValue( "Height" ) >>= aLogicalSize.Height;
196 
197         Reference< XPropertySet > xBackgroundPropSet;
198         if ( xPropertySet->getPropertyValue( "Background" ) >>= xBackgroundPropSet )
199             ImpAddFillBitmapEntity( rxMSF, xBackgroundPropSet, aLogicalSize, rGraphicEntities, rGraphicSettings, xPropertySet );
200     }
201     catch( Exception& )
202     {
203     }
204 }
205 
ImpCollectGraphicObjects(const Reference<XComponentContext> & rxMSF,const Reference<XShapes> & rxShapes,const GraphicSettings & rGraphicSettings,std::vector<GraphicCollector::GraphicEntity> & rGraphicEntities)206 static void ImpCollectGraphicObjects( const Reference< XComponentContext >& rxMSF, const Reference< XShapes >& rxShapes, const GraphicSettings& rGraphicSettings, std::vector< GraphicCollector::GraphicEntity >& rGraphicEntities )
207 {
208     for ( sal_Int32 i = 0; i < rxShapes->getCount(); i++ )
209     {
210         try
211         {
212             Reference< XShape > xShape( rxShapes->getByIndex( i ), UNO_QUERY_THROW );
213             const OUString sShapeType( xShape->getShapeType() );
214             if ( sShapeType == "com.sun.star.drawing.GroupShape" )
215             {
216                 Reference< XShapes > xShapes( xShape, UNO_QUERY_THROW );
217                 ImpCollectGraphicObjects( rxMSF, xShapes, rGraphicSettings, rGraphicEntities );
218                 continue;
219             }
220 
221             if ( sShapeType == "com.sun.star.drawing.GraphicObjectShape" ||
222                  sShapeType == "com.sun.star.presentation.GraphicObjectShape" )
223                 ImpAddGraphicEntity( rxMSF, xShape, rGraphicSettings, rGraphicEntities );
224 
225             // now check for a fillstyle
226             Reference< XPropertySet > xEmptyPagePropSet;
227             Reference< XPropertySet > xShapePropertySet( xShape, UNO_QUERY_THROW );
228             awt::Size aLogicalSize( xShape->getSize() );
229             ImpAddFillBitmapEntity( rxMSF, xShapePropertySet, aLogicalSize, rGraphicEntities, rGraphicSettings, xEmptyPagePropSet );
230         }
231         catch( Exception& )
232         {
233         }
234     }
235 }
236 
GetOriginalSize(const Reference<XComponentContext> & rxMSF,const Reference<XGraphic> & rxGraphic)237 awt::Size GraphicCollector::GetOriginalSize( const Reference< XComponentContext >& rxMSF, const Reference< XGraphic >& rxGraphic )
238 {
239     awt::Size aSize100thMM( 0, 0 );
240     Reference< XPropertySet > xGraphicPropertySet( rxGraphic, UNO_QUERY_THROW );
241     if ( xGraphicPropertySet->getPropertyValue( "Size100thMM" ) >>= aSize100thMM )
242     {
243         if ( !aSize100thMM.Width && !aSize100thMM.Height )
244         {   // MAPMODE_PIXEL USED :-(
245             awt::Size aSourceSizePixel( 0, 0 );
246             if ( xGraphicPropertySet->getPropertyValue( "SizePixel" ) >>= aSourceSizePixel )
247             {
248                 const DeviceInfo& rDeviceInfo( GraphicCollector::GetDeviceInfo( rxMSF ) );
249                 if ( rDeviceInfo.PixelPerMeterX && rDeviceInfo.PixelPerMeterY )
250                 {
251                     aSize100thMM.Width = static_cast< sal_Int32 >( ( aSourceSizePixel.Width * 100000.0 ) / rDeviceInfo.PixelPerMeterX );
252                     aSize100thMM.Height = static_cast< sal_Int32 >( ( aSourceSizePixel.Height * 100000.0 ) / rDeviceInfo.PixelPerMeterY );
253                 }
254             }
255         }
256     }
257     return aSize100thMM;
258 }
259 
CollectGraphics(const Reference<XComponentContext> & rxMSF,const Reference<XModel> & rxModel,const GraphicSettings & rGraphicSettings,std::vector<GraphicCollector::GraphicEntity> & rGraphicList)260 void GraphicCollector::CollectGraphics( const Reference< XComponentContext >& rxMSF, const Reference< XModel >& rxModel,
261         const GraphicSettings& rGraphicSettings, std::vector< GraphicCollector::GraphicEntity >& rGraphicList )
262 {
263     try
264     {
265         sal_Int32 i;
266         Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
267         Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW );
268         for ( i = 0; i < xDrawPages->getCount(); i++ )
269         {
270             Reference< XDrawPage > xDrawPage( xDrawPages->getByIndex( i ), UNO_QUERY_THROW );
271             ImpCollectBackgroundGraphic( rxMSF, xDrawPage, rGraphicSettings, rGraphicList );
272             ImpCollectGraphicObjects( rxMSF, xDrawPage, rGraphicSettings, rGraphicList );
273 
274             Reference< XPresentationPage > xPresentationPage( xDrawPage, UNO_QUERY_THROW );
275             Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() );
276             ImpCollectBackgroundGraphic( rxMSF, xNotesPage, rGraphicSettings, rGraphicList );
277             ImpCollectGraphicObjects( rxMSF, xNotesPage, rGraphicSettings, rGraphicList );
278         }
279         Reference< XMasterPagesSupplier > xMasterPagesSupplier( rxModel, UNO_QUERY_THROW );
280         Reference< XDrawPages > xMasterPages( xMasterPagesSupplier->getMasterPages(), UNO_SET_THROW );
281         for ( i = 0; i < xMasterPages->getCount(); i++ )
282         {
283             Reference< XDrawPage > xMasterPage( xMasterPages->getByIndex( i ), UNO_QUERY_THROW );
284             ImpCollectBackgroundGraphic( rxMSF, xMasterPage, rGraphicSettings, rGraphicList );
285             ImpCollectGraphicObjects( rxMSF, xMasterPage, rGraphicSettings, rGraphicList );
286         }
287 
288         for( auto& rGraphic : rGraphicList )
289         {
290             // check if it is possible to remove the crop area
291             rGraphic.mbRemoveCropArea = rGraphicSettings.mbRemoveCropArea;
292             if ( rGraphic.mbRemoveCropArea )
293             {
294                 std::vector< GraphicCollector::GraphicUser >::iterator aGUIter( rGraphic.maUser.begin() );
295                 while( rGraphic.mbRemoveCropArea && ( aGUIter != rGraphic.maUser.end() ) )
296                 {
297                     if ( aGUIter->maGraphicCropLogic.Left || aGUIter->maGraphicCropLogic.Top
298                         || aGUIter->maGraphicCropLogic.Right || aGUIter->maGraphicCropLogic.Bottom )
299                     {
300                         if ( aGUIter == rGraphic.maUser.begin() )
301                             rGraphic.maGraphicCropLogic = aGUIter->maGraphicCropLogic;
302                         else if ( ( rGraphic.maGraphicCropLogic.Left != aGUIter->maGraphicCropLogic.Left )
303                             || ( rGraphic.maGraphicCropLogic.Top != aGUIter->maGraphicCropLogic.Top )
304                             || ( rGraphic.maGraphicCropLogic.Right != aGUIter->maGraphicCropLogic.Right )
305                             || ( rGraphic.maGraphicCropLogic.Bottom != aGUIter->maGraphicCropLogic.Bottom ) )
306                         {
307                             rGraphic.mbRemoveCropArea = false;
308                         }
309                     }
310                     else
311                         rGraphic.mbRemoveCropArea = false;
312                     ++aGUIter;
313                 }
314             }
315             if ( !rGraphic.mbRemoveCropArea )
316                 rGraphic.maGraphicCropLogic = text::GraphicCrop( 0, 0, 0, 0 );
317         }
318     }
319     catch ( Exception& )
320     {
321     }
322 }
323 
ImpCountGraphicObjects(const Reference<XComponentContext> & rxMSF,const Reference<XShapes> & rxShapes,const GraphicSettings & rGraphicSettings,sal_Int32 & rnGraphics)324 static void ImpCountGraphicObjects( const Reference< XComponentContext >& rxMSF, const Reference< XShapes >& rxShapes, const GraphicSettings& rGraphicSettings, sal_Int32& rnGraphics )
325 {
326     for ( sal_Int32 i = 0; i < rxShapes->getCount(); i++ )
327     {
328         try
329         {
330             Reference< XShape > xShape( rxShapes->getByIndex( i ), UNO_QUERY_THROW );
331             const OUString sShapeType( xShape->getShapeType() );
332             if ( sShapeType == "com.sun.star.drawing.GroupShape" )
333             {
334                 Reference< XShapes > xShapes( xShape, UNO_QUERY_THROW );
335                 ImpCountGraphicObjects( rxMSF, xShapes, rGraphicSettings, rnGraphics );
336                 continue;
337             }
338 
339             if ( sShapeType == "com.sun.star.drawing.GraphicObjectShape" ||
340                  sShapeType == "com.sun.star.presentation.GraphicObjectShape" )
341             {
342                 rnGraphics++;
343             }
344 
345             // now check for a fillstyle
346             Reference< XPropertySet > xShapePropertySet( xShape, UNO_QUERY_THROW );
347             FillStyle eFillStyle;
348             if ( xShapePropertySet->getPropertyValue( "FillStyle" ) >>= eFillStyle )
349             {
350                 if ( eFillStyle == FillStyle_BITMAP )
351                 {
352                     rnGraphics++;
353                 }
354             }
355         }
356         catch( Exception& )
357         {
358         }
359     }
360 }
361 
ImpCountBackgroundGraphic(const Reference<XDrawPage> & rxDrawPage,sal_Int32 & rnGraphics)362 static void ImpCountBackgroundGraphic(
363     const Reference< XDrawPage >& rxDrawPage, sal_Int32& rnGraphics )
364 {
365     try
366     {
367         awt::Size aLogicalSize( 28000, 21000 );
368         Reference< XPropertySet > xPropertySet( rxDrawPage, UNO_QUERY_THROW );
369         xPropertySet->getPropertyValue( "Width" ) >>= aLogicalSize.Width;
370         xPropertySet->getPropertyValue( "Height" ) >>= aLogicalSize.Height;
371 
372         Reference< XPropertySet > xBackgroundPropSet;
373         if ( xPropertySet->getPropertyValue( "Background" ) >>= xBackgroundPropSet )
374         {
375             FillStyle eFillStyle;
376             if ( xBackgroundPropSet->getPropertyValue( "FillStyle" ) >>= eFillStyle )
377             {
378                 if ( eFillStyle == FillStyle_BITMAP )
379                 {
380                     rnGraphics++;
381                 }
382             }
383         }
384     }
385     catch( Exception& )
386     {
387     }
388 }
389 
CountGraphics(const Reference<XComponentContext> & rxMSF,const Reference<XModel> & rxModel,const GraphicSettings & rGraphicSettings,sal_Int32 & rnGraphics)390 void GraphicCollector::CountGraphics( const Reference< XComponentContext >& rxMSF, const Reference< XModel >& rxModel,
391         const GraphicSettings& rGraphicSettings, sal_Int32& rnGraphics )
392 {
393     try
394     {
395         sal_Int32 i;
396         Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
397         Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW );
398         for ( i = 0; i < xDrawPages->getCount(); i++ )
399         {
400             Reference< XDrawPage > xDrawPage( xDrawPages->getByIndex( i ), UNO_QUERY_THROW );
401             ImpCountBackgroundGraphic( xDrawPage, rnGraphics );
402             ImpCountGraphicObjects( rxMSF, xDrawPage, rGraphicSettings, rnGraphics );
403 
404             Reference< XPresentationPage > xPresentationPage( xDrawPage, UNO_QUERY_THROW );
405             Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() );
406             ImpCountBackgroundGraphic( xNotesPage, rnGraphics );
407             ImpCountGraphicObjects( rxMSF, xNotesPage, rGraphicSettings, rnGraphics );
408         }
409         Reference< XMasterPagesSupplier > xMasterPagesSupplier( rxModel, UNO_QUERY_THROW );
410         Reference< XDrawPages > xMasterPages( xMasterPagesSupplier->getMasterPages(), UNO_SET_THROW );
411         for ( i = 0; i < xMasterPages->getCount(); i++ )
412         {
413             Reference< XDrawPage > xMasterPage( xMasterPages->getByIndex( i ), UNO_QUERY_THROW );
414             ImpCountBackgroundGraphic( xMasterPage, rnGraphics );
415             ImpCountGraphicObjects( rxMSF, xMasterPage, rGraphicSettings, rnGraphics );
416         }
417     }
418     catch ( Exception& )
419     {
420     }
421 }
422 
423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
424