sw a11y: clang-format SidebarWinAccessible code
[LibreOffice.git] / vcl / source / graphic / UnoGraphicProvider.cxx
blob84abd74f291b3c7c382b6fedd95459207aab7de9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
49 #include <memory>
50 #include <string_view>
52 #include <vcl/TypeSerializer.hxx>
54 using namespace com::sun::star;
56 namespace vcl
58 BitmapEx GetBitmap(const css::uno::Reference<css::awt::XBitmap>& xBitmap)
60 BitmapEx aBmp;
61 if (auto xGraphic = xBitmap.query<css::graphic::XGraphic>())
63 Graphic aGraphic(xGraphic);
64 aBmp = aGraphic.GetBitmapEx();
66 else if (xBitmap)
68 // This is an unknown implementation of a XBitmap interface
69 Bitmap aMask;
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);
78 if (!aMask.IsEmpty())
80 Bitmap aDIB;
81 ReadDIB(aDIB, aMem, true);
82 aBmp = BitmapEx(aDIB, aMask);
84 else
86 ReadDIBBitmapEx(aBmp, aMem, true);
89 return aBmp;
92 css::uno::Reference<css::graphic::XGraphic> GetGraphic(const css::uno::Any& any)
94 if (auto xRet = any.query<css::graphic::XGraphic>())
95 return xRet;
97 if (BitmapEx aBmpEx = GetBitmap(any.query<css::awt::XBitmap>()); !aBmpEx.IsEmpty())
99 rtl::Reference pUnoGraphic(new unographic::Graphic);
100 pUnoGraphic->init(aBmpEx);
101 return pUnoGraphic;
104 return {};
108 namespace {
110 class GraphicProvider : public ::cppu::WeakImplHelper< css::graphic::XGraphicProvider2,
111 css::lang::XServiceInfo >
113 public:
115 GraphicProvider();
117 protected:
119 // 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;
124 // XTypeProvider
125 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
126 virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
128 // XGraphicProvider
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;
133 // XGraphicProvider2
134 uno::Sequence< uno::Reference<graphic::XGraphic> > SAL_CALL queryGraphics(const uno::Sequence< uno::Sequence<beans::PropertyValue> >& MediaPropertiesSeq ) override;
136 private:
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()
169 return aTypes;
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 ) );
191 xRet = pUnoGraphic;
195 return xRet;
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) )
205 BitmapEx aBitmap;
206 if ( vcl::ImageRepository::loadImage( OUString(sPathName), aBitmap ) )
208 Graphic aGraphic(aBitmap);
209 aGraphic.setOriginURL(OUString(rResourceURL));
210 xRet = aGraphic.GetXGraphic();
213 return xRet;
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();
240 return xRet;
244 uno::Reference< beans::XPropertySet > SAL_CALL GraphicProvider::queryGraphicDescriptor( const uno::Sequence< beans::PropertyValue >& rMediaProperties )
246 OUString aURL;
247 uno::Reference< io::XInputStream > xIStm;
248 uno::Any aBtm;
250 for( const auto& rMediaProperty : rMediaProperties )
252 const OUString aName( rMediaProperty.Name );
253 const uno::Any aValue( rMediaProperty.Value );
255 if (aName == "URL")
257 aValue >>= aURL;
259 else if (aName == "InputStream")
261 aValue >>= xIStm;
263 else if (aName == "Bitmap")
265 aBtm = aValue;
269 SolarMutexGuard g;
271 uno::Reference<beans::XPropertySet> xRet;
272 if( xIStm.is() )
274 rtl::Reference<unographic::GraphicDescriptor> pDescriptor = new unographic::GraphicDescriptor;
275 pDescriptor->init( xIStm, aURL );
276 xRet = pDescriptor;
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 );
288 if( xGraphic.is() )
290 xRet.set( xGraphic, uno::UNO_QUERY );
292 else
294 rtl::Reference<unographic::GraphicDescriptor> pDescriptor = new unographic::GraphicDescriptor;
295 pDescriptor->init( aURL );
296 xRet = pDescriptor;
299 else if (aBtm.hasValue())
301 xRet.set(vcl::GetGraphic(aBtm), uno::UNO_QUERY);
304 return xRet;
308 uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( const uno::Sequence< ::beans::PropertyValue >& rMediaProperties )
310 OUString aPath;
312 uno::Reference< io::XInputStream > xIStm;
313 uno::Any aBtm;
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 );
325 if (aName == "URL")
327 aValue >>= aPath;
329 else if (aName == "InputStream")
331 aValue >>= xIStm;
333 else if (aName == "Bitmap")
335 aBtm = aValue;
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;
374 SolarMutexGuard g;
376 uno::Reference<::graphic::XGraphic> xRet;
377 std::unique_ptr<SvStream> pIStm;
379 if( xIStm.is() )
381 pIStm = ::utl::UcbStreamHelper::CreateStream( xIStm );
383 else if( !aPath.isEmpty() )
385 xRet = implLoadMemory( aPath );
387 if ( !xRet.is() )
388 xRet = implLoadRepositoryImage( aPath );
390 if ( !xRet.is() )
391 xRet = implLoadStandardImage( aPath );
393 if( !xRet.is() )
394 pIStm = ::utl::UcbStreamHelper::CreateStream( aPath, StreamMode::READ );
396 else if (aBtm.hasValue())
398 xRet = vcl::GetGraphic(aBtm);
401 if( pIStm )
403 ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
406 Graphic aVCLGraphic;
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 )
415 bLazyRead = false;
418 ErrCode error = ERRCODE_NONE;
419 if (bLazyRead)
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 );
437 xRet = pUnoGraphic;
439 else{
440 SAL_WARN("svtools", "Could not create graphic for:" << aPath << " error: " << error);
445 return xRet;
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;
462 if (xStream.is())
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;
480 if (pGraphic)
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) )
496 return;
498 Size aSourceSizePixel( rGraphic.GetSizePixel() );
499 if ( !(aSourceSizePixel.Width() && aSourceSizePixel.Height()) )
500 return;
502 if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) )
503 return;
505 Size aSize100thMM( 0, 0 );
506 if( rGraphic.GetPrefMapMode().GetMapUnit() != MapUnit::MapPixel )
508 aSize100thMM = OutputDevice::LogicToLogic(rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM));
510 else
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 );
535 rGraphic = aBmpEx;
539 void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize )
541 if ( !(nImageResolution && rLogicalSize.Width && rLogicalSize.Height) )
542 return;
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
610 else
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 );
618 rGraphic = aBmpEx;
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() );
647 break;
649 case MetaActionType::PUSH:
651 const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
652 aDummyVDev->Push( pA->GetFlags() );
653 break;
655 case MetaActionType::POP:
657 aDummyVDev->Pop();
658 break;
660 case MetaActionType::BMPSCALE:
661 case MetaActionType::BMPEXSCALE:
663 BitmapEx aBmpEx;
664 Point aPos;
665 Size aSize;
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();
674 else
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 );
691 break;
693 default:
694 case MetaActionType::BMP:
695 case MetaActionType::BMPSCALEPART:
696 case MetaActionType::BMPEX:
697 case MetaActionType::BMPEXSCALEPART:
698 case MetaActionType::MASK:
699 case MetaActionType::MASKSCALE:
700 break;
703 rGraphic = aMtf;
709 void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties )
711 std::unique_ptr<SvStream> pOStm;
712 OUString aPath;
714 for( const auto& rMediaProperty : rMediaProperties )
716 const OUString aName( rMediaProperty.Name );
717 const uno::Any aValue( rMediaProperty.Value );
719 if (aName == "URL")
721 OUString aURL;
723 aValue >>= aURL;
724 pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, StreamMode::WRITE | StreamMode::TRUNC );
725 aPath = aURL;
727 else if (aName == "OutputStream")
729 uno::Reference< io::XStream > xOStm;
731 aValue >>= xOStm;
733 if( xOStm.is() )
734 pOStm = ::utl::UcbStreamHelper::CreateStream( xOStm );
737 if( pOStm )
738 break;
741 if( !pOStm )
742 return;
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")
758 OUString aMimeType;
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() )
802 return;
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);
825 else
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: */