LibreOffice Module sdext (master)  1
impoptimizer.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 
20 
21 #include "impoptimizer.hxx"
22 #include "pppoptimizer.hxx"
23 #include "graphiccollector.hxx"
24 #include "pagecollector.hxx"
25 #include "informationdialog.hxx"
26 
27 #include <vector>
28 #include <com/sun/star/util/URL.hpp>
29 #include <com/sun/star/util/XURLTransformer.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/awt/Size.hpp>
32 #include <com/sun/star/frame/XModel.hpp>
33 #include <com/sun/star/frame/Desktop.hpp>
34 #include <com/sun/star/awt/XWindow.hpp>
35 #include <com/sun/star/frame/XStorable.hpp>
36 #include <com/sun/star/frame/FrameSearchFlag.hpp>
37 #include <com/sun/star/frame/XDispatchProvider.hpp>
38 #include <com/sun/star/graphic/GraphicProvider.hpp>
39 #include <com/sun/star/graphic/XGraphicProvider.hpp>
40 #include <com/sun/star/drawing/XShapes.hpp>
41 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
42 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
43 #include <com/sun/star/presentation/XPresentationPage.hpp>
44 #include <com/sun/star/document/XFilter.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/graphic/GraphicType.hpp>
47 #include <com/sun/star/io/XStream.hpp>
48 #include <com/sun/star/io/XSeekable.hpp>
49 #include <com/sun/star/io/TempFile.hpp>
50 #include <com/sun/star/frame/XComponentLoader.hpp>
51 #include <com/sun/star/util/URLTransformer.hpp>
52 
53 using namespace ::std;
54 using namespace ::com::sun::star;
55 using namespace ::com::sun::star::io;
56 using namespace ::com::sun::star::awt;
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::lang;
59 using namespace ::com::sun::star::util;
60 using namespace ::com::sun::star::frame;
61 using namespace ::com::sun::star::beans;
62 using namespace ::com::sun::star::drawing;
63 using namespace ::com::sun::star::graphic;
64 using namespace ::com::sun::star::document;
65 using namespace ::com::sun::star::container;
66 using namespace ::com::sun::star::presentation;
67 
68 static void ImpExtractCustomShow( const Reference< XModel >& rxModel, const OUString& rCustomShowName )
69 {
70  vector< Reference< XDrawPage > > vNonUsedPageList;
71  try
72  {
73  PageCollector::CollectNonCustomShowPages( rxModel, rCustomShowName, vNonUsedPageList );
74  Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
75  Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW );
76  for( const auto& rxPage : vNonUsedPageList )
77  xDrawPages->remove( rxPage );
78  }
79  catch( Exception& )
80  {
81 
82  }
83 }
84 
85 static void ImpDeleteUnusedMasterPages( const Reference< XModel >& rxModel )
86 {
87  vector< PageCollector::MasterPageEntity > aMasterPageList;
88  PageCollector::CollectMasterPages( rxModel, aMasterPageList );
89 
90  // now master pages that are not marked can be deleted
91  Reference< XMasterPagesSupplier > xMasterPagesSupplier( rxModel, UNO_QUERY_THROW );
92  Reference< XDrawPages > xMasterPages( xMasterPagesSupplier->getMasterPages(), UNO_SET_THROW );
93  for( const auto& rMasterPage : aMasterPageList )
94  {
95  if ( !rMasterPage.bUsed )
96  xMasterPages->remove( rMasterPage.xMasterPage );
97  }
98 }
99 
100 static void ImpDeleteHiddenSlides( const Reference< XModel >& rxModel )
101 {
102  try
103  {
104  Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
105  Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW );
106  for( sal_Int32 i = 0; i < xDrawPages->getCount(); i++ )
107  {
108  Reference< XDrawPage > xDrawPage( xDrawPages->getByIndex( i ), UNO_QUERY_THROW );
109  Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY_THROW );
110 
111  bool bVisible = true;
112  if ( xPropSet->getPropertyValue( "Visible" ) >>= bVisible )
113  {
114  if (!bVisible )
115  {
116  xDrawPages->remove( xDrawPage );
117  i--;
118  }
119  }
120  }
121  }
122  catch( Exception& )
123  {
124  }
125 }
126 
127 static void ImpDeleteNotesPages( const Reference< XModel >& rxModel )
128 {
129  try
130  {
131  Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
132  Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW );
133  sal_Int32 i, nPages = xDrawPages->getCount();
134  for( i = 0; i < nPages; i++ )
135  {
136  Reference< XPresentationPage > xPresentationPage( xDrawPages->getByIndex( i ), UNO_QUERY_THROW );
137  Reference< XPropertySet > xPropSet( xPresentationPage->getNotesPage(), UNO_QUERY_THROW );
138  Reference< XShapes > xShapes( xPropSet, UNO_QUERY_THROW );
139  while( xShapes->getCount() )
140  xShapes->remove( Reference< XShape >( xShapes->getByIndex( xShapes->getCount() - 1 ), UNO_QUERY_THROW ) );
141 
142  xPropSet->setPropertyValue( "Layout", Any( sal_Int16(21) ) );
143  }
144  }
145  catch( Exception& )
146  {
147  }
148 }
149 
150 static void ImpConvertOLE( const Reference< XModel >& rxModel, sal_Int32 nOLEOptimizationType )
151 {
152  try
153  {
154  Reference< XDrawPagesSupplier > xDrawPagesSupplier( rxModel, UNO_QUERY_THROW );
155  Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW );
156  for ( sal_Int32 i = 0; i < xDrawPages->getCount(); i++ )
157  {
158  Reference< XShapes > xShapes( xDrawPages->getByIndex( i ), UNO_QUERY_THROW );
159  for ( sal_Int32 j = 0; j < xShapes->getCount(); j++ )
160  {
161  Reference< XShape > xShape( xShapes->getByIndex( j ), UNO_QUERY_THROW );
162  if ( xShape->getShapeType() == "com.sun.star.drawing.OLE2Shape" )
163  {
164  Reference< XPropertySet > xPropSet( xShape, UNO_QUERY_THROW );
165 
166  bool bConvertOLE = nOLEOptimizationType == 0;
167  if ( nOLEOptimizationType == 1 )
168  {
169  bool bIsInternal = true;
170  xPropSet->getPropertyValue( "IsInternal" ) >>= bIsInternal;
171  bConvertOLE = !bIsInternal;
172  }
173  if ( bConvertOLE )
174  {
175  Reference< XGraphic > xGraphic;
176  if ( xPropSet->getPropertyValue( "Graphic" ) >>= xGraphic )
177  {
178  Reference< XMultiServiceFactory > xFact( rxModel, UNO_QUERY_THROW );
179  Reference< XShape > xShape2( xFact->createInstance( "com.sun.star.drawing.GraphicObjectShape" ), UNO_QUERY_THROW );
180  xShapes->add( xShape2 );
181  xShape2->setPosition( xShape->getPosition() );
182  xShape2->setSize( xShape->getSize() );
183  Reference< XPropertySet > xPropSet2( xShape2, UNO_QUERY_THROW );
184  xPropSet2->setPropertyValue( "Graphic", Any( xGraphic ) );
185  xShapes->remove( xShape );
186  xPropSet2->setPropertyValue( "ZOrder", Any( j ) );
187  }
188  }
189  }
190  }
191  }
192  }
193  catch( Exception& )
194  {
195  }
196 }
197 
198 static void ImpCompressGraphic( Reference< XGraphicProvider > const & rxGraphicProvider, const Reference< XGraphic >& rxGraphic, Reference< XOutputStream > const & rxOutputStream,
199  const OUString& rDestMimeType, const awt::Size& rLogicalSize, sal_Int32 nJPEGQuality, sal_Int32 nImageResolution, bool bRemoveCropping, const text::GraphicCrop& rGraphicCropLogic )
200 {
201  try
202  {
203  if ( rxGraphicProvider.is() && rxOutputStream.is() )
204  {
205  Sequence< PropertyValue > aFilterData( 8 );
206  aFilterData[ 0 ].Name = "ImageResolution";
207  aFilterData[ 0 ].Value <<= nImageResolution;
208  aFilterData[ 1 ].Name = "ColorMode"; // todo: jpeg color mode (0->true color, 1->greyscale)
209  aFilterData[ 1 ].Value <<= sal_Int32(0);
210  aFilterData[ 2 ].Name = "Quality"; // quality that is used if we export to jpeg
211  aFilterData[ 2 ].Value <<= nJPEGQuality;
212  aFilterData[ 3 ].Name = "Compression"; // compression that is used if we export to png
213  aFilterData[ 3 ].Value <<= sal_Int32(6);
214  aFilterData[ 4 ].Name = "Interlaced"; // interlaced is turned off if we export to png
215  aFilterData[ 4 ].Value <<= sal_Int32(0);
216  aFilterData[ 5 ].Name = "LogicalSize";
217  aFilterData[ 5 ].Value <<= rLogicalSize;
218  aFilterData[ 6 ].Name = "RemoveCropArea";
219  aFilterData[ 6 ].Value <<= bRemoveCropping;
220  aFilterData[ 7 ].Name = "GraphicCropLogic";
221  aFilterData[ 7 ].Value <<= rGraphicCropLogic;
222 
223  Sequence< PropertyValue > aArgs( 3 );
224  aArgs[ 0 ].Name = "MimeType"; // the GraphicProvider is using "MimeType", the GraphicExporter "MediaType"...
225  aArgs[ 0 ].Value <<= rDestMimeType;
226  aArgs[ 1 ].Name = "OutputStream";
227  aArgs[ 1 ].Value <<= rxOutputStream;
228  aArgs[ 2 ].Name = "FilterData";
229  aArgs[ 2 ].Value <<= aFilterData;
230 
231  rxGraphicProvider->storeGraphic( rxGraphic, aArgs );
232  }
233  }
234  catch( Exception& )
235  {
236  }
237 }
238 
239 static Reference< XGraphic > ImpCompressGraphic( const Reference< XComponentContext >& rxContext,
240  const Reference< XGraphic >& xGraphic, const awt::Size& aLogicalSize, const text::GraphicCrop& aGraphicCropLogic,
241  const GraphicSettings& rGraphicSettings )
242 {
243  Reference< XGraphic > xNewGraphic;
244  try
245  {
246  OUString aSourceMimeType;
247  Reference< XPropertySet > xGraphicPropertySet( xGraphic, UNO_QUERY_THROW );
248  if ( xGraphicPropertySet->getPropertyValue( "MimeType" ) >>= aSourceMimeType )
249  {
250  sal_Int8 nGraphicType( xGraphic->getType() );
251  if ( nGraphicType == css::graphic::GraphicType::PIXEL )
252  {
253  bool bTransparent = false;
254  bool bAlpha = false;
255  bool bAnimated = false;
256 
257  awt::Size aSourceSizePixel( 0, 0 );
258  text::GraphicCrop aGraphicCropPixel( 0, 0, 0, 0 );
259 
260  if ( ( xGraphicPropertySet->getPropertyValue( "SizePixel" ) >>= aSourceSizePixel ) &&
261  ( xGraphicPropertySet->getPropertyValue( "Transparent" ) >>= bTransparent ) &&
262  ( xGraphicPropertySet->getPropertyValue( "Alpha" ) >>= bAlpha ) &&
263  ( xGraphicPropertySet->getPropertyValue( "Animated" ) >>= bAnimated ) )
264  {
265  awt::Size aDestSizePixel( aSourceSizePixel );
266  if ( !bAnimated )
267  {
268  bool bNeedsOptimizing = false;
269  bool bRemoveCropArea( rGraphicSettings.mbRemoveCropArea );
270 
271  // cropping has to be removed from SourceSizePixel
272  if ( aGraphicCropLogic.Left || aGraphicCropLogic.Top || aGraphicCropLogic.Right || aGraphicCropLogic.Bottom )
273  {
274  const awt::Size aSize100thMM( GraphicCollector::GetOriginalSize( rxContext, xGraphic ) );
275 
276  if ( bRemoveCropArea )
277  bNeedsOptimizing = true;
278 
279  if ( aSize100thMM.Width && aSize100thMM.Height )
280  {
281  aGraphicCropPixel.Left = static_cast< sal_Int32 >( ( static_cast<double>(aSourceSizePixel.Width) * aGraphicCropLogic.Left ) / aSize100thMM.Width );
282  aGraphicCropPixel.Top = static_cast< sal_Int32 >( ( static_cast<double>(aSourceSizePixel.Height)* aGraphicCropLogic.Top ) / aSize100thMM.Height );
283  aGraphicCropPixel.Right = static_cast< sal_Int32 >( ( static_cast<double>(aSourceSizePixel.Width) * ( aSize100thMM.Width - aGraphicCropLogic.Right ) ) / aSize100thMM.Width );
284  aGraphicCropPixel.Bottom = static_cast< sal_Int32 >( ( static_cast<double>(aSourceSizePixel.Height)* ( aSize100thMM.Height - aGraphicCropLogic.Bottom ) ) / aSize100thMM.Height );
285 
286  // first calculating new SourceSizePixel by removing the cropped area
287  aSourceSizePixel.Width = aGraphicCropPixel.Right - aGraphicCropPixel.Left;
288  aSourceSizePixel.Height= aGraphicCropPixel.Bottom - aGraphicCropPixel.Top;
289  }
290  else
291  {
292  bRemoveCropArea = false;
293  }
294  }
295  if ( ( aSourceSizePixel.Width > 0 ) && ( aSourceSizePixel.Height > 0 ) )
296  {
297  OUString aDestMimeType( "image/png" );
298  if (rGraphicSettings.mbJPEGCompression && !bTransparent && !bAlpha)
299  {
300  aDestMimeType = "image/jpeg";
301 // if( aSourceMimeType != aDestMimeType )
302  bNeedsOptimizing = true;
303  }
304  if ( bRemoveCropArea )
305  aDestSizePixel = aSourceSizePixel;
306  if ( rGraphicSettings.mnImageResolution && aLogicalSize.Width && aLogicalSize.Height )
307  {
308  const double fSourceDPIX = static_cast<double>(aSourceSizePixel.Width) / (static_cast<double>(aLogicalSize.Width) / 2540.0 );
309  const double fSourceDPIY = static_cast<double>(aSourceSizePixel.Height)/ (static_cast<double>(aLogicalSize.Height)/ 2540.0 );
310 
311  // check, if the bitmap DPI exceeds the maximum DPI
312  if( ( fSourceDPIX > rGraphicSettings.mnImageResolution ) || ( fSourceDPIY > rGraphicSettings.mnImageResolution ) )
313  {
314  const double fNewSizePixelX = (static_cast<double>(aDestSizePixel.Width) * rGraphicSettings.mnImageResolution ) / fSourceDPIX;
315  const double fNewSizePixelY = (static_cast<double>(aDestSizePixel.Height)* rGraphicSettings.mnImageResolution ) / fSourceDPIY;
316 
317  aDestSizePixel = awt::Size( static_cast<sal_Int32>(fNewSizePixelX), static_cast<sal_Int32>(fNewSizePixelY) );
318  bNeedsOptimizing = true;
319  }
320  }
321  if ( bNeedsOptimizing && aDestSizePixel.Width && aDestSizePixel.Height )
322  {
323  Reference< XStream > xTempFile( io::TempFile::create(rxContext), UNO_QUERY_THROW );
324  Reference< XOutputStream > xOutputStream( xTempFile->getOutputStream() );
325  Reference< XGraphicProvider > xGraphicProvider( GraphicProvider::create( rxContext ) );
326 
327  ImpCompressGraphic( xGraphicProvider, xGraphic, xOutputStream, aDestMimeType, aLogicalSize, rGraphicSettings.mnJPEGQuality, rGraphicSettings.mnImageResolution, bRemoveCropArea, aGraphicCropLogic );
328  Reference< XInputStream > xInputStream( xTempFile->getInputStream() );
329  Reference< XSeekable > xSeekable( xInputStream, UNO_QUERY_THROW );
330  xSeekable->seek( 0 );
331  Sequence< PropertyValue > aArgs( 1 );
332  aArgs[ 0 ].Name = "InputStream";
333  aArgs[ 0 ].Value <<= xInputStream;
334  xNewGraphic = xGraphicProvider->queryGraphic( aArgs );
335  }
336  }
337  }
338  }
339  }
340  else // this is a metafile
341  {
342  const OUString& aDestMimeType( aSourceMimeType );
343  Reference< XStream > xTempFile( io::TempFile::create(rxContext), UNO_QUERY_THROW );
344  Reference< XOutputStream > xOutputStream( xTempFile->getOutputStream() );
345  Reference< XGraphicProvider > xGraphicProvider( GraphicProvider::create( rxContext ) );
346  ImpCompressGraphic( xGraphicProvider, xGraphic, xOutputStream, aDestMimeType, aLogicalSize, rGraphicSettings.mnJPEGQuality, rGraphicSettings.mnImageResolution, false, aGraphicCropLogic );
347  Reference< XInputStream > xInputStream( xTempFile->getInputStream() );
348  Reference< XSeekable > xSeekable( xInputStream, UNO_QUERY_THROW );
349  xSeekable->seek( 0 );
350  Sequence< PropertyValue > aArgs( 1 );
351  aArgs[ 0 ].Name = "InputStream";
352  aArgs[ 0 ].Value <<= xInputStream;
353  xNewGraphic = xGraphicProvider->queryGraphic( aArgs );
354  }
355  }
356  }
357  catch( Exception& )
358  {
359  }
360  return xNewGraphic;
361 }
362 
363 static void CompressGraphics( ImpOptimizer& rOptimizer, const Reference< XComponentContext >& rxContext, const GraphicSettings& rGraphicSettings,
364  std::vector< GraphicCollector::GraphicEntity >& rGraphicList )
365 {
366  try
367  {
368  double i = 0;
369  for( auto& rGraphic : rGraphicList )
370  {
371  i++;
372  sal_Int32 nProgress = static_cast< sal_Int32 >( 40.0 * ( i / static_cast< double >( rGraphicList.size() ) ) ) + 50;
373  rOptimizer.SetStatusValue( TK_Progress, Any( nProgress ) );
374  rOptimizer.DispatchStatus();
375 
376  if ( !rGraphic.maUser.empty() )
377  {
378  GraphicSettings aGraphicSettings( rGraphicSettings );
379  aGraphicSettings.mbRemoveCropArea = rGraphic.mbRemoveCropArea;
380 
381  Reference< XGraphic > xGraphic;
382  if ( rGraphic.maUser[ 0 ].mbFillBitmap && rGraphic.maUser[ 0 ].mxPropertySet.is() )
383  {
384  Reference< XBitmap > xFillBitmap;
385  if ( rGraphic.maUser[ 0 ].mxPropertySet->getPropertyValue( "FillBitmap" ) >>= xFillBitmap )
386  xGraphic.set( xFillBitmap, UNO_QUERY_THROW );
387  }
388  else if ( rGraphic.maUser[ 0 ].mxShape.is() )
389  {
390  Reference< XPropertySet > xShapePropertySet( rGraphic.maUser[ 0 ].mxShape, UNO_QUERY_THROW );
391  xShapePropertySet->getPropertyValue( "Graphic" ) >>= xGraphic;
392  }
393  if ( xGraphic.is() )
394  {
395  Reference< XPropertySet > xNewGraphicPropertySet( xGraphic, UNO_QUERY_THROW );
396  awt::Size aSize100thMM( GraphicCollector::GetOriginalSize( rxContext, xGraphic ) );
397  Reference< XGraphic > xNewGraphic( ImpCompressGraphic( rxContext, xGraphic, rGraphic.maLogicalSize, rGraphic.maGraphicCropLogic, aGraphicSettings ) );
398  if ( xNewGraphic.is() )
399  {
400  // applying graphic to each user
401  for( auto& rGraphicUser : rGraphic.maUser )
402  {
403  if ( rGraphicUser.mxShape.is() )
404  {
405  Reference< XPropertySet > xShapePropertySet( rGraphicUser.mxShape, UNO_QUERY_THROW );
406  xShapePropertySet->setPropertyValue( "Graphic", Any( xNewGraphic ) );
407 
408  if ( rGraphicUser.maGraphicCropLogic.Left || rGraphicUser.maGraphicCropLogic.Top
409  || rGraphicUser.maGraphicCropLogic.Right || rGraphicUser.maGraphicCropLogic.Bottom )
410  { // removing crop area was not possible or shouldn't been applied
411  text::GraphicCrop aGraphicCropLogic( 0, 0, 0, 0 );
412  if ( !aGraphicSettings.mbRemoveCropArea )
413  {
414  awt::Size aNewSize( GraphicCollector::GetOriginalSize( rxContext, xNewGraphic ) );
415  aGraphicCropLogic.Left = static_cast<sal_Int32>(static_cast<double>(rGraphicUser.maGraphicCropLogic.Left) * (static_cast<double>(aNewSize.Width) / static_cast<double>(aSize100thMM.Width)));
416  aGraphicCropLogic.Top = static_cast<sal_Int32>(static_cast<double>(rGraphicUser.maGraphicCropLogic.Top) * (static_cast<double>(aNewSize.Height) / static_cast<double>(aSize100thMM.Height)));
417  aGraphicCropLogic.Right = static_cast<sal_Int32>(static_cast<double>(rGraphicUser.maGraphicCropLogic.Right) * (static_cast<double>(aNewSize.Width) / static_cast<double>(aSize100thMM.Width)));
418  aGraphicCropLogic.Bottom = static_cast<sal_Int32>(static_cast<double>(rGraphicUser.maGraphicCropLogic.Bottom) * (static_cast<double>(aNewSize.Height) / static_cast<double>(aSize100thMM.Height)));
419  }
420  xShapePropertySet->setPropertyValue( "GraphicCrop", Any( aGraphicCropLogic ) );
421  }
422  }
423  else if ( rGraphicUser.mxPropertySet.is() )
424  {
425  Reference< XBitmap > xFillBitmap( xNewGraphic, UNO_QUERY );
426  if ( xFillBitmap.is() )
427  {
428  awt::Size aSize;
429  bool bLogicalSize;
430 
431  Reference< XPropertySet >& rxPropertySet( rGraphicUser.mxPropertySet );
432  rxPropertySet->setPropertyValue( "FillBitmap", Any( xFillBitmap ) );
433  if ( ( rxPropertySet->getPropertyValue( "FillBitmapLogicalSize" ) >>= bLogicalSize )
434  && ( rxPropertySet->getPropertyValue( "FillBitmapSizeX" ) >>= aSize.Width )
435  && ( rxPropertySet->getPropertyValue( "FillBitmapSizeY" ) >>= aSize.Height ) )
436  {
437  if ( !aSize.Width || !aSize.Height )
438  {
439  rxPropertySet->setPropertyValue( "FillBitmapLogicalSize", Any( true ) );
440  rxPropertySet->setPropertyValue( "FillBitmapSizeX", Any( rGraphicUser.maLogicalSize.Width ) );
441  rxPropertySet->setPropertyValue( "FillBitmapSizeY", Any( rGraphicUser.maLogicalSize.Height ) );
442  }
443  }
444  if ( rGraphicUser.mxPagePropertySet.is() )
445  rGraphicUser.mxPagePropertySet->setPropertyValue( "Background", Any( rxPropertySet ) );
446  }
447  }
448  }
449  }
450  }
451  }
452  }
453  }
454  catch ( Exception& )
455  {
456  }
457 }
458 
459 
460 ImpOptimizer::ImpOptimizer( const Reference< XComponentContext >& rxContext, const Reference< XModel >& rxModel ) :
461  mxContext ( rxContext ),
462  mxModel ( rxModel ),
463  mbJPEGCompression ( false ),
464  mnJPEGQuality ( 90 ),
465  mbRemoveCropArea ( false ),
466  mnImageResolution ( 0 ),
467  mbEmbedLinkedGraphics ( true ),
468  mbOLEOptimization ( false ),
469  mnOLEOptimizationType ( 0 ),
470  mbDeleteUnusedMasterPages ( false ),
471  mbDeleteHiddenSlides ( false ),
472  mbDeleteNotesPages ( false ),
473  mbOpenNewDocument ( true )
474 {
475 }
476 
477 
479 {
480 }
481 
482 
484 {
485  if ( mxStatusDispatcher.is() )
486  {
487  URL aURL;
488  aURL.Protocol = "vnd.com.sun.star.comp.PresentationMinimizer:";
489  aURL.Path = "statusupdate";
490  mxStatusDispatcher->dispatch( aURL, GetStatusSequence() );
491  }
492 }
493 
494 
496 {
497 
498  if ( !maCustomShowName.isEmpty() )
500 
501  if ( mbDeleteHiddenSlides )
502  {
503  SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 40 ) ) );
504  SetStatusValue( TK_Status, Any( OUString("STR_DELETING_SLIDES") ) );
505  DispatchStatus();
507  }
508 
509  if ( mbDeleteNotesPages )
510  {
511  SetStatusValue( TK_Status, Any( OUString("STR_DELETING_SLIDES") ) );
512  DispatchStatus();
514  }
515 
517  {
518  SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 40 ) ) );
519  SetStatusValue( TK_Status, Any( OUString("STR_DELETING_SLIDES") ) );
520  DispatchStatus();
522  }
523 
524  if ( mbOLEOptimization )
525  {
526  SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 45 ) ) );
527  SetStatusValue( TK_Status, Any( OUString("STR_CREATING_OLE_REPLACEMENTS") ) );
528  DispatchStatus();
530  }
531 
533  {
534  SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 50 ) ) );
535  SetStatusValue( TK_Status, Any( OUString("STR_OPTIMIZING_GRAPHICS") ) );
536  DispatchStatus();
537 
538  std::vector< GraphicCollector::GraphicEntity > aGraphicList;
540  GraphicCollector::CollectGraphics( mxContext, mxModel, aGraphicSettings, aGraphicList );
541  CompressGraphics( *this, mxContext, aGraphicSettings, aGraphicList );
542  }
543  SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 100 ) ) );
544  DispatchStatus();
545 }
546 
547 static void DispatchURL( const Reference< XComponentContext >& xContext, const OUString& sURL, const Reference< XFrame >& xFrame )
548 {
549  try
550  {
551  Reference< XURLTransformer > xURLTransformer( URLTransformer::create(xContext) );
552  util::URL aUrl;
553  aUrl.Complete = sURL;
554  xURLTransformer->parseStrict( aUrl );
555  Sequence< PropertyValue > aArgs;
556  Reference< XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY_THROW );
557  Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aUrl, OUString(), 0 ); // "_self"
558  if ( xDispatch.is() )
559  xDispatch->dispatch( aUrl, aArgs );
560  }
561  catch( Exception& )
562  {
563  }
564 }
565 
566 
567 void ImpOptimizer::Optimize( const Sequence< PropertyValue >& rArguments )
568 {
569  if ( !mxModel.is() )
570  return;
571 
572  sal_Int64 nEstimatedFileSize = 0;
573  SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 0 ) ) );
574  DispatchStatus();
575 
576  for ( const auto& rArgument : rArguments )
577  {
578  switch( TKGet( rArgument.Name ) )
579  {
580  case TK_StatusDispatcher : rArgument.Value >>= mxStatusDispatcher; break;
581  case TK_InformationDialog: rArgument.Value >>= mxInformationDialog; break;
582  case TK_Settings :
583  {
584  css::uno::Sequence< css::beans::PropertyValue > aSettings;
585  rArgument.Value >>= aSettings;
586  for ( const auto& rSetting : std::as_const(aSettings) )
587  {
588  switch( TKGet( rSetting.Name ) )
589  {
590  case TK_JPEGCompression : rSetting.Value >>= mbJPEGCompression; break;
591  case TK_JPEGQuality : rSetting.Value >>= mnJPEGQuality; break;
592  case TK_RemoveCropArea : rSetting.Value >>= mbRemoveCropArea; break;
593  case TK_ImageResolution : rSetting.Value >>= mnImageResolution; break;
594  case TK_EmbedLinkedGraphics : rSetting.Value >>= mbEmbedLinkedGraphics; break;
595  case TK_OLEOptimization : rSetting.Value >>= mbOLEOptimization; break;
596  case TK_OLEOptimizationType : rSetting.Value >>= mnOLEOptimizationType; break;
597  case TK_CustomShowName : rSetting.Value >>= maCustomShowName; break;
598  case TK_DeleteUnusedMasterPages : rSetting.Value >>= mbDeleteUnusedMasterPages; break;
599  case TK_DeleteHiddenSlides : rSetting.Value >>= mbDeleteHiddenSlides; break;
600  case TK_DeleteNotesPages : rSetting.Value >>= mbDeleteNotesPages; break;
601  case TK_SaveAsURL : rSetting.Value >>= maSaveAsURL; break;
602  case TK_FilterName : rSetting.Value >>= maFilterName; break;
603  case TK_OpenNewDocument : rSetting.Value >>= mbOpenNewDocument; break;
604  case TK_EstimatedFileSize : rSetting.Value >>= nEstimatedFileSize; break;
605  default: break;
606  }
607  }
608  }
609  break;
610  default: break;
611  }
612  }
613 
614  sal_Int64 nSourceSize = 0;
615  sal_Int64 nDestSize = 0;
616 
617  Reference< XFrame > xSelf;
618  if ( !maSaveAsURL.isEmpty() )
619  {
620 
621  SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 10 ) ) );
622  SetStatusValue( TK_Status, Any( OUString("STR_DUPLICATING_PRESENTATION") ) );
623  DispatchStatus();
624 
625  Reference< XStorable >xStorable( mxModel, UNO_QUERY );
626  if ( xStorable.is() )
627  {
628  if ( xStorable->hasLocation() )
629  nSourceSize = PPPOptimizer::GetFileSize( xStorable->getLocation() );
630 
631  Sequence< PropertyValue > aArguments;
632  if ( !maFilterName.isEmpty() )
633  {
634  int nLength = aArguments.getLength();
635  aArguments.realloc( nLength + 1 );
636  aArguments[ nLength ].Name = "FilterName";
637  aArguments[ nLength ].Value <<= maFilterName;
638  }
639  xStorable->storeToURL( maSaveAsURL, aArguments );
640  if ( !nSourceSize )
641  nSourceSize = PPPOptimizer::GetFileSize( maSaveAsURL );
642 
643  SetStatusValue( TK_Progress, Any( static_cast< sal_Int32 >( 30 ) ) );
644  SetStatusValue( TK_Status, Any( OUString("STR_DUPLICATING_PRESENTATION") ) );
645  DispatchStatus();
646 
647  Reference< XDesktop2 > xDesktop = Desktop::create( mxContext );
648  xSelf = xDesktop->findFrame( "_blank", FrameSearchFlag::CREATE );
649  Reference< XComponentLoader > xComponentLoader( xSelf, UNO_QUERY );
650 
651  Sequence< PropertyValue > aLoadProps( 1 );
652  aLoadProps[ 0 ].Name = "Hidden";
653  aLoadProps[ 0 ].Value <<= true;
654  mxModel.set( xComponentLoader->loadComponentFromURL(
655  maSaveAsURL, "_self", 0, aLoadProps ), UNO_QUERY );
656  }
657  }
658 
659  // check if the document is ReadOnly -> error
660  Reference< XStorable > xStorable( mxModel, UNO_QUERY );
661  if ( xStorable.is() && !xStorable->isReadonly() )
662  {
663  mxModel->lockControllers();
664  Optimize();
665  mxModel->unlockControllers();
666 
667  // clearing undo stack:
668  Reference< XFrame > xFrame( xSelf.is() ? xSelf : mxInformationDialog );
669  if ( xFrame.is() )
670  {
671  const OUString sSlot( "slot:27115" );
672  DispatchURL( mxContext, sSlot, xFrame );
673  }
674  }
675 
676  if ( !maSaveAsURL.isEmpty() )
677  {
678  if ( xStorable.is() )
679  {
680  xStorable->store();
681  nDestSize = PPPOptimizer::GetFileSize( maSaveAsURL );
682  }
683  }
684 
685  if ( mxInformationDialog.is() )
686  {
687  InformationDialog aInformationDialog( mxContext, mxInformationDialog, maSaveAsURL, mbOpenNewDocument, nSourceSize, nDestSize, nEstimatedFileSize );
688  aInformationDialog.execute();
690  DispatchStatus();
691  }
692 
693  if ( !maSaveAsURL.isEmpty() )
694  {
695  if ( mbOpenNewDocument && xSelf.is() )
696  {
697  Reference< awt::XWindow > xContainerWindow( xSelf->getContainerWindow() );
698  xContainerWindow->setVisible( true );
699  }
700  else
701  {
702  mxModel->dispose();
703  }
704  }
705  if ( nSourceSize && nDestSize )
706  {
707  SetStatusValue( TK_FileSizeSource, Any( nSourceSize ) );
708  SetStatusValue( TK_FileSizeDestination, Any( nDestSize ) );
709  DispatchStatus();
710  }
711 }
712 
713 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::uno::XComponentContext > mxContext
sal_Int32 const mnJPEGQuality
URL aURL
bool bVisible
static void ImpDeleteNotesPages(const Reference< XModel > &rxModel)
static void ImpConvertOLE(const Reference< XModel > &rxModel, sal_Int32 nOLEOptimizationType)
sal_Int32 mnJPEGQuality
OUString maFilterName
signed char sal_Int8
Reference< XFrame > xFrame
bool mbRemoveCropArea
void SetStatusValue(const PPPOptimizerTokenEnum eStat, const css::uno::Any &rStatValue)
css::uno::Reference< css::frame::XModel2 > mxModel
bool mbOLEOptimization
static void DispatchURL(const Reference< XComponentContext > &xContext, const OUString &sURL, const Reference< XFrame > &xFrame)
static sal_Int64 GetFileSize(const OUString &rURL)
Sequence< PropertyValue > aArguments
static void CompressGraphics(ImpOptimizer &rOptimizer, const Reference< XComponentContext > &rxContext, const GraphicSettings &rGraphicSettings, std::vector< GraphicCollector::GraphicEntity > &rGraphicList)
OUString maSaveAsURL
bool mbEmbedLinkedGraphics
static css::awt::Size GetOriginalSize(const css::uno::Reference< css::uno::XComponentContext > &rxMSF, const css::uno::Reference< css::graphic::XGraphic > &rxGraphic)
bool mbDeleteNotesPages
sal_Int32 const mnImageResolution
static void ImpDeleteHiddenSlides(const Reference< XModel > &rxModel)
int i
static void ImpDeleteUnusedMasterPages(const Reference< XModel > &rxModel)
bool const mbJPEGCompression
bool mbOpenNewDocument
css::uno::Reference< css::frame::XFrame > mxInformationDialog
ImpOptimizer(const css::uno::Reference< css::uno::XComponentContext > &rXFactory, const css::uno::Reference< css::frame::XModel > &rxModel)
static void CollectMasterPages(const css::uno::Reference< css::frame::XModel > &, std::vector< MasterPageEntity > &)
Reference< XDispatch > xDispatch
sal_Int32 mnImageResolution
OUString maCustomShowName
static void ImpExtractCustomShow(const Reference< XModel > &rxModel, const OUString &rCustomShowName)
css::uno::Reference< css::frame::XDispatch > mxStatusDispatcher
static void CollectGraphics(const css::uno::Reference< css::uno::XComponentContext > &rxMSF, const css::uno::Reference< css::frame::XModel > &rxModel, const GraphicSettings &rGraphicSettings, std::vector< GraphicEntity > &io_rGraphicList)
PPPOptimizerTokenEnum TKGet(const OUString &rToken)
css::beans::PropertyValues GetStatusSequence()
bool mbDeleteUnusedMasterPages
static void CollectNonCustomShowPages(const css::uno::Reference< css::frame::XModel > &, const OUString &rCustomShow, std::vector< css::uno::Reference< css::drawing::XDrawPage > > &)
void DispatchStatus()
sal_Int32 const nLength
static void ImpCompressGraphic(Reference< XGraphicProvider > const &rxGraphicProvider, const Reference< XGraphic > &rxGraphic, Reference< XOutputStream > const &rxOutputStream, const OUString &rDestMimeType, const awt::Size &rLogicalSize, sal_Int32 nJPEGQuality, sal_Int32 nImageResolution, bool bRemoveCropping, const text::GraphicCrop &rGraphicCropLogic)
Reference< XGraphic > xGraphic
bool mbJPEGCompression
Reference< XComponentContext > mxContext
bool mbDeleteHiddenSlides
sal_Int32 mnOLEOptimizationType
css::uno::Reference< css::frame::XModel > mxModel