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 .
20 #include <sal/config.h>
24 #include <comphelper/propertyvalue.hxx>
25 #include <o3tl/safeint.hxx>
26 #include <tools/stream.hxx>
27 #include <tools/fract.hxx>
29 #include <vcl/graphicfilter.hxx>
30 #include <vcl/FilterConfigItem.hxx>
31 #include <svtools/strings.hrc>
32 #include <svtools/svtresid.hxx>
33 #include <svtools/DocumentToGraphicRenderer.hxx>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/awt/Size.hpp>
36 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
37 #include <com/sun/star/drawing/XDrawView.hpp>
38 #include <com/sun/star/frame/XModel.hpp>
39 #include <com/sun/star/frame/XController.hpp>
40 #include <com/sun/star/graphic/PrimitiveFactory2D.hpp>
41 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
42 #include <com/sun/star/io/XStream.hpp>
43 #include <unotools/streamwrap.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/outdev.hxx>
46 #include <vcl/graph.hxx>
47 #include <rtl/ustrbuf.hxx>
48 #include <basegfx/matrix/b2dhommatrix.hxx>
49 #include "exportdialog.hxx"
51 #define FORMAT_UNKNOWN 0
61 #define FORMAT_WEBP 17
63 #define UNIT_DEFAULT -1
69 #define UNIT_MAX_ID UNIT_PIXEL
71 using namespace ::com::sun::star
;
73 static sal_Int16
GetFilterFormat(std::u16string_view rExt
)
75 sal_Int16 nFormat
= FORMAT_UNKNOWN
;
78 else if ( rExt
== u
"PNG" )
80 else if ( rExt
== u
"BMP" )
82 else if ( rExt
== u
"GIF" )
84 else if ( rExt
== u
"TIF" )
86 else if ( rExt
== u
"WMF" )
88 else if ( rExt
== u
"EMF" )
90 else if ( rExt
== u
"EPS" )
92 else if ( rExt
== u
"SVG" )
94 else if ( rExt
== u
"WEBP" )
95 nFormat
= FORMAT_WEBP
;
99 static MapUnit
GetMapUnit( sal_Int32 nUnit
)
101 MapUnit
aMapUnit( MapUnit::MapPixel
);
104 case UNIT_INCH
: aMapUnit
= MapUnit::MapInch
; break;
105 case UNIT_CM
: aMapUnit
= MapUnit::MapCM
; break;
106 case UNIT_MM
: aMapUnit
= MapUnit::MapMM
; break;
107 case UNIT_POINT
: aMapUnit
= MapUnit::MapPoint
; break;
108 case UNIT_PIXEL
: aMapUnit
= MapUnit::MapPixel
; break;
113 sal_Int32
ExportDialog::GetDefaultUnit() const
115 sal_Int32 nDefaultUnit
= UNIT_CM
;
116 switch( mrFltCallPara
.eFieldUnit
)
118 // case FieldUnit::NONE :
119 // case FieldUnit::PERCENT :
120 // case FieldUnit::CUSTOM :
121 default: nDefaultUnit
= UNIT_CM
; break;
123 case FieldUnit::MILE
: // PASSTHROUGH INTENDED
124 case FieldUnit::FOOT
:
125 case FieldUnit::TWIP
:
126 case FieldUnit::PICA
: nDefaultUnit
= UNIT_INCH
; break;
128 case FieldUnit::KM
: // PASSTHROUGH INTENDED
130 case FieldUnit::MM_100TH
: nDefaultUnit
= UNIT_CM
; break;
132 case FieldUnit::INCH
: nDefaultUnit
= UNIT_INCH
; break;
133 case FieldUnit::CM
: nDefaultUnit
= UNIT_CM
; break;
134 case FieldUnit::MM
: nDefaultUnit
= UNIT_MM
; break;
135 case FieldUnit::POINT
: nDefaultUnit
= UNIT_POINT
; break;
140 static basegfx::B2DRange
GetShapeRangeForXShape( const uno::Reference
< drawing::XShape
>& rxShape
,
141 const uno::Reference
< graphic::XPrimitiveFactory2D
>& rxPrimitiveFactory2D
, const uno::Sequence
< beans::PropertyValue
>& rViewInformation
)
143 basegfx::B2DRange aShapeRange
;
145 const uno::Sequence
< beans::PropertyValue
> aParams
;
146 const uno::Sequence
< uno::Reference
< graphic::XPrimitive2D
> > aPrimitiveSequence( rxPrimitiveFactory2D
->createPrimitivesFromXShape( rxShape
, aParams
) );
148 for( const auto& rPrimitive
: aPrimitiveSequence
)
150 const geometry::RealRectangle2D
aRect( rPrimitive
->getRange( rViewInformation
) );
151 aShapeRange
.expand( basegfx::B2DTuple( aRect
.X1
, aRect
.Y1
) );
152 aShapeRange
.expand( basegfx::B2DTuple( aRect
.X2
, aRect
.Y2
) );
157 uno::Sequence
< beans::PropertyValue
> ExportDialog::GetFilterData( bool bUpdateConfig
)
161 sal_Int32 nUnit
= mxLbSizeX
->get_active();
165 if ( ( mnInitialResolutionUnit
== UNIT_DEFAULT
) && ( nUnit
== GetDefaultUnit() ) )
166 nUnit
= UNIT_DEFAULT
;
168 // updating ui configuration
169 if ( mbIsPixelFormat
)
171 if ( nUnit
> UNIT_MAX_ID
)
174 sal_Int32 nResolution
= mxNfResolution
->get_value();
175 if ( nResolution
< 1 )
178 mpOptionsItem
->WriteInt32("PixelExportUnit", nUnit
);
179 mpOptionsItem
->WriteInt32("PixelExportResolution", nResolution
);
180 mpOptionsItem
->WriteInt32("PixelExportResolutionUnit", mxLbResolution
->get_active());
184 if ( nUnit
>= UNIT_PIXEL
)
187 mpOptionsItem
->WriteInt32("VectorExportUnit", nUnit
);
191 FilterConfigItem
* pFilterOptions
;
193 pFilterOptions
= mpFilterOptionsItem
.get();
196 uno::Sequence
< beans::PropertyValue
> aFilterData( mpFilterOptionsItem
->GetFilterData() );
197 pFilterOptions
= new FilterConfigItem( &aFilterData
);
200 static const OUStringLiteral
sLogicalWidth(u
"LogicalWidth");
201 static const OUStringLiteral
sLogicalHeight(u
"LogicalHeight");
202 if ( mbIsPixelFormat
)
204 pFilterOptions
->WriteInt32("PixelWidth", maSize
.Width
);
205 pFilterOptions
->WriteInt32("PixelHeight", maSize
.Height
);
206 if ( maResolution
.Width
&& maResolution
.Height
)
208 const double f100thmmPerPixelX
= 100000.0 / maResolution
.Width
;
209 const double f100thmmPerPixelY
= 100000.0 / maResolution
.Height
;
210 sal_Int32 nLogicalWidth
= static_cast< sal_Int32
>( f100thmmPerPixelX
* maSize
.Width
);
211 sal_Int32 nLogicalHeight
= static_cast< sal_Int32
>( f100thmmPerPixelY
* maSize
.Height
);
212 if ( nLogicalWidth
&& nLogicalHeight
)
214 pFilterOptions
->WriteInt32( sLogicalWidth
, nLogicalWidth
);
215 pFilterOptions
->WriteInt32( sLogicalHeight
, nLogicalHeight
);
221 pFilterOptions
->WriteInt32( sLogicalWidth
, maSize
.Width
);
222 pFilterOptions
->WriteInt32( sLogicalHeight
, maSize
.Height
);
228 sal_Int32 nColor
= mxLbColorDepth
->get_active();
233 pFilterOptions
->WriteInt32("ColorMode", nColor
);
234 assert(mpSbCompression
);
235 pFilterOptions
->WriteInt32("Quality", static_cast<sal_Int32
>(mpSbCompression
->get_value()));
241 assert(mpSbCompression
);
242 pFilterOptions
->WriteInt32("Compression", static_cast<sal_Int32
>(mpSbCompression
->get_value()));
243 sal_Int32 nInterlace
= 0;
244 if ( mxCbInterlaced
->get_active() )
246 pFilterOptions
->WriteInt32("Interlaced", nInterlace
);
247 sal_Int32 nValue
= 0;
248 if ( mxCbSaveTransparency
->get_active() )
250 pFilterOptions
->WriteInt32("Translucent", nValue
);
256 pFilterOptions
->WriteInt32("Color", mxLbColorDepth
->get_active() + 1);
257 pFilterOptions
->WriteBool("RLE_Coding", mxCbRLEEncoding
->get_active());
263 sal_Int32 nValue
= 0;
264 if ( mxCbInterlaced
->get_active() )
266 pFilterOptions
->WriteInt32("Interlaced", nValue
);
269 if (mxCbSaveTransparency
->get_active())
271 pFilterOptions
->WriteInt32("Translucent", nValue
);
277 sal_Int32 nCheck
= 0;
278 if ( mxCbEPSPreviewTIFF
->get_active() )
280 if ( mxCbEPSPreviewEPSI
->get_active() )
282 pFilterOptions
->WriteInt32("Preview", nCheck
);
285 if ( mxRbEPSLevel2
->get_active() )
287 pFilterOptions
->WriteInt32("Version", nCheck
);
290 if ( mxRbEPSColorFormat2
->get_active() )
292 pFilterOptions
->WriteInt32("ColorFormat", nCheck
);
295 if ( mxRbEPSCompressionNone
->get_active() )
297 pFilterOptions
->WriteInt32("CompressionMode", nCheck
);
303 assert(mpSbCompression
);
304 pFilterOptions
->WriteInt32("Quality", static_cast<sal_Int32
>(mpSbCompression
->get_value()));
305 pFilterOptions
->WriteBool("Lossless", mxCbLossless
->get_active());
311 uno::Sequence
< beans::PropertyValue
> aRet( pFilterOptions
->GetFilterData() );
312 if ( !bUpdateConfig
)
313 delete pFilterOptions
;
318 awt::Size
ExportDialog::GetOriginalSize()
320 basegfx::B2DRange aShapesRange
;
324 uno::Reference
< beans::XPropertySet
> xPagePropSet( mxPage
, uno::UNO_QUERY
);
325 if ( xPagePropSet
.is() )
327 sal_Int32 nWidth
= 0;
328 sal_Int32 nHeight
= 0;
330 aAny
= xPagePropSet
->getPropertyValue("Width");
332 aAny
= xPagePropSet
->getPropertyValue("Height");
334 aShapesRange
= basegfx::B2DRange( 0, 0, nWidth
, nHeight
);
337 else if (mxShapes
.is() || mxShape
.is())
339 uno::Reference
< graphic::XPrimitiveFactory2D
> xPrimitiveFactory
= graphic::PrimitiveFactory2D::create( mxContext
);
341 basegfx::B2DHomMatrix
aViewTransformation( Application::GetDefaultDevice()->GetViewTransformation() );
342 css::geometry::AffineMatrix2D aTransformation
;
343 aTransformation
.m00
= aViewTransformation
.get(0,0);
344 aTransformation
.m01
= aViewTransformation
.get(0,1);
345 aTransformation
.m02
= aViewTransformation
.get(0,2);
346 aTransformation
.m10
= aViewTransformation
.get(1,0);
347 aTransformation
.m11
= aViewTransformation
.get(1,1);
348 aTransformation
.m12
= aViewTransformation
.get(1,2);
350 uno::Sequence
< beans::PropertyValue
> aViewInformation
{ comphelper::makePropertyValue(
351 "ViewTransformation", aTransformation
) };
354 aShapesRange
= GetShapeRangeForXShape( mxShape
, xPrimitiveFactory
, aViewInformation
);
355 else if ( mxShapes
.is() )
357 const sal_Int32 nCount
= mxShapes
->getCount();
358 for( sal_Int32 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
360 uno::Reference
< drawing::XShape
> xShape
;
361 mxShapes
->getByIndex( nIndex
) >>= xShape
;
362 aShapesRange
.expand( GetShapeRangeForXShape( xShape
, xPrimitiveFactory
, aViewInformation
) );
366 else if (!mbGraphicsSource
)
368 DocumentToGraphicRenderer
aRenderer( mxSourceDocument
, mbExportSelection
);
369 const sal_Int32 nCurrentPage
= aRenderer
.getCurrentPage();
370 const Size aSize
= aRenderer
.getDocumentSizeIn100mm( nCurrentPage
);
371 return awt::Size( aSize
.Width(), aSize
.Height());
373 return awt::Size( static_cast<sal_Int32
>(aShapesRange
.getWidth()), static_cast<sal_Int32
>(aShapesRange
.getHeight()) );
376 void ExportDialog::GetGraphicSource()
381 if ( !mxSourceDocument
.is() )
384 uno::Reference
< frame::XModel
> xModel( mxSourceDocument
, uno::UNO_QUERY
);
388 uno::Reference
< frame::XController
> xController( xModel
->getCurrentController() );
389 if ( !xController
.is() )
392 if ( mbExportSelection
) // check if there is a selection
394 if (DocumentToGraphicRenderer::isShapeSelected( mxShapes
, mxShape
, xController
))
395 mbGraphicsSource
= true;
397 if ( !mxShape
.is() && !mxShapes
.is() && mbGraphicsSource
)
399 uno::Reference
< drawing::XDrawView
> xDrawView( xController
, uno::UNO_QUERY
);
400 if ( xDrawView
.is() )
402 uno::Reference
< drawing::XDrawPage
> xCurrentPage( xDrawView
->getCurrentPage() );
403 if ( xCurrentPage
.is() )
405 mxPage
= xCurrentPage
; // exporting whole page
409 // For !mbGraphicsSource the mxSourceDocument is used, from
410 // which XRenderable can query XController and
411 // XSelectionSupplier the same.
414 void ExportDialog::GetGraphicStream()
416 if ( !IsTempExportAvailable() )
418 mpTempStream
.reset(new SvMemoryStream());
422 bool bRecreateOutputStream
= mpTempStream
->Tell() == 0;
424 static uno::Sequence
< beans::PropertyValue
> aOldFilterData
;
425 uno::Sequence
< beans::PropertyValue
> aNewFilterData( GetFilterData( false ) );
426 if ( aOldFilterData
!= aNewFilterData
)
428 aOldFilterData
= aNewFilterData
;
429 bRecreateOutputStream
= true;
433 if ( bRecreateOutputStream
)
435 mpTempStream
.reset(new SvMemoryStream());
437 uno::Reference
< graphic::XGraphic
> xGraphic
;
438 if (!mbGraphicsSource
&& !mxGraphic
.is())
440 // Create a Graphic to be used below.
441 DocumentToGraphicRenderer
aRenderer( mxSourceDocument
, mbExportSelection
);
442 const sal_Int32 nCurrentPage
= aRenderer
.getCurrentPage();
443 const Size aDocumentSizePixel
= aRenderer
.getDocumentSizeInPixels( nCurrentPage
);
445 const Size
aTargetSizePixel( mbIsPixelFormat
?
446 Size( maSize
.Width
, maSize
.Height
) :
447 aDocumentSizePixel
);
449 Graphic
aGraphic( aRenderer
.renderToGraphic( nCurrentPage
,
450 aDocumentSizePixel
, aTargetSizePixel
, COL_WHITE
, /*bExtOutDevData=*/false));
451 xGraphic
= aGraphic
.GetXGraphic();
454 if ( mxGraphic
.is() || xGraphic
.is() )
456 Graphic
aGraphic( mxGraphic
.is() ? mxGraphic
: xGraphic
);
458 if ( aGraphic
.GetType() == GraphicType::Bitmap
)
460 Size
aSizePixel( aGraphic
.GetSizePixel() );
461 if( maSize
.Width
&& maSize
.Height
&&
462 ( ( maSize
.Width
!= aSizePixel
.Width() ) ||
463 ( maSize
.Height
!= aSizePixel
.Height() ) ) )
465 BitmapEx
aBmpEx( aGraphic
.GetBitmapEx() );
466 // export: use highest quality
467 aBmpEx
.Scale( Size( maSize
.Width
, maSize
.Height
), BmpScaleFlag::Lanczos
);
472 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
473 const sal_uInt16 nFilter
= rFilter
.GetExportFormatNumberForShortName( maExt
);
474 if ( rFilter
.IsExportPixelFormat( nFilter
) )
476 mpTempStream
->SetResizeOffset(1024);
477 mpTempStream
->SetStreamSize(1024);
478 rFilter
.ExportGraphic( aGraphic
, u
"", *mpTempStream
, nFilter
, &aNewFilterData
);
483 uno::Reference
< lang::XComponent
> xSourceDoc
;
485 xSourceDoc
.set( mxPage
, uno::UNO_QUERY_THROW
);
486 else if ( mxShapes
.is() )
487 xSourceDoc
.set( mxShapes
, uno::UNO_QUERY_THROW
);
488 else if ( mxShape
.is() )
489 xSourceDoc
.set( mxShape
, uno::UNO_QUERY_THROW
);
490 if ( xSourceDoc
.is() )
492 uno::Reference
< io::XStream
> xStream( new utl::OStreamWrapper( *mpTempStream
) );
493 uno::Reference
< io::XOutputStream
> xOutputStream( xStream
->getOutputStream() );
495 OUString
sFormat( maExt
);
496 uno::Sequence
< beans::PropertyValue
> aDescriptor
{
497 comphelper::makePropertyValue("OutputStream", xOutputStream
),
498 comphelper::makePropertyValue("FilterName", sFormat
),
499 comphelper::makePropertyValue("FilterData", aNewFilterData
)
502 uno::Reference
< drawing::XGraphicExportFilter
> xGraphicExporter
=
503 drawing::GraphicExportFilter::create( mxContext
);
505 xGraphicExporter
->setSourceDocument( xSourceDoc
);
506 xGraphicExporter
->filter( aDescriptor
);
511 catch( uno::Exception
& )
519 sal_uInt32
ExportDialog::GetRawFileSize() const
521 sal_uInt64 nRawFileSize
= 0;
522 if ( mbIsPixelFormat
)
524 sal_Int32 nBitsPerPixel
= 24;
525 OUString
aEntry(mxLbColorDepth
->get_active_text());
526 if ( ms1BitThreshold
== aEntry
)
528 else if ( ms8BitGrayscale
== aEntry
)
530 else if ( ms8BitColorPalette
== aEntry
)
532 else if ( ms24BitColor
== aEntry
)
535 if ( mbIsPixelFormat
)
537 nRawFileSize
= ( maSize
.Width
* nBitsPerPixel
+ 7 ) &~ 7; // rounding up to 8 bits
538 nRawFileSize
/= 8; // in bytes
539 nRawFileSize
*= maSize
.Height
;
541 if ( nRawFileSize
> SAL_MAX_UINT32
)
544 return static_cast< sal_uInt32
>( nRawFileSize
);
547 // checks if the source dimension/resolution is not too big
548 // to determine the exact graphic output size and preview for jpg
549 bool ExportDialog::IsTempExportAvailable() const
551 return GetRawFileSize() < o3tl::make_unsigned( mnMaxFilesizeForRealtimePreview
);
554 ExportDialog::ExportDialog(FltCallDialogParameter
& rPara
,
555 css::uno::Reference
< css::uno::XComponentContext
> xContext
,
556 const css::uno::Reference
< css::lang::XComponent
>& rxSourceDocument
,
557 bool bExportSelection
, bool bIsPixelFormat
, bool bGraphicsSource
,
558 const css::uno::Reference
< css::graphic::XGraphic
>& rxGraphic
)
559 : GenericDialogController(rPara
.pWindow
, "svt/ui/graphicexport.ui", "GraphicExportDialog")
560 , mrFltCallPara(rPara
)
561 , mxContext(std::move(xContext
))
562 , mxSourceDocument(rxSourceDocument
)
563 , mxGraphic(rxGraphic
)
564 , msEstimatedSizePix1(SvtResId(STR_SVT_ESTIMATED_SIZE_PIX_1
))
565 , msEstimatedSizePix2(SvtResId(STR_SVT_ESTIMATED_SIZE_PIX_2
))
566 , msEstimatedSizeVec(SvtResId(STR_SVT_ESTIMATED_SIZE_VEC
))
567 , ms1BitThreshold(SvtResId(STR_SVT_1BIT_THRESHOLD
))
568 , ms8BitGrayscale(SvtResId(STR_SVT_8BIT_GRAYSCALE
))
569 , ms8BitColorPalette(SvtResId(STR_SVT_8BIT_COLOR_PALETTE
))
570 , ms24BitColor(SvtResId(STR_SVT_24BIT_TRUE_COLOR
))
571 , maExt(rPara
.aFilterExt
)
572 , mnFormat(FORMAT_UNKNOWN
)
573 , mnMaxFilesizeForRealtimePreview(0)
574 , mpTempStream(new SvMemoryStream())
575 , maOriginalSize(awt::Size(0, 0))
576 , mbIsPixelFormat(bIsPixelFormat
)
577 , mbExportSelection(bExportSelection
)
578 , mbGraphicsSource(bGraphicsSource
)
579 , mpSbCompression(nullptr)
580 , mpNfCompression(nullptr)
581 , mxMfSizeX(m_xBuilder
->weld_spin_button("widthmf"))
582 , mxLbSizeX(m_xBuilder
->weld_combo_box("widthlb"))
583 , mxMfSizeY(m_xBuilder
->weld_spin_button( "heightmf"))
584 , mxFtResolution(m_xBuilder
->weld_label("resolutionft"))
585 , mxNfResolution(m_xBuilder
->weld_spin_button("resolutionmf"))
586 , mxLbResolution(m_xBuilder
->weld_combo_box("resolutionlb"))
587 , mxColorDepth(m_xBuilder
->weld_widget("colordepth"))
588 , mxLbColorDepth(m_xBuilder
->weld_combo_box("colordepthlb"))
589 , mxJPGWEBPQuality(m_xBuilder
->weld_widget("jpgwebpquality"))
590 , mxPNGCompression(m_xBuilder
->weld_widget("pngcompression"))
591 , mxSbPngCompression(m_xBuilder
->weld_scale("compressionpngsb"))
592 , mxNfPngCompression(m_xBuilder
->weld_spin_button("compressionpngnf"))
593 , mxSbJpgWebpCompression(m_xBuilder
->weld_scale("compressionjpgwebpsb"))
594 , mxNfJpgWebpCompression(m_xBuilder
->weld_spin_button("compressionjpgwebpnf"))
595 , mxCbLossless(m_xBuilder
->weld_check_button("losslesscb"))
596 , mxMode(m_xBuilder
->weld_widget("mode"))
597 , mxCbInterlaced(m_xBuilder
->weld_check_button("interlacedcb"))
598 , mxBMPCompression(m_xBuilder
->weld_widget("bmpcompression"))
599 , mxCbRLEEncoding(m_xBuilder
->weld_check_button("rlecb"))
600 , mxDrawingObjects(m_xBuilder
->weld_widget("drawingobjects"))
601 , mxCbSaveTransparency(m_xBuilder
->weld_check_button("savetransparencycb"))
602 , mxEncoding(m_xBuilder
->weld_widget("encoding"))
603 , mxRbBinary(m_xBuilder
->weld_radio_button("binarycb"))
604 , mxRbText(m_xBuilder
->weld_radio_button("textcb"))
605 , mxEPSGrid(m_xBuilder
->weld_widget("epsgrid"))
606 , mxModifyDimension(m_xBuilder
->weld_radio_button("modifydimensionscb"))
607 , mxModifyResolution(m_xBuilder
->weld_radio_button("modifyresolutioncb"))
608 , mxCbEPSPreviewTIFF(m_xBuilder
->weld_check_button("tiffpreviewcb"))
609 , mxCbEPSPreviewEPSI(m_xBuilder
->weld_check_button("epsipreviewcb"))
610 , mxRbEPSLevel1(m_xBuilder
->weld_radio_button("level1rb"))
611 , mxRbEPSLevel2(m_xBuilder
->weld_radio_button("level2rb"))
612 , mxRbEPSColorFormat1(m_xBuilder
->weld_radio_button("color1rb"))
613 , mxRbEPSColorFormat2(m_xBuilder
->weld_radio_button("color2rb"))
614 , mxRbEPSCompressionLZW(m_xBuilder
->weld_radio_button("compresslzw"))
615 , mxRbEPSCompressionNone(m_xBuilder
->weld_radio_button("compressnone"))
616 , mxInfo(m_xBuilder
->weld_widget("information"))
617 , mxFtEstimatedSize(m_xBuilder
->weld_label("estsizeft"))
618 , mxBtnOK(m_xBuilder
->weld_button("ok"))
622 maExt
= maExt
.toAsciiUpperCase();
624 OUString
aFilterConfigPath( "Office.Common/Filter/Graphic/Export/" );
625 mpOptionsItem
.reset(new FilterConfigItem( aFilterConfigPath
, &rPara
.aFilterData
));
626 aFilterConfigPath
+= maExt
;
627 mpFilterOptionsItem
.reset(new FilterConfigItem( aFilterConfigPath
, &rPara
.aFilterData
));
629 mnInitialResolutionUnit
= mbIsPixelFormat
630 ? mpOptionsItem
->ReadInt32("PixelExportUnit", UNIT_DEFAULT
)
631 : mpOptionsItem
->ReadInt32("VectorExportUnit", UNIT_DEFAULT
);
633 mnMaxFilesizeForRealtimePreview
= std::max(
634 mpOptionsItem
->ReadInt32("MaxFilesizeForRealtimePreview", 0), sal_Int32(0));
635 mxFtEstimatedSize
->set_label(" \n ");
637 m_xDialog
->set_title(m_xDialog
->get_title().replaceFirst("%1", maExt
)); //Set dialog title
639 mnFormat
= GetFilterFormat( maExt
);
641 Size
aResolution( Application::GetDefaultDevice()->LogicToPixel(Size(100, 100), MapMode(MapUnit::MapCM
)) );
642 maResolution
.Width
= aResolution
.Width();
643 maResolution
.Height
= aResolution
.Height();
645 if ( mxGraphic
.is() )
647 Graphic
aGraphic(mxGraphic
);
648 Size aSize
= aGraphic
.GetSizePixel();
649 maSize
= awt::Size(aSize
.getWidth(), aSize
.getHeight());
650 double f100thmmPerPixel
= 100000.0 / static_cast< double >( maResolution
.Width
);
651 maOriginalSize
= awt::Size(
652 static_cast< sal_Int32
>( f100thmmPerPixel
* maSize
.Width
),
653 static_cast< sal_Int32
>( f100thmmPerPixel
* maSize
.Height
) );
657 maOriginalSize
= GetOriginalSize();
658 if ( bIsPixelFormat
)
660 double fPixelsPer100thmm
= static_cast< double >( maResolution
.Width
) / 100000.0;
661 maSize
= awt::Size( static_cast< sal_Int32
>( ( fPixelsPer100thmm
* maOriginalSize
.Width
) + 0.5 ),
662 static_cast< sal_Int32
>( ( fPixelsPer100thmm
* maOriginalSize
.Height
) + 0.5 ) );
666 maSize
= maOriginalSize
;
672 mxLbSizeX
->connect_changed( LINK( this, ExportDialog
, SelectListBoxHdl
) );
675 mpSbCompression
->connect_value_changed(LINK(this, ExportDialog
, SbCompressionUpdateHdl
));
677 mpNfCompression
->connect_value_changed(LINK(this, ExportDialog
, SelectHdl
));
679 mxMfSizeX
->connect_value_changed( LINK( this, ExportDialog
, UpdateHdlMtfSizeX
) );
680 mxMfSizeY
->connect_value_changed( LINK( this, ExportDialog
, UpdateHdlMtfSizeY
) );
682 mxNfResolution
->connect_value_changed( LINK( this, ExportDialog
, UpdateHdlNfResolution
) );
683 mxLbResolution
->connect_changed( LINK( this, ExportDialog
, SelectListBoxHdl
) );
685 mxLbColorDepth
->connect_changed( LINK( this, ExportDialog
, SelectListBoxHdl
) );
687 mxCbInterlaced
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
689 mxCbLossless
->connect_toggled( LINK( this, ExportDialog
, UpdateHdlLossless
) );
691 mxCbSaveTransparency
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
693 mxModifyDimension
->connect_toggled( LINK( this, ExportDialog
, UpdateLock
) );
694 mxModifyResolution
->connect_toggled( LINK( this, ExportDialog
, UpdateLock
) );
696 mxCbEPSPreviewTIFF
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
697 mxCbEPSPreviewEPSI
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
699 mxRbEPSCompressionLZW
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
700 mxRbEPSCompressionNone
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
702 mxRbBinary
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
703 mxRbText
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
706 mxCbRLEEncoding
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
709 mxRbEPSLevel1
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
710 mxRbEPSLevel2
->connect_toggled( LINK( this, ExportDialog
, UpdateHdl
) );
712 mxBtnOK
->connect_clicked( LINK( this, ExportDialog
, OK
) );
717 void ExportDialog::setupSizeControls()
719 sal_Int32 nUnit
= mnInitialResolutionUnit
;
720 if (nUnit
== UNIT_DEFAULT
)
721 nUnit
= GetDefaultUnit();
723 if (!mbIsPixelFormat
)
725 mxFtResolution
->hide();
726 mxNfResolution
->hide();
727 mxLbResolution
->hide();
728 mxLbSizeX
->remove( UNIT_PIXEL
); // removing pixel
729 if ( nUnit
>= UNIT_PIXEL
)
732 else if ( nUnit
> UNIT_MAX_ID
)
736 mxLbSizeX
->set_active( static_cast< sal_uInt16
>( nUnit
) );
738 if ( !mbIsPixelFormat
) // TODO: (metafileresolutionsupport) should be supported for vector formats also... this makes
741 // sense eg for bitmap fillings in metafiles, to preserve high dpi output
742 // (atm without special vector support the bitmaps are rendered with 96dpi)
743 sal_Int32 nResolution
= mpOptionsItem
->ReadInt32("PixelExportResolution", 96);
744 if ( nResolution
< 1 )
746 mxNfResolution
->set_value( nResolution
);
748 sal_Int32 nResolutionUnit
= mpOptionsItem
->ReadInt32("PixelExportResolutionUnit", 1);
749 if ( ( nResolutionUnit
< 0 ) || ( nResolutionUnit
> 2 ) )
751 mxLbResolution
->set_active( static_cast< sal_uInt16
>( nResolutionUnit
) );
754 void ExportDialog::createFilterOptions()
760 sal_Int32 nColor
= mpFilterOptionsItem
->ReadInt32("ColorMode", 0);
765 mxLbColorDepth
->append_text( ms8BitGrayscale
);
766 mxLbColorDepth
->append_text( ms24BitColor
);
767 mxLbColorDepth
->set_active( nColor
);
768 mxColorDepth
->show();
771 mxJPGWEBPQuality
->show();
772 sal_Int32 nQuality
= mpFilterOptionsItem
->ReadInt32("Quality", 75);
773 if ((nQuality
< 1 ) || (nQuality
> 100))
775 mpSbCompression
= mxSbJpgWebpCompression
.get();
776 mpNfCompression
= mxNfJpgWebpCompression
.get();
777 mpSbCompression
->set_range(1, 100);
778 mpNfCompression
->set_range(1, 100);
779 mpNfCompression
->set_value(nQuality
);
780 mxCbLossless
->hide(); // only for WebP
786 mxPNGCompression
->show();
787 sal_Int32 nCompression
= mpFilterOptionsItem
->ReadInt32("Compression", 6);
788 if ( ( nCompression
< 1 ) || ( nCompression
> 9 ) )
791 mpSbCompression
= mxSbPngCompression
.get();
792 mpNfCompression
= mxNfPngCompression
.get();
793 mpSbCompression
->set_range(1, 9);
794 mpNfCompression
->set_range(1, 9);
795 mpNfCompression
->set_value(nCompression
);
799 mxCbInterlaced
->set_active(mpFilterOptionsItem
->ReadInt32("Interlaced", 0) != 0);
802 mxDrawingObjects
->show();
803 mxCbSaveTransparency
->set_active(mpFilterOptionsItem
->ReadInt32("Translucent", 1) != 0);
808 sal_Int32 nColor
= mpFilterOptionsItem
->ReadInt32("Color", 0);
813 mxLbColorDepth
->append_text( ms1BitThreshold
);
814 mxLbColorDepth
->append_text( ms8BitGrayscale
);
815 mxLbColorDepth
->append_text( ms8BitColorPalette
);
816 mxLbColorDepth
->append_text( ms24BitColor
);
817 mxLbColorDepth
->set_active( nColor
);
818 mxColorDepth
->show();
821 mxBMPCompression
->show();
822 mxCbRLEEncoding
->set_active(mpFilterOptionsItem
->ReadBool("RLE_Coding", true));
829 mxCbInterlaced
->set_active(mpFilterOptionsItem
->ReadInt32("Interlaced", 1) != 0);
832 mxDrawingObjects
->show();
833 mxCbSaveTransparency
->set_active(mpFilterOptionsItem
->ReadInt32("Translucent", 1) != 0);
840 sal_Int32 nPreview
= mpFilterOptionsItem
->ReadInt32("Preview", 0);
841 sal_Int32 nVersion
= mpFilterOptionsItem
->ReadInt32("Version", 2);
842 sal_Int32 nColor
= mpFilterOptionsItem
->ReadInt32("ColorFormat", 0);
843 sal_Int32 nCompr
= mpFilterOptionsItem
->ReadInt32("CompressionMode", 2);
845 mpFilterOptionsItem
->ReadInt32("TextMode", 0);
847 mxCbEPSPreviewTIFF
->set_active( ( nPreview
& 1 ) != 0 );
848 mxCbEPSPreviewEPSI
->set_active( ( nPreview
& 2 ) != 0 );
850 mxRbEPSLevel1
->set_active( nVersion
== 1 );
851 mxRbEPSLevel2
->set_active( nVersion
== 2 );
853 mxRbEPSColorFormat1
->set_active( nColor
== 1 );
854 mxRbEPSColorFormat2
->set_active( nColor
!= 1 );
856 mxRbEPSCompressionLZW
->set_active( nCompr
== 1 );
857 mxRbEPSCompressionNone
->set_active( nCompr
!= 1 );
863 mxJPGWEBPQuality
->show();
864 sal_Int32 nQuality
= mpFilterOptionsItem
->ReadInt32("Quality", 75);
865 if ((nQuality
< 1 ) || (nQuality
> 100))
867 mpSbCompression
= mxSbJpgWebpCompression
.get();
868 mpNfCompression
= mxNfJpgWebpCompression
.get();
869 mpSbCompression
->set_range(1, 100);
870 mpNfCompression
->set_range(1, 100);
871 mpNfCompression
->set_value(nQuality
);
874 mxCbLossless
->set_active(mpFilterOptionsItem
->ReadBool("Lossless", true));
875 UpdateHdlLossless(*mxCbLossless
);
881 void ExportDialog::setupControls()
884 createFilterOptions();
886 if (mnMaxFilesizeForRealtimePreview
|| mbIsPixelFormat
)
890 static OUString
ImpValueOfInKB( sal_Int64 rVal
)
892 double fVal( static_cast<double>( rVal
) );
895 OUStringBuffer
aVal( OUString::number( fVal
) );
896 sal_Int32
nX( aVal
.indexOf( '.' ) );
898 aVal
.setLength( nX
+ 2 );
899 return aVal
.makeStringAndClear();
902 void ExportDialog::updateControls()
905 if ( !mbIsPixelFormat
)
907 awt::Size
aSize100thmm( maSize
);
908 Size
aSize( OutputDevice::LogicToLogic( Size(aSize100thmm
.Width
* 100, aSize100thmm
.Height
* 100),
909 MapMode(MapUnit::Map100thMM
),
910 MapMode( GetMapUnit( mxLbSizeX
->get_active() ) ) ) );
911 mxMfSizeX
->set_value( aSize
.Width() );
912 mxMfSizeY
->set_value( aSize
.Height() );
916 MapUnit
aMapUnit( GetMapUnit( mxLbSizeX
->get_active() ) );
917 if ( aMapUnit
== MapUnit::MapPixel
)
918 { // calculating pixel count via resolution and original graphic size
919 mxMfSizeX
->set_digits( 0 );
920 mxMfSizeY
->set_digits( 0 );
921 mxMfSizeX
->set_value( maSize
.Width
);
922 mxMfSizeY
->set_value( maSize
.Height
);
926 mxMfSizeX
->set_digits( 2 );
927 mxMfSizeY
->set_digits( 2 );
929 switch( GetMapUnit( mxLbSizeX
->get_active() ) )
931 case MapUnit::MapInch
: fRatio
= static_cast< double >( maResolution
.Width
) * 0.0254; break;
932 case MapUnit::MapMM
: fRatio
= static_cast< double >( maResolution
.Width
) * 0.001; break;
933 case MapUnit::MapPoint
:fRatio
= ( static_cast< double >( maResolution
.Width
) * 0.0254 ) / 72.0; break;
935 case MapUnit::MapCM
: fRatio
= static_cast< double >( maResolution
.Width
) * 0.01; break;
937 mxMfSizeX
->set_value( static_cast< sal_Int32
>( ( static_cast< double >( maSize
.Width
* 100 ) / fRatio
) + 0.5 ) );
938 mxMfSizeY
->set_value( static_cast< sal_Int32
>( ( static_cast< double >( maSize
.Height
* 100 ) / fRatio
) + 0.5 ) );
941 sal_Int32 nResolution
= 0;
942 switch( mxLbResolution
->get_active() )
944 case 0 : nResolution
= maResolution
.Width
/ 100; break; // pixels / cm
945 case 2 : nResolution
= maResolution
.Width
; break; // pixels / meter
947 case 1 : nResolution
= static_cast< sal_Int32
>(maResolution
.Width
* 0.0254); break; // pixels / inch
949 mxNfResolution
->set_value( nResolution
);
951 if (mpSbCompression
&& mpSbCompression
->get_visible() && mpNfCompression
)
952 mpSbCompression
->set_value(mpNfCompression
->get_value());
956 // updating estimated size
957 sal_Int64
nRealFileSize( mpTempStream
->Tell() );
958 if ( mbIsPixelFormat
)
960 OUString
aEst( nRealFileSize
? msEstimatedSizePix2
: msEstimatedSizePix1
);
961 sal_Int64
nRawFileSize( GetRawFileSize() );
962 sal_Int32 nInd
= aEst
.indexOf( "%" );
964 aEst
= aEst
.replaceAt( nInd
, 2, ImpValueOfInKB( nRawFileSize
) );
966 if ( nRealFileSize
&& nInd
!= -1 )
968 nInd
= aEst
.indexOf( "%", nInd
);
970 aEst
= aEst
.replaceAt( nInd
, 2, ImpValueOfInKB( nRealFileSize
) );
972 mxFtEstimatedSize
->set_label( aEst
);
976 if ( mnMaxFilesizeForRealtimePreview
)
978 OUString
aEst( msEstimatedSizeVec
);
979 sal_Int32 nInd
= aEst
.indexOf( "%" );
981 aEst
= aEst
.replaceAt( nInd
, 2, ImpValueOfInKB( nRealFileSize
) );
982 mxFtEstimatedSize
->set_label( aEst
);
987 if ( mxRbEPSLevel1
->get_visible() )
989 bool bEnabled
= !mxRbEPSLevel1
->get_active();
990 mxRbEPSColorFormat1
->set_sensitive( bEnabled
);
991 mxRbEPSColorFormat2
->set_sensitive( bEnabled
);
992 mxRbEPSCompressionLZW
->set_sensitive( bEnabled
);
993 mxRbEPSCompressionNone
->set_sensitive( bEnabled
);
997 ExportDialog::~ExportDialog()
1001 /*************************************************************************
1003 |* stores values set in the ini-file
1005 \************************************************************************/
1006 IMPL_LINK_NOARG(ExportDialog
, SelectHdl
, weld::SpinButton
&, void)
1011 IMPL_LINK_NOARG(ExportDialog
, SelectListBoxHdl
, weld::ComboBox
&, void)
1016 IMPL_LINK_NOARG(ExportDialog
, UpdateHdl
, weld::Toggleable
&, void)
1021 IMPL_LINK_NOARG(ExportDialog
, UpdateHdlLossless
, weld::Toggleable
&, void)
1023 mpSbCompression
->set_sensitive(!mxCbLossless
->get_active());
1024 mpNfCompression
->set_sensitive(!mxCbLossless
->get_active());
1028 IMPL_LINK_NOARG(ExportDialog
, UpdateLock
, weld::Toggleable
&, void)
1030 if (mxModifyResolution
->get_active())
1032 mxMfSizeY
->set_sensitive(false);
1033 mxMfSizeX
->set_sensitive(false);
1034 mxNfResolution
->set_sensitive(true);
1038 mxMfSizeY
->set_sensitive(true);
1039 mxMfSizeX
->set_sensitive(true);
1040 mxNfResolution
->set_sensitive(false);
1046 IMPL_LINK_NOARG(ExportDialog
, UpdateHdlMtfSizeX
, weld::SpinButton
&, void)
1048 double fRatio
= static_cast< double >( maOriginalSize
.Height
) / maOriginalSize
.Width
;
1050 if ( mbIsPixelFormat
)
1052 switch( GetMapUnit( mxLbSizeX
->get_active() ) )
1054 case MapUnit::MapInch
: maSize
.Width
= static_cast< sal_Int32
>( static_cast< double >( maResolution
.Width
) * 0.0254 * mxMfSizeX
->get_value() / 100.0 + 0.5 ); break;
1055 case MapUnit::MapCM
: maSize
.Width
= static_cast< sal_Int32
>( static_cast< double >( maResolution
.Width
) * 0.01 * mxMfSizeX
->get_value() / 100.0 + 0.5 ); break;
1056 case MapUnit::MapMM
: maSize
.Width
= static_cast< sal_Int32
>( static_cast< double >( maResolution
.Width
) * 0.001 * mxMfSizeX
->get_value() / 100.0 + 0.5 ); break;
1057 case MapUnit::MapPoint
: maSize
.Width
= static_cast< sal_Int32
>( static_cast< double >( maResolution
.Width
) * 0.0254 * mxMfSizeX
->get_value() / 100.0 * 72 + 0.5 ); break;
1059 case MapUnit::MapPixel
: maSize
.Width
= mxMfSizeX
->get_value(); break;
1061 maSize
.Height
= static_cast< sal_Int32
>( fRatio
* maSize
.Width
+ 0.5 );
1065 Fraction
aFract( 1, 100 );
1066 sal_Int32 nWidth
= mxMfSizeX
->get_value();
1067 sal_Int32 nHeight
= static_cast< sal_Int32
>( nWidth
* fRatio
);
1068 const Size
aSource( nWidth
, nHeight
);
1069 MapMode
aSourceMapMode( GetMapUnit( mxLbSizeX
->get_active() ),Point(), aFract
, aFract
);
1070 Size
aDest(OutputDevice::LogicToLogic(aSource
, aSourceMapMode
, MapMode(MapUnit::Map100thMM
)));
1072 maSize
.Width
= aDest
.Width();
1073 maSize
.Height
= aDest
.Height();
1078 IMPL_LINK_NOARG(ExportDialog
, UpdateHdlMtfSizeY
, weld::SpinButton
&, void)
1080 double fRatio
= static_cast< double >( maOriginalSize
.Width
) / maOriginalSize
.Height
;
1082 if ( mbIsPixelFormat
)
1084 switch( GetMapUnit( mxLbSizeX
->get_active() ) )
1086 case MapUnit::MapInch
: maSize
.Height
= static_cast< sal_Int32
>( static_cast< double >( maResolution
.Height
) * 0.0254 * mxMfSizeY
->get_value() / 100.0 + 0.5 ); break;
1087 case MapUnit::MapCM
: maSize
.Height
= static_cast< sal_Int32
>( static_cast< double >( maResolution
.Height
) * 0.01 * mxMfSizeY
->get_value() / 100.0 + 0.5 ); break;
1088 case MapUnit::MapMM
: maSize
.Height
= static_cast< sal_Int32
>( static_cast< double >( maResolution
.Height
) * 0.001 * mxMfSizeY
->get_value() / 100.0 + 0.5 ); break;
1089 case MapUnit::MapPoint
: maSize
.Height
= static_cast< sal_Int32
>( static_cast< double >( maResolution
.Height
) * 0.0254 * mxMfSizeY
->get_value() / 100.0 * 72 + 0.5 ); break;
1091 case MapUnit::MapPixel
: maSize
.Height
= mxMfSizeY
->get_value(); break;
1093 maSize
.Width
= static_cast< sal_Int32
>( fRatio
* maSize
.Height
+ 0.5 );
1097 Fraction
aFract( 1, 100 );
1098 sal_Int32 nHeight
= mxMfSizeY
->get_value();
1099 sal_Int32 nWidth
= static_cast< sal_Int32
>( nHeight
* fRatio
);
1100 const Size
aSource( nWidth
, nHeight
);
1101 MapMode
aSourceMapMode( GetMapUnit( mxLbSizeX
->get_active() ),Point(), aFract
, aFract
);
1102 Size
aDest( OutputDevice::LogicToLogic(aSource
, aSourceMapMode
, MapMode(MapUnit::Map100thMM
)) );
1104 maSize
.Height
= aDest
.Height();
1105 maSize
.Width
= aDest
.Width();
1110 IMPL_LINK_NOARG(ExportDialog
, UpdateHdlNfResolution
, weld::SpinButton
&, void)
1112 auto nResolution
= mxNfResolution
->get_value();
1113 if ( mxLbResolution
->get_active() == 0 ) // pixels / cm
1115 else if ( mxLbResolution
->get_active() == 1 ) // pixels / inch
1116 nResolution
= static_cast< sal_Int32
>( ( ( static_cast< double >( nResolution
) + 0.5 ) / 0.0254 ) );
1117 maResolution
.Width
= nResolution
;
1118 maResolution
.Height
= nResolution
;
1123 IMPL_LINK_NOARG(ExportDialog
, SbCompressionUpdateHdl
, weld::Scale
&, void)
1125 mpNfCompression
->set_value(mpSbCompression
->get_value());
1129 IMPL_LINK_NOARG(ExportDialog
, OK
, weld::Button
&, void)
1131 // writing config parameter
1133 mrFltCallPara
.aFilterData
= GetFilterData( true );
1134 m_xDialog
->response(RET_OK
);
1137 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */