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 <o3tl/string_view.hxx>
21 #include <vcl/svapp.hxx>
22 #include <vcl/image.hxx>
23 #include <vcl/metaact.hxx>
24 #include <imagerepository.hxx>
25 #include <tools/fract.hxx>
26 #include <unotools/ucbstreamhelper.hxx>
27 #include <vcl/graphic/BitmapHelper.hxx>
28 #include <vcl/graphicfilter.hxx>
29 #include <vcl/stdtext.hxx>
30 #include <vcl/wmfexternal.hxx>
31 #include <vcl/virdev.hxx>
32 #include <com/sun/star/awt/XBitmap.hpp>
33 #include <com/sun/star/graphic/XGraphicProvider2.hpp>
34 #include <com/sun/star/io/XStream.hpp>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <com/sun/star/text/GraphicCrop.hpp>
37 #include <com/sun/star/uno/XComponentContext.hpp>
38 #include <comphelper/fileformat.h>
39 #include <comphelper/servicehelper.hxx>
40 #include <cppuhelper/implbase.hxx>
41 #include <cppuhelper/supportsservice.hxx>
42 #include <sal/log.hxx>
44 #include <graphic/UnoGraphicDescriptor.hxx>
45 #include <graphic/UnoGraphic.hxx>
46 #include <rtl/ref.hxx>
47 #include <vcl/dibtools.hxx>
48 #include <comphelper/sequence.hxx>
50 #include <string_view>
52 #include <vcl/TypeSerializer.hxx>
54 using namespace com::sun::star
;
58 BitmapEx
GetBitmap(const css::uno::Reference
<css::awt::XBitmap
>& xBitmap
)
61 if (auto xGraphic
= xBitmap
.query
<css::graphic::XGraphic
>())
63 Graphic
aGraphic(xGraphic
);
64 aBmp
= aGraphic
.GetBitmapEx();
68 // This is an unknown implementation of a XBitmap interface
70 if (css::uno::Sequence
<sal_Int8
> aBytes
= xBitmap
->getMaskDIB(); aBytes
.hasElements())
72 SvMemoryStream
aMem(aBytes
.getArray(), aBytes
.getLength(), StreamMode::READ
);
73 ReadDIB(aMask
, aMem
, true);
74 aMask
.Invert(); // Convert from transparency to alpha
76 css::uno::Sequence
<sal_Int8
> aBytes
= xBitmap
->getDIB();
77 SvMemoryStream
aMem(aBytes
.getArray(), aBytes
.getLength(), StreamMode::READ
);
81 ReadDIB(aDIB
, aMem
, true);
82 aBmp
= BitmapEx(aDIB
, aMask
);
86 ReadDIBBitmapEx(aBmp
, aMem
, true);
92 css::uno::Reference
<css::graphic::XGraphic
> GetGraphic(const css::uno::Any
& any
)
94 if (auto xRet
= any
.query
<css::graphic::XGraphic
>())
97 if (BitmapEx aBmpEx
= GetBitmap(any
.query
<css::awt::XBitmap
>()); !aBmpEx
.IsEmpty())
99 rtl::Reference
pUnoGraphic(new unographic::Graphic
);
100 pUnoGraphic
->init(aBmpEx
);
110 class GraphicProvider
: public ::cppu::WeakImplHelper
< css::graphic::XGraphicProvider2
,
111 css::lang::XServiceInfo
>
120 virtual OUString SAL_CALL
getImplementationName() override
;
121 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
122 virtual css::uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
125 virtual css::uno::Sequence
< css::uno::Type
> SAL_CALL
getTypes( ) override
;
126 virtual css::uno::Sequence
< sal_Int8
> SAL_CALL
getImplementationId( ) override
;
129 virtual css::uno::Reference
< css::beans::XPropertySet
> SAL_CALL
queryGraphicDescriptor( const css::uno::Sequence
< css::beans::PropertyValue
>& MediaProperties
) override
;
130 virtual css::uno::Reference
< css::graphic::XGraphic
> SAL_CALL
queryGraphic( const css::uno::Sequence
< css::beans::PropertyValue
>& MediaProperties
) override
;
131 virtual void SAL_CALL
storeGraphic( const css::uno::Reference
< css::graphic::XGraphic
>& Graphic
, const css::uno::Sequence
< css::beans::PropertyValue
>& MediaProperties
) override
;
134 uno::Sequence
< uno::Reference
<graphic::XGraphic
> > SAL_CALL
queryGraphics(const uno::Sequence
< uno::Sequence
<beans::PropertyValue
> >& MediaPropertiesSeq
) override
;
138 static css::uno::Reference
< css::graphic::XGraphic
> implLoadMemory( std::u16string_view rResourceURL
);
139 static css::uno::Reference
< css::graphic::XGraphic
> implLoadRepositoryImage( std::u16string_view rResourceURL
);
140 static css::uno::Reference
< css::graphic::XGraphic
> implLoadStandardImage( std::u16string_view rResourceURL
);
143 GraphicProvider::GraphicProvider()
147 OUString SAL_CALL
GraphicProvider::getImplementationName()
149 return u
"com.sun.star.comp.graphic.GraphicProvider"_ustr
;
152 sal_Bool SAL_CALL
GraphicProvider::supportsService( const OUString
& ServiceName
)
154 return cppu::supportsService( this, ServiceName
);
157 uno::Sequence
< OUString
> SAL_CALL
GraphicProvider::getSupportedServiceNames()
159 return { u
"com.sun.star.graphic.GraphicProvider"_ustr
};
162 uno::Sequence
< uno::Type
> SAL_CALL
GraphicProvider::getTypes()
164 static const uno::Sequence
< uno::Type
> aTypes
{
165 cppu::UnoType
<lang::XServiceInfo
>::get(),
166 cppu::UnoType
<lang::XTypeProvider
>::get(),
167 cppu::UnoType
<graphic::XGraphicProvider
>::get()
172 uno::Sequence
< sal_Int8
> SAL_CALL
GraphicProvider::getImplementationId()
174 return css::uno::Sequence
<sal_Int8
>();
177 uno::Reference
< ::graphic::XGraphic
> GraphicProvider::implLoadMemory( std::u16string_view rResourceURL
)
179 uno::Reference
< ::graphic::XGraphic
> xRet
;
180 sal_Int32 nIndex
= 0;
182 if( o3tl::getToken(rResourceURL
, 0, '/', nIndex
) == u
"private:memorygraphic" )
184 sal_Int64 nGraphicAddress
= o3tl::toInt64(o3tl::getToken(rResourceURL
, 0, '/', nIndex
));
186 if( nGraphicAddress
)
188 rtl::Reference
<::unographic::Graphic
> pUnoGraphic
= new ::unographic::Graphic
;
190 pUnoGraphic
->init( *reinterpret_cast< ::Graphic
* >( nGraphicAddress
) );
198 uno::Reference
< ::graphic::XGraphic
> GraphicProvider::implLoadRepositoryImage( std::u16string_view rResourceURL
)
200 uno::Reference
< ::graphic::XGraphic
> xRet
;
202 std::u16string_view sPathName
;
203 if( o3tl::starts_with(rResourceURL
, u
"private:graphicrepository/", &sPathName
) )
206 if ( vcl::ImageRepository::loadImage( OUString(sPathName
), aBitmap
) )
208 Graphic
aGraphic(aBitmap
);
209 aGraphic
.setOriginURL(OUString(rResourceURL
));
210 xRet
= aGraphic
.GetXGraphic();
216 uno::Reference
< ::graphic::XGraphic
> GraphicProvider::implLoadStandardImage( std::u16string_view rResourceURL
)
218 uno::Reference
< ::graphic::XGraphic
> xRet
;
220 std::u16string_view sImageName
;
221 if( o3tl::starts_with(rResourceURL
, u
"private:standardimage/", &sImageName
) )
223 if ( sImageName
== u
"info" )
225 xRet
= Graphic(GetStandardInfoBoxImage().GetBitmapEx()).GetXGraphic();
227 else if ( sImageName
== u
"warning" )
229 xRet
= Graphic(GetStandardWarningBoxImage().GetBitmapEx()).GetXGraphic();
231 else if ( sImageName
== u
"error" )
233 xRet
= Graphic(GetStandardErrorBoxImage().GetBitmapEx()).GetXGraphic();
235 else if ( sImageName
== u
"query" )
237 xRet
= Graphic(GetStandardQueryBoxImage().GetBitmapEx()).GetXGraphic();
244 uno::Reference
< beans::XPropertySet
> SAL_CALL
GraphicProvider::queryGraphicDescriptor( const uno::Sequence
< beans::PropertyValue
>& rMediaProperties
)
247 uno::Reference
< io::XInputStream
> xIStm
;
250 for( const auto& rMediaProperty
: rMediaProperties
)
252 const OUString
aName( rMediaProperty
.Name
);
253 const uno::Any
aValue( rMediaProperty
.Value
);
259 else if (aName
== "InputStream")
263 else if (aName
== "Bitmap")
271 uno::Reference
<beans::XPropertySet
> xRet
;
274 rtl::Reference
<unographic::GraphicDescriptor
> pDescriptor
= new unographic::GraphicDescriptor
;
275 pDescriptor
->init( xIStm
, aURL
);
278 else if( !aURL
.isEmpty() )
280 uno::Reference
< ::graphic::XGraphic
> xGraphic( implLoadMemory( aURL
) );
282 if ( !xGraphic
.is() )
283 xGraphic
= implLoadRepositoryImage( aURL
);
285 if ( !xGraphic
.is() )
286 xGraphic
= implLoadStandardImage( aURL
);
290 xRet
.set( xGraphic
, uno::UNO_QUERY
);
294 rtl::Reference
<unographic::GraphicDescriptor
> pDescriptor
= new unographic::GraphicDescriptor
;
295 pDescriptor
->init( aURL
);
299 else if (aBtm
.hasValue())
301 xRet
.set(vcl::GetGraphic(aBtm
), uno::UNO_QUERY
);
308 uno::Reference
< ::graphic::XGraphic
> SAL_CALL
GraphicProvider::queryGraphic( const uno::Sequence
< ::beans::PropertyValue
>& rMediaProperties
)
312 uno::Reference
< io::XInputStream
> xIStm
;
315 uno::Sequence
< ::beans::PropertyValue
> aFilterData
;
317 bool bLazyRead
= false;
318 bool bLoadAsLink
= false;
320 for (const auto& rMediaProperty
: rMediaProperties
)
322 const OUString
aName( rMediaProperty
.Name
);
323 const uno::Any
aValue( rMediaProperty
.Value
);
329 else if (aName
== "InputStream")
333 else if (aName
== "Bitmap")
337 else if (aName
== "FilterData")
339 aValue
>>= aFilterData
;
341 else if (aName
== "LazyRead")
343 aValue
>>= bLazyRead
;
345 else if (aName
== "LoadAsLink")
347 aValue
>>= bLoadAsLink
;
351 // Check for the goal width and height if they are defined
352 sal_uInt16 nExtWidth
= 0;
353 sal_uInt16 nExtHeight
= 0;
354 sal_uInt16 nExtMapMode
= 0;
355 for (const auto& rProp
: aFilterData
)
357 const OUString
aName( rProp
.Name
);
358 const uno::Any
aValue( rProp
.Value
);
360 if (aName
== "ExternalWidth")
362 aValue
>>= nExtWidth
;
364 else if (aName
== "ExternalHeight")
366 aValue
>>= nExtHeight
;
368 else if (aName
== "ExternalMapMode")
370 aValue
>>= nExtMapMode
;
376 uno::Reference
<::graphic::XGraphic
> xRet
;
377 std::unique_ptr
<SvStream
> pIStm
;
381 pIStm
= ::utl::UcbStreamHelper::CreateStream( xIStm
);
383 else if( !aPath
.isEmpty() )
385 xRet
= implLoadMemory( aPath
);
388 xRet
= implLoadRepositoryImage( aPath
);
391 xRet
= implLoadStandardImage( aPath
);
394 pIStm
= ::utl::UcbStreamHelper::CreateStream( aPath
, StreamMode::READ
);
396 else if (aBtm
.hasValue())
398 xRet
= vcl::GetGraphic(aBtm
);
403 ::GraphicFilter
& rFilter
= ::GraphicFilter::GetGraphicFilter();
408 // Define APM Header if goal height and width are defined
409 WmfExternal aExtHeader
;
410 aExtHeader
.xExt
= nExtWidth
;
411 aExtHeader
.yExt
= nExtHeight
;
412 aExtHeader
.mapMode
= nExtMapMode
;
413 if ( nExtMapMode
> 0 )
418 ErrCode error
= ERRCODE_NONE
;
421 Graphic aGraphic
= rFilter
.ImportUnloadedGraphic(*pIStm
);
422 if (!aGraphic
.IsNone())
423 aVCLGraphic
= std::move(aGraphic
);
425 if (aVCLGraphic
.IsNone())
426 error
= rFilter
.ImportGraphic(aVCLGraphic
, aPath
, *pIStm
, GRFILTER_FORMAT_DONTKNOW
, nullptr, GraphicFilterImportFlags::NONE
);
428 if( (error
== ERRCODE_NONE
) &&
429 ( aVCLGraphic
.GetType() != GraphicType::NONE
) )
431 if (!aPath
.isEmpty() && bLoadAsLink
)
432 aVCLGraphic
.setOriginURL(aPath
);
434 rtl::Reference
<::unographic::Graphic
> pUnoGraphic
= new ::unographic::Graphic
;
436 pUnoGraphic
->init( aVCLGraphic
);
440 SAL_WARN("svtools", "Could not create graphic for:" << aPath
<< " error: " << error
);
448 uno::Sequence
< uno::Reference
<graphic::XGraphic
> > SAL_CALL
GraphicProvider::queryGraphics(const uno::Sequence
< uno::Sequence
<beans::PropertyValue
> >& rMediaPropertiesSeq
)
450 // Turn properties into streams.
451 std::vector
< std::unique_ptr
<SvStream
> > aStreams
;
452 for (const auto& rMediaProperties
: rMediaPropertiesSeq
)
454 std::unique_ptr
<SvStream
> pStream
;
455 uno::Reference
<io::XInputStream
> xStream
;
457 auto pProp
= std::find_if(rMediaProperties
.begin(), rMediaProperties
.end(),
458 [](const beans::PropertyValue
& rProp
) { return rProp
.Name
== "InputStream"; });
459 if (pProp
!= rMediaProperties
.end())
461 pProp
->Value
>>= xStream
;
463 pStream
= utl::UcbStreamHelper::CreateStream(xStream
);
466 aStreams
.push_back(std::move(pStream
));
469 // Import: streams to graphics.
470 std::vector
< std::shared_ptr
<Graphic
> > aGraphics
;
471 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
472 rFilter
.ImportGraphics(aGraphics
, std::move(aStreams
));
474 // Returning: graphics to UNO objects.
475 std::vector
< uno::Reference
<graphic::XGraphic
> > aRet
;
476 for (const auto& pGraphic
: aGraphics
)
478 uno::Reference
<graphic::XGraphic
> xGraphic
;
482 rtl::Reference
<unographic::Graphic
> pUnoGraphic
= new unographic::Graphic();
483 pUnoGraphic
->init(*pGraphic
);
484 xGraphic
= pUnoGraphic
;
487 aRet
.push_back(xGraphic
);
490 return comphelper::containerToSequence(aRet
);
493 void ImplCalculateCropRect( ::Graphic
const & rGraphic
, const text::GraphicCrop
& rGraphicCropLogic
, tools::Rectangle
& rGraphicCropPixel
)
495 if ( !(rGraphicCropLogic
.Left
|| rGraphicCropLogic
.Top
|| rGraphicCropLogic
.Right
|| rGraphicCropLogic
.Bottom
) )
498 Size
aSourceSizePixel( rGraphic
.GetSizePixel() );
499 if ( !(aSourceSizePixel
.Width() && aSourceSizePixel
.Height()) )
502 if ( !(rGraphicCropLogic
.Left
|| rGraphicCropLogic
.Top
|| rGraphicCropLogic
.Right
|| rGraphicCropLogic
.Bottom
) )
505 Size
aSize100thMM( 0, 0 );
506 if( rGraphic
.GetPrefMapMode().GetMapUnit() != MapUnit::MapPixel
)
508 aSize100thMM
= OutputDevice::LogicToLogic(rGraphic
.GetPrefSize(), rGraphic
.GetPrefMapMode(), MapMode(MapUnit::Map100thMM
));
512 aSize100thMM
= Application::GetDefaultDevice()->PixelToLogic(rGraphic
.GetPrefSize(), MapMode(MapUnit::Map100thMM
));
514 if ( aSize100thMM
.Width() && aSize100thMM
.Height() )
516 double fSourceSizePixelWidth
= static_cast<double>(aSourceSizePixel
.Width());
517 double fSourceSizePixelHeight
= static_cast<double>(aSourceSizePixel
.Height());
518 rGraphicCropPixel
.SetLeft( static_cast< sal_Int32
>((fSourceSizePixelWidth
* rGraphicCropLogic
.Left
) / aSize100thMM
.Width()) );
519 rGraphicCropPixel
.SetTop( static_cast< sal_Int32
>((fSourceSizePixelHeight
* rGraphicCropLogic
.Top
) / aSize100thMM
.Height()) );
520 rGraphicCropPixel
.SetRight( static_cast< sal_Int32
>(( fSourceSizePixelWidth
* ( aSize100thMM
.Width() - rGraphicCropLogic
.Right
) ) / aSize100thMM
.Width() ) );
521 rGraphicCropPixel
.SetBottom( static_cast< sal_Int32
>(( fSourceSizePixelHeight
* ( aSize100thMM
.Height() - rGraphicCropLogic
.Bottom
) ) / aSize100thMM
.Height() ) );
525 void ImplApplyBitmapScaling( ::Graphic
& rGraphic
, sal_Int32 nPixelWidth
, sal_Int32 nPixelHeight
)
527 if ( nPixelWidth
&& nPixelHeight
)
529 BitmapEx
aBmpEx( rGraphic
.GetBitmapEx() );
530 MapMode
aPrefMapMode( aBmpEx
.GetPrefMapMode() );
531 Size
aPrefSize( aBmpEx
.GetPrefSize() );
532 aBmpEx
.Scale( Size( nPixelWidth
, nPixelHeight
) );
533 aBmpEx
.SetPrefMapMode( aPrefMapMode
);
534 aBmpEx
.SetPrefSize( aPrefSize
);
539 void ImplApplyBitmapResolution( ::Graphic
& rGraphic
, sal_Int32 nImageResolution
, const Size
& rVisiblePixelSize
, const awt::Size
& rLogicalSize
)
541 if ( !(nImageResolution
&& rLogicalSize
.Width
&& rLogicalSize
.Height
) )
544 const double fImageResolution
= static_cast<double>( nImageResolution
);
545 const double fSourceDPIX
= ( static_cast<double>(rVisiblePixelSize
.Width()) * 2540.0 ) / static_cast<double>(rLogicalSize
.Width
);
546 const double fSourceDPIY
= ( static_cast<double>(rVisiblePixelSize
.Height()) * 2540.0 ) / static_cast<double>(rLogicalSize
.Height
);
547 const sal_Int32
nSourcePixelWidth( rGraphic
.GetSizePixel().Width() );
548 const sal_Int32
nSourcePixelHeight( rGraphic
.GetSizePixel().Height() );
549 const double fSourcePixelWidth
= static_cast<double>( nSourcePixelWidth
);
550 const double fSourcePixelHeight
= static_cast<double>( nSourcePixelHeight
);
552 sal_Int32 nDestPixelWidth
= nSourcePixelWidth
;
553 sal_Int32 nDestPixelHeight
= nSourcePixelHeight
;
555 // check, if the bitmap DPI exceeds the maximum DPI
556 if( fSourceDPIX
> fImageResolution
)
558 nDestPixelWidth
= static_cast<sal_Int32
>(( fSourcePixelWidth
* fImageResolution
) / fSourceDPIX
);
559 if ( !nDestPixelWidth
|| ( nDestPixelWidth
> nSourcePixelWidth
) )
560 nDestPixelWidth
= nSourcePixelWidth
;
562 if ( fSourceDPIY
> fImageResolution
)
564 nDestPixelHeight
= static_cast<sal_Int32
>(( fSourcePixelHeight
* fImageResolution
) / fSourceDPIY
);
565 if ( !nDestPixelHeight
|| ( nDestPixelHeight
> nSourcePixelHeight
) )
566 nDestPixelHeight
= nSourcePixelHeight
;
568 if ( ( nDestPixelWidth
!= nSourcePixelWidth
) || ( nDestPixelHeight
!= nSourcePixelHeight
) )
569 ImplApplyBitmapScaling( rGraphic
, nDestPixelWidth
, nDestPixelHeight
);
572 void ImplApplyFilterData( ::Graphic
& rGraphic
, const uno::Sequence
< beans::PropertyValue
>& rFilterData
)
574 /* this method applies following attributes to the graphic, in the first step the
575 cropping area (logical size in 100thmm) is applied, in the second step the resolution
576 is applied, in the third step the graphic is scaled to the corresponding pixelsize.
577 if a parameter value is zero or not available the corresponding step will be skipped */
579 sal_Int32 nPixelWidth
= 0;
580 sal_Int32 nPixelHeight
= 0;
581 sal_Int32 nImageResolution
= 0;
582 awt::Size
aLogicalSize( 0, 0 );
583 text::GraphicCrop
aCropLogic( 0, 0, 0, 0 );
584 bool bRemoveCropArea
= true;
586 for( const auto& rProp
: rFilterData
)
588 const OUString
aName( rProp
.Name
);
589 const uno::Any
aValue( rProp
.Value
);
591 if (aName
== "PixelWidth")
592 aValue
>>= nPixelWidth
;
593 else if (aName
== "PixelHeight")
594 aValue
>>= nPixelHeight
;
595 else if (aName
== "LogicalSize")
596 aValue
>>= aLogicalSize
;
597 else if (aName
== "GraphicCropLogic")
598 aValue
>>= aCropLogic
;
599 else if (aName
== "RemoveCropArea")
600 aValue
>>= bRemoveCropArea
;
601 else if (aName
== "ImageResolution")
602 aValue
>>= nImageResolution
;
604 if ( rGraphic
.GetType() == GraphicType::Bitmap
)
606 if(rGraphic
.getVectorGraphicData())
608 // embedded Vector Graphic Data, no need to scale. Also no method to apply crop data currently
612 tools::Rectangle
aCropPixel( Point( 0, 0 ), rGraphic
.GetSizePixel() );
613 ImplCalculateCropRect( rGraphic
, aCropLogic
, aCropPixel
);
614 if ( bRemoveCropArea
)
616 BitmapEx
aBmpEx( rGraphic
.GetBitmapEx() );
617 aBmpEx
.Crop( aCropPixel
);
620 Size
aVisiblePixelSize( bRemoveCropArea
? rGraphic
.GetSizePixel() : aCropPixel
.GetSize() );
621 ImplApplyBitmapResolution( rGraphic
, nImageResolution
, aVisiblePixelSize
, aLogicalSize
);
622 ImplApplyBitmapScaling( rGraphic
, nPixelWidth
, nPixelHeight
);
625 else if ( ( rGraphic
.GetType() == GraphicType::GdiMetafile
) && nImageResolution
)
627 ScopedVclPtrInstance
< VirtualDevice
> aDummyVDev
;
628 GDIMetaFile
aMtf( rGraphic
.GetGDIMetaFile() );
629 Size
aMtfSize( OutputDevice::LogicToLogic(aMtf
.GetPrefSize(), aMtf
.GetPrefMapMode(), MapMode(MapUnit::Map100thMM
)) );
630 if ( aMtfSize
.Width() && aMtfSize
.Height() )
632 MapMode
aNewMapMode( MapUnit::Map100thMM
);
633 aNewMapMode
.SetScaleX( Fraction( aLogicalSize
.Width
, aMtfSize
.Width() ) );
634 aNewMapMode
.SetScaleY( Fraction( aLogicalSize
.Height
, aMtfSize
.Height() ) );
635 aDummyVDev
->EnableOutput( false );
636 aDummyVDev
->SetMapMode( aNewMapMode
);
638 for( size_t i
= 0, nObjCount
= aMtf
.GetActionSize(); i
< nObjCount
; i
++ )
640 MetaAction
* pAction
= aMtf
.GetAction( i
);
641 switch( pAction
->GetType() )
643 // only optimizing common bitmap actions:
644 case MetaActionType::MAPMODE
:
646 pAction
->Execute( aDummyVDev
.get() );
649 case MetaActionType::PUSH
:
651 const MetaPushAction
* pA
= static_cast<const MetaPushAction
*>(pAction
);
652 aDummyVDev
->Push( pA
->GetFlags() );
655 case MetaActionType::POP
:
660 case MetaActionType::BMPSCALE
:
661 case MetaActionType::BMPEXSCALE
:
666 if ( pAction
->GetType() == MetaActionType::BMPSCALE
)
668 MetaBmpScaleAction
* pScaleAction
= dynamic_cast< MetaBmpScaleAction
* >( pAction
);
669 assert(pScaleAction
);
670 aBmpEx
= pScaleAction
->GetBitmap();
671 aPos
= pScaleAction
->GetPoint();
672 aSize
= pScaleAction
->GetSize();
676 MetaBmpExScaleAction
* pScaleAction
= dynamic_cast< MetaBmpExScaleAction
* >( pAction
);
677 assert(pScaleAction
);
678 aBmpEx
= pScaleAction
->GetBitmapEx();
679 aPos
= pScaleAction
->GetPoint();
680 aSize
= pScaleAction
->GetSize();
682 ::Graphic
aGraphic( aBmpEx
);
683 const Size
aSize100thmm( aDummyVDev
->LogicToPixel( aSize
) );
684 Size
aSize100thmm2( aDummyVDev
->PixelToLogic(aSize100thmm
, MapMode(MapUnit::Map100thMM
)) );
686 ImplApplyBitmapResolution( aGraphic
, nImageResolution
,
687 aGraphic
.GetSizePixel(), awt::Size( aSize100thmm2
.Width(), aSize100thmm2
.Height() ) );
689 rtl::Reference
<MetaAction
> pNewAction
= new MetaBmpExScaleAction( aPos
, aSize
, aGraphic
.GetBitmapEx() );
690 aMtf
.ReplaceAction( pNewAction
, i
);
694 case MetaActionType::BMP
:
695 case MetaActionType::BMPSCALEPART
:
696 case MetaActionType::BMPEX
:
697 case MetaActionType::BMPEXSCALEPART
:
698 case MetaActionType::MASK
:
699 case MetaActionType::MASKSCALE
:
709 void SAL_CALL
GraphicProvider::storeGraphic( const uno::Reference
< ::graphic::XGraphic
>& rxGraphic
, const uno::Sequence
< beans::PropertyValue
>& rMediaProperties
)
711 std::unique_ptr
<SvStream
> pOStm
;
714 for( const auto& rMediaProperty
: rMediaProperties
)
716 const OUString
aName( rMediaProperty
.Name
);
717 const uno::Any
aValue( rMediaProperty
.Value
);
724 pOStm
= ::utl::UcbStreamHelper::CreateStream( aURL
, StreamMode::WRITE
| StreamMode::TRUNC
);
727 else if (aName
== "OutputStream")
729 uno::Reference
< io::XStream
> xOStm
;
734 pOStm
= ::utl::UcbStreamHelper::CreateStream( xOStm
);
744 uno::Sequence
< beans::PropertyValue
> aFilterDataSeq
;
745 OUString sFilterShortName
;
747 for( const auto& rMediaProperty
: rMediaProperties
)
749 const OUString
aName( rMediaProperty
.Name
);
750 const uno::Any
aValue( rMediaProperty
.Value
);
752 if (aName
== "FilterData")
754 aValue
>>= aFilterDataSeq
;
756 else if (aName
== "MimeType")
760 aValue
>>= aMimeType
;
762 if (aMimeType
== MIMETYPE_BMP
)
763 sFilterShortName
= "bmp";
764 else if (aMimeType
== MIMETYPE_EPS
)
765 sFilterShortName
= "eps";
766 else if (aMimeType
== MIMETYPE_GIF
)
767 sFilterShortName
= "gif";
768 else if (aMimeType
== MIMETYPE_JPG
)
769 sFilterShortName
= "jpg";
770 else if (aMimeType
== MIMETYPE_MET
)
771 sFilterShortName
= "met";
772 else if (aMimeType
== MIMETYPE_PNG
)
773 sFilterShortName
= "png";
774 else if (aMimeType
== MIMETYPE_PCT
)
775 sFilterShortName
= "pct";
776 else if (aMimeType
== MIMETYPE_PBM
)
777 sFilterShortName
= "pbm";
778 else if (aMimeType
== MIMETYPE_PGM
)
779 sFilterShortName
= "pgm";
780 else if (aMimeType
== MIMETYPE_PPM
)
781 sFilterShortName
= "ppm";
782 else if (aMimeType
== MIMETYPE_RAS
)
783 sFilterShortName
= "ras";
784 else if (aMimeType
== MIMETYPE_SVM
)
785 sFilterShortName
= "svm";
786 else if (aMimeType
== MIMETYPE_TIF
)
787 sFilterShortName
= "tif";
788 else if (aMimeType
== MIMETYPE_EMF
)
789 sFilterShortName
= "emf";
790 else if (aMimeType
== MIMETYPE_WMF
)
791 sFilterShortName
= "wmf";
792 else if (aMimeType
== MIMETYPE_XPM
)
793 sFilterShortName
= "xpm";
794 else if (aMimeType
== MIMETYPE_SVG
)
795 sFilterShortName
= "svg";
796 else if (aMimeType
== MIMETYPE_VCLGRAPHIC
)
797 sFilterShortName
= MIMETYPE_VCLGRAPHIC
;
801 if( sFilterShortName
.isEmpty() )
804 ::GraphicFilter
& rFilter
= ::GraphicFilter::GetGraphicFilter();
807 const uno::Reference
< XInterface
> xIFace( rxGraphic
, uno::UNO_QUERY
);
808 const ::unographic::Graphic
* pUnoGraphic
= dynamic_cast<::unographic::Graphic
*>(xIFace
.get());
809 const ::Graphic
* pGraphic
= pUnoGraphic
? &pUnoGraphic
->GetGraphic() : nullptr;
811 if( pGraphic
&& ( pGraphic
->GetType() != GraphicType::NONE
) )
813 ::Graphic
aGraphic( *pGraphic
);
814 ImplApplyFilterData( aGraphic
, aFilterDataSeq
);
816 /* sj: using a temporary memory stream, because some graphic filters are seeking behind
817 stream end (which leads to an invalid argument exception then). */
818 SvMemoryStream aMemStrm
;
819 aMemStrm
.SetVersion( SOFFICE_FILEFORMAT_CURRENT
);
820 if( sFilterShortName
== MIMETYPE_VCLGRAPHIC
)
822 TypeSerializer
aSerializer(aMemStrm
);
823 aSerializer
.writeGraphic(aGraphic
);
827 rFilter
.ExportGraphic( aGraphic
, aPath
, aMemStrm
,
828 rFilter
.GetExportFormatNumberForShortName( sFilterShortName
),
829 ( aFilterDataSeq
.hasElements() ? &aFilterDataSeq
: nullptr ) );
831 pOStm
->WriteBytes( aMemStrm
.GetData(), aMemStrm
.TellEnd() );
838 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
839 com_sun_star_comp_graphic_GraphicProvider_get_implementation(
840 css::uno::XComponentContext
*,
841 css::uno::Sequence
<css::uno::Any
> const &)
843 return cppu::acquire(new GraphicProvider
);
846 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */