diff options
Diffstat (limited to 'svtools/source/graphic/provider.cxx')
-rw-r--r-- | svtools/source/graphic/provider.cxx | 864 |
1 files changed, 864 insertions, 0 deletions
diff --git a/svtools/source/graphic/provider.cxx b/svtools/source/graphic/provider.cxx new file mode 100644 index 000000000000..f8f1c77b255d --- /dev/null +++ b/svtools/source/graphic/provider.cxx @@ -0,0 +1,864 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: provider.cxx,v $ + * $Revision: 1.18 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +#include <rtl/uuid.h> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <vcl/image.hxx> +#include <vcl/metaact.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/imagerepository.hxx> +#include <tools/rcid.h> +#include <tools/resid.hxx> +#include <tools/resmgr.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <svtools/filter.hxx> +#include <svl/solar.hrc> +#include <vcl/salbtype.hxx> +#include <vcl/virdev.hxx> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/text/GraphicCrop.hpp> + +#include "descriptor.hxx" +#include "graphic.hxx" +#include <svtools/grfmgr.hxx> +#include "provider.hxx" + +using namespace com::sun::star; + +namespace unographic { + +#define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:" + +// ------------------- +// - GraphicProvider - +// ------------------- + +uno::Reference< uno::XInterface > SAL_CALL GraphicProvider_CreateInstance( const uno::Reference< lang::XMultiServiceFactory >& ) +{ + return SAL_STATIC_CAST( ::cppu::OWeakObject*, new GraphicProvider ); +} + +GraphicProvider::GraphicProvider() +{ +} + +// ------------------------------------------------------------------------------ + +GraphicProvider::~GraphicProvider() +{ +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString GraphicProvider::getImplementationName_Static() + throw() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.graphic.GraphicProvider" ) ); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > GraphicProvider::getSupportedServiceNames_Static() + throw() +{ + uno::Sequence< ::rtl::OUString > aSeq( 1 ); + + aSeq.getArray()[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.GraphicProvider" ) ); + + return aSeq; +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString SAL_CALL GraphicProvider::getImplementationName() + throw( uno::RuntimeException ) +{ + return getImplementationName_Static(); +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL GraphicProvider::supportsService( const ::rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > aSNL( getSupportedServiceNames() ); + const ::rtl::OUString* pArray = aSNL.getConstArray(); + + for( int i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return true; + + return false; +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > SAL_CALL GraphicProvider::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return getSupportedServiceNames_Static(); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes() + throw(uno::RuntimeException) +{ + uno::Sequence< uno::Type > aTypes( 3 ); + uno::Type* pTypes = aTypes.getArray(); + + *pTypes++ = ::getCppuType((const uno::Reference< lang::XServiceInfo>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< lang::XTypeProvider>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< graphic::XGraphicProvider>*)0); + + return aTypes; +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId() + throw(uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + static uno::Sequence< sal_Int8 > aId; + + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( reinterpret_cast< sal_uInt8* >( aId.getArray() ), 0, sal_True ); + } + + return aId; +} + +// ------------------------------------------------------------------------------ + +uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadGraphicObject( const ::rtl::OUString& rResourceURL ) const +{ + uno::Reference< ::graphic::XGraphic > xRet; + if( rResourceURL.compareToAscii( UNO_NAME_GRAPHOBJ_URLPREFIX, RTL_CONSTASCII_LENGTH( UNO_NAME_GRAPHOBJ_URLPREFIX ) ) == 0 ) + { + // graphic manager url + String aTmpStr( rResourceURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 ) ); + ByteString aUniqueID( aTmpStr, RTL_TEXTENCODING_UTF8 ); + GraphicObject aGrafObj( aUniqueID ); + // I don't call aGrafObj.GetXGraphic because it will call us back + // into implLoadMemory ( with "private:memorygraphic" test ) + ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; + pUnoGraphic->init( aGrafObj.GetGraphic() ); + xRet = pUnoGraphic; + } + return xRet; +} + +uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( const ::rtl::OUString& rResourceURL ) const +{ + uno::Reference< ::graphic::XGraphic > xRet; + sal_Int32 nIndex = 0; + + if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:memorygraphic" ) ) ) + { + sal_Int64 nGraphicAddress = rResourceURL.getToken( 0, '/', nIndex ).toInt64(); + + if( nGraphicAddress ) + { + ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; + + pUnoGraphic->init( *reinterpret_cast< ::Graphic* >( nGraphicAddress ) ); + xRet = pUnoGraphic; + } + } + + return xRet; +} + +// ------------------------------------------------------------------------------ + +uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( const ::rtl::OUString& rResourceURL ) const +{ + uno::Reference< ::graphic::XGraphic > xRet; + sal_Int32 nIndex = 0; + + if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:graphicrepository" ) ) ) + { + String sPathName( rResourceURL.copy( nIndex ) ); + BitmapEx aBitmap; + if ( ::vcl::ImageRepository::loadImage( sPathName, aBitmap, false ) ) + { + Image aImage( aBitmap ); + xRet = aImage.GetXGraphic(); + } + } + return xRet; +} + + +// ------------------------------------------------------------------------------ + +uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadStandardImage( const ::rtl::OUString& rResourceURL ) const +{ + uno::Reference< ::graphic::XGraphic > xRet; + sal_Int32 nIndex = 0; + + if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:standardimage" ) ) ) + { + rtl::OUString sImageName( rResourceURL.copy( nIndex ) ); + if ( sImageName.compareToAscii( "info" ) ) + { + xRet = InfoBox::GetStandardImage().GetXGraphic(); + } + else if ( sImageName.compareToAscii( "warning" ) ) + { + xRet = WarningBox::GetStandardImage().GetXGraphic(); + } + else if ( sImageName.compareToAscii( "error" ) ) + { + xRet = ErrorBox::GetStandardImage().GetXGraphic(); + } + else if ( sImageName.compareToAscii( "query" ) ) + { + xRet = QueryBox::GetStandardImage().GetXGraphic(); + } + } + return xRet; +} + +// ------------------------------------------------------------------------------ + +uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadBitmap( const uno::Reference< awt::XBitmap >& xBtm ) const +{ + 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(), STREAM_READ ); + Bitmap aBmp; + aBmpStream >> aBmp; + + BitmapEx aBmpEx; + + if( aMaskSeq.getLength() ) + { + SvMemoryStream aMaskStream( aMaskSeq.getArray(), aMaskSeq.getLength(), STREAM_READ ); + Bitmap aMask; + aMaskStream >> aMask; + aBmpEx = BitmapEx( aBmp, aMask ); + } + else + aBmpEx = BitmapEx( aBmp ); + + if( !aBmpEx.IsEmpty() ) + { + ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; + + pUnoGraphic->init( aBmpEx ); + xRet = pUnoGraphic; + } + return xRet; +} + +// ------------------------------------------------------------------------------ + +uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadResource( const ::rtl::OUString& rResourceURL ) const +{ + uno::Reference< ::graphic::XGraphic > xRet; + sal_Int32 nIndex = 0; + + if( ( 0 == rResourceURL.getToken( 0, '/', nIndex ).compareToAscii( "private:resource" ) ) ) + { + ByteString aResMgrName( String( rResourceURL.getToken( 0, '/', nIndex ) ), RTL_TEXTENCODING_ASCII_US ); + + ResMgr* pResMgr = ResMgr::CreateResMgr( aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() ); + + if( pResMgr ) + { + const ::rtl::OUString aResourceType( rResourceURL.getToken( 0, '/', nIndex ) ); + const ResId aResId( rResourceURL.getToken( 0, '/', nIndex ).toInt32(), *pResMgr ); + + if( aResourceType.getLength() ) + { + BitmapEx aBmpEx; + + if( ( 0 == aResourceType.compareToAscii( "bitmap" ) ) || + ( 0 == aResourceType.compareToAscii( "bitmapex" ) ) ) + { + aResId.SetRT( RSC_BITMAP ); + + if( pResMgr->IsAvailable( aResId ) ) + { + aBmpEx = BitmapEx( aResId ); + } + } + else if( 0 == aResourceType.compareToAscii( "image" ) ) + { + aResId.SetRT( RSC_IMAGE ); + + if( pResMgr->IsAvailable( aResId ) ) + { + const Image aImage( aResId ); + aBmpEx = aImage.GetBitmapEx(); + } + } + else if( 0 == aResourceType.compareToAscii( "imagelist" ) ) + { + aResId.SetRT( RSC_IMAGELIST ); + + if( pResMgr->IsAvailable( aResId ) ) + { + const ImageList aImageList( aResId ); + sal_Int32 nImageId = ( nIndex > -1 ) ? rResourceURL.getToken( 0, '/', nIndex ).toInt32() : 0; + + if( 0 < nImageId ) + { + const Image aImage( aImageList.GetImage( sal::static_int_cast< USHORT >(nImageId) ) ); + aBmpEx = aImage.GetBitmapEx(); + } + else + { + aBmpEx = aImageList.GetAsHorizontalStrip(); + } + } + } + + if( !aBmpEx.IsEmpty() ) + { + ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; + + pUnoGraphic->init( aBmpEx ); + xRet = pUnoGraphic; + } + } + + delete pResMgr; + } + } + + return xRet; +} + +// ------------------------------------------------------------------------------ + +uno::Reference< beans::XPropertySet > SAL_CALL GraphicProvider::queryGraphicDescriptor( const uno::Sequence< beans::PropertyValue >& rMediaProperties ) + throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + uno::Reference< beans::XPropertySet > xRet; + + ::rtl::OUString aURL; + uno::Reference< io::XInputStream > xIStm; + uno::Reference< awt::XBitmap >xBtm; + + for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !xRet.is(); ++i ) + { + const ::rtl::OUString aName( rMediaProperties[ i ].Name ); + const uno::Any aValue( rMediaProperties[ i ].Value ); + + if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) ) + { + aValue >>= aURL; + } + else if( COMPARE_EQUAL == aName.compareToAscii( "InputStream" ) ) + { + aValue >>= xIStm; + } + else if( COMPARE_EQUAL == aName.compareToAscii( "Bitmap" ) ) + { + aValue >>= xBtm; + } + } + + if( xIStm.is() ) + { + GraphicDescriptor* pDescriptor = new GraphicDescriptor; + pDescriptor->init( xIStm, aURL ); + xRet = pDescriptor; + } + else if( aURL.getLength() ) + { + uno::Reference< ::graphic::XGraphic > xGraphic( implLoadMemory( aURL ) ); + if( !xGraphic.is() ) + xGraphic = implLoadResource( aURL ); + if( !xGraphic.is() ) + xGraphic = implLoadGraphicObject( aURL ); + + if ( !xGraphic.is() ) + xGraphic = implLoadRepositoryImage( aURL ); + + if ( !xGraphic.is() ) + xGraphic = implLoadStandardImage( aURL ); + + if( xGraphic.is() ) + { + xRet = uno::Reference< beans::XPropertySet >( xGraphic, uno::UNO_QUERY ); + } + else + { + GraphicDescriptor* pDescriptor = new GraphicDescriptor; + pDescriptor->init( aURL ); + xRet = pDescriptor; + } + } + else if( xBtm.is() ) + { + uno::Reference< ::graphic::XGraphic > xGraphic( implLoadBitmap( xBtm ) ); + if( xGraphic.is() ) + xRet = uno::Reference< beans::XPropertySet >( xGraphic, uno::UNO_QUERY ); + } + + return xRet; +} + +// ------------------------------------------------------------------------------ + +uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( const uno::Sequence< ::beans::PropertyValue >& rMediaProperties ) + throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + uno::Reference< ::graphic::XGraphic > xRet; + String aPath; + SvStream* pIStm = NULL; + + uno::Reference< io::XInputStream > xIStm; + uno::Reference< awt::XBitmap >xBtm; + + for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !pIStm && !xRet.is(); ++i ) + { + const ::rtl::OUString aName( rMediaProperties[ i ].Name ); + const uno::Any aValue( rMediaProperties[ i ].Value ); + + if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) ) + { + ::rtl::OUString aURL; + aValue >>= aURL; + aPath = aURL; + } + else if( COMPARE_EQUAL == aName.compareToAscii( "InputStream" ) ) + { + aValue >>= xIStm; + } + else if( COMPARE_EQUAL == aName.compareToAscii( "Bitmap" ) ) + { + aValue >>= xBtm; + } + } + + if( xIStm.is() ) + { + pIStm = ::utl::UcbStreamHelper::CreateStream( xIStm ); + } + else if( aPath.Len() ) + { + xRet = implLoadMemory( aPath ); + + if( !xRet.is() ) + xRet = implLoadGraphicObject( aPath ); + + if( !xRet.is() ) + xRet = implLoadResource( aPath ); + + if ( !xRet.is() ) + xRet = implLoadRepositoryImage( aPath ); + + if ( !xRet.is() ) + xRet = implLoadStandardImage( aPath ); + + if( !xRet.is() ) + pIStm = ::utl::UcbStreamHelper::CreateStream( aPath, STREAM_READ ); + } + else if( xBtm.is() ) + { + xRet = implLoadBitmap( xBtm ); + } + + if( pIStm ) + { + ::GraphicFilter* pFilter = ::GraphicFilter::GetGraphicFilter(); + + if( pFilter ) + { + ::Graphic aVCLGraphic; + + if( ( pFilter->ImportGraphic( aVCLGraphic, aPath, *pIStm ) == GRFILTER_OK ) && + ( aVCLGraphic.GetType() != GRAPHIC_NONE ) ) + { + ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; + + pUnoGraphic->init( aVCLGraphic ); + xRet = pUnoGraphic; + } + } + + delete pIStm; + } + + return xRet; +} + +void ImplCalculateCropRect( ::Graphic& rGraphic, const text::GraphicCrop& rGraphicCropLogic, Rectangle& rGraphicCropPixel ) +{ + if ( rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom ) + { + Size aSourceSizePixel( rGraphic.GetSizePixel() ); + if ( aSourceSizePixel.Width() && aSourceSizePixel.Height() ) + { + if ( rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom ) + { + Size aSize100thMM( 0, 0 ); + if( rGraphic.GetPrefMapMode().GetMapUnit() != MAP_PIXEL ) + { + aSize100thMM = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MAP_100TH_MM ); + } + else + { + aSize100thMM = Application::GetDefaultDevice()->PixelToLogic( rGraphic.GetPrefSize(), MAP_100TH_MM ); + } + if ( aSize100thMM.Width() && aSize100thMM.Height() ) + { + double fSourceSizePixelWidth = static_cast<double>(aSourceSizePixel.Width()); + double fSourceSizePixelHeight= static_cast<double>(aSourceSizePixel.Height()); + rGraphicCropPixel.Left() = static_cast< sal_Int32 >((fSourceSizePixelWidth * rGraphicCropLogic.Left ) / aSize100thMM.Width()); + rGraphicCropPixel.Top() = static_cast< sal_Int32 >((fSourceSizePixelHeight * rGraphicCropLogic.Top ) / aSize100thMM.Height()); + rGraphicCropPixel.Right() = static_cast< sal_Int32 >(( fSourceSizePixelWidth * ( aSize100thMM.Width() - rGraphicCropLogic.Right ) ) / aSize100thMM.Width() ); + rGraphicCropPixel.Bottom() = 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 ) + { + const double fImageResolution = static_cast<double>( nImageResolution ); + const double fSourceDPIX = ( static_cast<double>(rVisiblePixelSize.Width()) * 2540.0 ) / static_cast<double>(rLogicalSize.Width); + const double fSourceDPIY = ( static_cast<double>(rVisiblePixelSize.Height()) * 2540.0 ) / static_cast<double>(rLogicalSize.Height); + const sal_Int32 nSourcePixelWidth( rGraphic.GetSizePixel().Width() ); + const sal_Int32 nSourcePixelHeight( rGraphic.GetSizePixel().Height() ); + const double fSourcePixelWidth = static_cast<double>( nSourcePixelWidth ); + const double fSourcePixelHeight= static_cast<double>( nSourcePixelHeight ); + + sal_Int32 nDestPixelWidth = nSourcePixelWidth; + sal_Int32 nDestPixelHeight = nSourcePixelHeight; + + // check, if the bitmap DPI exceeds the maximum DPI + if( fSourceDPIX > fImageResolution ) + { + nDestPixelWidth = static_cast<sal_Int32>(( fSourcePixelWidth * fImageResolution ) / fSourceDPIX); + if ( !nDestPixelWidth || ( nDestPixelWidth > nSourcePixelWidth ) ) + nDestPixelWidth = nSourcePixelWidth; + } + if ( fSourceDPIY > fImageResolution ) + { + nDestPixelHeight= static_cast<sal_Int32>(( fSourcePixelHeight* fImageResolution ) / fSourceDPIY); + if ( !nDestPixelHeight || ( nDestPixelHeight > nSourcePixelHeight ) ) + nDestPixelHeight = nSourcePixelHeight; + } + if ( ( nDestPixelWidth != nSourcePixelWidth ) || ( nDestPixelHeight != nSourcePixelHeight ) ) + ImplApplyBitmapScaling( rGraphic, nDestPixelWidth, nDestPixelHeight ); + } +} + +void ImplApplyFilterData( ::Graphic& rGraphic, 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 ); + sal_Bool bRemoveCropArea = sal_True; + + for( sal_Int32 i = 0; i < rFilterData.getLength(); ++i ) + { + const ::rtl::OUString aName( rFilterData[ i ].Name ); + const uno::Any aValue( rFilterData[ i ].Value ); + + if( COMPARE_EQUAL == aName.compareToAscii( "PixelWidth" ) ) + aValue >>= nPixelWidth; + else if( COMPARE_EQUAL == aName.compareToAscii( "PixelHeight" ) ) + aValue >>= nPixelHeight; + else if( COMPARE_EQUAL == aName.compareToAscii( "LogicalSize" ) ) + aValue >>= aLogicalSize; + else if (COMPARE_EQUAL == aName.compareToAscii( "GraphicCropLogic" ) ) + aValue >>= aCropLogic; + else if (COMPARE_EQUAL == aName.compareToAscii( "RemoveCropArea" ) ) + aValue >>= bRemoveCropArea; + else if (COMPARE_EQUAL == aName.compareToAscii( "ImageResolution" ) ) + aValue >>= nImageResolution; + } + if ( rGraphic.GetType() == GRAPHIC_BITMAP ) + { + 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() == GRAPHIC_GDIMETAFILE ) && nImageResolution ) + { + VirtualDevice aDummyVDev; + GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() ); + Size aMtfSize( aDummyVDev.LogicToLogic( aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MAP_100TH_MM ) ); + if ( aMtfSize.Width() && aMtfSize.Height() ) + { + MapMode aNewMapMode( MAP_100TH_MM ); + aNewMapMode.SetScaleX( static_cast< double >( aLogicalSize.Width ) / static_cast< double >( aMtfSize.Width() ) ); + aNewMapMode.SetScaleY( static_cast< double >( aLogicalSize.Height ) / static_cast< double >( aMtfSize.Height() ) ); + aDummyVDev.EnableOutput( sal_False ); + aDummyVDev.SetMapMode( aNewMapMode ); + + for( sal_uInt32 i = 0, nObjCount = aMtf.GetActionCount(); i < nObjCount; i++ ) + { + MetaAction* pAction = aMtf.GetAction( i ); + switch( pAction->GetType() ) + { + // only optimizing common bitmap actions: + case( META_MAPMODE_ACTION ): + { + const_cast< MetaAction* >( pAction )->Execute( &aDummyVDev ); + break; + } + case( META_PUSH_ACTION ): + { + const MetaPushAction* pA = (const MetaPushAction*)pAction; + aDummyVDev.Push( pA->GetFlags() ); + break; + } + case( META_POP_ACTION ): + { + aDummyVDev.Pop(); + break; + } + case( META_BMPSCALE_ACTION ): + case( META_BMPEXSCALE_ACTION ): + { + BitmapEx aBmpEx; + Point aPos; + Size aSize; + if ( pAction->GetType() == META_BMPSCALE_ACTION ) + { + MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction ); + aBmpEx = pScaleAction->GetBitmap(); + aPos = pScaleAction->GetPoint(); + aSize = pScaleAction->GetSize(); + } + else + { + MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction ); + aBmpEx = pScaleAction->GetBitmapEx(); + aPos = pScaleAction->GetPoint(); + aSize = pScaleAction->GetSize(); + } + ::Graphic aGraphic( aBmpEx ); + const Size aSize100thmm( aDummyVDev.LogicToPixel( aSize ) ); + Size aSize100thmm2( aDummyVDev.PixelToLogic( aSize100thmm, MAP_100TH_MM ) ); + + ImplApplyBitmapResolution( aGraphic, nImageResolution, + aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) ); + + MetaAction* pNewAction; + if ( pAction->GetType() == META_BMPSCALE_ACTION ) + pNewAction = new MetaBmpScaleAction ( aPos, aSize, aGraphic.GetBitmap() ); + else + pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() ); + + aMtf.ReplaceAction( pNewAction, i ); + pAction->Delete(); + break; + } + default: + case( META_BMP_ACTION ): + case( META_BMPSCALEPART_ACTION ): + case( META_BMPEX_ACTION ): + case( META_BMPEXSCALEPART_ACTION ): + case( META_MASK_ACTION ): + case( META_MASKSCALE_ACTION ): + break; + } + } + rGraphic = aMtf; + } + } +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties ) + throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + SvStream* pOStm = NULL; + String aPath; + sal_Int32 i; + + for( i = 0; ( i < rMediaProperties.getLength() ) && !pOStm; ++i ) + { + const ::rtl::OUString aName( rMediaProperties[ i ].Name ); + const uno::Any aValue( rMediaProperties[ i ].Value ); + + if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) ) + { + ::rtl::OUString aURL; + + aValue >>= aURL; + pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, STREAM_WRITE | STREAM_TRUNC ); + aPath = aURL; + } + else if( COMPARE_EQUAL == aName.compareToAscii( "OutputStream" ) ) + { + uno::Reference< io::XStream > xOStm; + + aValue >>= xOStm; + + if( xOStm.is() ) + pOStm = ::utl::UcbStreamHelper::CreateStream( xOStm ); + } + } + + if( pOStm ) + { + uno::Sequence< beans::PropertyValue > aFilterDataSeq; + const char* pFilterShortName = NULL; + + for( i = 0; i < rMediaProperties.getLength(); ++i ) + { + const ::rtl::OUString aName( rMediaProperties[ i ].Name ); + const uno::Any aValue( rMediaProperties[ i ].Value ); + + if( COMPARE_EQUAL == aName.compareToAscii( "FilterData" ) ) + { + aValue >>= aFilterDataSeq; + } + else if( COMPARE_EQUAL == aName.compareToAscii( "MimeType" ) ) + { + ::rtl::OUString aMimeType; + + aValue >>= aMimeType; + + if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_BMP ) ) + pFilterShortName = "bmp"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_EPS ) ) + pFilterShortName = "eps"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_GIF ) ) + pFilterShortName = "gif"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_JPG ) ) + pFilterShortName = "jpg"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_MET ) ) + pFilterShortName = "met"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PNG ) ) + pFilterShortName = "png"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PCT ) ) + pFilterShortName = "pct"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PBM ) ) + pFilterShortName = "pbm"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PGM ) ) + pFilterShortName = "pgm"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PPM ) ) + pFilterShortName = "ppm"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_RAS ) ) + pFilterShortName = "ras"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_SVM ) ) + pFilterShortName = "svm"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_TIF ) ) + pFilterShortName = "tif"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_EMF ) ) + pFilterShortName = "emf"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_WMF ) ) + pFilterShortName = "wmf"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_XPM ) ) + pFilterShortName = "xpm"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_SVG ) ) + pFilterShortName = "svg"; + else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_VCLGRAPHIC ) ) + pFilterShortName = MIMETYPE_VCLGRAPHIC; + } + } + + if( pFilterShortName ) + { + ::GraphicFilter* pFilter = ::GraphicFilter::GetGraphicFilter(); + + if( pFilter ) + { + const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY ); + const ::Graphic* pGraphic = ::unographic::Graphic::getImplementation( xIFace ); + + if( pGraphic && ( pGraphic->GetType() != GRAPHIC_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( 0 == strcmp( pFilterShortName, MIMETYPE_VCLGRAPHIC ) ) + aMemStrm << aGraphic; + else + { + pFilter->ExportGraphic( aGraphic, aPath, aMemStrm, + pFilter->GetExportFormatNumberForShortName( ::rtl::OUString::createFromAscii( pFilterShortName ) ), + ( aFilterDataSeq.getLength() ? &aFilterDataSeq : NULL ) ); + } + aMemStrm.Seek( STREAM_SEEK_TO_END ); + pOStm->Write( aMemStrm.GetData(), aMemStrm.Tell() ); + } + } + } + delete pOStm; + } +} + +} |