/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star; namespace { class GraphicProvider : public ::cppu::WeakImplHelper< css::graphic::XGraphicProvider2, css::lang::XServiceInfo > { public: GraphicProvider(); protected: // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; // XTypeProvider virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override; virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override; // XGraphicProvider virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL queryGraphicDescriptor( const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override; virtual css::uno::Reference< css::graphic::XGraphic > SAL_CALL queryGraphic( const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override; virtual void SAL_CALL storeGraphic( const css::uno::Reference< css::graphic::XGraphic >& Graphic, const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override; // XGraphicProvider2 uno::Sequence< uno::Reference > SAL_CALL queryGraphics(const uno::Sequence< uno::Sequence >& MediaPropertiesSeq ) override; private: static css::uno::Reference< css::graphic::XGraphic > implLoadMemory( const OUString& rResourceURL ); static css::uno::Reference< css::graphic::XGraphic > implLoadRepositoryImage( std::u16string_view rResourceURL ); static css::uno::Reference< css::graphic::XGraphic > implLoadBitmap( const css::uno::Reference< css::awt::XBitmap >& rBitmap ); static css::uno::Reference< css::graphic::XGraphic > implLoadStandardImage( std::u16string_view rResourceURL ); }; GraphicProvider::GraphicProvider() { } OUString SAL_CALL GraphicProvider::getImplementationName() { return "com.sun.star.comp.graphic.GraphicProvider"; } sal_Bool SAL_CALL GraphicProvider::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } uno::Sequence< OUString > SAL_CALL GraphicProvider::getSupportedServiceNames() { return { "com.sun.star.graphic.GraphicProvider" }; } uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes() { static const uno::Sequence< uno::Type > aTypes { cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get() }; return aTypes; } uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId() { return css::uno::Sequence(); } uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( const OUString& rResourceURL ) { uno::Reference< ::graphic::XGraphic > xRet; sal_Int32 nIndex = 0; if( rResourceURL.getToken( 0, '/', nIndex ) == "private:memorygraphic" ) { sal_Int64 nGraphicAddress = rResourceURL.getToken( 0, '/', nIndex ).toInt64(); if( nGraphicAddress ) { rtl::Reference<::unographic::Graphic> pUnoGraphic = new ::unographic::Graphic; pUnoGraphic->init( *reinterpret_cast< ::Graphic* >( nGraphicAddress ) ); xRet = pUnoGraphic; } } return xRet; } uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( std::u16string_view rResourceURL ) { uno::Reference< ::graphic::XGraphic > xRet; std::u16string_view sPathName; if( o3tl::starts_with(rResourceURL, u"private:graphicrepository/", &sPathName) ) { BitmapEx aBitmap; if ( vcl::ImageRepository::loadImage( OUString(sPathName), aBitmap ) ) { xRet = Graphic(aBitmap).GetXGraphic(); } } return xRet; } uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadStandardImage( std::u16string_view rResourceURL ) { uno::Reference< ::graphic::XGraphic > xRet; std::u16string_view sImageName; if( o3tl::starts_with(rResourceURL, u"private:standardimage/", &sImageName) ) { if ( sImageName == u"info" ) { xRet = Graphic(GetStandardInfoBoxImage().GetBitmapEx()).GetXGraphic(); } else if ( sImageName == u"warning" ) { xRet = Graphic(GetStandardWarningBoxImage().GetBitmapEx()).GetXGraphic(); } else if ( sImageName == u"error" ) { xRet = Graphic(GetStandardErrorBoxImage().GetBitmapEx()).GetXGraphic(); } else if ( sImageName == u"query" ) { xRet = Graphic(GetStandardQueryBoxImage().GetBitmapEx()).GetXGraphic(); } } return xRet; } uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadBitmap( const uno::Reference< awt::XBitmap >& xBtm ) { uno::Reference< ::graphic::XGraphic > xRet; uno::Sequence< sal_Int8 > aBmpSeq( xBtm->getDIB() ); uno::Sequence< sal_Int8 > aMaskSeq( xBtm->getMaskDIB() ); SvMemoryStream aBmpStream( aBmpSeq.getArray(), aBmpSeq.getLength(), StreamMode::READ ); Bitmap aBmp; BitmapEx aBmpEx; ReadDIB(aBmp, aBmpStream, true); if( aMaskSeq.hasElements() ) { SvMemoryStream aMaskStream( aMaskSeq.getArray(), aMaskSeq.getLength(), StreamMode::READ ); Bitmap aMask; ReadDIB(aMask, aMaskStream, true); aBmpEx = BitmapEx( aBmp, aMask ); } else aBmpEx = BitmapEx( aBmp ); if( !aBmpEx.IsEmpty() ) { rtl::Reference<::unographic::Graphic> pUnoGraphic = new ::unographic::Graphic; pUnoGraphic->init( aBmpEx ); xRet = pUnoGraphic; } return xRet; } uno::Reference< beans::XPropertySet > SAL_CALL GraphicProvider::queryGraphicDescriptor( const uno::Sequence< beans::PropertyValue >& rMediaProperties ) { uno::Reference< beans::XPropertySet > xRet; OUString aURL; uno::Reference< io::XInputStream > xIStm; uno::Reference< awt::XBitmap >xBtm; for( const auto& rMediaProperty : rMediaProperties ) { if (xRet.is()) break; const OUString aName( rMediaProperty.Name ); const uno::Any aValue( rMediaProperty.Value ); if (aName == "URL") { aValue >>= aURL; } else if (aName == "InputStream") { aValue >>= xIStm; } else if (aName == "Bitmap") { aValue >>= xBtm; } } SolarMutexGuard g; if( xIStm.is() ) { rtl::Reference pDescriptor = new unographic::GraphicDescriptor; pDescriptor->init( xIStm, aURL ); xRet = pDescriptor; } else if( !aURL.isEmpty() ) { uno::Reference< ::graphic::XGraphic > xGraphic( implLoadMemory( aURL ) ); if ( !xGraphic.is() ) xGraphic = implLoadRepositoryImage( aURL ); if ( !xGraphic.is() ) xGraphic = implLoadStandardImage( aURL ); if( xGraphic.is() ) { xRet.set( xGraphic, uno::UNO_QUERY ); } else { rtl::Reference pDescriptor = new unographic::GraphicDescriptor; pDescriptor->init( aURL ); xRet = pDescriptor; } } else if( xBtm.is() ) { uno::Reference< ::graphic::XGraphic > xGraphic( implLoadBitmap( xBtm ) ); if( xGraphic.is() ) xRet.set( xGraphic, uno::UNO_QUERY ); } return xRet; } uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( const uno::Sequence< ::beans::PropertyValue >& rMediaProperties ) { uno::Reference< ::graphic::XGraphic > xRet; OUString aPath; uno::Reference< io::XInputStream > xIStm; uno::Reference< awt::XBitmap >xBtm; uno::Sequence< ::beans::PropertyValue > aFilterData; bool bLazyRead = false; bool bLoadAsLink = false; for (const auto& rMediaProperty : rMediaProperties) { if (xRet.is()) break; const OUString aName( rMediaProperty.Name ); const uno::Any aValue( rMediaProperty.Value ); if (aName == "URL") { OUString aURL; aValue >>= aURL; aPath = aURL; } else if (aName == "InputStream") { aValue >>= xIStm; } else if (aName == "Bitmap") { aValue >>= xBtm; } else if (aName == "FilterData") { aValue >>= aFilterData; } else if (aName == "LazyRead") { aValue >>= bLazyRead; } else if (aName == "LoadAsLink") { aValue >>= bLoadAsLink; } } // Check for the goal width and height if they are defined sal_uInt16 nExtWidth = 0; sal_uInt16 nExtHeight = 0; sal_uInt16 nExtMapMode = 0; for( const auto& rProp : std::as_const(aFilterData) ) { const OUString aName( rProp.Name ); const uno::Any aValue( rProp.Value ); if (aName == "ExternalWidth") { aValue >>= nExtWidth; } else if (aName == "ExternalHeight") { aValue >>= nExtHeight; } else if (aName == "ExternalMapMode") { aValue >>= nExtMapMode; } } SolarMutexGuard g; std::unique_ptr pIStm; if( xIStm.is() ) { pIStm = ::utl::UcbStreamHelper::CreateStream( xIStm ); } else if( !aPath.isEmpty() ) { xRet = implLoadMemory( aPath ); if ( !xRet.is() ) xRet = implLoadRepositoryImage( aPath ); if ( !xRet.is() ) xRet = implLoadStandardImage( aPath ); if( !xRet.is() ) pIStm = ::utl::UcbStreamHelper::CreateStream( aPath, StreamMode::READ ); } else if( xBtm.is() ) { xRet = implLoadBitmap( xBtm ); } if( pIStm ) { ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter(); { Graphic aVCLGraphic; // Define APM Header if goal height and width are defined WmfExternal aExtHeader; aExtHeader.xExt = nExtWidth; aExtHeader.yExt = nExtHeight; aExtHeader.mapMode = nExtMapMode; WmfExternal *pExtHeader = nullptr; if ( nExtMapMode > 0 ) { pExtHeader = &aExtHeader; bLazyRead = false; } ErrCode error = ERRCODE_NONE; if (bLazyRead) { Graphic aGraphic = rFilter.ImportUnloadedGraphic(*pIStm); if (!aGraphic.IsNone()) aVCLGraphic = aGraphic; } if (aVCLGraphic.IsNone()) error = rFilter.ImportGraphic(aVCLGraphic, aPath, *pIStm, GRFILTER_FORMAT_DONTKNOW, nullptr, GraphicFilterImportFlags::NONE, pExtHeader); if( (error == ERRCODE_NONE ) && ( aVCLGraphic.GetType() != GraphicType::NONE ) ) { if (!aPath.isEmpty() && bLoadAsLink) aVCLGraphic.setOriginURL(aPath); rtl::Reference<::unographic::Graphic> pUnoGraphic = new ::unographic::Graphic; pUnoGraphic->init( aVCLGraphic ); xRet = pUnoGraphic; } else{ SAL_WARN("svtools", "Could not create graphic for:" << aPath << " error: " << error); } } } return xRet; } uno::Sequence< uno::Reference > SAL_CALL GraphicProvider::queryGraphics(const uno::Sequence< uno::Sequence >& rMediaPropertiesSeq) { SolarMutexGuard aGuard; // Turn properties into streams. std::vector< std::unique_ptr > aStreams; for (const auto& rMediaProperties : rMediaPropertiesSeq) { std::unique_ptr pStream; uno::Reference xStream; auto pProp = std::find_if(rMediaProperties.begin(), rMediaProperties.end(), [](const beans::PropertyValue& rProp) { return rProp.Name == "InputStream"; }); if (pProp != rMediaProperties.end()) { pProp->Value >>= xStream; if (xStream.is()) pStream = utl::UcbStreamHelper::CreateStream(xStream); } aStreams.push_back(std::move(pStream)); } // Import: streams to graphics. std::vector< std::shared_ptr > aGraphics; GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); rFilter.ImportGraphics(aGraphics, std::move(aStreams)); // Returning: graphics to UNO objects. std::vector< uno::Reference > aRet; for (const auto& pGraphic : aGraphics) { uno::Reference xGraphic; if (pGraphic) { rtl::Reference pUnoGraphic = new unographic::Graphic(); pUnoGraphic->init(*pGraphic); xGraphic = pUnoGraphic; } aRet.push_back(xGraphic); } return comphelper::containerToSequence(aRet); } void ImplCalculateCropRect( ::Graphic const & rGraphic, const text::GraphicCrop& rGraphicCropLogic, tools::Rectangle& rGraphicCropPixel ) { if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) ) return; Size aSourceSizePixel( rGraphic.GetSizePixel() ); if ( !(aSourceSizePixel.Width() && aSourceSizePixel.Height()) ) return; if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) ) return; Size aSize100thMM( 0, 0 ); if( rGraphic.GetPrefMapMode().GetMapUnit() != MapUnit::MapPixel ) { aSize100thMM = OutputDevice::LogicToLogic(rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)); } else { aSize100thMM = Application::GetDefaultDevice()->PixelToLogic(rGraphic.GetPrefSize(), MapMode(MapUnit::Map100thMM)); } if ( aSize100thMM.Width() && aSize100thMM.Height() ) { double fSourceSizePixelWidth = static_cast(aSourceSizePixel.Width()); double fSourceSizePixelHeight= static_cast(aSourceSizePixel.Height()); rGraphicCropPixel.SetLeft( static_cast< sal_Int32 >((fSourceSizePixelWidth * rGraphicCropLogic.Left ) / aSize100thMM.Width()) ); rGraphicCropPixel.SetTop( static_cast< sal_Int32 >((fSourceSizePixelHeight * rGraphicCropLogic.Top ) / aSize100thMM.Height()) ); rGraphicCropPixel.SetRight( static_cast< sal_Int32 >(( fSourceSizePixelWidth * ( aSize100thMM.Width() - rGraphicCropLogic.Right ) ) / aSize100thMM.Width() ) ); rGraphicCropPixel.SetBottom( static_cast< sal_Int32 >(( fSourceSizePixelHeight * ( aSize100thMM.Height() - rGraphicCropLogic.Bottom ) ) / aSize100thMM.Height() ) ); } } void ImplApplyBitmapScaling( ::Graphic& rGraphic, sal_Int32 nPixelWidth, sal_Int32 nPixelHeight ) { if ( nPixelWidth && nPixelHeight ) { BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); MapMode aPrefMapMode( aBmpEx.GetPrefMapMode() ); Size aPrefSize( aBmpEx.GetPrefSize() ); aBmpEx.Scale( Size( nPixelWidth, nPixelHeight ) ); aBmpEx.SetPrefMapMode( aPrefMapMode ); aBmpEx.SetPrefSize( aPrefSize ); rGraphic = aBmpEx; } } void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize ) { if ( !(nImageResolution && rLogicalSize.Width && rLogicalSize.Height) ) return; const double fImageResolution = static_cast( nImageResolution ); const double fSourceDPIX = ( static_cast(rVisiblePixelSize.Width()) * 2540.0 ) / static_cast(rLogicalSize.Width); const double fSourceDPIY = ( static_cast(rVisiblePixelSize.Height()) * 2540.0 ) / static_cast(rLogicalSize.Height); const sal_Int32 nSourcePixelWidth( rGraphic.GetSizePixel().Width() ); const sal_Int32 nSourcePixelHeight( rGraphic.GetSizePixel().Height() ); const double fSourcePixelWidth = static_cast( nSourcePixelWidth ); const double fSourcePixelHeight= static_cast( nSourcePixelHeight ); sal_Int32 nDestPixelWidth = nSourcePixelWidth; sal_Int32 nDestPixelHeight = nSourcePixelHeight; // check, if the bitmap DPI exceeds the maximum DPI if( fSourceDPIX > fImageResolution ) { nDestPixelWidth = static_cast(( fSourcePixelWidth * fImageResolution ) / fSourceDPIX); if ( !nDestPixelWidth || ( nDestPixelWidth > nSourcePixelWidth ) ) nDestPixelWidth = nSourcePixelWidth; } if ( fSourceDPIY > fImageResolution ) { nDestPixelHeight= static_cast(( fSourcePixelHeight* fImageResolution ) / fSourceDPIY); if ( !nDestPixelHeight || ( nDestPixelHeight > nSourcePixelHeight ) ) nDestPixelHeight = nSourcePixelHeight; } if ( ( nDestPixelWidth != nSourcePixelWidth ) || ( nDestPixelHeight != nSourcePixelHeight ) ) ImplApplyBitmapScaling( rGraphic, nDestPixelWidth, nDestPixelHeight ); } void ImplApplyFilterData( ::Graphic& rGraphic, const uno::Sequence< beans::PropertyValue >& rFilterData ) { /* this method applies following attributes to the graphic, in the first step the cropping area (logical size in 100thmm) is applied, in the second step the resolution is applied, in the third step the graphic is scaled to the corresponding pixelsize. if a parameter value is zero or not available the corresponding step will be skipped */ sal_Int32 nPixelWidth = 0; sal_Int32 nPixelHeight= 0; sal_Int32 nImageResolution = 0; awt::Size aLogicalSize( 0, 0 ); text::GraphicCrop aCropLogic( 0, 0, 0, 0 ); bool bRemoveCropArea = true; for( const auto& rProp : rFilterData ) { const OUString aName( rProp.Name ); const uno::Any aValue( rProp.Value ); if (aName == "PixelWidth") aValue >>= nPixelWidth; else if (aName == "PixelHeight") aValue >>= nPixelHeight; else if (aName == "LogicalSize") aValue >>= aLogicalSize; else if (aName == "GraphicCropLogic") aValue >>= aCropLogic; else if (aName == "RemoveCropArea") aValue >>= bRemoveCropArea; else if (aName == "ImageResolution") aValue >>= nImageResolution; } if ( rGraphic.GetType() == GraphicType::Bitmap ) { if(rGraphic.getVectorGraphicData()) { // embedded Vector Graphic Data, no need to scale. Also no method to apply crop data currently } else { tools::Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() ); ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel ); if ( bRemoveCropArea ) { BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); aBmpEx.Crop( aCropPixel ); rGraphic = aBmpEx; } Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() ); ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize ); ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight ); } } else if ( ( rGraphic.GetType() == GraphicType::GdiMetafile ) && nImageResolution ) { ScopedVclPtrInstance< VirtualDevice > aDummyVDev; GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() ); Size aMtfSize( OutputDevice::LogicToLogic(aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) ); if ( aMtfSize.Width() && aMtfSize.Height() ) { MapMode aNewMapMode( MapUnit::Map100thMM ); aNewMapMode.SetScaleX( Fraction( aLogicalSize.Width, aMtfSize.Width() ) ); aNewMapMode.SetScaleY( Fraction( aLogicalSize.Height, aMtfSize.Height() ) ); aDummyVDev->EnableOutput( false ); aDummyVDev->SetMapMode( aNewMapMode ); for( size_t i = 0, nObjCount = aMtf.GetActionSize(); i < nObjCount; i++ ) { MetaAction* pAction = aMtf.GetAction( i ); switch( pAction->GetType() ) { // only optimizing common bitmap actions: case MetaActionType::MAPMODE: { pAction->Execute( aDummyVDev.get() ); break; } case MetaActionType::PUSH: { const MetaPushAction* pA = static_cast(pAction); aDummyVDev->Push( pA->GetFlags() ); break; } case MetaActionType::POP: { aDummyVDev->Pop(); break; } case MetaActionType::BMPSCALE: case MetaActionType::BMPEXSCALE: { BitmapEx aBmpEx; Point aPos; Size aSize; if ( pAction->GetType() == MetaActionType::BMPSCALE ) { MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction ); assert(pScaleAction); aBmpEx = pScaleAction->GetBitmap(); aPos = pScaleAction->GetPoint(); aSize = pScaleAction->GetSize(); } else { MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction ); assert(pScaleAction); aBmpEx = pScaleAction->GetBitmapEx(); aPos = pScaleAction->GetPoint(); aSize = pScaleAction->GetSize(); } ::Graphic aGraphic( aBmpEx ); const Size aSize100thmm( aDummyVDev->LogicToPixel( aSize ) ); Size aSize100thmm2( aDummyVDev->PixelToLogic(aSize100thmm, MapMode(MapUnit::Map100thMM)) ); ImplApplyBitmapResolution( aGraphic, nImageResolution, aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) ); rtl::Reference pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() ); aMtf.ReplaceAction( pNewAction, i ); break; } default: case MetaActionType::BMP: case MetaActionType::BMPSCALEPART: case MetaActionType::BMPEX: case MetaActionType::BMPEXSCALEPART: case MetaActionType::MASK: case MetaActionType::MASKSCALE: break; } } rGraphic = aMtf; } } } void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties ) { SolarMutexGuard g; std::unique_ptr pOStm; OUString aPath; for( const auto& rMediaProperty : rMediaProperties ) { const OUString aName( rMediaProperty.Name ); const uno::Any aValue( rMediaProperty.Value ); if (aName == "URL") { OUString aURL; aValue >>= aURL; pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, StreamMode::WRITE | StreamMode::TRUNC ); aPath = aURL; } else if (aName == "OutputStream") { uno::Reference< io::XStream > xOStm; aValue >>= xOStm; if( xOStm.is() ) pOStm = ::utl::UcbStreamHelper::CreateStream( xOStm ); } if( pOStm ) break; } if( !pOStm ) return; uno::Sequence< beans::PropertyValue > aFilterDataSeq; OUString sFilterShortName; for( const auto& rMediaProperty : rMediaProperties ) { const OUString aName( rMediaProperty.Name ); const uno::Any aValue( rMediaProperty.Value ); if (aName == "FilterData") { aValue >>= aFilterDataSeq; } else if (aName == "MimeType") { OUString aMimeType; aValue >>= aMimeType; if (aMimeType == MIMETYPE_BMP) sFilterShortName = "bmp"; else if (aMimeType == MIMETYPE_EPS) sFilterShortName = "eps"; else if (aMimeType == MIMETYPE_GIF) sFilterShortName = "gif"; else if (aMimeType == MIMETYPE_JPG) sFilterShortName = "jpg"; else if (aMimeType == MIMETYPE_MET) sFilterShortName = "met"; else if (aMimeType == MIMETYPE_PNG) sFilterShortName = "png"; else if (aMimeType == MIMETYPE_PCT) sFilterShortName = "pct"; else if (aMimeType == MIMETYPE_PBM) sFilterShortName = "pbm"; else if (aMimeType == MIMETYPE_PGM) sFilterShortName = "pgm"; else if (aMimeType == MIMETYPE_PPM) sFilterShortName = "ppm"; else if (aMimeType == MIMETYPE_RAS) sFilterShortName = "ras"; else if (aMimeType == MIMETYPE_SVM) sFilterShortName = "svm"; else if (aMimeType == MIMETYPE_TIF) sFilterShortName = "tif"; else if (aMimeType == MIMETYPE_EMF) sFilterShortName = "emf"; else if (aMimeType == MIMETYPE_WMF) sFilterShortName = "wmf"; else if (aMimeType == MIMETYPE_XPM) sFilterShortName = "xpm"; else if (aMimeType == MIMETYPE_SVG) sFilterShortName = "svg"; else if (aMimeType == MIMETYPE_VCLGRAPHIC) sFilterShortName = MIMETYPE_VCLGRAPHIC; } } if( sFilterShortName.isEmpty() ) return; ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter(); { const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY ); const ::Graphic* pGraphic = comphelper::getFromUnoTunnel<::Graphic>( xIFace ); if( pGraphic && ( pGraphic->GetType() != GraphicType::NONE ) ) { ::Graphic aGraphic( *pGraphic ); ImplApplyFilterData( aGraphic, aFilterDataSeq ); /* sj: using a temporary memory stream, because some graphic filters are seeking behind stream end (which leads to an invalid argument exception then). */ SvMemoryStream aMemStrm; aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT ); if( sFilterShortName == MIMETYPE_VCLGRAPHIC ) { TypeSerializer aSerializer(aMemStrm); aSerializer.writeGraphic(aGraphic); } else { rFilter.ExportGraphic( aGraphic, aPath, aMemStrm, rFilter.GetExportFormatNumberForShortName( sFilterShortName ), ( aFilterDataSeq.hasElements() ? &aFilterDataSeq : nullptr ) ); } pOStm->WriteBytes( aMemStrm.GetData(), aMemStrm.TellEnd() ); } } } } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_graphic_GraphicProvider_get_implementation( css::uno::XComponentContext *, css::uno::Sequence const &) { return cppu::acquire(new GraphicProvider); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */