xref: /trunk/main/sdext/source/minimizer/impoptimizer.cxx (revision ffd38472365e95f6a578737bc9a5eb0fac624a86)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sdext.hxx"
24 
25 #include "impoptimizer.hxx"
26 #include "pppoptimizer.hxx"
27 #include "graphiccollector.hxx"
28 #include "pagecollector.hxx"
29 #include "informationdialog.hxx"
30 
31 #include "minimizer.hrc"
32 
33 #include <vector>
34 #include "com/sun/star/util/URL.hpp"
35 #include "com/sun/star/util/XURLTransformer.hpp"
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/awt/Rectangle.hpp>
38 #include <com/sun/star/awt/Size.hpp>
39 #include <com/sun/star/util/MeasureUnit.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
41 #include <com/sun/star/frame/XDesktop.hpp>
42 #include <com/sun/star/awt/XWindow.hpp>
43 #include <com/sun/star/frame/XStorable.hpp>
44 #include <com/sun/star/frame/FrameSearchFlag.hpp>
45 #include <com/sun/star/frame/XDispatchProvider.hpp>
46 #include <com/sun/star/graphic/XGraphicProvider.hpp>
47 #include <com/sun/star/lang/XServiceInfo.hpp>
48 #include <com/sun/star/container/XNamed.hpp>
49 #include <com/sun/star/drawing/XShapes.hpp>
50 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
51 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
52 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
53 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
54 #include <com/sun/star/container/XNameAccess.hpp>
55 #include <com/sun/star/presentation/XPresentation.hpp>
56 #include <com/sun/star/presentation/XPresentationPage.hpp>
57 #include <com/sun/star/document/XFilter.hpp>
58 #include <com/sun/star/document/XExporter.hpp>
59 #include <com/sun/star/uno/RuntimeException.hpp>
60 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
61 #include <com/sun/star/graphic/XGraphicProvider.hpp>
62 #include <com/sun/star/graphic/GraphicType.hpp>
63 #include <com/sun/star/io/XStream.hpp>
64 #include <com/sun/star/io/XSeekable.hpp>
65 #include <com/sun/star/frame/XComponentLoader.hpp>
66 #include <com/sun/star/util/URL.hpp>
67 
68 using namespace ::std;
69 using namespace ::com::sun::star;
70 using namespace ::com::sun::star::io;
71 using namespace ::com::sun::star::awt;
72 using namespace ::com::sun::star::uno;
73 using namespace ::com::sun::star::lang;
74 using namespace ::com::sun::star::util;
75 using namespace ::com::sun::star::frame;
76 using namespace ::com::sun::star::beans;
77 using namespace ::com::sun::star::drawing;
78 using namespace ::com::sun::star::graphic;
79 using namespace ::com::sun::star::document;
80 using namespace ::com::sun::star::container;
81 using namespace ::com::sun::star::presentation;
82 
83 using ::rtl::OUString;
84 
85 void ImpExtractCustomShow( const Reference< XModel >& rxModel, const OUString& rCustomShowName )
86 {
87     vector< Reference< XDrawPage > > vNonUsedPageList;
88     try
89     {
90         PageCollector::CollectNonCustomShowPages( rxModel, rCustomShowName, vNonUsedPageList );
91         Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
92         Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY_THROW );
93         vector< Reference< XDrawPage > >::iterator aIter( vNonUsedPageList.begin() );
94         while( aIter != vNonUsedPageList.end() )
95             xDrawPages->remove( *aIter++ );
96     }
97     catch( Exception& )
98     {
99 
100     }
101 }
102 
103 void ImpDeleteUnusedMasterPages( const Reference< XModel >& rxModel )
104 {
105     vector< PageCollector::MasterPageEntity > aMasterPageList;
106     PageCollector::CollectMasterPages( rxModel, aMasterPageList );
107 
108     // now master pages that are not marked can be deleted
109     Reference< XMasterPagesSupplier > xMasterPagesSupplier( rxModel, UNO_QUERY_THROW );
110     Reference< XDrawPages > xMasterPages( xMasterPagesSupplier->getMasterPages(), UNO_QUERY_THROW );
111     vector< PageCollector::MasterPageEntity >::iterator aIter( aMasterPageList.begin() );
112     while( aIter != aMasterPageList.end() )
113     {
114         if ( !aIter->bUsed )
115             xMasterPages->remove( aIter->xMasterPage );
116         aIter++;
117     }
118 }
119 
120 void ImpDeleteHiddenSlides( const Reference< XModel >& rxModel )
121 {
122     try
123     {
124         Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
125         Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY_THROW );
126         for( sal_Int32 i = 0; i < xDrawPages->getCount(); i++ )
127         {
128             Reference< XDrawPage > xDrawPage( xDrawPages->getByIndex( i ), UNO_QUERY_THROW );
129             Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY_THROW );
130 
131             sal_Bool bVisible = sal_True;
132             const OUString sVisible( RTL_CONSTASCII_USTRINGPARAM( "Visible" ) );
133             if ( xPropSet->getPropertyValue( sVisible ) >>= bVisible )
134             {
135                 if (!bVisible )
136                 {
137                     xDrawPages->remove( xDrawPage );
138                     i--;
139                 }
140             }
141         }
142     }
143     catch( Exception& )
144     {
145     }
146 }
147 
148 void ImpDeleteNotesPages( const Reference< XModel >& rxModel )
149 {
150     try
151     {
152         Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
153         Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY_THROW );
154         sal_Int32 i, nPages = xDrawPages->getCount();
155         for( i = 0; i < nPages; i++ )
156         {
157             Reference< XPresentationPage > xPresentationPage( xDrawPages->getByIndex( i ), UNO_QUERY_THROW );
158             Reference< XPropertySet > xPropSet( xPresentationPage->getNotesPage(), UNO_QUERY_THROW );
159             Reference< XShapes > xShapes( xPropSet, UNO_QUERY_THROW );
160             while( xShapes->getCount() )
161                 xShapes->remove( Reference< XShape >( xShapes->getByIndex( xShapes->getCount() - 1 ), UNO_QUERY_THROW ) );
162 
163             const OUString sLayout( RTL_CONSTASCII_USTRINGPARAM( "Layout" ) );
164             xPropSet->setPropertyValue( sLayout, Any( (sal_Int16)21 ) );
165         }
166     }
167     catch( Exception& )
168     {
169     }
170 }
171 
172 void ImpConvertOLE( const Reference< XModel >& rxModel, sal_Int32 nOLEOptimizationType )
173 {
174     try
175     {
176         Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
177         Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY_THROW );
178         for ( sal_Int32 i = 0; i < xDrawPages->getCount(); i++ )
179         {
180             Reference< XShapes > xShapes( xDrawPages->getByIndex( i ), UNO_QUERY_THROW );
181             for ( sal_Int32 j = 0; j < xShapes->getCount(); j++ )
182             {
183                 const OUString sOLE2Shape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.OLE2Shape" ) );
184                 Reference< XShape > xShape( xShapes->getByIndex( j ), UNO_QUERY_THROW );
185                 if ( xShape->getShapeType() == sOLE2Shape )
186                 {
187                     Reference< XPropertySet > xPropSet( xShape, UNO_QUERY_THROW );
188 
189                     sal_Bool bConvertOLE = nOLEOptimizationType == 0;
190                     if ( nOLEOptimizationType == 1 )
191                     {
192                         sal_Bool bIsInternal = sal_True;
193                         xPropSet->getPropertyValue( TKGet( TK_IsInternal ) ) >>= bIsInternal;
194                         bConvertOLE = !bIsInternal;
195                     }
196                     if ( bConvertOLE )
197                     {
198                         Reference< XGraphic > xGraphic;
199                         if ( xPropSet->getPropertyValue( TKGet( TK_Graphic ) ) >>= xGraphic )
200                         {
201                             const OUString sGraphicShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GraphicObjectShape" ) );
202                             Reference< XMultiServiceFactory > xFact( rxModel, UNO_QUERY_THROW );
203                             Reference< XShape > xShape2( xFact->createInstance( sGraphicShape ), UNO_QUERY_THROW );
204                             xShapes->add( xShape2 );
205                             xShape2->setPosition( xShape->getPosition() );
206                             xShape2->setSize( xShape->getSize() );
207                             Reference< XPropertySet > xPropSet2( xShape2, UNO_QUERY_THROW );
208                             xPropSet2->setPropertyValue( TKGet( TK_Graphic ), Any( xGraphic ) );
209                             xShapes->remove( xShape );
210                             xPropSet2->setPropertyValue( TKGet( TK_ZOrder ), Any( j ) );
211                         }
212                     }
213                 }
214             }
215         }
216     }
217     catch( Exception& )
218     {
219     }
220 }
221 
222 void ImpCompressGraphic( Reference< XGraphicProvider >& rxGraphicProvider, const Reference< XGraphic >& rxGraphic, Reference< XOutputStream >& rxOutputStream,
223     const OUString& rDestMimeType, const awt::Size& rLogicalSize, sal_Int32 nJPEGQuality, sal_Int32 nImageResolution, sal_Bool bRemoveCropping, const text::GraphicCrop& rGraphicCropLogic )
224 {
225     try
226     {
227         if ( rxGraphicProvider.is() && rxOutputStream.is() )
228         {
229             Sequence< PropertyValue > aFilterData( 8 );
230             aFilterData[ 0 ].Name = TKGet( TK_ImageResolution );
231             aFilterData[ 0 ].Value <<= nImageResolution;
232             aFilterData[ 1 ].Name = TKGet( TK_ColorMode );      // todo: jpeg color mode (0->true color, 1->grayscale)
233             aFilterData[ 1 ].Value <<= (sal_Int32)0;
234             aFilterData[ 2 ].Name = TKGet( TK_Quality );        // quality that is used if we export to jpeg
235             aFilterData[ 2 ].Value <<= nJPEGQuality;
236             aFilterData[ 3 ].Name = TKGet( TK_Compression );    // compression that is used if we export to png
237             aFilterData[ 3 ].Value <<= (sal_Int32)6;
238             aFilterData[ 4 ].Name = TKGet( TK_Interlaced );     // interlaced is turned off if we export to png
239             aFilterData[ 4 ].Value <<= (sal_Int32)0;
240             aFilterData[ 5 ].Name = TKGet( TK_LogicalSize );
241             aFilterData[ 5 ].Value <<= rLogicalSize;
242             aFilterData[ 6 ].Name = TKGet( TK_RemoveCropArea );
243             aFilterData[ 6 ].Value <<= bRemoveCropping;
244             aFilterData[ 7 ].Name = TKGet( TK_GraphicCropLogic );
245             aFilterData[ 7 ].Value <<= rGraphicCropLogic;
246 
247             Sequence< PropertyValue > aArgs( 3 );
248             aArgs[ 0 ].Name = TKGet( TK_MimeType );             // the GraphicProvider is using "MimeType", the GraphicExporter "MediaType"...
249             aArgs[ 0 ].Value <<= rDestMimeType;
250             aArgs[ 1 ].Name = TKGet( TK_OutputStream );
251             aArgs[ 1 ].Value <<= rxOutputStream;
252             aArgs[ 2 ].Name = TKGet( TK_FilterData );
253             aArgs[ 2 ].Value <<= aFilterData;
254 
255             rxGraphicProvider->storeGraphic( rxGraphic, aArgs );
256         }
257     }
258     catch( Exception& )
259     {
260     }
261 }
262 
263 Reference< XGraphic > ImpCompressGraphic( const Reference< XComponentContext >& rxContext,
264     const Reference< XGraphic >& xGraphic, const awt::Size& aLogicalSize, const text::GraphicCrop& aGraphicCropLogic,
265         const GraphicSettings& rGraphicSettings )
266 {
267     Reference< XGraphic > xNewGraphic;
268     try
269     {
270         OUString aSourceMimeType;
271         Reference< XPropertySet > xGraphicPropertySet( xGraphic, UNO_QUERY_THROW );
272         if ( xGraphicPropertySet->getPropertyValue( TKGet( TK_MimeType ) ) >>= aSourceMimeType )
273         {
274             sal_Int8 nGraphicType( xGraphic->getType() );
275             if ( nGraphicType == com::sun::star::graphic::GraphicType::PIXEL )
276             {
277                 sal_Bool bTransparent = sal_False;
278                 sal_Bool bAlpha       = sal_False;
279                 sal_Bool bAnimated    = sal_False;
280 
281                 awt::Size aSourceSizePixel( 0, 0 );
282                 text::GraphicCrop aGraphicCropPixel( 0, 0, 0, 0 );
283 
284                 if ( ( xGraphicPropertySet->getPropertyValue( TKGet( TK_SizePixel ) ) >>= aSourceSizePixel ) &&
285                     ( xGraphicPropertySet->getPropertyValue( TKGet( TK_Transparent ) ) >>= bTransparent ) &&
286                     ( xGraphicPropertySet->getPropertyValue( TKGet( TK_Alpha ) ) >>= bAlpha ) &&
287                     ( xGraphicPropertySet->getPropertyValue( TKGet( TK_Animated ) ) >>= bAnimated ) )
288                 {
289                     awt::Size aDestSizePixel( aSourceSizePixel );
290                     if ( !bAnimated )
291                     {
292                         sal_Bool bNeedsOptimizing = sal_False;
293                         sal_Bool bRemoveCropArea( rGraphicSettings.mbRemoveCropArea );
294 
295                         // cropping has to be removed from SourceSizePixel
296                         if ( aGraphicCropLogic.Left || aGraphicCropLogic.Top || aGraphicCropLogic.Right || aGraphicCropLogic.Bottom )
297                         {
298                             const awt::Size aSize100thMM( GraphicCollector::GetOriginalSize( rxContext, xGraphic ) );
299 
300                             if ( bRemoveCropArea )
301                                 bNeedsOptimizing = sal_True;
302 
303                             if ( aSize100thMM.Width && aSize100thMM.Height )
304                             {
305                                 aGraphicCropPixel.Left = static_cast< sal_Int32 >( ( (double)aSourceSizePixel.Width * aGraphicCropLogic.Left ) / aSize100thMM.Width );
306                                 aGraphicCropPixel.Top = static_cast< sal_Int32 >( ( (double)aSourceSizePixel.Height* aGraphicCropLogic.Top ) / aSize100thMM.Height );
307                                 aGraphicCropPixel.Right = static_cast< sal_Int32 >( ( (double)aSourceSizePixel.Width * ( aSize100thMM.Width - aGraphicCropLogic.Right ) ) / aSize100thMM.Width );
308                                 aGraphicCropPixel.Bottom = static_cast< sal_Int32 >( ( (double)aSourceSizePixel.Height* ( aSize100thMM.Height - aGraphicCropLogic.Bottom ) ) / aSize100thMM.Height );
309 
310                                 // first calculating new SourceSizePixel by removing the cropped area
311                                 aSourceSizePixel.Width = aGraphicCropPixel.Right - aGraphicCropPixel.Left;
312                                 aSourceSizePixel.Height= aGraphicCropPixel.Bottom - aGraphicCropPixel.Top;
313                             }
314                             else
315                             {
316                                 bRemoveCropArea = sal_False;
317                             }
318                         }
319                         if ( ( aSourceSizePixel.Width > 0 ) && ( aSourceSizePixel.Height > 0 ) )
320                         {
321                             OUString aDestMimeType( RTL_CONSTASCII_USTRINGPARAM( "image/png" ) );
322                             if ( rGraphicSettings.mbJPEGCompression && !bTransparent && !bAlpha && !bAnimated )
323                             {
324                                 aDestMimeType = OUString( RTL_CONSTASCII_USTRINGPARAM( "image/jpeg" ) );
325 //                                      if( aSourceMimeType != aDestMimeType )
326                                 bNeedsOptimizing = sal_True;
327                             }
328                             if ( bRemoveCropArea )
329                                 aDestSizePixel = aSourceSizePixel;
330                             if ( rGraphicSettings.mnImageResolution && aLogicalSize.Width && aLogicalSize.Height )
331                             {
332                                 const double fSourceDPIX = ((double)aSourceSizePixel.Width / ((double)aLogicalSize.Width / 2540.0 ));
333                                 const double fSourceDPIY = ((double)aSourceSizePixel.Height/ ((double)aLogicalSize.Height/ 2540.0 ));
334 
335                                 // check, if the bitmap DPI exceeds the maximum DPI
336                                 if( ( fSourceDPIX > rGraphicSettings.mnImageResolution ) || ( fSourceDPIY > rGraphicSettings.mnImageResolution ) )
337                                 {
338                                     const double fNewSizePixelX = ((double)aDestSizePixel.Width * rGraphicSettings.mnImageResolution ) / fSourceDPIX;
339                                     const double fNewSizePixelY = ((double)aDestSizePixel.Height* rGraphicSettings.mnImageResolution ) / fSourceDPIY;
340 
341                                     aDestSizePixel = awt::Size( (sal_Int32)fNewSizePixelX, (sal_Int32)fNewSizePixelY );
342                                     bNeedsOptimizing = sal_True;
343                                 }
344                             }
345                             if ( bNeedsOptimizing && aDestSizePixel.Width && aDestSizePixel.Height )
346                             {
347                                 Reference< XStream > xTempFile( rxContext->getServiceManager()->createInstanceWithContext( OUString::createFromAscii( "com.sun.star.io.TempFile" ), rxContext ), UNO_QUERY_THROW );
348                                 Reference< XOutputStream > xOutputStream( xTempFile->getOutputStream() );
349                                 Reference< XGraphicProvider > xGraphicProvider( rxContext->getServiceManager()->createInstanceWithContext( OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ), rxContext ), UNO_QUERY_THROW );
350 
351                                 ImpCompressGraphic( xGraphicProvider, xGraphic, xOutputStream, aDestMimeType, aLogicalSize, rGraphicSettings.mnJPEGQuality, rGraphicSettings.mnImageResolution, bRemoveCropArea, aGraphicCropLogic );
352                                 Reference< XInputStream > xInputStream( xTempFile->getInputStream() );
353                                 Reference< XSeekable > xSeekable( xInputStream, UNO_QUERY_THROW );
354                                 xSeekable->seek( 0 );
355                                 Sequence< PropertyValue > aArgs( 1 );
356                                 aArgs[ 0 ].Name = TKGet( TK_InputStream );
357                                 aArgs[ 0 ].Value <<= xInputStream;
358                                 xNewGraphic = xGraphicProvider->queryGraphic( aArgs );
359                             }
360                         }
361                     }
362                 }
363             }
364             else // this is a metafile
365             {
366                 rtl::OUString aDestMimeType( aSourceMimeType );
367                 Reference< XStream > xTempFile( rxContext->getServiceManager()->createInstanceWithContext( OUString::createFromAscii( "com.sun.star.io.TempFile" ), rxContext ), UNO_QUERY_THROW );
368                 Reference< XOutputStream > xOutputStream( xTempFile->getOutputStream() );
369                 Reference< XGraphicProvider > xGraphicProvider( rxContext->getServiceManager()->createInstanceWithContext( OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ), rxContext ), UNO_QUERY_THROW );
370                 ImpCompressGraphic( xGraphicProvider, xGraphic, xOutputStream, aDestMimeType, aLogicalSize, rGraphicSettings.mnJPEGQuality, rGraphicSettings.mnImageResolution, sal_False, aGraphicCropLogic );
371                 Reference< XInputStream > xInputStream( xTempFile->getInputStream() );
372                 Reference< XSeekable > xSeekable( xInputStream, UNO_QUERY_THROW );
373                 xSeekable->seek( 0 );
374                 Sequence< PropertyValue > aArgs( 1 );
375                 aArgs[ 0 ].Name = TKGet( TK_InputStream );
376                 aArgs[ 0 ].Value <<= xInputStream;
377                 xNewGraphic = xGraphicProvider->queryGraphic( aArgs );
378             }
379         }
380     }
381     catch( Exception& )
382     {
383     }
384     return xNewGraphic;
385 }
386 
387 void CompressGraphics( ImpOptimizer& rOptimizer, const Reference< XComponentContext >& rxContext, const GraphicSettings& rGraphicSettings,
388     std::vector< GraphicCollector::GraphicEntity >& rGraphicList )
389 {
390     try
391     {
392         std::vector< GraphicCollector::GraphicEntity >::iterator aGraphicIter( rGraphicList.begin() );
393         std::vector< GraphicCollector::GraphicEntity >::iterator aGraphicIEnd( rGraphicList.end() );
394         double i = 0;
395         while( aGraphicIter != aGraphicIEnd )
396         {
397             i++;
398             sal_Int32 nProgress = static_cast< sal_Int32 >( 40.0 * ( i / static_cast< double >( rGraphicList.size() ) ) ) + 50;
399             rOptimizer.SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( nProgress ) ) );
400             rOptimizer.DispatchStatus();
401 
402             if ( aGraphicIter->maUser.size() )
403             {
404                 GraphicSettings aGraphicSettings( rGraphicSettings );
405                 aGraphicSettings.mbRemoveCropArea = aGraphicIter->mbRemoveCropArea;
406 
407                 Reference< XGraphic > xGraphic;
408                 if ( aGraphicIter->maUser[ 0 ].mbFillBitmap && aGraphicIter->maUser[ 0 ].mxPropertySet.is() )
409                 {
410                     Reference< XBitmap > xFillBitmap;
411                     if ( aGraphicIter->maUser[ 0 ].mxPropertySet->getPropertyValue( TKGet( TK_FillBitmap ) ) >>= xFillBitmap )
412                         xGraphic = Reference< XGraphic >( xFillBitmap, UNO_QUERY_THROW );
413                 }
414                 else if ( aGraphicIter->maUser[ 0 ].mxShape.is() )
415                 {
416                     Reference< XPropertySet > xShapePropertySet( aGraphicIter->maUser[ 0 ].mxShape, UNO_QUERY_THROW );
417                     xShapePropertySet->getPropertyValue( TKGet( TK_Graphic ) ) >>= xGraphic;
418                 }
419                 if ( xGraphic.is() )
420                 {
421                     Reference< XPropertySet > xNewGraphicPropertySet( xGraphic, UNO_QUERY_THROW );
422                     awt::Size aSize100thMM( GraphicCollector::GetOriginalSize( rxContext, xGraphic ) );
423                     Reference< XGraphic > xNewGraphic( ImpCompressGraphic( rxContext, xGraphic, aGraphicIter->maLogicalSize, aGraphicIter->maGraphicCropLogic, aGraphicSettings ) );
424                     if ( xNewGraphic.is() )
425                     {
426                         // applying graphic to each user
427                         std::vector< GraphicCollector::GraphicUser >::iterator aGraphicUserIter( aGraphicIter->maUser.begin() );
428                         while( aGraphicUserIter != aGraphicIter->maUser.end() )
429                         {
430                             if ( aGraphicUserIter->mxShape.is() )
431                             {
432                                 rtl::OUString sEmptyGraphicURL;
433                                 Reference< XPropertySet > xShapePropertySet( aGraphicUserIter->mxShape, UNO_QUERY_THROW );
434                                 xShapePropertySet->setPropertyValue( TKGet( TK_GraphicURL ), Any( sEmptyGraphicURL ) );
435                                 xShapePropertySet->setPropertyValue( TKGet( TK_Graphic ), Any( xNewGraphic ) );
436 
437                                 if ( aGraphicUserIter->maGraphicCropLogic.Left || aGraphicUserIter->maGraphicCropLogic.Top
438                                 || aGraphicUserIter->maGraphicCropLogic.Right || aGraphicUserIter->maGraphicCropLogic.Bottom )
439                                 {   // removing crop area was not possible or shouldn't be applied
440                                     text::GraphicCrop aGraphicCropLogic( 0, 0, 0, 0 );
441                                     if ( !aGraphicSettings.mbRemoveCropArea )
442                                     {
443                                         awt::Size aNewSize( GraphicCollector::GetOriginalSize( rxContext, xNewGraphic ) );
444                                         aGraphicCropLogic.Left = (sal_Int32)((double)aGraphicUserIter->maGraphicCropLogic.Left * ((double)aNewSize.Width / (double)aSize100thMM.Width));
445                                         aGraphicCropLogic.Top = (sal_Int32)((double)aGraphicUserIter->maGraphicCropLogic.Top * ((double)aNewSize.Height / (double)aSize100thMM.Height));
446                                         aGraphicCropLogic.Right = (sal_Int32)((double)aGraphicUserIter->maGraphicCropLogic.Right * ((double)aNewSize.Width / (double)aSize100thMM.Width));
447                                         aGraphicCropLogic.Bottom = (sal_Int32)((double)aGraphicUserIter->maGraphicCropLogic.Bottom * ((double)aNewSize.Height / (double)aSize100thMM.Height));
448                                     }
449                                     xShapePropertySet->setPropertyValue( TKGet( TK_GraphicCrop ), Any( aGraphicCropLogic ) );
450                                 }
451                             }
452                             else if ( aGraphicUserIter->mxPropertySet.is() )
453                             {
454                                 Reference< XBitmap > xFillBitmap( xNewGraphic, UNO_QUERY );
455                                 if ( xFillBitmap.is() )
456                                 {
457                                     awt::Size aSize;
458                                     sal_Bool bLogicalSize;
459 
460                                     Reference< XPropertySet >& rxPropertySet( aGraphicUserIter->mxPropertySet );
461                                     rxPropertySet->setPropertyValue( TKGet( TK_FillBitmap ), Any( xFillBitmap ) );
462                                     if ( ( rxPropertySet->getPropertyValue( TKGet( TK_FillBitmapLogicalSize ) ) >>= bLogicalSize )
463                                         && ( rxPropertySet->getPropertyValue( TKGet( TK_FillBitmapSizeX ) ) >>= aSize.Width )
464                                         && ( rxPropertySet->getPropertyValue( TKGet( TK_FillBitmapSizeY ) ) >>= aSize.Height ) )
465                                     {
466                                         if ( !aSize.Width || !aSize.Height )
467                                         {
468                                             rxPropertySet->setPropertyValue( TKGet( TK_FillBitmapLogicalSize ), Any( sal_True ) );
469                                             rxPropertySet->setPropertyValue( TKGet( TK_FillBitmapSizeX ), Any( aGraphicUserIter->maLogicalSize.Width ) );
470                                             rxPropertySet->setPropertyValue( TKGet( TK_FillBitmapSizeY ), Any( aGraphicUserIter->maLogicalSize.Height ) );
471                                         }
472                                     }
473                                     if ( aGraphicUserIter->mxPagePropertySet.is() )
474                                         aGraphicUserIter->mxPagePropertySet->setPropertyValue( TKGet( TK_Background ), Any( rxPropertySet ) );
475                                 }
476                             }
477                             aGraphicUserIter++;
478                         }
479                     }
480                 }
481             }
482             aGraphicIter++;
483         }
484     }
485     catch ( Exception& )
486     {
487     }
488 }
489 
490 // ----------------
491 // - ImpOptimizer -
492 // ----------------
493 
494 ImpOptimizer::ImpOptimizer( const Reference< XComponentContext >& rxContext, const Reference< XModel >& rxModel ) :
495     mxContext                       ( rxContext ),
496     mxModel                     ( rxModel ),
497     mbJPEGCompression           ( sal_False ),
498     mnJPEGQuality               ( 90 ),
499     mbRemoveCropArea            ( sal_False ),
500     mnImageResolution           ( 0 ),
501     mbEmbedLinkedGraphics       ( sal_True ),
502     mbOLEOptimization           ( sal_False ),
503     mnOLEOptimizationType       ( 0 ),
504     mbDeleteUnusedMasterPages   ( sal_False ),
505     mbDeleteHiddenSlides        ( sal_False ),
506     mbDeleteNotesPages          ( sal_False ),
507     mbOpenNewDocument           ( sal_True )
508 {
509     OSL_TRACE("ImpOptimizer::ImpOptimizer");
510     Reference< XController > xController( mxModel->getCurrentController() );
511     if (xController.is() )
512         mxFrame.set( xController->getFrame() );
513 }
514 
515 // -----------------------------------------------------------------------------
516 
517 ImpOptimizer::~ImpOptimizer()
518 {
519     OSL_TRACE("ImpOptimizer::~ImpOptimizer");
520 }
521 
522 // -----------------------------------------------------------------------------
523 
524 void ImpOptimizer::DispatchStatus()
525 {
526     if ( mxStatusListener.is() )
527     {
528         FeatureStateEvent aState;
529         aState.IsEnabled = sal_True;
530         aState.State <<= GetStatusSequence();
531         mxStatusListener->statusChanged( aState );
532     }
533 }
534 
535 // -----------------------------------------------------------------------------
536 
537 sal_Bool ImpOptimizer::ImplOptimize()
538 {
539 
540     if ( maCustomShowName.getLength() )
541         ImpExtractCustomShow( mxModel, maCustomShowName );
542 
543     if ( mbDeleteUnusedMasterPages )
544     {
545         SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 40 ) ) );
546         SetStatusValue( TK_Status, Any( ConfigurationAccess::getString( STR_DELETING_SLIDES ) ) );
547         DispatchStatus();
548         ImpDeleteUnusedMasterPages( mxModel );
549     }
550 
551     if ( mbDeleteHiddenSlides )
552     {
553         SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 40 ) ) );
554         SetStatusValue( TK_Status, Any( ConfigurationAccess::getString( STR_DELETING_SLIDES ) ) );
555         DispatchStatus();
556         ImpDeleteHiddenSlides( mxModel );
557     }
558 
559     if ( mbDeleteNotesPages )
560     {
561         SetStatusValue( TK_Status, Any( ConfigurationAccess::getString( STR_DELETING_SLIDES ) ) );
562         DispatchStatus();
563         ImpDeleteNotesPages( mxModel );
564     }
565 
566     if ( mbOLEOptimization )
567     {
568         SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 45 ) ) );
569         SetStatusValue( TK_Status, Any( ConfigurationAccess::getString( STR_CREATING_OLE_REPLACEMENTS ) ) );
570         DispatchStatus();
571         ImpConvertOLE( mxModel, mnOLEOptimizationType );
572     }
573 
574     if ( mbJPEGCompression || mbRemoveCropArea || mnImageResolution )
575     {
576         SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 50 ) ) );
577         SetStatusValue( TK_Status, Any( ConfigurationAccess::getString( STR_OPTIMIZING_GRAPHICS ) ) );
578         DispatchStatus();
579 
580         std::vector< GraphicCollector::GraphicEntity > aGraphicList;
581         GraphicSettings aGraphicSettings( mbJPEGCompression, mnJPEGQuality, mbRemoveCropArea, mnImageResolution, mbEmbedLinkedGraphics );
582         GraphicCollector::CollectGraphics( mxContext, mxModel, aGraphicSettings, aGraphicList );
583         CompressGraphics( *this, mxContext, aGraphicSettings, aGraphicList );
584     }
585     SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 100 ) ) );
586     DispatchStatus();
587     return sal_True;
588 }
589 
590 static void DispatchURL( Reference< XComponentContext > xMSF, OUString sURL, Reference< XFrame > xFrame )
591 {
592     try
593     {
594         Reference< XURLTransformer > xURLTransformer( xMSF->getServiceManager()->createInstanceWithContext(
595                 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ) ), xMSF ), UNO_QUERY_THROW );
596         util::URL aUrl;
597         aUrl.Complete = sURL;
598         xURLTransformer->parseStrict( aUrl );
599         Sequence< PropertyValue > aArgs;
600         Reference< XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY_THROW );
601         Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aUrl, OUString(), 0 ); // "_self"
602         if ( xDispatch.is() )
603             xDispatch->dispatch( aUrl, aArgs );
604     }
605     catch( Exception& )
606     {
607     }
608 }
609 
610 // -----------------------------------------------------------------------------
611 
612 sal_Bool ImpOptimizer::Optimize( const Sequence< PropertyValue >& rArguments )
613 {
614     OSL_TRACE("ImpOptimizer::Optimize");
615     sal_Bool bRet = sal_True;
616 
617     if ( mxModel.is() )
618     {
619         Reference< XWindowPeer > xParentWindow;
620         sal_Int64 nEstimatedFileSize = 0;
621         SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 0 ) ) );
622         DispatchStatus();
623 
624         int i, nICount;
625         for ( i = 0, nICount = rArguments.getLength(); i < nICount; i++ )
626         {
627             switch( TKGet( rArguments[ i ].Name ) )
628             {
629                 case TK_StatusListener : rArguments[ i ].Value >>= mxStatusListener; break;
630                 case TK_ParentWindow: rArguments[ i ].Value >>= xParentWindow; break;
631                 case TK_Settings :
632                 {
633                     com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aSettings;
634                     int j, nJCount;
635                     rArguments[ i ].Value >>= aSettings;
636                     for ( j = 0, nJCount = aSettings.getLength(); j < nJCount; j++ )
637                     {
638                         switch( TKGet( aSettings[ j ].Name ) )
639                         {
640                             case TK_JPEGCompression         : aSettings[ j ].Value >>= mbJPEGCompression; break;
641                             case TK_JPEGQuality             : aSettings[ j ].Value >>= mnJPEGQuality; break;
642                             case TK_RemoveCropArea          : aSettings[ j ].Value >>= mbRemoveCropArea; break;
643                             case TK_ImageResolution         : aSettings[ j ].Value >>= mnImageResolution; break;
644                             case TK_EmbedLinkedGraphics     : aSettings[ j ].Value >>= mbEmbedLinkedGraphics; break;
645                             case TK_OLEOptimization         : aSettings[ j ].Value >>= mbOLEOptimization; break;
646                             case TK_OLEOptimizationType     : aSettings[ j ].Value >>= mnOLEOptimizationType; break;
647                             case TK_CustomShowName          : aSettings[ j ].Value >>= maCustomShowName; break;
648                             case TK_DeleteUnusedMasterPages : aSettings[ j ].Value >>= mbDeleteUnusedMasterPages; break;
649                             case TK_DeleteHiddenSlides      : aSettings[ j ].Value >>= mbDeleteHiddenSlides; break;
650                             case TK_DeleteNotesPages        : aSettings[ j ].Value >>= mbDeleteNotesPages; break;
651                             case TK_SaveAsURL               : aSettings[ j ].Value >>= maSaveAsURL; break;
652                             case TK_FilterName              : aSettings[ j ].Value >>= maFilterName; break;
653                             case TK_OpenNewDocument         : aSettings[ j ].Value >>= mbOpenNewDocument; break;
654                             case TK_EstimatedFileSize       : aSettings[ j ].Value >>= nEstimatedFileSize; break;
655                             default: break;
656                         }
657                     }
658                 }
659                 break;
660                 default: break;
661             }
662         }
663 
664         sal_Int64 nSourceSize = 0;
665         sal_Int64 nDestSize = 0;
666 
667         Reference< XFrame > xSelf;
668         if ( maSaveAsURL.getLength() )
669         {
670 
671             SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 10 ) ) );
672             SetStatusValue( TK_Status, Any( ConfigurationAccess::getString( STR_DUPLICATING_PRESENTATION ) ) );
673             DispatchStatus();
674 
675             Reference< XStorable >xStorable( mxModel, UNO_QUERY );
676             if ( xStorable.is() )
677             {
678                 if ( xStorable->hasLocation() )
679                     nSourceSize = PPPOptimizer::GetFileSize( xStorable->getLocation() );
680 
681                 Sequence< PropertyValue > aArguments;
682                 if ( maFilterName.getLength() )
683                 {
684                     int nLength = aArguments.getLength();
685                     aArguments.realloc( nLength + 1 );
686                     aArguments[ nLength ].Name = TKGet( TK_FilterName );
687                     aArguments[ nLength ].Value <<= maFilterName;
688                 }
689                 xStorable->storeToURL( maSaveAsURL, aArguments );
690                 if ( !nSourceSize )
691                     nSourceSize = PPPOptimizer::GetFileSize( maSaveAsURL );
692 
693                 SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 30 ) ) );
694                 SetStatusValue( TK_Status, Any( ConfigurationAccess::getString( STR_DUPLICATING_PRESENTATION ) ) );
695                 DispatchStatus();
696 
697                 Reference< XDesktop > xDesktop( mxContext->getServiceManager()->createInstanceWithContext(
698                         OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ), mxContext ), UNO_QUERY );
699                 Reference< XFrame > xFrame( xDesktop, UNO_QUERY );
700                 xSelf = xFrame->findFrame( TKGet( TK__blank ), FrameSearchFlag::CREATE );
701                 Reference< XComponentLoader > xComponentLoader( xSelf, UNO_QUERY );
702 
703                 Sequence< PropertyValue > aLoadProps( 1 );
704                 aLoadProps[ 0 ].Name = TKGet( TK_Hidden );
705                 aLoadProps[ 0 ].Value <<= (sal_Bool)( sal_True );
706                 mxModel = Reference< XModel >( xComponentLoader->loadComponentFromURL(
707                     maSaveAsURL, TKGet( TK__self ), 0, aLoadProps ), UNO_QUERY );
708             }
709         }
710 
711         // check if the document is ReadOnly -> error
712         Reference< XStorable > xStorable( mxModel, UNO_QUERY );
713         if ( xStorable.is() && !xStorable->isReadonly() )
714         {
715             mxModel->lockControllers();
716             bRet = ImplOptimize();
717             mxModel->unlockControllers();
718 
719             // clearing undo stack:
720             Reference< XFrame > xFrame( mxFrame );
721             if ( xFrame.is() )
722             {
723                 const OUString sSlot( RTL_CONSTASCII_USTRINGPARAM( "slot:27115" ) );
724                 DispatchURL( mxContext, sSlot, xFrame );
725             }
726         }
727 
728         if ( maSaveAsURL.getLength() )
729         {
730             if ( xStorable.is() )
731             {
732                 xStorable->store();
733                 nDestSize = PPPOptimizer::GetFileSize( maSaveAsURL );
734             }
735         }
736 
737         if ( xParentWindow.is() )
738         {
739             InformationDialog aInformationDialog(
740                 mxContext, xParentWindow, maSaveAsURL, mbOpenNewDocument,
741                 nSourceSize, nDestSize, nEstimatedFileSize );
742             aInformationDialog.execute();
743             SetStatusValue( TK_OpenNewDocument, Any( mbOpenNewDocument ) );
744             DispatchStatus();
745         }
746 
747         if ( maSaveAsURL.getLength() )
748         {
749             if ( mbOpenNewDocument && xSelf.is() )
750             {
751                 Reference< awt::XWindow > xContainerWindow( xSelf->getContainerWindow() );
752                 xContainerWindow->setVisible( sal_True );
753             }
754             else
755             {
756                 Reference< XComponent > xComponent( mxModel, UNO_QUERY );
757                 xComponent->dispose();
758             }
759         }
760         if ( nSourceSize && nDestSize )
761         {
762             SetStatusValue( TK_FileSizeSource, Any( nSourceSize ) );
763             SetStatusValue( TK_FileSizeDestination, Any( nDestSize ) );
764             DispatchStatus();
765         }
766     }
767     else
768         bRet = sal_False;
769     return bRet;
770 }
771 
772 /* vim: set noet sw=4 ts=4: */
773