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