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/rendering/XBitmap.hpp>
45 #include <com/sun/star/document/XFilter.hpp>
46 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
47 #include <com/sun/star/graphic/GraphicType.hpp>
48 #include <com/sun/star/io/XStream.hpp>
49 #include <com/sun/star/io/XSeekable.hpp>
50 #include <com/sun/star/io/TempFile.hpp>
51 #include <com/sun/star/frame/XComponentLoader.hpp>
52 #include <com/sun/star/util/URLTransformer.hpp>
54 #include <comphelper/propertyvalue.hxx>
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::container
;
67 using namespace ::com::sun::star::presentation
;
69 static void ImpExtractCustomShow( const Reference
< XModel
>& rxModel
, std::u16string_view rCustomShowName
)
71 std::vector
< Reference
< XDrawPage
> > vNonUsedPageList
;
74 PageCollector::CollectNonCustomShowPages( rxModel
, rCustomShowName
, vNonUsedPageList
);
75 Reference
< XDrawPagesSupplier
> xDrawPagesSupplier( rxModel
, UNO_QUERY_THROW
);
76 Reference
< XDrawPages
> xDrawPages( xDrawPagesSupplier
->getDrawPages(), UNO_SET_THROW
);
77 for( const auto& rxPage
: vNonUsedPageList
)
78 xDrawPages
->remove( rxPage
);
86 static void ImpDeleteUnusedMasterPages( const Reference
< XModel
>& rxModel
)
88 std::vector
< PageCollector::MasterPageEntity
> aMasterPageList
;
89 PageCollector::CollectMasterPages( rxModel
, aMasterPageList
);
91 // now master pages that are not marked can be deleted
92 Reference
< XMasterPagesSupplier
> xMasterPagesSupplier( rxModel
, UNO_QUERY_THROW
);
93 Reference
< XDrawPages
> xMasterPages( xMasterPagesSupplier
->getMasterPages(), UNO_SET_THROW
);
94 for( const auto& rMasterPage
: aMasterPageList
)
96 if ( !rMasterPage
.bUsed
)
97 xMasterPages
->remove( rMasterPage
.xMasterPage
);
101 static void ImpDeleteHiddenSlides( const Reference
< XModel
>& rxModel
)
105 Reference
< XDrawPagesSupplier
> xDrawPagesSupplier( rxModel
, UNO_QUERY_THROW
);
106 Reference
< XDrawPages
> xDrawPages( xDrawPagesSupplier
->getDrawPages(), UNO_SET_THROW
);
107 for( sal_Int32 i
= 0; i
< xDrawPages
->getCount(); i
++ )
109 Reference
< XDrawPage
> xDrawPage( xDrawPages
->getByIndex( i
), UNO_QUERY_THROW
);
110 Reference
< XPropertySet
> xPropSet( xDrawPage
, UNO_QUERY_THROW
);
112 bool bVisible
= true;
113 if ( xPropSet
->getPropertyValue( u
"Visible"_ustr
) >>= bVisible
)
117 xDrawPages
->remove( xDrawPage
);
128 static void ImpDeleteNotesPages( const Reference
< XModel
>& rxModel
)
132 Reference
< XDrawPagesSupplier
> xDrawPagesSupplier( rxModel
, UNO_QUERY_THROW
);
133 Reference
< XDrawPages
> xDrawPages( xDrawPagesSupplier
->getDrawPages(), UNO_SET_THROW
);
134 sal_Int32 i
, nPages
= xDrawPages
->getCount();
135 for( i
= 0; i
< nPages
; i
++ )
137 Reference
< XPresentationPage
> xPresentationPage( xDrawPages
->getByIndex( i
), UNO_QUERY_THROW
);
138 Reference
< XPropertySet
> xPropSet( xPresentationPage
->getNotesPage(), UNO_QUERY_THROW
);
139 Reference
< XShapes
> xShapes( xPropSet
, UNO_QUERY_THROW
);
140 while( xShapes
->getCount() )
141 xShapes
->remove( Reference
< XShape
>( xShapes
->getByIndex( xShapes
->getCount() - 1 ), UNO_QUERY_THROW
) );
143 xPropSet
->setPropertyValue( u
"Layout"_ustr
, Any( sal_Int16(21) ) );
151 static void ImpConvertOLE( const Reference
< XModel
>& rxModel
, sal_Int32 nOLEOptimizationType
)
155 Reference
< XDrawPagesSupplier
> xDrawPagesSupplier( rxModel
, UNO_QUERY_THROW
);
156 Reference
< XDrawPages
> xDrawPages( xDrawPagesSupplier
->getDrawPages(), UNO_SET_THROW
);
157 for ( sal_Int32 i
= 0; i
< xDrawPages
->getCount(); i
++ )
159 Reference
< XShapes
> xShapes( xDrawPages
->getByIndex( i
), UNO_QUERY_THROW
);
160 for ( sal_Int32 j
= 0; j
< xShapes
->getCount(); j
++ )
162 Reference
< XShape
> xShape( xShapes
->getByIndex( j
), UNO_QUERY_THROW
);
163 if ( xShape
->getShapeType() == "com.sun.star.drawing.OLE2Shape" )
165 Reference
< XPropertySet
> xPropSet( xShape
, UNO_QUERY_THROW
);
167 bool bConvertOLE
= nOLEOptimizationType
== 0;
168 if ( nOLEOptimizationType
== 1 )
170 bool bIsInternal
= true;
171 xPropSet
->getPropertyValue( u
"IsInternal"_ustr
) >>= bIsInternal
;
172 bConvertOLE
= !bIsInternal
;
176 Reference
< XGraphic
> xGraphic
;
177 if ( xPropSet
->getPropertyValue( u
"Graphic"_ustr
) >>= xGraphic
)
179 Reference
< XMultiServiceFactory
> xFact( rxModel
, UNO_QUERY_THROW
);
180 Reference
< XShape
> xShape2( xFact
->createInstance( u
"com.sun.star.drawing.GraphicObjectShape"_ustr
), UNO_QUERY_THROW
);
181 xShapes
->add( xShape2
);
182 xShape2
->setPosition( xShape
->getPosition() );
183 xShape2
->setSize( xShape
->getSize() );
184 Reference
< XPropertySet
> xPropSet2( xShape2
, UNO_QUERY_THROW
);
185 xPropSet2
->setPropertyValue( u
"Graphic"_ustr
, Any( xGraphic
) );
186 xShapes
->remove( xShape
);
187 xPropSet2
->setPropertyValue( u
"ZOrder"_ustr
, Any( j
) );
199 static void ImpCompressGraphic( Reference
< XGraphicProvider
> const & rxGraphicProvider
, const Reference
< XGraphic
>& rxGraphic
, Reference
< XOutputStream
> const & rxOutputStream
,
200 const OUString
& rDestMimeType
, const awt::Size
& rLogicalSize
, sal_Int32 nJPEGQuality
, sal_Int32 nImageResolution
, bool bRemoveCropping
, const text::GraphicCrop
& rGraphicCropLogic
)
204 if ( rxGraphicProvider
.is() && rxOutputStream
.is() )
206 Sequence
< PropertyValue
> aFilterData
{
207 comphelper::makePropertyValue(u
"ImageResolution"_ustr
, nImageResolution
),
208 comphelper::makePropertyValue(u
"ColorMode"_ustr
, sal_Int32(0)), // todo: jpeg color mode (0->true color, 1->greyscale)
209 comphelper::makePropertyValue(u
"Quality"_ustr
, nJPEGQuality
), // quality that is used if we export to jpeg
210 comphelper::makePropertyValue(u
"Compression"_ustr
, sal_Int32(6)), // compression that is used if we export to png
211 comphelper::makePropertyValue(u
"Interlaced"_ustr
, sal_Int32(0)), // interlaced is turned off if we export to png
212 comphelper::makePropertyValue(u
"LogicalSize"_ustr
, rLogicalSize
),
213 comphelper::makePropertyValue(u
"RemoveCropArea"_ustr
, bRemoveCropping
),
214 comphelper::makePropertyValue(u
"GraphicCropLogic"_ustr
, rGraphicCropLogic
)
217 Sequence
< PropertyValue
> aArgs
{
218 comphelper::makePropertyValue(u
"MimeType"_ustr
, rDestMimeType
), // the GraphicProvider is using "MimeType", the GraphicExporter "MediaType"...
219 comphelper::makePropertyValue(u
"OutputStream"_ustr
, rxOutputStream
),
220 comphelper::makePropertyValue(u
"FilterData"_ustr
, aFilterData
)
223 rxGraphicProvider
->storeGraphic( rxGraphic
, aArgs
);
231 static Reference
< XGraphic
> ImpCompressGraphic( const Reference
< XComponentContext
>& rxContext
,
232 const Reference
< XGraphic
>& xGraphic
, const awt::Size
& aLogicalSize
, const text::GraphicCrop
& aGraphicCropLogic
,
233 const GraphicSettings
& rGraphicSettings
)
235 Reference
< XGraphic
> xNewGraphic
;
238 OUString aSourceMimeType
;
239 Reference
< XPropertySet
> xGraphicPropertySet( xGraphic
, UNO_QUERY_THROW
);
240 if ( xGraphicPropertySet
->getPropertyValue( u
"MimeType"_ustr
) >>= aSourceMimeType
)
242 sal_Int8
nGraphicType( xGraphic
->getType() );
243 if ( nGraphicType
== css::graphic::GraphicType::PIXEL
)
245 bool bTransparent
= false;
247 bool bAnimated
= false;
249 awt::Size
aSourceSizePixel( 0, 0 );
250 text::GraphicCrop
aGraphicCropPixel( 0, 0, 0, 0 );
252 if ( ( xGraphicPropertySet
->getPropertyValue( u
"SizePixel"_ustr
) >>= aSourceSizePixel
) &&
253 ( xGraphicPropertySet
->getPropertyValue( u
"Transparent"_ustr
) >>= bTransparent
) &&
254 ( xGraphicPropertySet
->getPropertyValue( u
"Alpha"_ustr
) >>= bAlpha
) &&
255 ( xGraphicPropertySet
->getPropertyValue( u
"Animated"_ustr
) >>= bAnimated
) )
257 awt::Size
aDestSizePixel( aSourceSizePixel
);
260 bool bNeedsOptimizing
= false;
261 bool bRemoveCropArea( rGraphicSettings
.mbRemoveCropArea
);
263 // cropping has to be removed from SourceSizePixel
264 if ( aGraphicCropLogic
.Left
|| aGraphicCropLogic
.Top
|| aGraphicCropLogic
.Right
|| aGraphicCropLogic
.Bottom
)
266 const awt::Size
aSize100thMM( GraphicCollector::GetOriginalSize( rxContext
, xGraphic
) );
268 if ( bRemoveCropArea
)
269 bNeedsOptimizing
= true;
271 if ( aSize100thMM
.Width
&& aSize100thMM
.Height
)
273 aGraphicCropPixel
.Left
= static_cast< sal_Int32
>( ( static_cast<double>(aSourceSizePixel
.Width
) * aGraphicCropLogic
.Left
) / aSize100thMM
.Width
);
274 aGraphicCropPixel
.Top
= static_cast< sal_Int32
>( ( static_cast<double>(aSourceSizePixel
.Height
)* aGraphicCropLogic
.Top
) / aSize100thMM
.Height
);
275 aGraphicCropPixel
.Right
= static_cast< sal_Int32
>( ( static_cast<double>(aSourceSizePixel
.Width
) * ( aSize100thMM
.Width
- aGraphicCropLogic
.Right
) ) / aSize100thMM
.Width
);
276 aGraphicCropPixel
.Bottom
= static_cast< sal_Int32
>( ( static_cast<double>(aSourceSizePixel
.Height
)* ( aSize100thMM
.Height
- aGraphicCropLogic
.Bottom
) ) / aSize100thMM
.Height
);
278 // first calculating new SourceSizePixel by removing the cropped area
279 aSourceSizePixel
.Width
= aGraphicCropPixel
.Right
- aGraphicCropPixel
.Left
;
280 aSourceSizePixel
.Height
= aGraphicCropPixel
.Bottom
- aGraphicCropPixel
.Top
;
284 bRemoveCropArea
= false;
287 if ( ( aSourceSizePixel
.Width
> 0 ) && ( aSourceSizePixel
.Height
> 0 ) )
289 OUString
aDestMimeType( u
"image/png"_ustr
);
290 if (rGraphicSettings
.mbJPEGCompression
&& !bTransparent
&& !bAlpha
)
292 aDestMimeType
= "image/jpeg";
293 // if( aSourceMimeType != aDestMimeType )
294 bNeedsOptimizing
= true;
296 if ( bRemoveCropArea
)
297 aDestSizePixel
= aSourceSizePixel
;
298 if ( rGraphicSettings
.mnImageResolution
&& aLogicalSize
.Width
&& aLogicalSize
.Height
)
300 const double fSourceDPIX
= static_cast<double>(aSourceSizePixel
.Width
) / (static_cast<double>(aLogicalSize
.Width
) / 2540.0 );
301 const double fSourceDPIY
= static_cast<double>(aSourceSizePixel
.Height
)/ (static_cast<double>(aLogicalSize
.Height
)/ 2540.0 );
303 // check, if the bitmap DPI exceeds the maximum DPI
304 if( ( fSourceDPIX
> rGraphicSettings
.mnImageResolution
) || ( fSourceDPIY
> rGraphicSettings
.mnImageResolution
) )
306 const double fNewSizePixelX
= (static_cast<double>(aDestSizePixel
.Width
) * rGraphicSettings
.mnImageResolution
) / fSourceDPIX
;
307 const double fNewSizePixelY
= (static_cast<double>(aDestSizePixel
.Height
)* rGraphicSettings
.mnImageResolution
) / fSourceDPIY
;
309 aDestSizePixel
= awt::Size( static_cast<sal_Int32
>(fNewSizePixelX
), static_cast<sal_Int32
>(fNewSizePixelY
) );
310 bNeedsOptimizing
= true;
313 if ( bNeedsOptimizing
&& aDestSizePixel
.Width
&& aDestSizePixel
.Height
)
315 Reference
< XStream
> xTempFile( io::TempFile::create(rxContext
), UNO_QUERY_THROW
);
316 Reference
< XOutputStream
> xOutputStream( xTempFile
->getOutputStream() );
317 Reference
< XGraphicProvider
> xGraphicProvider( GraphicProvider::create( rxContext
) );
319 ImpCompressGraphic( xGraphicProvider
, xGraphic
, xOutputStream
, aDestMimeType
, aLogicalSize
, rGraphicSettings
.mnJPEGQuality
, rGraphicSettings
.mnImageResolution
, bRemoveCropArea
, aGraphicCropLogic
);
320 Reference
< XInputStream
> xInputStream( xTempFile
->getInputStream() );
321 Reference
< XSeekable
> xSeekable( xInputStream
, UNO_QUERY_THROW
);
322 xSeekable
->seek( 0 );
323 Sequence
< PropertyValue
> aArgs
{ comphelper::makePropertyValue(
324 u
"InputStream"_ustr
, xInputStream
) };
325 xNewGraphic
= xGraphicProvider
->queryGraphic( aArgs
);
331 else // this is a metafile
333 const OUString
& aDestMimeType( aSourceMimeType
);
334 Reference
< XStream
> xTempFile( io::TempFile::create(rxContext
), UNO_QUERY_THROW
);
335 Reference
< XOutputStream
> xOutputStream( xTempFile
->getOutputStream() );
336 Reference
< XGraphicProvider
> xGraphicProvider( GraphicProvider::create( rxContext
) );
337 ImpCompressGraphic( xGraphicProvider
, xGraphic
, xOutputStream
, aDestMimeType
, aLogicalSize
, rGraphicSettings
.mnJPEGQuality
, rGraphicSettings
.mnImageResolution
, false, aGraphicCropLogic
);
338 Reference
< XInputStream
> xInputStream( xTempFile
->getInputStream() );
339 Reference
< XSeekable
> xSeekable( xInputStream
, UNO_QUERY_THROW
);
340 xSeekable
->seek( 0 );
341 Sequence
< PropertyValue
> aArgs
{ comphelper::makePropertyValue(u
"InputStream"_ustr
,
343 xNewGraphic
= xGraphicProvider
->queryGraphic( aArgs
);
353 static void CompressGraphics( ImpOptimizer
& rOptimizer
, const Reference
< XComponentContext
>& rxContext
, const GraphicSettings
& rGraphicSettings
,
354 std::vector
< GraphicCollector::GraphicEntity
>& rGraphicList
)
359 for( auto& rGraphic
: rGraphicList
)
362 sal_Int32 nProgress
= static_cast< sal_Int32
>( 40.0 * ( i
/ static_cast< double >( rGraphicList
.size() ) ) ) + 50;
363 rOptimizer
.SetStatusValue( TK_Progress
, Any( nProgress
) );
364 rOptimizer
.DispatchStatus();
366 if ( !rGraphic
.maUser
.empty() )
368 GraphicSettings
aGraphicSettings( rGraphicSettings
);
369 aGraphicSettings
.mbRemoveCropArea
= rGraphic
.mbRemoveCropArea
;
371 Reference
< XGraphic
> xGraphic
;
372 if ( rGraphic
.maUser
[ 0 ].mbFillBitmap
&& rGraphic
.maUser
[ 0 ].mxPropertySet
.is() )
374 Reference
< rendering::XBitmap
> xFillBitmap
;
375 if ( rGraphic
.maUser
[ 0 ].mxPropertySet
->getPropertyValue( u
"FillBitmap"_ustr
) >>= xFillBitmap
)
376 xGraphic
.set( xFillBitmap
, UNO_QUERY_THROW
);
378 else if ( rGraphic
.maUser
[ 0 ].mxShape
.is() )
380 Reference
< XPropertySet
> xShapePropertySet( rGraphic
.maUser
[ 0 ].mxShape
, UNO_QUERY_THROW
);
381 xShapePropertySet
->getPropertyValue( u
"Graphic"_ustr
) >>= xGraphic
;
385 Reference
< XPropertySet
> xNewGraphicPropertySet( xGraphic
, UNO_QUERY_THROW
);
386 awt::Size
aSize100thMM( GraphicCollector::GetOriginalSize( rxContext
, xGraphic
) );
387 Reference
< XGraphic
> xNewGraphic( ImpCompressGraphic( rxContext
, xGraphic
, rGraphic
.maLogicalSize
, rGraphic
.maGraphicCropLogic
, aGraphicSettings
) );
388 if ( xNewGraphic
.is() )
390 // applying graphic to each user
391 for( auto& rGraphicUser
: rGraphic
.maUser
)
393 if ( rGraphicUser
.mxShape
.is() )
395 Reference
< XPropertySet
> xShapePropertySet( rGraphicUser
.mxShape
, UNO_QUERY_THROW
);
396 xShapePropertySet
->setPropertyValue( u
"Graphic"_ustr
, Any( xNewGraphic
) );
398 if ( rGraphicUser
.maGraphicCropLogic
.Left
|| rGraphicUser
.maGraphicCropLogic
.Top
399 || rGraphicUser
.maGraphicCropLogic
.Right
|| rGraphicUser
.maGraphicCropLogic
.Bottom
)
400 { // removing crop area was not possible or shouldn't been applied
401 text::GraphicCrop
aGraphicCropLogic( 0, 0, 0, 0 );
402 if ( !aGraphicSettings
.mbRemoveCropArea
)
404 awt::Size
aNewSize( GraphicCollector::GetOriginalSize( rxContext
, xNewGraphic
) );
405 aGraphicCropLogic
.Left
= static_cast<sal_Int32
>(static_cast<double>(rGraphicUser
.maGraphicCropLogic
.Left
) * (static_cast<double>(aNewSize
.Width
) / static_cast<double>(aSize100thMM
.Width
)));
406 aGraphicCropLogic
.Top
= static_cast<sal_Int32
>(static_cast<double>(rGraphicUser
.maGraphicCropLogic
.Top
) * (static_cast<double>(aNewSize
.Height
) / static_cast<double>(aSize100thMM
.Height
)));
407 aGraphicCropLogic
.Right
= static_cast<sal_Int32
>(static_cast<double>(rGraphicUser
.maGraphicCropLogic
.Right
) * (static_cast<double>(aNewSize
.Width
) / static_cast<double>(aSize100thMM
.Width
)));
408 aGraphicCropLogic
.Bottom
= static_cast<sal_Int32
>(static_cast<double>(rGraphicUser
.maGraphicCropLogic
.Bottom
) * (static_cast<double>(aNewSize
.Height
) / static_cast<double>(aSize100thMM
.Height
)));
410 xShapePropertySet
->setPropertyValue( u
"GraphicCrop"_ustr
, Any( aGraphicCropLogic
) );
413 else if ( rGraphicUser
.mxPropertySet
.is() )
415 Reference
< rendering::XBitmap
> xFillBitmap( xNewGraphic
, UNO_QUERY
);
416 if ( xFillBitmap
.is() )
421 Reference
< XPropertySet
>& rxPropertySet( rGraphicUser
.mxPropertySet
);
422 rxPropertySet
->setPropertyValue( u
"FillBitmap"_ustr
, Any( xFillBitmap
) );
423 if ( ( rxPropertySet
->getPropertyValue( u
"FillBitmapLogicalSize"_ustr
) >>= bLogicalSize
)
424 && ( rxPropertySet
->getPropertyValue( u
"FillBitmapSizeX"_ustr
) >>= aSize
.Width
)
425 && ( rxPropertySet
->getPropertyValue( u
"FillBitmapSizeY"_ustr
) >>= aSize
.Height
) )
427 if ( !aSize
.Width
|| !aSize
.Height
)
429 rxPropertySet
->setPropertyValue( u
"FillBitmapLogicalSize"_ustr
, Any( true ) );
430 rxPropertySet
->setPropertyValue( u
"FillBitmapSizeX"_ustr
, Any( rGraphicUser
.maLogicalSize
.Width
) );
431 rxPropertySet
->setPropertyValue( u
"FillBitmapSizeY"_ustr
, Any( rGraphicUser
.maLogicalSize
.Height
) );
434 if ( rGraphicUser
.mxPagePropertySet
.is() )
435 rGraphicUser
.mxPagePropertySet
->setPropertyValue( u
"Background"_ustr
, Any( rxPropertySet
) );
450 ImpOptimizer::ImpOptimizer( const Reference
< XComponentContext
>& rxContext
, const Reference
< XModel
>& rxModel
) :
451 mxContext ( rxContext
),
453 mbJPEGCompression ( false ),
454 mnJPEGQuality ( 90 ),
455 mbRemoveCropArea ( false ),
456 mnImageResolution ( 0 ),
457 mbEmbedLinkedGraphics ( true ),
458 mbOLEOptimization ( false ),
459 mnOLEOptimizationType ( 0 ),
460 mbDeleteUnusedMasterPages ( false ),
461 mbDeleteHiddenSlides ( false ),
462 mbDeleteNotesPages ( false ),
463 mbOpenNewDocument ( true )
468 ImpOptimizer::~ImpOptimizer()
473 void ImpOptimizer::DispatchStatus()
475 if ( mxStatusDispatcher
.is() )
478 aURL
.Protocol
= "vnd.com.sun.star.comp.PresentationMinimizer:";
479 aURL
.Path
= "statusupdate";
480 mxStatusDispatcher
->dispatch( aURL
, GetStatusSequence() );
485 void ImpOptimizer::Optimize()
488 if ( !maCustomShowName
.isEmpty() )
489 ImpExtractCustomShow( mxModel
, maCustomShowName
);
491 if ( mbDeleteHiddenSlides
)
493 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 40 ) ) );
494 SetStatusValue( TK_Status
, Any( u
"STR_DELETING_SLIDES"_ustr
) );
496 ImpDeleteHiddenSlides( mxModel
);
499 if ( mbDeleteNotesPages
)
501 SetStatusValue( TK_Status
, Any( u
"STR_DELETING_SLIDES"_ustr
) );
503 ImpDeleteNotesPages( mxModel
);
506 if ( mbDeleteUnusedMasterPages
)
508 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 40 ) ) );
509 SetStatusValue( TK_Status
, Any( u
"STR_DELETING_SLIDES"_ustr
) );
511 ImpDeleteUnusedMasterPages( mxModel
);
514 if ( mbOLEOptimization
)
516 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 45 ) ) );
517 SetStatusValue( TK_Status
, Any( u
"STR_CREATING_OLE_REPLACEMENTS"_ustr
) );
519 ImpConvertOLE( mxModel
, mnOLEOptimizationType
);
522 if ( mbJPEGCompression
|| mbRemoveCropArea
|| mnImageResolution
)
524 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 50 ) ) );
525 SetStatusValue( TK_Status
, Any( u
"STR_OPTIMIZING_GRAPHICS"_ustr
) );
528 std::vector
< GraphicCollector::GraphicEntity
> aGraphicList
;
529 GraphicSettings
aGraphicSettings( mbJPEGCompression
, mnJPEGQuality
, mbRemoveCropArea
, mnImageResolution
, mbEmbedLinkedGraphics
);
530 GraphicCollector::CollectGraphics( mxContext
, mxModel
, aGraphicSettings
, aGraphicList
);
531 CompressGraphics( *this, mxContext
, aGraphicSettings
, aGraphicList
);
533 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 100 ) ) );
537 static void DispatchURL( const Reference
< XComponentContext
>& xContext
, const OUString
& sURL
, const Reference
< XFrame
>& xFrame
)
541 Reference
< XURLTransformer
> xURLTransformer( URLTransformer::create(xContext
) );
543 aUrl
.Complete
= sURL
;
544 xURLTransformer
->parseStrict( aUrl
);
545 Sequence
< PropertyValue
> aArgs
;
546 Reference
< XDispatchProvider
> xDispatchProvider( xFrame
, UNO_QUERY_THROW
);
547 Reference
< XDispatch
> xDispatch
= xDispatchProvider
->queryDispatch( aUrl
, OUString(), 0 ); // "_self"
548 if ( xDispatch
.is() )
549 xDispatch
->dispatch( aUrl
, aArgs
);
557 void ImpOptimizer::Optimize( const Sequence
< PropertyValue
>& rArguments
)
562 sal_Int64 nEstimatedFileSize
= 0;
563 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 0 ) ) );
566 for ( const auto& rArgument
: rArguments
)
568 switch( TKGet( rArgument
.Name
) )
570 case TK_StatusDispatcher
: rArgument
.Value
>>= mxStatusDispatcher
; break;
571 case TK_DocumentFrame
: rArgument
.Value
>>= mxDocumentFrame
; break;
572 case TK_DialogParentWindow
: rArgument
.Value
>>= mxDialogParentWindow
; break;
575 css::uno::Sequence
< css::beans::PropertyValue
> aSettings
;
576 rArgument
.Value
>>= aSettings
;
577 for (const auto& rSetting
: aSettings
)
579 switch( TKGet( rSetting
.Name
) )
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;
605 sal_Int64 nSourceSize
= 0;
606 sal_Int64 nDestSize
= 0;
608 Reference
< XFrame
> xSelf
;
609 if ( !maSaveAsURL
.isEmpty() )
612 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 10 ) ) );
613 SetStatusValue( TK_Status
, Any( u
"STR_DUPLICATING_PRESENTATION"_ustr
) );
616 Reference
< XStorable
>xStorable( mxModel
, UNO_QUERY
);
617 if ( xStorable
.is() )
619 if ( xStorable
->hasLocation() )
620 nSourceSize
= PPPOptimizer::GetFileSize( xStorable
->getLocation() );
622 Sequence
< PropertyValue
> aArguments
;
623 if ( !maFilterName
.isEmpty() )
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
;
631 xStorable
->storeToURL( maSaveAsURL
, aArguments
);
633 nSourceSize
= PPPOptimizer::GetFileSize( maSaveAsURL
);
635 SetStatusValue( TK_Progress
, Any( static_cast< sal_Int32
>( 30 ) ) );
636 SetStatusValue( TK_Status
, Any( u
"STR_DUPLICATING_PRESENTATION"_ustr
) );
639 Reference
< XDesktop2
> xDesktop
= Desktop::create( mxContext
);
640 xSelf
= xDesktop
->findFrame( u
"_blank"_ustr
, FrameSearchFlag::CREATE
);
641 Reference
< XComponentLoader
> xComponentLoader( xSelf
, UNO_QUERY
);
643 Sequence
< PropertyValue
> aLoadProps
{ comphelper::makePropertyValue(u
"Hidden"_ustr
, true) };
644 mxModel
.set( xComponentLoader
->loadComponentFromURL(
645 maSaveAsURL
, u
"_self"_ustr
, 0, aLoadProps
), UNO_QUERY
);
649 // check if the document is ReadOnly -> error
650 Reference
< XStorable
> xStorable( mxModel
, UNO_QUERY
);
651 if ( xStorable
.is() && !xStorable
->isReadonly() )
653 mxModel
->lockControllers();
655 mxModel
->unlockControllers();
657 // clearing undo stack:
658 Reference
< XFrame
> xFrame( xSelf
.is() ? xSelf
: mxDocumentFrame
);
661 DispatchURL(mxContext
, u
".uno:ClearUndoStack"_ustr
, xFrame
);
665 if ( !maSaveAsURL
.isEmpty() )
667 if ( xStorable
.is() )
670 nDestSize
= PPPOptimizer::GetFileSize( maSaveAsURL
);
674 if ( mxDocumentFrame
.is() )
676 InformationDialog
aInformationDialog( mxContext
, mxDialogParentWindow
, maSaveAsURL
, mbOpenNewDocument
, nSourceSize
, nDestSize
, nEstimatedFileSize
);
677 aInformationDialog
.execute();
678 SetStatusValue( TK_OpenNewDocument
, Any( mbOpenNewDocument
) );
682 if ( !maSaveAsURL
.isEmpty() )
684 if ( mbOpenNewDocument
&& xSelf
.is() )
686 Reference
< awt::XWindow
> xContainerWindow( xSelf
->getContainerWindow() );
687 xContainerWindow
->setVisible( true );
694 if ( nSourceSize
&& nDestSize
)
696 SetStatusValue( TK_FileSizeSource
, Any( nSourceSize
) );
697 SetStatusValue( TK_FileSizeDestination
, Any( nDestSize
) );
702 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */