loplugin:sequenceloop in unoxml..vcl
[LibreOffice.git] / vcl / source / graphic / UnoGraphicProvider.cxx
blobc5919770402c8d7d7884ec1f6c12fcedba218ea8
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 <vcl/svapp.hxx>
21 #include <vcl/image.hxx>
22 #include <vcl/metaact.hxx>
23 #include <vcl/msgbox.hxx>
24 #include <vcl/imagerepository.hxx>
25 #include <tools/fract.hxx>
26 #include <unotools/ucbstreamhelper.hxx>
27 #include <vcl/graphicfilter.hxx>
28 #include <vcl/wmfexternal.hxx>
29 #include <vcl/virdev.hxx>
30 #include <com/sun/star/awt/XBitmap.hpp>
31 #include <com/sun/star/graphic/XGraphicProvider2.hpp>
32 #include <com/sun/star/io/XStream.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/text/GraphicCrop.hpp>
35 #include <com/sun/star/uno/XComponentContext.hpp>
36 #include <comphelper/fileformat.h>
37 #include <comphelper/servicehelper.hxx>
38 #include <cppuhelper/implbase.hxx>
39 #include <cppuhelper/supportsservice.hxx>
40 #include <sal/log.hxx>
42 #include <graphic/UnoGraphicDescriptor.hxx>
43 #include <graphic/UnoGraphic.hxx>
44 #include <rtl/ref.hxx>
45 #include <vcl/dibtools.hxx>
46 #include <comphelper/sequence.hxx>
47 #include <memory>
49 using namespace com::sun::star;
51 namespace {
53 class GraphicProvider : public ::cppu::WeakImplHelper< css::graphic::XGraphicProvider2,
54 css::lang::XServiceInfo >
56 public:
58 GraphicProvider();
60 protected:
62 // XServiceInfo
63 virtual OUString SAL_CALL getImplementationName() override;
64 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
65 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
67 // XTypeProvider
68 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
69 virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
71 // XGraphicProvider
72 virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL queryGraphicDescriptor( const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override;
73 virtual css::uno::Reference< css::graphic::XGraphic > SAL_CALL queryGraphic( const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override;
74 virtual void SAL_CALL storeGraphic( const css::uno::Reference< css::graphic::XGraphic >& Graphic, const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override;
76 // XGraphicProvider2
77 uno::Sequence< uno::Reference<graphic::XGraphic> > SAL_CALL queryGraphics(const uno::Sequence< uno::Sequence<beans::PropertyValue> >& MediaPropertiesSeq ) override;
79 private:
81 static css::uno::Reference< css::graphic::XGraphic > implLoadMemory( const OUString& rResourceURL );
82 static css::uno::Reference< css::graphic::XGraphic > implLoadRepositoryImage( const OUString& rResourceURL );
83 static css::uno::Reference< css::graphic::XGraphic > implLoadBitmap( const css::uno::Reference< css::awt::XBitmap >& rBitmap );
84 static css::uno::Reference< css::graphic::XGraphic > implLoadStandardImage( const OUString& rResourceURL );
87 GraphicProvider::GraphicProvider()
91 OUString SAL_CALL GraphicProvider::getImplementationName()
93 return "com.sun.star.comp.graphic.GraphicProvider";
96 sal_Bool SAL_CALL GraphicProvider::supportsService( const OUString& ServiceName )
98 return cppu::supportsService( this, ServiceName );
101 uno::Sequence< OUString > SAL_CALL GraphicProvider::getSupportedServiceNames()
103 uno::Sequence<OUString> aSeq { "com.sun.star.graphic.GraphicProvider" };
104 return aSeq;
107 uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes()
109 static const uno::Sequence< uno::Type > aTypes {
110 cppu::UnoType<lang::XServiceInfo>::get(),
111 cppu::UnoType<lang::XTypeProvider>::get(),
112 cppu::UnoType<graphic::XGraphicProvider>::get()
114 return aTypes;
117 uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId()
119 return css::uno::Sequence<sal_Int8>();
122 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( const OUString& rResourceURL )
124 uno::Reference< ::graphic::XGraphic > xRet;
125 sal_Int32 nIndex = 0;
127 if( rResourceURL.getToken( 0, '/', nIndex ) == "private:memorygraphic" )
129 sal_Int64 nGraphicAddress = rResourceURL.getToken( 0, '/', nIndex ).toInt64();
131 if( nGraphicAddress )
133 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
135 pUnoGraphic->init( *reinterpret_cast< ::Graphic* >( nGraphicAddress ) );
136 xRet = pUnoGraphic;
140 return xRet;
144 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( const OUString& rResourceURL )
146 uno::Reference< ::graphic::XGraphic > xRet;
148 OUString sPathName;
149 if( rResourceURL.startsWith("private:graphicrepository/", &sPathName) )
151 BitmapEx aBitmap;
152 if ( vcl::ImageRepository::loadImage( sPathName, aBitmap ) )
154 xRet = Graphic(aBitmap).GetXGraphic();
157 return xRet;
161 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadStandardImage( const OUString& rResourceURL )
163 uno::Reference< ::graphic::XGraphic > xRet;
165 OUString sImageName;
166 if( rResourceURL.startsWith("private:standardimage/", &sImageName) )
168 if ( sImageName == "info" )
170 xRet = Graphic(GetStandardInfoBoxImage().GetBitmapEx()).GetXGraphic();
172 else if ( sImageName == "warning" )
174 xRet = Graphic(GetStandardWarningBoxImage().GetBitmapEx()).GetXGraphic();
176 else if ( sImageName == "error" )
178 xRet = Graphic(GetStandardErrorBoxImage().GetBitmapEx()).GetXGraphic();
180 else if ( sImageName == "query" )
182 xRet = Graphic(GetStandardQueryBoxImage().GetBitmapEx()).GetXGraphic();
185 return xRet;
189 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadBitmap( const uno::Reference< awt::XBitmap >& xBtm )
191 uno::Reference< ::graphic::XGraphic > xRet;
192 uno::Sequence< sal_Int8 > aBmpSeq( xBtm->getDIB() );
193 uno::Sequence< sal_Int8 > aMaskSeq( xBtm->getMaskDIB() );
194 SvMemoryStream aBmpStream( aBmpSeq.getArray(), aBmpSeq.getLength(), StreamMode::READ );
195 Bitmap aBmp;
196 BitmapEx aBmpEx;
198 ReadDIB(aBmp, aBmpStream, true);
200 if( aMaskSeq.hasElements() )
202 SvMemoryStream aMaskStream( aMaskSeq.getArray(), aMaskSeq.getLength(), StreamMode::READ );
203 Bitmap aMask;
205 ReadDIB(aMask, aMaskStream, true);
206 aBmpEx = BitmapEx( aBmp, aMask );
208 else
209 aBmpEx = BitmapEx( aBmp );
211 if( !aBmpEx.IsEmpty() )
213 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
215 pUnoGraphic->init( aBmpEx );
216 xRet = pUnoGraphic;
218 return xRet;
221 uno::Reference< beans::XPropertySet > SAL_CALL GraphicProvider::queryGraphicDescriptor( const uno::Sequence< beans::PropertyValue >& rMediaProperties )
223 uno::Reference< beans::XPropertySet > xRet;
225 OUString aURL;
226 uno::Reference< io::XInputStream > xIStm;
227 uno::Reference< awt::XBitmap >xBtm;
229 for( const auto& rMediaProperty : rMediaProperties )
231 if (xRet.is())
232 break;
234 const OUString aName( rMediaProperty.Name );
235 const uno::Any aValue( rMediaProperty.Value );
237 if (aName == "URL")
239 aValue >>= aURL;
241 else if (aName == "InputStream")
243 aValue >>= xIStm;
245 else if (aName == "Bitmap")
247 aValue >>= xBtm;
251 SolarMutexGuard g;
253 if( xIStm.is() )
255 unographic::GraphicDescriptor* pDescriptor = new unographic::GraphicDescriptor;
256 pDescriptor->init( xIStm, aURL );
257 xRet = pDescriptor;
259 else if( !aURL.isEmpty() )
261 uno::Reference< ::graphic::XGraphic > xGraphic( implLoadMemory( aURL ) );
263 if ( !xGraphic.is() )
264 xGraphic = implLoadRepositoryImage( aURL );
266 if ( !xGraphic.is() )
267 xGraphic = implLoadStandardImage( aURL );
269 if( xGraphic.is() )
271 xRet.set( xGraphic, uno::UNO_QUERY );
273 else
275 unographic::GraphicDescriptor* pDescriptor = new unographic::GraphicDescriptor;
276 pDescriptor->init( aURL );
277 xRet = pDescriptor;
280 else if( xBtm.is() )
282 uno::Reference< ::graphic::XGraphic > xGraphic( implLoadBitmap( xBtm ) );
283 if( xGraphic.is() )
284 xRet.set( xGraphic, uno::UNO_QUERY );
287 return xRet;
291 uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( const uno::Sequence< ::beans::PropertyValue >& rMediaProperties )
293 uno::Reference< ::graphic::XGraphic > xRet;
294 OUString aPath;
296 uno::Reference< io::XInputStream > xIStm;
297 uno::Reference< awt::XBitmap >xBtm;
299 uno::Sequence< ::beans::PropertyValue > aFilterData;
301 bool bLazyRead = false;
302 bool bLoadAsLink = false;
304 for (const auto& rMediaProperty : rMediaProperties)
306 if (xRet.is())
307 break;
309 const OUString aName( rMediaProperty.Name );
310 const uno::Any aValue( rMediaProperty.Value );
312 if (aName == "URL")
314 OUString aURL;
315 aValue >>= aURL;
316 aPath = aURL;
318 else if (aName == "InputStream")
320 aValue >>= xIStm;
322 else if (aName == "Bitmap")
324 aValue >>= xBtm;
326 else if (aName == "FilterData")
328 aValue >>= aFilterData;
330 else if (aName == "LazyRead")
332 aValue >>= bLazyRead;
334 else if (aName == "LoadAsLink")
336 aValue >>= bLoadAsLink;
340 // Check for the goal width and height if they are defined
341 sal_uInt16 nExtWidth = 0;
342 sal_uInt16 nExtHeight = 0;
343 sal_uInt16 nExtMapMode = 0;
344 for( const auto& rProp : std::as_const(aFilterData) )
346 const OUString aName( rProp.Name );
347 const uno::Any aValue( rProp.Value );
349 if (aName == "ExternalWidth")
351 aValue >>= nExtWidth;
353 else if (aName == "ExternalHeight")
355 aValue >>= nExtHeight;
357 else if (aName == "ExternalMapMode")
359 aValue >>= nExtMapMode;
363 SolarMutexGuard g;
365 std::unique_ptr<SvStream> pIStm;
367 if( xIStm.is() )
369 pIStm = ::utl::UcbStreamHelper::CreateStream( xIStm );
371 else if( !aPath.isEmpty() )
373 xRet = implLoadMemory( aPath );
375 if ( !xRet.is() )
376 xRet = implLoadRepositoryImage( aPath );
378 if ( !xRet.is() )
379 xRet = implLoadStandardImage( aPath );
381 if( !xRet.is() )
382 pIStm = ::utl::UcbStreamHelper::CreateStream( aPath, StreamMode::READ );
384 else if( xBtm.is() )
386 xRet = implLoadBitmap( xBtm );
389 if( pIStm )
391 ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
394 Graphic aVCLGraphic;
396 // Define APM Header if goal height and width are defined
397 WmfExternal aExtHeader;
398 aExtHeader.xExt = nExtWidth;
399 aExtHeader.yExt = nExtHeight;
400 aExtHeader.mapMode = nExtMapMode;
401 WmfExternal *pExtHeader = nullptr;
402 if ( nExtMapMode > 0 )
404 pExtHeader = &aExtHeader;
405 bLazyRead = false;
408 ErrCode error = ERRCODE_NONE;
409 if (bLazyRead)
411 Graphic aGraphic = rFilter.ImportUnloadedGraphic(*pIStm);
412 if (!aGraphic.IsNone())
413 aVCLGraphic = aGraphic;
415 if (aVCLGraphic.IsNone())
416 error = rFilter.ImportGraphic(aVCLGraphic, aPath, *pIStm, GRFILTER_FORMAT_DONTKNOW,
417 nullptr, GraphicFilterImportFlags::NONE, pExtHeader);
419 if( (error == ERRCODE_NONE ) &&
420 ( aVCLGraphic.GetType() != GraphicType::NONE ) )
422 if (!aPath.isEmpty() && bLoadAsLink)
423 aVCLGraphic.setOriginURL(aPath);
425 ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
427 pUnoGraphic->init( aVCLGraphic );
428 xRet = pUnoGraphic;
430 else{
431 SAL_WARN("svtools", "Could not create graphic: " << error);
436 return xRet;
439 uno::Sequence< uno::Reference<graphic::XGraphic> > SAL_CALL GraphicProvider::queryGraphics(const uno::Sequence< uno::Sequence<beans::PropertyValue> >& rMediaPropertiesSeq)
441 SolarMutexGuard aGuard;
443 // Turn properties into streams.
444 std::vector< std::unique_ptr<SvStream> > aStreams;
445 for (const auto& rMediaProperties : rMediaPropertiesSeq)
447 std::unique_ptr<SvStream> pStream;
448 uno::Reference<io::XInputStream> xStream;
450 auto pProp = std::find_if(rMediaProperties.begin(), rMediaProperties.end(),
451 [](const beans::PropertyValue& rProp) { return rProp.Name == "InputStream"; });
452 if (pProp != rMediaProperties.end())
454 pProp->Value >>= xStream;
455 if (xStream.is())
456 pStream = utl::UcbStreamHelper::CreateStream(xStream);
459 aStreams.push_back(std::move(pStream));
462 // Import: streams to graphics.
463 std::vector< std::shared_ptr<Graphic> > aGraphics;
464 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
465 rFilter.ImportGraphics(aGraphics, std::move(aStreams));
467 // Returning: graphics to UNO objects.
468 std::vector< uno::Reference<graphic::XGraphic> > aRet;
469 for (const auto& pGraphic : aGraphics)
471 uno::Reference<graphic::XGraphic> xGraphic;
473 if (pGraphic)
475 auto pUnoGraphic = new unographic::Graphic();
476 pUnoGraphic->init(*pGraphic);
477 xGraphic = pUnoGraphic;
480 aRet.push_back(xGraphic);
483 return comphelper::containerToSequence(aRet);
486 void ImplCalculateCropRect( ::Graphic const & rGraphic, const text::GraphicCrop& rGraphicCropLogic, tools::Rectangle& rGraphicCropPixel )
488 if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) )
489 return;
491 Size aSourceSizePixel( rGraphic.GetSizePixel() );
492 if ( !(aSourceSizePixel.Width() && aSourceSizePixel.Height()) )
493 return;
495 if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) )
496 return;
498 Size aSize100thMM( 0, 0 );
499 if( rGraphic.GetPrefMapMode().GetMapUnit() != MapUnit::MapPixel )
501 aSize100thMM = OutputDevice::LogicToLogic(rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM));
503 else
505 aSize100thMM = Application::GetDefaultDevice()->PixelToLogic(rGraphic.GetPrefSize(), MapMode(MapUnit::Map100thMM));
507 if ( aSize100thMM.Width() && aSize100thMM.Height() )
509 double fSourceSizePixelWidth = static_cast<double>(aSourceSizePixel.Width());
510 double fSourceSizePixelHeight= static_cast<double>(aSourceSizePixel.Height());
511 rGraphicCropPixel.SetLeft( static_cast< sal_Int32 >((fSourceSizePixelWidth * rGraphicCropLogic.Left ) / aSize100thMM.Width()) );
512 rGraphicCropPixel.SetTop( static_cast< sal_Int32 >((fSourceSizePixelHeight * rGraphicCropLogic.Top ) / aSize100thMM.Height()) );
513 rGraphicCropPixel.SetRight( static_cast< sal_Int32 >(( fSourceSizePixelWidth * ( aSize100thMM.Width() - rGraphicCropLogic.Right ) ) / aSize100thMM.Width() ) );
514 rGraphicCropPixel.SetBottom( static_cast< sal_Int32 >(( fSourceSizePixelHeight * ( aSize100thMM.Height() - rGraphicCropLogic.Bottom ) ) / aSize100thMM.Height() ) );
518 void ImplApplyBitmapScaling( ::Graphic& rGraphic, sal_Int32 nPixelWidth, sal_Int32 nPixelHeight )
520 if ( nPixelWidth && nPixelHeight )
522 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
523 MapMode aPrefMapMode( aBmpEx.GetPrefMapMode() );
524 Size aPrefSize( aBmpEx.GetPrefSize() );
525 aBmpEx.Scale( Size( nPixelWidth, nPixelHeight ) );
526 aBmpEx.SetPrefMapMode( aPrefMapMode );
527 aBmpEx.SetPrefSize( aPrefSize );
528 rGraphic = aBmpEx;
532 void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize )
534 if ( !(nImageResolution && rLogicalSize.Width && rLogicalSize.Height) )
535 return;
537 const double fImageResolution = static_cast<double>( nImageResolution );
538 const double fSourceDPIX = ( static_cast<double>(rVisiblePixelSize.Width()) * 2540.0 ) / static_cast<double>(rLogicalSize.Width);
539 const double fSourceDPIY = ( static_cast<double>(rVisiblePixelSize.Height()) * 2540.0 ) / static_cast<double>(rLogicalSize.Height);
540 const sal_Int32 nSourcePixelWidth( rGraphic.GetSizePixel().Width() );
541 const sal_Int32 nSourcePixelHeight( rGraphic.GetSizePixel().Height() );
542 const double fSourcePixelWidth = static_cast<double>( nSourcePixelWidth );
543 const double fSourcePixelHeight= static_cast<double>( nSourcePixelHeight );
545 sal_Int32 nDestPixelWidth = nSourcePixelWidth;
546 sal_Int32 nDestPixelHeight = nSourcePixelHeight;
548 // check, if the bitmap DPI exceeds the maximum DPI
549 if( fSourceDPIX > fImageResolution )
551 nDestPixelWidth = static_cast<sal_Int32>(( fSourcePixelWidth * fImageResolution ) / fSourceDPIX);
552 if ( !nDestPixelWidth || ( nDestPixelWidth > nSourcePixelWidth ) )
553 nDestPixelWidth = nSourcePixelWidth;
555 if ( fSourceDPIY > fImageResolution )
557 nDestPixelHeight= static_cast<sal_Int32>(( fSourcePixelHeight* fImageResolution ) / fSourceDPIY);
558 if ( !nDestPixelHeight || ( nDestPixelHeight > nSourcePixelHeight ) )
559 nDestPixelHeight = nSourcePixelHeight;
561 if ( ( nDestPixelWidth != nSourcePixelWidth ) || ( nDestPixelHeight != nSourcePixelHeight ) )
562 ImplApplyBitmapScaling( rGraphic, nDestPixelWidth, nDestPixelHeight );
565 void ImplApplyFilterData( ::Graphic& rGraphic, const uno::Sequence< beans::PropertyValue >& rFilterData )
567 /* this method applies following attributes to the graphic, in the first step the
568 cropping area (logical size in 100thmm) is applied, in the second step the resolution
569 is applied, in the third step the graphic is scaled to the corresponding pixelsize.
570 if a parameter value is zero or not available the corresponding step will be skipped */
572 sal_Int32 nPixelWidth = 0;
573 sal_Int32 nPixelHeight= 0;
574 sal_Int32 nImageResolution = 0;
575 awt::Size aLogicalSize( 0, 0 );
576 text::GraphicCrop aCropLogic( 0, 0, 0, 0 );
577 bool bRemoveCropArea = true;
579 for( const auto& rProp : rFilterData )
581 const OUString aName( rProp.Name );
582 const uno::Any aValue( rProp.Value );
584 if (aName == "PixelWidth")
585 aValue >>= nPixelWidth;
586 else if (aName == "PixelHeight")
587 aValue >>= nPixelHeight;
588 else if (aName == "LogicalSize")
589 aValue >>= aLogicalSize;
590 else if (aName == "GraphicCropLogic")
591 aValue >>= aCropLogic;
592 else if (aName == "RemoveCropArea")
593 aValue >>= bRemoveCropArea;
594 else if (aName == "ImageResolution")
595 aValue >>= nImageResolution;
597 if ( rGraphic.GetType() == GraphicType::Bitmap )
599 if(rGraphic.getVectorGraphicData().get())
601 // embedded Vector Graphic Data, no need to scale. Also no method to apply crop data currently
603 else
605 tools::Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() );
606 ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel );
607 if ( bRemoveCropArea )
609 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
610 aBmpEx.Crop( aCropPixel );
611 rGraphic = aBmpEx;
613 Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() );
614 ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize );
615 ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight );
618 else if ( ( rGraphic.GetType() == GraphicType::GdiMetafile ) && nImageResolution )
620 ScopedVclPtrInstance< VirtualDevice > aDummyVDev;
621 GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
622 Size aMtfSize( OutputDevice::LogicToLogic(aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
623 if ( aMtfSize.Width() && aMtfSize.Height() )
625 MapMode aNewMapMode( MapUnit::Map100thMM );
626 aNewMapMode.SetScaleX( Fraction( aLogicalSize.Width, aMtfSize.Width() ) );
627 aNewMapMode.SetScaleY( Fraction( aLogicalSize.Height, aMtfSize.Height() ) );
628 aDummyVDev->EnableOutput( false );
629 aDummyVDev->SetMapMode( aNewMapMode );
631 for( size_t i = 0, nObjCount = aMtf.GetActionSize(); i < nObjCount; i++ )
633 MetaAction* pAction = aMtf.GetAction( i );
634 switch( pAction->GetType() )
636 // only optimizing common bitmap actions:
637 case MetaActionType::MAPMODE:
639 pAction->Execute( aDummyVDev.get() );
640 break;
642 case MetaActionType::PUSH:
644 const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
645 aDummyVDev->Push( pA->GetFlags() );
646 break;
648 case MetaActionType::POP:
650 aDummyVDev->Pop();
651 break;
653 case MetaActionType::BMPSCALE:
654 case MetaActionType::BMPEXSCALE:
656 BitmapEx aBmpEx;
657 Point aPos;
658 Size aSize;
659 if ( pAction->GetType() == MetaActionType::BMPSCALE )
661 MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction );
662 assert(pScaleAction);
663 aBmpEx = pScaleAction->GetBitmap();
664 aPos = pScaleAction->GetPoint();
665 aSize = pScaleAction->GetSize();
667 else
669 MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction );
670 assert(pScaleAction);
671 aBmpEx = pScaleAction->GetBitmapEx();
672 aPos = pScaleAction->GetPoint();
673 aSize = pScaleAction->GetSize();
675 ::Graphic aGraphic( aBmpEx );
676 const Size aSize100thmm( aDummyVDev->LogicToPixel( aSize ) );
677 Size aSize100thmm2( aDummyVDev->PixelToLogic(aSize100thmm, MapMode(MapUnit::Map100thMM)) );
679 ImplApplyBitmapResolution( aGraphic, nImageResolution,
680 aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) );
682 rtl::Reference<MetaAction> pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() );
683 aMtf.ReplaceAction( pNewAction, i );
684 break;
686 default:
687 case MetaActionType::BMP:
688 case MetaActionType::BMPSCALEPART:
689 case MetaActionType::BMPEX:
690 case MetaActionType::BMPEXSCALEPART:
691 case MetaActionType::MASK:
692 case MetaActionType::MASKSCALE:
693 break;
696 rGraphic = aMtf;
702 void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties )
704 SolarMutexGuard g;
706 std::unique_ptr<SvStream> pOStm;
707 OUString aPath;
709 for( const auto& rMediaProperty : rMediaProperties )
711 const OUString aName( rMediaProperty.Name );
712 const uno::Any aValue( rMediaProperty.Value );
714 if (aName == "URL")
716 OUString aURL;
718 aValue >>= aURL;
719 pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, StreamMode::WRITE | StreamMode::TRUNC );
720 aPath = aURL;
722 else if (aName == "OutputStream")
724 uno::Reference< io::XStream > xOStm;
726 aValue >>= xOStm;
728 if( xOStm.is() )
729 pOStm = ::utl::UcbStreamHelper::CreateStream( xOStm );
732 if( pOStm )
733 break;
736 if( !pOStm )
737 return;
739 uno::Sequence< beans::PropertyValue > aFilterDataSeq;
740 const char* pFilterShortName = nullptr;
742 for( const auto& rMediaProperty : rMediaProperties )
744 const OUString aName( rMediaProperty.Name );
745 const uno::Any aValue( rMediaProperty.Value );
747 if (aName == "FilterData")
749 aValue >>= aFilterDataSeq;
751 else if (aName == "MimeType")
753 OUString aMimeType;
755 aValue >>= aMimeType;
757 if (aMimeType == MIMETYPE_BMP)
758 pFilterShortName = "bmp";
759 else if (aMimeType == MIMETYPE_EPS)
760 pFilterShortName = "eps";
761 else if (aMimeType == MIMETYPE_GIF)
762 pFilterShortName = "gif";
763 else if (aMimeType == MIMETYPE_JPG)
764 pFilterShortName = "jpg";
765 else if (aMimeType == MIMETYPE_MET)
766 pFilterShortName = "met";
767 else if (aMimeType == MIMETYPE_PNG)
768 pFilterShortName = "png";
769 else if (aMimeType == MIMETYPE_PCT)
770 pFilterShortName = "pct";
771 else if (aMimeType == MIMETYPE_PBM)
772 pFilterShortName = "pbm";
773 else if (aMimeType == MIMETYPE_PGM)
774 pFilterShortName = "pgm";
775 else if (aMimeType == MIMETYPE_PPM)
776 pFilterShortName = "ppm";
777 else if (aMimeType == MIMETYPE_RAS)
778 pFilterShortName = "ras";
779 else if (aMimeType == MIMETYPE_SVM)
780 pFilterShortName = "svm";
781 else if (aMimeType == MIMETYPE_TIF)
782 pFilterShortName = "tif";
783 else if (aMimeType == MIMETYPE_EMF)
784 pFilterShortName = "emf";
785 else if (aMimeType == MIMETYPE_WMF)
786 pFilterShortName = "wmf";
787 else if (aMimeType == MIMETYPE_XPM)
788 pFilterShortName = "xpm";
789 else if (aMimeType == MIMETYPE_SVG)
790 pFilterShortName = "svg";
791 else if (aMimeType == MIMETYPE_VCLGRAPHIC)
792 pFilterShortName = MIMETYPE_VCLGRAPHIC;
796 if( !pFilterShortName )
797 return;
799 ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
802 const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY );
803 const ::Graphic* pGraphic = comphelper::getUnoTunnelImplementation<::Graphic>( xIFace );
805 if( pGraphic && ( pGraphic->GetType() != GraphicType::NONE ) )
807 ::Graphic aGraphic( *pGraphic );
808 ImplApplyFilterData( aGraphic, aFilterDataSeq );
810 /* sj: using a temporary memory stream, because some graphic filters are seeking behind
811 stream end (which leads to an invalid argument exception then). */
812 SvMemoryStream aMemStrm;
813 aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
814 if( 0 == strcmp( pFilterShortName, MIMETYPE_VCLGRAPHIC ) )
815 WriteGraphic( aMemStrm, aGraphic );
816 else
818 rFilter.ExportGraphic( aGraphic, aPath, aMemStrm,
819 rFilter.GetExportFormatNumberForShortName( OUString::createFromAscii( pFilterShortName ) ),
820 ( aFilterDataSeq.hasElements() ? &aFilterDataSeq : nullptr ) );
822 pOStm->WriteBytes( aMemStrm.GetData(), aMemStrm.TellEnd() );
829 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
830 com_sun_star_comp_graphic_GraphicProvider_get_implementation(
831 css::uno::XComponentContext *,
832 css::uno::Sequence<css::uno::Any> const &)
834 return cppu::acquire(new GraphicProvider);
837 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */