1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "impoptimizer.hxx"
22 #include "pppoptimizer.hxx"
23 #include "graphiccollector.hxx"
24 #include "pagecollector.hxx"
25 #include "informationdialog.hxx"
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>
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
;
68 static void ImpExtractCustomShow( const Reference
< XModel
>& rxModel
, const OUString
& rCustomShowName
)
70 vector
< Reference
< XDrawPage
> > vNonUsedPageList
;
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
);
85 static void ImpDeleteUnusedMasterPages( const Reference
< XModel
>& rxModel
)
87 vector
< PageCollector::MasterPageEntity
> aMasterPageList
;
88 PageCollector::CollectMasterPages( rxModel
, aMasterPageList
);
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
)
95 if ( !rMasterPage
.bUsed
)
96 xMasterPages
->remove( rMasterPage
.xMasterPage
);
100 static void ImpDeleteHiddenSlides( const Reference
< XModel
>& rxModel
)
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
++ )
108 Reference
< XDrawPage
> xDrawPage( xDrawPages
->getByIndex( i
), UNO_QUERY_THROW
);
109 Reference
< XPropertySet
> xPropSet( xDrawPage
, UNO_QUERY_THROW
);
111 bool bVisible
= true;
112 if ( xPropSet
->getPropertyValue( "Visible" ) >>= bVisible
)
116 xDrawPages
->remove( xDrawPage
);
127 static void ImpDeleteNotesPages( const Reference
< XModel
>& rxModel
)
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
++ )
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
) );
142 xPropSet
->setPropertyValue( "Layout", Any( sal_Int16(21) ) );
150 static void ImpConvertOLE( const Reference
< XModel
>& rxModel
, sal_Int32 nOLEOptimizationType
)
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
++ )
158 Reference
< XShapes
> xShapes( xDrawPages
->getByIndex( i
), UNO_QUERY_THROW
);
159 for ( sal_Int32 j
= 0; j
< xShapes
->getCount(); j
++ )
161 Reference
< XShape
> xShape( xShapes
->getByIndex( j
), UNO_QUERY_THROW
);
162 if ( xShape
->getShapeType() == "com.sun.star.drawing.OLE2Shape" )
164 Reference
< XPropertySet
> xPropSet( xShape
, UNO_QUERY_THROW
);
166 bool bConvertOLE
= nOLEOptimizationType
== 0;
167 if ( nOLEOptimizationType
== 1 )
169 bool bIsInternal
= true;
170 xPropSet
->getPropertyValue( "IsInternal" ) >>= bIsInternal
;
171 bConvertOLE
= !bIsInternal
;
175 Reference
< XGraphic
> xGraphic
;
176 if ( xPropSet
->getPropertyValue( "Graphic" ) >>= xGraphic
)
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
) );
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
)
203 if ( rxGraphicProvider
.is() && rxOutputStream
.is() )
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
;
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
;
231 rxGraphicProvider
->storeGraphic( rxGraphic
, aArgs
);
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
)
243 Reference
< XGraphic
> xNewGraphic
;
246 OUString aSourceMimeType
;
247 Reference
< XPropertySet
> xGraphicPropertySet( xGraphic
, UNO_QUERY_THROW
);
248 if ( xGraphicPropertySet
->getPropertyValue( "MimeType" ) >>= aSourceMimeType
)
250 sal_Int8
nGraphicType( xGraphic
->getType() );
251 if ( nGraphicType
== css::graphic::GraphicType::PIXEL
)
253 bool bTransparent
= false;
255 bool bAnimated
= false;
257 awt::Size
aSourceSizePixel( 0, 0 );
258 text::GraphicCrop
aGraphicCropPixel( 0, 0, 0, 0 );
260 if ( ( xGraphicPropertySet
->getPropertyValue( "SizePixel" ) >>= aSourceSizePixel
) &&
261 ( xGraphicPropertySet
->getPropertyValue( "Transparent" ) >>= bTransparent
) &&
262 ( xGraphicPropertySet
->getPropertyValue( "Alpha" ) >>= bAlpha
) &&
263 ( xGraphicPropertySet
->getPropertyValue( "Animated" ) >>= bAnimated
) )
265 awt::Size
aDestSizePixel( aSourceSizePixel
);
268 bool bNeedsOptimizing
= false;
269 bool bRemoveCropArea( rGraphicSettings
.mbRemoveCropArea
);
271 // cropping has to be removed from SourceSizePixel
272 if ( aGraphicCropLogic
.Left
|| aGraphicCropLogic
.Top
|| aGraphicCropLogic
.Right
|| aGraphicCropLogic
.Bottom
)
274 const awt::Size
aSize100thMM( GraphicCollector::GetOriginalSize( rxContext
, xGraphic
) );
276 if ( bRemoveCropArea
)
277 bNeedsOptimizing
= true;
279 if ( aSize100thMM
.Width
&& aSize100thMM
.Height
)
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
);
286 // first calculating new SourceSizePixel by removing the cropped area
287 aSourceSizePixel
.Width
= aGraphicCropPixel
.Right
- aGraphicCropPixel
.Left
;
288 aSourceSizePixel
.Height
= aGraphicCropPixel
.Bottom
- aGraphicCropPixel
.Top
;
292 bRemoveCropArea
= false;
295 if ( ( aSourceSizePixel
.Width
> 0 ) && ( aSourceSizePixel
.Height
> 0 ) )
297 OUString
aDestMimeType( "image/png" );
298 if (rGraphicSettings
.mbJPEGCompression
&& !bTransparent
&& !bAlpha
)
300 aDestMimeType
= "image/jpeg";
301 // if( aSourceMimeType != aDestMimeType )
302 bNeedsOptimizing
= true;
304 if ( bRemoveCropArea
)
305 aDestSizePixel
= aSourceSizePixel
;
306 if ( rGraphicSettings
.mnImageResolution
&& aLogicalSize
.Width
&& aLogicalSize
.Height
)
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 );
311 // check, if the bitmap DPI exceeds the maximum DPI
312 if( ( fSourceDPIX
> rGraphicSettings
.mnImageResolution
) || ( fSourceDPIY
> rGraphicSettings
.mnImageResolution
) )
314 const double fNewSizePixelX
= (static_cast<double>(aDestSizePixel
.Width
) * rGraphicSettings
.mnImageResolution
) / fSourceDPIX
;
315 const double fNewSizePixelY
= (static_cast<double>(aDestSizePixel
.Height
)* rGraphicSettings
.mnImageResolution
) / fSourceDPIY
;
317 aDestSizePixel
= awt::Size( static_cast<sal_Int32
>(fNewSizePixelX
), static_cast<sal_Int32
>(fNewSizePixelY
) );
318 bNeedsOptimizing
= true;
321 if ( bNeedsOptimizing
&& aDestSizePixel
.Width
&& aDestSizePixel
.Height
)
323 Reference
< XStream
> xTempFile( io::TempFile::create(rxContext
), UNO_QUERY_THROW
);
324 Reference
< XOutputStream
> xOutputStream( xTempFile
->getOutputStream() );
325 Reference
< XGraphicProvider
> xGraphicProvider( GraphicProvider::create( rxContext
) );
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
);
340 else // this is a metafile
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
);
363 static void CompressGraphics( ImpOptimizer
& rOptimizer
, const Reference
< XComponentContext
>& rxContext
, const GraphicSettings
& rGraphicSettings
,
364 std::vector
< GraphicCollector::GraphicEntity
>& rGraphicList
)
369 for( auto& rGraphic
: rGraphicList
)
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();
376 if ( !rGraphic
.maUser
.empty() )
378 GraphicSettings
aGraphicSettings( rGraphicSettings
);
379 aGraphicSettings
.mbRemoveCropArea
= rGraphic
.mbRemoveCropArea
;
381 Reference
< XGraphic
> xGraphic
;
382 if ( rGraphic
.maUser
[ 0 ].mbFillBitmap
&& rGraphic
.maUser
[ 0 ].mxPropertySet
.is() )
384 Reference
< XBitmap
> xFillBitmap
;
385 if ( rGraphic
.maUser
[ 0 ].mxPropertySet
->getPropertyValue( "FillBitmap" ) >>= xFillBitmap
)
386 xGraphic
.set( xFillBitmap
, UNO_QUERY_THROW
);
388 else if ( rGraphic
.maUser
[ 0 ].mxShape
.is() )
390 Reference
< XPropertySet
> xShapePropertySet( rGraphic
.maUser
[ 0 ].mxShape
, UNO_QUERY_THROW
);
391 xShapePropertySet
->getPropertyValue( "Graphic" ) >>= xGraphic
;
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() )
400 // applying graphic to each user
401 for( auto& rGraphicUser
: rGraphic
.maUser
)
403 if ( rGraphicUser
.mxShape
.is() )
405 Reference
< XPropertySet
> xShapePropertySet( rGraphicUser
.mxShape
, UNO_QUERY_THROW
);
406 xShapePropertySet
->setPropertyValue( "Graphic", Any( xNewGraphic
) );
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
)
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
)));
420 xShapePropertySet
->setPropertyValue( "GraphicCrop", Any( aGraphicCropLogic
) );
423 else if ( rGraphicUser
.mxPropertySet
.is() )
425 Reference
< XBitmap
> xFillBitmap( xNewGraphic
, UNO_QUERY
);
426 if ( xFillBitmap
.is() )
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
) )
437 if ( !aSize
.Width
|| !aSize
.Height
)
439 rxPropertySet
->setPropertyValue( "FillBitmapLogicalSize", Any( true ) );
440 rxPropertySet
->setPropertyValue( "FillBitmapSizeX", Any( rGraphicUser
.maLogicalSize
.Width
) );
441 rxPropertySet
->setPropertyValue( "FillBitmapSizeY", Any( rGraphicUser
.maLogicalSize
.Height
) );
444 if ( rGraphicUser
.mxPagePropertySet
.is() )
445 rGraphicUser
.mxPagePropertySet
->setPropertyValue( "Background", Any( rxPropertySet
) );
460 ImpOptimizer::ImpOptimizer( const Reference
< XComponentContext
>& rxContext
, const Reference
< XModel
>& rxModel
) :
461 mxContext ( rxContext
),
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 )
478 ImpOptimizer::~ImpOptimizer()
483 void ImpOptimizer::DispatchStatus()
485 if ( mxStatusDispatcher
.is() )
488 aURL
.Protocol
= "vnd.com.sun.star.comp.PresentationMinimizer:";
489 aURL
.Path
= "statusupdate";
490 mxStatusDispatcher
->dispatch( aURL
, GetStatusSequence() );
495 void ImpOptimizer::Optimize()
498 if ( !maCustomShowName
.isEmpty() )
499 ImpExtractCustomShow( mxModel
, maCustomShowName
);
501 if ( mbDeleteHiddenSlides
)
503 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 40 ) ) );
504 SetStatusValue( TK_Status
, Any( OUString("STR_DELETING_SLIDES") ) );
506 ImpDeleteHiddenSlides( mxModel
);
509 if ( mbDeleteNotesPages
)
511 SetStatusValue( TK_Status
, Any( OUString("STR_DELETING_SLIDES") ) );
513 ImpDeleteNotesPages( mxModel
);
516 if ( mbDeleteUnusedMasterPages
)
518 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 40 ) ) );
519 SetStatusValue( TK_Status
, Any( OUString("STR_DELETING_SLIDES") ) );
521 ImpDeleteUnusedMasterPages( mxModel
);
524 if ( mbOLEOptimization
)
526 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 45 ) ) );
527 SetStatusValue( TK_Status
, Any( OUString("STR_CREATING_OLE_REPLACEMENTS") ) );
529 ImpConvertOLE( mxModel
, mnOLEOptimizationType
);
532 if ( mbJPEGCompression
|| mbRemoveCropArea
|| mnImageResolution
)
534 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 50 ) ) );
535 SetStatusValue( TK_Status
, Any( OUString("STR_OPTIMIZING_GRAPHICS") ) );
538 std::vector
< GraphicCollector::GraphicEntity
> aGraphicList
;
539 GraphicSettings
aGraphicSettings( mbJPEGCompression
, mnJPEGQuality
, mbRemoveCropArea
, mnImageResolution
, mbEmbedLinkedGraphics
);
540 GraphicCollector::CollectGraphics( mxContext
, mxModel
, aGraphicSettings
, aGraphicList
);
541 CompressGraphics( *this, mxContext
, aGraphicSettings
, aGraphicList
);
543 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 100 ) ) );
547 static void DispatchURL( const Reference
< XComponentContext
>& xContext
, const OUString
& sURL
, const Reference
< XFrame
>& xFrame
)
551 Reference
< XURLTransformer
> xURLTransformer( URLTransformer::create(xContext
) );
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
);
567 void ImpOptimizer::Optimize( const Sequence
< PropertyValue
>& rArguments
)
572 sal_Int64 nEstimatedFileSize
= 0;
573 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 0 ) ) );
576 for ( const auto& rArgument
: rArguments
)
578 switch( TKGet( rArgument
.Name
) )
580 case TK_StatusDispatcher
: rArgument
.Value
>>= mxStatusDispatcher
; break;
581 case TK_InformationDialog
: rArgument
.Value
>>= mxInformationDialog
; break;
584 css::uno::Sequence
< css::beans::PropertyValue
> aSettings
;
585 rArgument
.Value
>>= aSettings
;
586 for ( const auto& rSetting
: std::as_const(aSettings
) )
588 switch( TKGet( rSetting
.Name
) )
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;
614 sal_Int64 nSourceSize
= 0;
615 sal_Int64 nDestSize
= 0;
617 Reference
< XFrame
> xSelf
;
618 if ( !maSaveAsURL
.isEmpty() )
621 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 10 ) ) );
622 SetStatusValue( TK_Status
, Any( OUString("STR_DUPLICATING_PRESENTATION") ) );
625 Reference
< XStorable
>xStorable( mxModel
, UNO_QUERY
);
626 if ( xStorable
.is() )
628 if ( xStorable
->hasLocation() )
629 nSourceSize
= PPPOptimizer::GetFileSize( xStorable
->getLocation() );
631 Sequence
< PropertyValue
> aArguments
;
632 if ( !maFilterName
.isEmpty() )
634 int nLength
= aArguments
.getLength();
635 aArguments
.realloc( nLength
+ 1 );
636 aArguments
[ nLength
].Name
= "FilterName";
637 aArguments
[ nLength
].Value
<<= maFilterName
;
639 xStorable
->storeToURL( maSaveAsURL
, aArguments
);
641 nSourceSize
= PPPOptimizer::GetFileSize( maSaveAsURL
);
643 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 30 ) ) );
644 SetStatusValue( TK_Status
, Any( OUString("STR_DUPLICATING_PRESENTATION") ) );
647 Reference
< XDesktop2
> xDesktop
= Desktop::create( mxContext
);
648 xSelf
= xDesktop
->findFrame( "_blank", FrameSearchFlag::CREATE
);
649 Reference
< XComponentLoader
> xComponentLoader( xSelf
, UNO_QUERY
);
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
);
659 // check if the document is ReadOnly -> error
660 Reference
< XStorable
> xStorable( mxModel
, UNO_QUERY
);
661 if ( xStorable
.is() && !xStorable
->isReadonly() )
663 mxModel
->lockControllers();
665 mxModel
->unlockControllers();
667 // clearing undo stack:
668 Reference
< XFrame
> xFrame( xSelf
.is() ? xSelf
: mxInformationDialog
);
671 const OUString
sSlot( "slot:27115" );
672 DispatchURL( mxContext
, sSlot
, xFrame
);
676 if ( !maSaveAsURL
.isEmpty() )
678 if ( xStorable
.is() )
681 nDestSize
= PPPOptimizer::GetFileSize( maSaveAsURL
);
685 if ( mxInformationDialog
.is() )
687 InformationDialog
aInformationDialog( mxContext
, mxInformationDialog
, maSaveAsURL
, mbOpenNewDocument
, nSourceSize
, nDestSize
, nEstimatedFileSize
);
688 aInformationDialog
.execute();
689 SetStatusValue( TK_OpenNewDocument
, Any( mbOpenNewDocument
) );
693 if ( !maSaveAsURL
.isEmpty() )
695 if ( mbOpenNewDocument
&& xSelf
.is() )
697 Reference
< awt::XWindow
> xContainerWindow( xSelf
->getContainerWindow() );
698 xContainerWindow
->setVisible( true );
705 if ( nSourceSize
&& nDestSize
)
707 SetStatusValue( TK_FileSizeSource
, Any( nSourceSize
) );
708 SetStatusValue( TK_FileSizeDestination
, Any( nDestSize
) );
713 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */