diff options
author | Mathias Bauer <mba@openoffice.org> | 2009-12-15 21:55:40 +0100 |
---|---|---|
committer | Mathias Bauer <mba@openoffice.org> | 2009-12-15 21:55:40 +0100 |
commit | 4770f50e0c8e6706f0f514bd73a8bcfd7dd88cb3 (patch) | |
tree | b21b3409ecc71d4802ab2f5eafd6e01c3bfd5254 /svtools/source | |
parent | 003fc5390522ecad9e1f3a2c99b2a0a324ae5473 (diff) |
#i107706#: liquidate goodies module
Diffstat (limited to 'svtools/source')
-rw-r--r-- | svtools/source/graphic/descriptor.cxx | 501 | ||||
-rw-r--r-- | svtools/source/graphic/descriptor.hxx | 143 | ||||
-rw-r--r-- | svtools/source/graphic/graphic.cxx | 303 | ||||
-rw-r--r-- | svtools/source/graphic/graphic.hxx | 106 | ||||
-rw-r--r-- | svtools/source/graphic/graphicunofactory.cxx | 106 | ||||
-rw-r--r-- | svtools/source/graphic/grfattr.cxx | 121 | ||||
-rw-r--r-- | svtools/source/graphic/grfcache.cxx | 1055 | ||||
-rw-r--r-- | svtools/source/graphic/grfcache.hxx | 112 | ||||
-rw-r--r-- | svtools/source/graphic/grfmgr.cxx | 1319 | ||||
-rw-r--r-- | svtools/source/graphic/grfmgr2.cxx | 2385 | ||||
-rw-r--r-- | svtools/source/graphic/makefile.mk | 70 | ||||
-rw-r--r-- | svtools/source/graphic/provider.cxx | 864 | ||||
-rw-r--r-- | svtools/source/graphic/renderer.cxx | 348 | ||||
-rw-r--r-- | svtools/source/graphic/transformer.cxx | 159 | ||||
-rw-r--r-- | svtools/source/graphic/transformer.hxx | 66 | ||||
-rw-r--r-- | svtools/source/inc/provider.hxx | 85 | ||||
-rw-r--r-- | svtools/source/inc/renderer.hxx | 103 | ||||
-rw-r--r-- | svtools/source/uno/miscservices.cxx | 68 |
18 files changed, 7910 insertions, 4 deletions
diff --git a/svtools/source/graphic/descriptor.cxx b/svtools/source/graphic/descriptor.cxx new file mode 100644 index 000000000000..f4ef69982cea --- /dev/null +++ b/svtools/source/graphic/descriptor.cxx @@ -0,0 +1,501 @@ +/************************************************************************* + * + * 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: descriptor.cxx,v $ + * $Revision: 1.10 $ + * + * 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 "descriptor.hxx" + +#include <rtl/uuid.h> +#include <vos/mutex.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <svtools/filter.hxx> +#include <svl/itemprop.hxx> + +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/graphic/GraphicType.hpp> + +#include "vcl/graph.hxx" +#include "vcl/svapp.hxx" + +#define UNOGRAPHIC_GRAPHICTYPE 1 +#define UNOGRAPHIC_MIMETYPE 2 +#define UNOGRAPHIC_SIZEPIXEL 3 +#define UNOGRAPHIC_SIZE100THMM 4 +#define UNOGRAPHIC_BITSPERPIXEL 5 +#define UNOGRAPHIC_TRANSPARENT 6 +#define UNOGRAPHIC_ALPHA 7 +#define UNOGRAPHIC_ANIMATED 8 + +using namespace ::com::sun::star; + +namespace unographic { + +// --------------------- +// - GraphicDescriptor - +// --------------------- + +GraphicDescriptor::GraphicDescriptor() : + ::comphelper::PropertySetHelper( createPropertySetInfo(), SAL_NO_ACQUIRE ), + mpGraphic( NULL ), + meType( GRAPHIC_NONE ), + mnBitsPerPixel ( 0 ), + mbTransparent ( false ), + mbAlpha( false ), + mbAnimated( false ) +{ +} + +// ------------------------------------------------------------------------------ + +GraphicDescriptor::~GraphicDescriptor() + throw() +{ +} + +// ------------------------------------------------------------------------------ + +void GraphicDescriptor::init( const ::Graphic& rGraphic ) + throw() +{ + mpGraphic = &rGraphic; +} + +// ------------------------------------------------------------------------------ + +void GraphicDescriptor::init( const ::rtl::OUString& rURL ) + throw() +{ + SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( rURL, STREAM_READ ); + + if( pIStm ) + { + implCreate( *pIStm, &rURL ); + delete pIStm; + } +} + +// ------------------------------------------------------------------------------ + +void GraphicDescriptor::init( const uno::Reference< io::XInputStream >& rxIStm, const ::rtl::OUString& rURL ) + throw() +{ + SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( rxIStm ); + + if( pIStm ) + { + implCreate( *pIStm, &rURL ); + delete pIStm; + } +} + +// ------------------------------------------------------------------------------ + +bool GraphicDescriptor::isValid() const +{ + return( mpGraphic ? ( mpGraphic->GetType() != GRAPHIC_NONE ) : ( meType != GRAPHIC_NONE ) ); +} + +// ------------------------------------------------------------------------------ + +void GraphicDescriptor::implCreate( SvStream& rIStm, const ::rtl::OUString* pURL ) +{ + String aURL; + if( pURL ) + aURL = *pURL; + ::GraphicDescriptor aDescriptor( rIStm, &aURL ); + + mpGraphic = NULL; + maMimeType = ::rtl::OUString(); + meType = GRAPHIC_NONE; + mnBitsPerPixel = 0; + mbTransparent = false; + + if( aDescriptor.Detect( true ) && aDescriptor.GetFileFormat() != GFF_NOT ) + { + const char* pMimeType = NULL; + sal_uInt8 cType = graphic::GraphicType::EMPTY; + + switch( aDescriptor.GetFileFormat() ) + { + case( GFF_BMP ): pMimeType = MIMETYPE_BMP; cType = graphic::GraphicType::PIXEL; break; + case( GFF_GIF ): pMimeType = MIMETYPE_GIF; cType = graphic::GraphicType::PIXEL; break; + case( GFF_JPG ): pMimeType = MIMETYPE_JPG; cType = graphic::GraphicType::PIXEL; break; + case( GFF_PCD ): pMimeType = MIMETYPE_PCD; cType = graphic::GraphicType::PIXEL; break; + case( GFF_PCX ): pMimeType = MIMETYPE_PCX; cType = graphic::GraphicType::PIXEL; break; + case( GFF_PNG ): pMimeType = MIMETYPE_PNG; cType = graphic::GraphicType::PIXEL; break; + case( GFF_TIF ): pMimeType = MIMETYPE_TIF; cType = graphic::GraphicType::PIXEL; break; + case( GFF_XBM ): pMimeType = MIMETYPE_XBM; cType = graphic::GraphicType::PIXEL; break; + case( GFF_XPM ): pMimeType = MIMETYPE_XPM; cType = graphic::GraphicType::PIXEL; break; + case( GFF_PBM ): pMimeType = MIMETYPE_PBM; cType = graphic::GraphicType::PIXEL; break; + case( GFF_PGM ): pMimeType = MIMETYPE_PGM; cType = graphic::GraphicType::PIXEL; break; + case( GFF_PPM ): pMimeType = MIMETYPE_PPM; cType = graphic::GraphicType::PIXEL; break; + case( GFF_RAS ): pMimeType = MIMETYPE_RAS; cType = graphic::GraphicType::PIXEL; break; + case( GFF_TGA ): pMimeType = MIMETYPE_TGA; cType = graphic::GraphicType::PIXEL; break; + case( GFF_PSD ): pMimeType = MIMETYPE_PSD; cType = graphic::GraphicType::PIXEL; break; + + case( GFF_EPS ): pMimeType = MIMETYPE_EPS; cType = graphic::GraphicType::VECTOR; break; + case( GFF_DXF ): pMimeType = MIMETYPE_DXF; cType = graphic::GraphicType::VECTOR; break; + case( GFF_MET ): pMimeType = MIMETYPE_MET; cType = graphic::GraphicType::VECTOR; break; + case( GFF_PCT ): pMimeType = MIMETYPE_PCT; cType = graphic::GraphicType::VECTOR; break; + case( GFF_SGF ): pMimeType = MIMETYPE_SGF; cType = graphic::GraphicType::VECTOR; break; + case( GFF_SVM ): pMimeType = MIMETYPE_SVM; cType = graphic::GraphicType::VECTOR; break; + case( GFF_WMF ): pMimeType = MIMETYPE_WMF; cType = graphic::GraphicType::VECTOR; break; + case( GFF_SGV ): pMimeType = MIMETYPE_SGV; cType = graphic::GraphicType::VECTOR; break; + case( GFF_EMF ): pMimeType = MIMETYPE_EMF; cType = graphic::GraphicType::VECTOR; break; + + default: + break; + } + + if( graphic::GraphicType::EMPTY != cType ) + { + meType = ( ( graphic::GraphicType::PIXEL == cType ) ? GRAPHIC_BITMAP : GRAPHIC_GDIMETAFILE ); + maMimeType = String( pMimeType, RTL_TEXTENCODING_ASCII_US ); + maSizePixel = aDescriptor.GetSizePixel(); + maSize100thMM = aDescriptor.GetSize_100TH_MM(); + mnBitsPerPixel = aDescriptor.GetBitsPerPixel(); + mbTransparent = ( graphic::GraphicType::VECTOR == cType ); + mbAlpha = mbAnimated = false; + } + } +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString GraphicDescriptor::getImplementationName_Static() + throw() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.graphic.GraphicDescriptor" ) ); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > GraphicDescriptor::getSupportedServiceNames_Static() + throw( ) +{ + uno::Sequence< ::rtl::OUString > aSeq( 1 ); + + aSeq.getArray()[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.GraphicDescriptor" ) ); + + return aSeq; +} + +// ------------------------------------------------------------------------------ + +uno::Any SAL_CALL GraphicDescriptor::queryAggregation( const uno::Type & rType ) + throw( uno::RuntimeException ) +{ + uno::Any aAny; + + if( rType == ::getCppuType((const uno::Reference< lang::XServiceInfo >*)0) ) + aAny <<= uno::Reference< lang::XServiceInfo >(this); + else if( rType == ::getCppuType((const uno::Reference< lang::XTypeProvider >*)0) ) + aAny <<= uno::Reference< lang::XTypeProvider >(this); + else if( rType == ::getCppuType((const uno::Reference< beans::XPropertySet >*)0) ) + aAny <<= uno::Reference< beans::XPropertySet >(this); + else if( rType == ::getCppuType((const uno::Reference< beans::XPropertyState >*)0) ) + aAny <<= uno::Reference< beans::XPropertyState >(this); + else if( rType == ::getCppuType((const uno::Reference< beans::XMultiPropertySet >*)0) ) + aAny <<= uno::Reference< beans::XMultiPropertySet >(this); + else + aAny <<= OWeakAggObject::queryAggregation( rType ); + + return aAny; +} + +// ------------------------------------------------------------------------------ + +uno::Any SAL_CALL GraphicDescriptor::queryInterface( const uno::Type & rType ) + throw( uno::RuntimeException ) +{ + return OWeakAggObject::queryInterface( rType ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL GraphicDescriptor::acquire() + throw() +{ + OWeakAggObject::acquire(); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL GraphicDescriptor::release() + throw() +{ + OWeakAggObject::release(); +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString SAL_CALL GraphicDescriptor::getImplementationName() + throw( uno::RuntimeException ) +{ + return getImplementationName_Static(); +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL GraphicDescriptor::supportsService( const rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > aSNL( getSupportedServiceNames() ); + const ::rtl::OUString* pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return true; + + return false; +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< rtl::OUString > SAL_CALL GraphicDescriptor::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return getSupportedServiceNames_Static(); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< uno::Type > SAL_CALL GraphicDescriptor::getTypes() + throw( uno::RuntimeException ) +{ + uno::Sequence< uno::Type > aTypes( 6 ); + uno::Type* pTypes = aTypes.getArray(); + + *pTypes++ = ::getCppuType((const uno::Reference< uno::XAggregation>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< lang::XServiceInfo>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< lang::XTypeProvider>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< beans::XPropertySet>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< beans::XPropertyState>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< beans::XMultiPropertySet>*)0); + + return aTypes; +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< sal_Int8 > SAL_CALL GraphicDescriptor::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; +} + +// ------------------------------------------------------------------------------ + +::comphelper::PropertySetInfo* GraphicDescriptor::createPropertySetInfo() +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + ::comphelper::PropertySetInfo* pRet = new ::comphelper::PropertySetInfo(); + + static ::comphelper::PropertyMapEntry aEntries[] = + { + { MAP_CHAR_LEN( "GraphicType" ), UNOGRAPHIC_GRAPHICTYPE, &::getCppuType( (const sal_Int8*)(0)), beans::PropertyAttribute::READONLY, 0 }, + { MAP_CHAR_LEN( "MimeType" ), UNOGRAPHIC_MIMETYPE, &::getCppuType( (const ::rtl::OUString*)(0)), beans::PropertyAttribute::READONLY, 0 }, + { MAP_CHAR_LEN( "SizePixel" ), UNOGRAPHIC_SIZEPIXEL, &::getCppuType( (const awt::Size*)(0)), beans::PropertyAttribute::READONLY, 0 }, + { MAP_CHAR_LEN( "Size100thMM" ), UNOGRAPHIC_SIZE100THMM, &::getCppuType( (const awt::Size*)(0)), beans::PropertyAttribute::READONLY, 0 }, + { MAP_CHAR_LEN( "BitsPerPixel" ), UNOGRAPHIC_BITSPERPIXEL, &::getCppuType( (const sal_uInt8*)(0)), beans::PropertyAttribute::READONLY, 0 }, + { MAP_CHAR_LEN( "Transparent" ), UNOGRAPHIC_TRANSPARENT, &::getCppuType( (const sal_Bool*)(0)), beans::PropertyAttribute::READONLY, 0 }, + { MAP_CHAR_LEN( "Alpha" ), UNOGRAPHIC_ALPHA, &::getCppuType( (const sal_Bool*)(0)), beans::PropertyAttribute::READONLY, 0 }, + { MAP_CHAR_LEN( "Animated" ), UNOGRAPHIC_ANIMATED, &::getCppuType( (const sal_Bool*)(0)), beans::PropertyAttribute::READONLY, 0 }, + + { 0,0,0,0,0,0 } + }; + + pRet->acquire(); + pRet->add( aEntries ); + + return pRet; +} + +// ------------------------------------------------------------------------------ + +void GraphicDescriptor::_setPropertyValues( const comphelper::PropertyMapEntry** /*ppEntries*/, const uno::Any* /*pValues*/ ) + throw( beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException ) +{ + // we only have readonly attributes +} + +// ------------------------------------------------------------------------------ + +void GraphicDescriptor::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, uno::Any* pValues ) + throw( beans::UnknownPropertyException, lang::WrappedTargetException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + while( *ppEntries ) + { + switch( (*ppEntries)->mnHandle ) + { + case( UNOGRAPHIC_GRAPHICTYPE ): + { + const GraphicType eType( mpGraphic ? mpGraphic->GetType() : meType ); + + *pValues <<= ( ( eType == GRAPHIC_BITMAP ? graphic::GraphicType::PIXEL : + ( eType == GRAPHIC_GDIMETAFILE ? graphic::GraphicType::VECTOR : + graphic::GraphicType::EMPTY ) ) ); + } + break; + + case( UNOGRAPHIC_MIMETYPE ): + { + ::rtl::OUString aMimeType; + + if( mpGraphic ) + { + if( mpGraphic->IsLink() ) + { + const char* pMimeType; + + switch( const_cast< Graphic* >( mpGraphic )->GetLink().GetType() ) + { + case( GFX_LINK_TYPE_NATIVE_GIF ): pMimeType = MIMETYPE_GIF; break; + case( GFX_LINK_TYPE_NATIVE_JPG ): pMimeType = MIMETYPE_JPG; break; + case( GFX_LINK_TYPE_NATIVE_PNG ): pMimeType = MIMETYPE_PNG; break; + case( GFX_LINK_TYPE_NATIVE_WMF ): pMimeType = MIMETYPE_WMF; break; + case( GFX_LINK_TYPE_NATIVE_MET ): pMimeType = MIMETYPE_MET; break; + case( GFX_LINK_TYPE_NATIVE_PCT ): pMimeType = MIMETYPE_PCT ; break; + + default: + pMimeType = NULL; + break; + } + + if( pMimeType ) + aMimeType = ::rtl::OUString::createFromAscii( pMimeType ); + } + + if( !aMimeType.getLength() && ( mpGraphic->GetType() != GRAPHIC_NONE ) ) + aMimeType = ::rtl::OUString::createFromAscii( MIMETYPE_VCLGRAPHIC ); + } + else + aMimeType = maMimeType; + + *pValues <<= aMimeType; + } + break; + + case( UNOGRAPHIC_SIZEPIXEL ): + { + awt::Size aAWTSize( 0, 0 ); + + if( mpGraphic ) + { + if( mpGraphic->GetType() == GRAPHIC_BITMAP ) + { + const Size aSizePix( mpGraphic->GetBitmapEx().GetSizePixel() ); + aAWTSize = awt::Size( aSizePix.Width(), aSizePix.Height() ); + } + } + else + aAWTSize = awt::Size( maSizePixel.Width(), maSizePixel.Height() ); + + *pValues <<= aAWTSize; + } + break; + + case( UNOGRAPHIC_SIZE100THMM ): + { + awt::Size aAWTSize( 0, 0 ); + + if( mpGraphic ) + { + if( mpGraphic->GetPrefMapMode().GetMapUnit() != MAP_PIXEL ) + { + const Size aSizeLog( OutputDevice::LogicToLogic( mpGraphic->GetPrefSize(), mpGraphic->GetPrefMapMode(), MAP_100TH_MM ) ); + aAWTSize = awt::Size( aSizeLog.Width(), aSizeLog.Height() ); + } + } + else + aAWTSize = awt::Size( maSize100thMM.Width(), maSize100thMM.Height() ); + + *pValues <<= aAWTSize; + } + break; + + case( UNOGRAPHIC_BITSPERPIXEL ): + { + USHORT nBitsPerPixel = 0; + + if( mpGraphic ) + { + if( mpGraphic->GetType() == GRAPHIC_BITMAP ) + nBitsPerPixel = mpGraphic->GetBitmapEx().GetBitmap().GetBitCount(); + } + else + nBitsPerPixel = mnBitsPerPixel; + + *pValues <<= sal::static_int_cast< sal_Int8 >(nBitsPerPixel); + } + break; + + case( UNOGRAPHIC_TRANSPARENT ): + { + *pValues <<= static_cast< sal_Bool >( mpGraphic ? mpGraphic->IsTransparent() : mbTransparent ); + } + break; + + case( UNOGRAPHIC_ALPHA ): + { + *pValues <<= static_cast< sal_Bool >( mpGraphic ? mpGraphic->IsAlpha() : mbAlpha ); + } + break; + + case( UNOGRAPHIC_ANIMATED ): + { + *pValues <<= static_cast< sal_Bool >( mpGraphic ? mpGraphic->IsAnimated() : mbAnimated ); + } + break; + } + + ++ppEntries; + ++pValues; + } +} + +} diff --git a/svtools/source/graphic/descriptor.hxx b/svtools/source/graphic/descriptor.hxx new file mode 100644 index 000000000000..5bbb982846ff --- /dev/null +++ b/svtools/source/graphic/descriptor.hxx @@ -0,0 +1,143 @@ +/************************************************************************* + * + * 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: descriptor.hxx,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _GOODIES_DESCRIPTOR_HXX +#define _GOODIES_DESCRIPTOR_HXX + +#include <comphelper/propertysethelper.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <comphelper/propertysetinfo.hxx> +#include <vcl/graph.hxx> + +#define MIMETYPE_BMP "image/x-MS-bmp" +#define MIMETYPE_GIF "image/gif" +#define MIMETYPE_JPG "image/jpeg" +#define MIMETYPE_PCD "image/x-photo-cd" +#define MIMETYPE_PCX "image/x-pcx" +#define MIMETYPE_PNG "image/png" +#define MIMETYPE_TIF "image/tiff" +#define MIMETYPE_XBM "image/x-xbitmap" +#define MIMETYPE_XPM "image/x-xpixmap" +#define MIMETYPE_PBM "image/x-portable-bitmap" +#define MIMETYPE_PGM "image/x-portable-graymap" +#define MIMETYPE_PPM "image/x-portable-pixmap" +#define MIMETYPE_RAS "image/x-cmu-raster" +#define MIMETYPE_TGA "image/x-targa" +#define MIMETYPE_PSD "image/vnd.adobe.photoshop" +#define MIMETYPE_EPS "image/x-eps" +#define MIMETYPE_DXF "image/vnd.dxf" +#define MIMETYPE_MET "image/x-met" +#define MIMETYPE_PCT "image/x-pict" +#define MIMETYPE_SGF "image/x-sgf" +#define MIMETYPE_SVM "image/x-svm" +#define MIMETYPE_WMF "image/x-wmf" +#define MIMETYPE_SGV "image/x-sgv" +#define MIMETYPE_EMF "image/x-emf" +#define MIMETYPE_SVG "image/svg+xml" +#define MIMETYPE_VCLGRAPHIC "image/x-vclgraphic" + +using namespace com::sun::star; + +namespace comphelper { class PropertySetInfo; } +namespace com { namespace sun { namespace star { namespace io { class XInputStream; } } } } + +class Graphic; + +namespace unographic { + +// ------------------- +// - GraphicProvider - +// ------------------- + +class GraphicDescriptor : public ::cppu::OWeakAggObject, + public ::com::sun::star::lang::XServiceInfo, + public ::com::sun::star::lang::XTypeProvider, + public ::comphelper::PropertySetHelper +{ +public: + + GraphicDescriptor(); + ~GraphicDescriptor() throw(); + + void init( const ::Graphic& rGraphic ) throw(); + void init( const ::rtl::OUString& rURL ) throw(); + void init( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxIStm, const ::rtl::OUString& rURL ) throw(); + + bool isValid() const; + + static ::rtl::OUString getImplementationName_Static() throw(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static() throw(); + +protected: + + static ::comphelper::PropertySetInfo* createPropertySetInfo(); + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XServiceInfo + virtual rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException); + + // PropertySetHelper + virtual void _setPropertyValues( const comphelper::PropertyMapEntry** ppEntries, const ::com::sun::star::uno::Any* pValues ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException ); + virtual void _getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, ::com::sun::star::uno::Any* pValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException ); + +private: + + const ::Graphic* mpGraphic; + GraphicType meType; + ::rtl::OUString maMimeType; + Size maSizePixel; + Size maSize100thMM; + USHORT mnBitsPerPixel; + bool mbTransparent; + bool mbAlpha; + bool mbAnimated; + + GraphicDescriptor( const GraphicDescriptor& rDescriptor ); + + GraphicDescriptor& operator=( const GraphicDescriptor& ); + + void implCreate( SvStream& rIStm, const ::rtl::OUString* pPath ); +}; + +} + +#endif diff --git a/svtools/source/graphic/graphic.cxx b/svtools/source/graphic/graphic.cxx new file mode 100644 index 000000000000..aa1d276c437f --- /dev/null +++ b/svtools/source/graphic/graphic.cxx @@ -0,0 +1,303 @@ +/************************************************************************* + * + * 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: graphic.cxx,v $ + * $Revision: 1.7 $ + * + * 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 <com/sun/star/graphic/GraphicType.hpp> +#include <com/sun/star/graphic/XGraphicTransformer.hpp> +#include <vcl/graph.hxx> +#include "graphic.hxx" + +using namespace com::sun::star; + +namespace unographic { + +// ------------------- +// - GraphicProvider - +// ------------------- + +Graphic::Graphic() : + mpGraphic( NULL ) +{ +} + +// ------------------------------------------------------------------------------ + +Graphic::~Graphic() + throw() +{ + delete mpGraphic; +} + +// ------------------------------------------------------------------------------ + +void Graphic::init( const ::Graphic& rGraphic ) + throw() +{ + delete mpGraphic; + mpGraphic = new ::Graphic( rGraphic ); + ::unographic::GraphicDescriptor::init( *mpGraphic ); +} + +// ------------------------------------------------------------------------------ + +uno::Any SAL_CALL Graphic::queryAggregation( const uno::Type& rType ) + throw( uno::RuntimeException ) +{ + uno::Any aAny; + if( rType == ::getCppuType((const uno::Reference< graphic::XGraphic >*)0) ) + aAny <<= uno::Reference< graphic::XGraphic >( this ); + else if( rType == ::getCppuType((const uno::Reference< awt::XBitmap >*)0) ) + aAny <<= uno::Reference< awt::XBitmap >( this ); + else if( rType == ::getCppuType((const uno::Reference< lang::XUnoTunnel >*)0) ) + aAny <<= uno::Reference< lang::XUnoTunnel >(this); + else + aAny <<= ::unographic::GraphicDescriptor::queryAggregation( rType ); + + return aAny ; +} + +// ------------------------------------------------------------------------------ + +uno::Any SAL_CALL Graphic::queryInterface( const uno::Type & rType ) + throw( uno::RuntimeException ) +{ + ::com::sun::star::uno::Any aReturn = ::unographic::GraphicDescriptor::queryInterface( rType ); + if ( !aReturn.hasValue() ) + aReturn = ::cppu::queryInterface ( rType, static_cast< graphic::XGraphicTransformer*>( this ) ); + return aReturn; +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Graphic::acquire() + throw() +{ + ::unographic::GraphicDescriptor::acquire(); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL Graphic::release() throw() +{ + ::unographic::GraphicDescriptor::release(); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< sal_Int8 > SAL_CALL Graphic::getImplementationId_Static() + 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; +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString Graphic::getImplementationName_Static() + throw() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.graphic.Graphic" ) ); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > Graphic::getSupportedServiceNames_Static() + throw() +{ + uno::Sequence< ::rtl::OUString > aSeq( 1 ); + + aSeq.getArray()[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.Graphic" ) ); + + return aSeq; +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString SAL_CALL Graphic::getImplementationName() + throw( uno::RuntimeException ) +{ + return getImplementationName_Static(); +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL Graphic::supportsService( const ::rtl::OUString& rServiceName ) + throw( uno::RuntimeException ) +{ + if( ::unographic::GraphicDescriptor::supportsService( rServiceName ) ) + return true; + else + { + uno::Sequence< ::rtl::OUString > aSNL( getSupportedServiceNames() ); + const ::rtl::OUString* pArray = aSNL.getConstArray(); + + for( int i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == rServiceName ) + return true; + + return false; + } +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > SAL_CALL Graphic::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > aRet( ::unographic::GraphicDescriptor::getSupportedServiceNames() ); + uno::Sequence< ::rtl::OUString > aNew( getSupportedServiceNames_Static() ); + sal_Int32 nOldCount = aRet.getLength(); + + aRet.realloc( nOldCount + aNew.getLength() ); + + for( sal_Int32 i = 0; i < aNew.getLength(); ++i ) + aRet[ nOldCount++ ] = aNew[ i ]; + + return aRet; +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< uno::Type > SAL_CALL Graphic::getTypes() + throw(uno::RuntimeException) +{ + uno::Sequence< uno::Type > aRet( ::unographic::GraphicDescriptor::getTypes() ); + sal_Int32 nOldCount = aRet.getLength(); + + aRet.realloc( nOldCount + 2 ); + aRet[ nOldCount ] = ::getCppuType((const uno::Reference< graphic::XGraphic>*)0); + aRet[ nOldCount+1 ] = ::getCppuType((const uno::Reference< awt::XBitmap>*)0); + + return aRet; +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< sal_Int8 > SAL_CALL Graphic::getImplementationId() + throw(uno::RuntimeException) +{ + return getImplementationId_Static(); +} + +// ------------------------------------------------------------------------------ + +::sal_Int8 SAL_CALL Graphic::getType() + throw (uno::RuntimeException) +{ + ::sal_Int8 cRet = graphic::GraphicType::EMPTY; + + if( mpGraphic && ( mpGraphic->GetType() != GRAPHIC_NONE ) ) + cRet = ( ( mpGraphic->GetType() == GRAPHIC_BITMAP ) ? graphic::GraphicType::PIXEL : graphic::GraphicType::VECTOR ); + + return cRet; +} + +//---------------------------------------------------------------------- +// XBitmap +//---------------------------------------------------------------------- + +awt::Size SAL_CALL Graphic::getSize( ) throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + ::Size aVclSize; + if( mpGraphic && ( mpGraphic->GetType() != GRAPHIC_NONE ) ) + aVclSize = mpGraphic->GetSizePixel(); + + return awt::Size( aVclSize.Width(), aVclSize.Height() ); +} + +//---------------------------------------------------------------------- + +uno::Sequence< ::sal_Int8 > SAL_CALL Graphic::getDIB( ) throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( mpGraphic && ( mpGraphic->GetType() != GRAPHIC_NONE ) ) + { + SvMemoryStream aMem; + aMem << mpGraphic->GetBitmapEx().GetBitmap(); + return ::com::sun::star::uno::Sequence<sal_Int8>( (sal_Int8*) aMem.GetData(), aMem.Tell() ); + } + else + { + return uno::Sequence<sal_Int8>(); + } +} + +//---------------------------------------------------------------------- + +uno::Sequence< ::sal_Int8 > SAL_CALL Graphic::getMaskDIB( ) throw (uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( mpGraphic && ( mpGraphic->GetType() != GRAPHIC_NONE ) ) + { + SvMemoryStream aMem; + aMem << mpGraphic->GetBitmapEx().GetMask(); + return ::com::sun::star::uno::Sequence<sal_Int8>( (sal_Int8*) aMem.GetData(), aMem.Tell() ); + } + else + { + return uno::Sequence<sal_Int8>(); + } +} + +//---------------------------------------------------------------------- +const ::Graphic* Graphic::getImplementation( const uno::Reference< uno::XInterface >& rxIFace ) + throw() +{ + uno::Reference< lang::XUnoTunnel > xTunnel( rxIFace, uno::UNO_QUERY ); + return( xTunnel.is() ? reinterpret_cast< ::Graphic* >( xTunnel->getSomething( getImplementationId_Static() ) ) : NULL ); +} + +//---------------------------------------------------------------------- +sal_Int64 SAL_CALL Graphic::getSomething( const uno::Sequence< sal_Int8 >& rId ) + throw( uno::RuntimeException ) +{ + return( ( rId.getLength() == 16 && 0 == rtl_compareMemory( getImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) ? + reinterpret_cast< sal_Int64 >( mpGraphic ) : + 0 ); +} + +} diff --git a/svtools/source/graphic/graphic.hxx b/svtools/source/graphic/graphic.hxx new file mode 100644 index 000000000000..a7687458be19 --- /dev/null +++ b/svtools/source/graphic/graphic.hxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * 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: graphic.hxx,v $ + * $Revision: 1.7 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _GOODIES_GRAPHIC_HXX +#define _GOODIES_GRAPHIC_HXX + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/awt/XBitmap.hpp> + +#include "descriptor.hxx" +#include "transformer.hxx" + +using namespace com::sun::star; + +class Graphic; + +namespace unographic { + +// ------------------- +// - GraphicProvider - +// ------------------- + +class Graphic : public ::com::sun::star::graphic::XGraphic, + public ::com::sun::star::awt::XBitmap, + public ::com::sun::star::lang::XUnoTunnel, + public ::unographic::GraphicDescriptor, + public ::unographic::GraphicTransformer +{ +public: + + Graphic(); + ~Graphic() throw(); + + using unographic::GraphicDescriptor::init; + void init( const ::Graphic& rGraphic ) throw(); + + static const ::Graphic* getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw(); + static ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId_Static( ) throw(::com::sun::star::uno::RuntimeException); + static ::rtl::OUString getImplementationName_Static() throw(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static() throw(); + +protected: + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XServiceInfo + virtual rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException); + + // XGraphic + virtual ::sal_Int8 SAL_CALL getType( ) throw (::com::sun::star::uno::RuntimeException); + + // XBitmap + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL getDIB( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL getMaskDIB( ) throw (::com::sun::star::uno::RuntimeException); + + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw(::com::sun::star::uno::RuntimeException); + +private: + + ::Graphic* mpGraphic; +}; + +} + +#endif diff --git a/svtools/source/graphic/graphicunofactory.cxx b/svtools/source/graphic/graphicunofactory.cxx new file mode 100644 index 000000000000..9aea39ca7460 --- /dev/null +++ b/svtools/source/graphic/graphicunofactory.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * 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: graphicunofactory.cxx,v $ + * $Revision: 1.1.2.1 $ + * + * 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 <comphelper/servicedecl.hxx> +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/graphic/XGraphicObject.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <svtools/grfmgr.hxx> + +using namespace com::sun::star; + +namespace unographic { + +typedef ::cppu::WeakImplHelper1< graphic::XGraphicObject > GObjectAccess_BASE; + // Simple uno wrapper around the GraphicObject class to allow basic + // access. ( and solves a horrible cyclic link problem between + // goodies/toolkit/extensions ) +class GObjectImpl : public GObjectAccess_BASE +{ + ::osl::Mutex m_aMutex; + std::auto_ptr< GraphicObject > mpGObject; +public: + GObjectImpl( uno::Sequence< uno::Any > const & args, uno::Reference< uno::XComponentContext > const & xComponentContext ) throw (uno::RuntimeException); + + // XGraphicObject + virtual uno::Reference< graphic::XGraphic > SAL_CALL getGraphic() throw (uno::RuntimeException); + virtual void SAL_CALL setGraphic( const uno::Reference< graphic::XGraphic >& _graphic ) throw (uno::RuntimeException); + ::rtl::OUString SAL_CALL getUniqueID() throw (uno::RuntimeException); +}; + +GObjectImpl::GObjectImpl( uno::Sequence< uno::Any > const & args, uno::Reference< uno::XComponentContext > const & /*xComponentContext*/ ) throw (uno::RuntimeException) +{ + if ( args.getLength() == 1 ) + { + rtl::OUString sId; + if ( !( args[ 0 ] >>= sId ) || sId.getLength() == 0 ) + throw lang::IllegalArgumentException(); + ByteString bsId( sId.getStr(), RTL_TEXTENCODING_UTF8 ); + mpGObject.reset( new GraphicObject( bsId ) ); + } + else + mpGObject.reset( new GraphicObject() ); +} + +uno::Reference< graphic::XGraphic > SAL_CALL GObjectImpl::getGraphic() throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !mpGObject.get() ) + throw uno::RuntimeException(); + return mpGObject->GetGraphic().GetXGraphic(); +} + +void SAL_CALL GObjectImpl::setGraphic( const uno::Reference< graphic::XGraphic >& _graphic ) throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !mpGObject.get() ) + throw uno::RuntimeException(); + Graphic aGraphic( _graphic ); + mpGObject->SetGraphic( aGraphic ); +} + +::rtl::OUString SAL_CALL GObjectImpl::getUniqueID() throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + rtl::OUString sId; + if ( mpGObject.get() ) + sId = String( mpGObject->GetUniqueID().GetBuffer(), RTL_TEXTENCODING_ASCII_US ); + return sId; +} + + +namespace sdecl = comphelper::service_decl; +sdecl::class_<GObjectImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( serviceBI, "com.sun.star.graphic.GraphicObject", "com.sun.star.graphic.GraphicObject" ); + +} diff --git a/svtools/source/graphic/grfattr.cxx b/svtools/source/graphic/grfattr.cxx new file mode 100644 index 000000000000..6b3fe6f16c02 --- /dev/null +++ b/svtools/source/graphic/grfattr.cxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * 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: grfattr.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <tools/vcompat.hxx> +#include <svtools/grfmgr.hxx> + +// --------------- +// - GraphicAttr - +// --------------- + +GraphicAttr::GraphicAttr() : + mfGamma ( 1.0 ), + mnMirrFlags ( 0 ), + mnLeftCrop ( 0 ), + mnTopCrop ( 0 ), + mnRightCrop ( 0 ), + mnBottomCrop ( 0 ), + mnRotate10 ( 0 ), + mnContPercent ( 0 ), + mnLumPercent ( 0 ), + mnRPercent ( 0 ), + mnGPercent ( 0 ), + mnBPercent ( 0 ), + mbInvert ( FALSE ), + mcTransparency ( 0 ), + meDrawMode ( GRAPHICDRAWMODE_STANDARD ) +{ +} + +// ------------------------------------------------------------------------ + +GraphicAttr::~GraphicAttr() +{ +} + +// ------------------------------------------------------------------------ + +BOOL GraphicAttr::operator==( const GraphicAttr& rAttr ) const +{ + return( ( mfGamma == rAttr.mfGamma ) && + ( mnMirrFlags == rAttr.mnMirrFlags ) && + ( mnLeftCrop == rAttr.mnLeftCrop ) && + ( mnTopCrop == rAttr.mnTopCrop ) && + ( mnRightCrop == rAttr.mnRightCrop ) && + ( mnBottomCrop == rAttr.mnBottomCrop ) && + ( mnRotate10 == rAttr.mnRotate10 ) && + ( mnContPercent == rAttr.mnContPercent ) && + ( mnLumPercent == rAttr.mnLumPercent ) && + ( mnRPercent == rAttr.mnRPercent ) && + ( mnGPercent == rAttr.mnGPercent ) && + ( mnBPercent == rAttr.mnBPercent ) && + ( mbInvert == rAttr.mbInvert ) && + ( mcTransparency == rAttr.mcTransparency ) && + ( meDrawMode == rAttr.meDrawMode ) ); +} + +// ------------------------------------------------------------------------ + +SvStream& operator>>( SvStream& rIStm, GraphicAttr& rAttr ) +{ + VersionCompat aCompat( rIStm, STREAM_READ ); + sal_uInt32 nTmp32; + UINT16 nTmp16; + + rIStm >> nTmp32 >> nTmp32 >> rAttr.mfGamma >> rAttr.mnMirrFlags >> rAttr.mnRotate10; + rIStm >> rAttr.mnContPercent >> rAttr.mnLumPercent >> rAttr.mnRPercent >> rAttr.mnGPercent >> rAttr.mnBPercent; + rIStm >> rAttr.mbInvert >> rAttr.mcTransparency >> nTmp16; + rAttr.meDrawMode = (GraphicDrawMode) nTmp16; + + if( aCompat.GetVersion() >= 2 ) + { + rIStm >> rAttr.mnLeftCrop >> rAttr.mnTopCrop >> rAttr.mnRightCrop >> rAttr.mnBottomCrop; + } + + return rIStm; +} + +// ------------------------------------------------------------------------ + +SvStream& operator<<( SvStream& rOStm, const GraphicAttr& rAttr ) +{ + VersionCompat aCompat( rOStm, STREAM_WRITE, 2 ); + const sal_uInt32 nTmp32 = 0; + + rOStm << nTmp32 << nTmp32 << rAttr.mfGamma << rAttr.mnMirrFlags << rAttr.mnRotate10; + rOStm << rAttr.mnContPercent << rAttr.mnLumPercent << rAttr.mnRPercent << rAttr.mnGPercent << rAttr.mnBPercent; + rOStm << rAttr.mbInvert << rAttr.mcTransparency << (UINT16) rAttr.meDrawMode; + rOStm << rAttr.mnLeftCrop << rAttr.mnTopCrop << rAttr.mnRightCrop << rAttr.mnBottomCrop; + + return rOStm; +} diff --git a/svtools/source/graphic/grfcache.cxx b/svtools/source/graphic/grfcache.cxx new file mode 100644 index 000000000000..b9d91ccf85d9 --- /dev/null +++ b/svtools/source/graphic/grfcache.cxx @@ -0,0 +1,1055 @@ +/************************************************************************* + * + * 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: grfcache.cxx,v $ + * $Revision: 1.23.38.1 $ + * + * 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 <vos/timer.hxx> +#include <tools/debug.hxx> +#include <vcl/outdev.hxx> +#include <tools/poly.hxx> +#include "grfcache.hxx" + +// ----------- +// - Defines - +// ----------- + +#define RELEASE_TIMEOUT 10000 +#define MAX_BMP_EXTENT 4096 + +// ----------- +// - statics - +// ----------- + +static const char aHexData[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +// ------------- +// - GraphicID - +// ------------- + +class GraphicID +{ +private: + + sal_uInt32 mnID1; + sal_uInt32 mnID2; + sal_uInt32 mnID3; + sal_uInt32 mnID4; + + GraphicID(); + +public: + + + GraphicID( const GraphicObject& rObj ); + ~GraphicID() {} + + BOOL operator==( const GraphicID& rID ) const + { + return( rID.mnID1 == mnID1 && rID.mnID2 == mnID2 && + rID.mnID3 == mnID3 && rID.mnID4 == mnID4 ); + } + + ByteString GetIDString() const; + BOOL IsEmpty() const { return( 0 == mnID4 ); } +}; + +// ----------------------------------------------------------------------------- + +GraphicID::GraphicID( const GraphicObject& rObj ) +{ + const Graphic& rGraphic = rObj.GetGraphic(); + + mnID1 = ( (ULONG) rGraphic.GetType() ) << 28; + + switch( rGraphic.GetType() ) + { + case( GRAPHIC_BITMAP ): + { + if( rGraphic.IsAnimated() ) + { + const Animation aAnimation( rGraphic.GetAnimation() ); + + mnID1 |= ( aAnimation.Count() & 0x0fffffff ); + mnID2 = aAnimation.GetDisplaySizePixel().Width(); + mnID3 = aAnimation.GetDisplaySizePixel().Height(); + mnID4 = rGraphic.GetChecksum(); + } + else + { + const BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + + mnID1 |= ( ( ( (ULONG) aBmpEx.GetTransparentType() << 8 ) | ( aBmpEx.IsAlpha() ? 1 : 0 ) ) & 0x0fffffff ); + mnID2 = aBmpEx.GetSizePixel().Width(); + mnID3 = aBmpEx.GetSizePixel().Height(); + mnID4 = rGraphic.GetChecksum(); + } + } + break; + + case( GRAPHIC_GDIMETAFILE ): + { + const GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() ); + + mnID1 |= ( aMtf.GetActionCount() & 0x0fffffff ); + mnID2 = aMtf.GetPrefSize().Width(); + mnID3 = aMtf.GetPrefSize().Height(); + mnID4 = rGraphic.GetChecksum(); + } + break; + + default: + mnID2 = mnID3 = mnID4 = 0; + break; + } +} + +// ----------------------------------------------------------------------------- + +ByteString GraphicID::GetIDString() const +{ + ByteString aHexStr; + sal_Char* pStr = aHexStr.AllocBuffer( 32 ); + sal_Int32 nShift; + + for( nShift = 28; nShift >= 0; nShift -= 4 ) + *pStr++ = aHexData[ ( mnID1 >> (sal_uInt32) nShift ) & 0xf ]; + + for( nShift = 28; nShift >= 0; nShift -= 4 ) + *pStr++ = aHexData[ ( mnID2 >> (sal_uInt32) nShift ) & 0xf ]; + + for( nShift = 28; nShift >= 0; nShift -= 4 ) + *pStr++ = aHexData[ ( mnID3 >> (sal_uInt32) nShift ) & 0xf ]; + + for( nShift = 28; nShift >= 0; nShift -= 4 ) + *pStr++ = aHexData[ ( mnID4 >> (sal_uInt32) nShift ) & 0xf ]; + + return aHexStr; +} + +// --------------------- +// - GraphicCacheEntry - +// --------------------- + +class GraphicCacheEntry +{ +private: + + List maGraphicObjectList; + GraphicID maID; + GfxLink maGfxLink; + BitmapEx* mpBmpEx; + GDIMetaFile* mpMtf; + Animation* mpAnimation; + BOOL mbSwappedAll; + + BOOL ImplInit( const GraphicObject& rObj ); + BOOL ImplMatches( const GraphicObject& rObj ) const { return( GraphicID( rObj ) == maID ); } + void ImplFillSubstitute( Graphic& rSubstitute ); + +public: + + GraphicCacheEntry( const GraphicObject& rObj ); + ~GraphicCacheEntry(); + + const GraphicID& GetID() const { return maID; } + + void AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute ); + BOOL ReleaseGraphicObjectReference( const GraphicObject& rObj ); + ULONG GetGraphicObjectReferenceCount() { return maGraphicObjectList.Count(); } + BOOL HasGraphicObjectReference( const GraphicObject& rObj ); + + void TryToSwapIn(); + void GraphicObjectWasSwappedOut( const GraphicObject& rObj ); + BOOL FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute ); + void GraphicObjectWasSwappedIn( const GraphicObject& rObj ); +}; + +// ----------------------------------------------------------------------------- + +GraphicCacheEntry::GraphicCacheEntry( const GraphicObject& rObj ) : + maID ( rObj ), + mpBmpEx ( NULL ), + mpMtf ( NULL ), + mpAnimation ( NULL ), + mbSwappedAll ( !ImplInit( rObj ) ) +{ + maGraphicObjectList.Insert( (void*) &rObj, LIST_APPEND ); +} + +// ----------------------------------------------------------------------------- + +GraphicCacheEntry::~GraphicCacheEntry() +{ + DBG_ASSERT( !maGraphicObjectList.Count(), "GraphicCacheEntry::~GraphicCacheEntry(): Not all GraphicObjects are removed from this entry" ); + + delete mpBmpEx; + delete mpMtf; + delete mpAnimation; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCacheEntry::ImplInit( const GraphicObject& rObj ) +{ + BOOL bRet; + + if( !rObj.IsSwappedOut() ) + { + const Graphic& rGraphic = rObj.GetGraphic(); + + if( mpBmpEx ) + delete mpBmpEx, mpBmpEx = NULL; + + if( mpMtf ) + delete mpMtf, mpMtf = NULL; + + if( mpAnimation ) + delete mpAnimation, mpAnimation = NULL; + + switch( rGraphic.GetType() ) + { + case( GRAPHIC_BITMAP ): + { + if( rGraphic.IsAnimated() ) + mpAnimation = new Animation( rGraphic.GetAnimation() ); + else + mpBmpEx = new BitmapEx( rGraphic.GetBitmapEx() ); + } + break; + + case( GRAPHIC_GDIMETAFILE ): + { + mpMtf = new GDIMetaFile( rGraphic.GetGDIMetaFile() ); + } + break; + + default: + DBG_ASSERT( GetID().IsEmpty(), "GraphicCacheEntry::ImplInit: Could not initialize graphic! (=>KA)" ); + break; + } + + if( rGraphic.IsLink() ) + maGfxLink = ( (Graphic&) rGraphic ).GetLink(); + else + maGfxLink = GfxLink(); + + bRet = TRUE; + } + else + bRet = FALSE; + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void GraphicCacheEntry::ImplFillSubstitute( Graphic& rSubstitute ) +{ + // create substitute for graphic; + const Size aPrefSize( rSubstitute.GetPrefSize() ); + const MapMode aPrefMapMode( rSubstitute.GetPrefMapMode() ); + const Link aAnimationNotifyHdl( rSubstitute.GetAnimationNotifyHdl() ); + const String aDocFileName( rSubstitute.GetDocFileName() ); + const ULONG nDocFilePos = rSubstitute.GetDocFilePos(); + const GraphicType eOldType = rSubstitute.GetType(); + const BOOL bDefaultType = ( rSubstitute.GetType() == GRAPHIC_DEFAULT ); + + if( rSubstitute.IsLink() && ( GFX_LINK_TYPE_NONE == maGfxLink.GetType() ) ) + maGfxLink = rSubstitute.GetLink(); + + if( mpBmpEx ) + rSubstitute = *mpBmpEx; + else if( mpAnimation ) + rSubstitute = *mpAnimation; + else if( mpMtf ) + rSubstitute = *mpMtf; + else + rSubstitute.Clear(); + + if( eOldType != GRAPHIC_NONE ) + { + rSubstitute.SetPrefSize( aPrefSize ); + rSubstitute.SetPrefMapMode( aPrefMapMode ); + rSubstitute.SetAnimationNotifyHdl( aAnimationNotifyHdl ); + rSubstitute.SetDocFileName( aDocFileName, nDocFilePos ); + } + + if( GFX_LINK_TYPE_NONE != maGfxLink.GetType() ) + rSubstitute.SetLink( maGfxLink ); + + if( bDefaultType ) + rSubstitute.SetDefaultType(); +} + +// ----------------------------------------------------------------------------- + +void GraphicCacheEntry::AddGraphicObjectReference( const GraphicObject& rObj, Graphic& rSubstitute ) +{ + if( mbSwappedAll ) + mbSwappedAll = !ImplInit( rObj ); + + ImplFillSubstitute( rSubstitute ); + maGraphicObjectList.Insert( (void*) &rObj, LIST_APPEND ); +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCacheEntry::ReleaseGraphicObjectReference( const GraphicObject& rObj ) +{ + BOOL bRet = FALSE; + + for( void* pObj = maGraphicObjectList.First(); !bRet && pObj; pObj = maGraphicObjectList.Next() ) + { + if( &rObj == (GraphicObject*) pObj ) + { + maGraphicObjectList.Remove( pObj ); + bRet = TRUE; + } + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCacheEntry::HasGraphicObjectReference( const GraphicObject& rObj ) +{ + BOOL bRet = FALSE; + + for( void* pObj = maGraphicObjectList.First(); !bRet && pObj; pObj = maGraphicObjectList.Next() ) + if( &rObj == (GraphicObject*) pObj ) + bRet = TRUE; + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void GraphicCacheEntry::TryToSwapIn() +{ + if( mbSwappedAll && maGraphicObjectList.Count() ) + ( (GraphicObject*) maGraphicObjectList.First() )->FireSwapInRequest(); +} + +// ----------------------------------------------------------------------------- + +void GraphicCacheEntry::GraphicObjectWasSwappedOut( const GraphicObject& /*rObj*/ ) +{ + mbSwappedAll = TRUE; + + for( void* pObj = maGraphicObjectList.First(); mbSwappedAll && pObj; pObj = maGraphicObjectList.Next() ) + if( !( (GraphicObject*) pObj )->IsSwappedOut() ) + mbSwappedAll = FALSE; + + if( mbSwappedAll ) + { + delete mpBmpEx, mpBmpEx = NULL; + delete mpMtf, mpMtf = NULL; + delete mpAnimation, mpAnimation = NULL; + } +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCacheEntry::FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute ) +{ + BOOL bRet; + + if( !mbSwappedAll && rObj.IsSwappedOut() ) + { + ImplFillSubstitute( rSubstitute ); + bRet = TRUE; + } + else + bRet = FALSE; + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void GraphicCacheEntry::GraphicObjectWasSwappedIn( const GraphicObject& rObj ) +{ + if( mbSwappedAll ) + mbSwappedAll = !ImplInit( rObj ); +} + +// ---------------------------- +// - GraphicDisplayCacheEntry - +// ---------------------------- + +class GraphicDisplayCacheEntry +{ +private: + + ::vos::TTimeValue maReleaseTime; + const GraphicCacheEntry* mpRefCacheEntry; + GDIMetaFile* mpMtf; + BitmapEx* mpBmpEx; + GraphicAttr maAttr; + Size maOutSizePix; + ULONG mnCacheSize; + ULONG mnOutDevDrawMode; + USHORT mnOutDevBitCount; + +public: + + static ULONG GetNeededSize( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr ); + +public: + + GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry, + OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr, + const BitmapEx& rBmpEx ) : + mpRefCacheEntry( pRefCacheEntry ), + mpMtf( NULL ), mpBmpEx( new BitmapEx( rBmpEx ) ), + maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ), + mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ), + mnOutDevDrawMode( pOut->GetDrawMode() ), + mnOutDevBitCount( pOut->GetBitCount() ) + { + } + + GraphicDisplayCacheEntry( const GraphicCacheEntry* pRefCacheEntry, + OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr, + const GDIMetaFile& rMtf ) : + mpRefCacheEntry( pRefCacheEntry ), + mpMtf( new GDIMetaFile( rMtf ) ), mpBmpEx( NULL ), + maAttr( rAttr ), maOutSizePix( pOut->LogicToPixel( rSz ) ), + mnCacheSize( GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) ), + mnOutDevDrawMode( pOut->GetDrawMode() ), + mnOutDevBitCount( pOut->GetBitCount() ) + { + } + + + ~GraphicDisplayCacheEntry(); + + const GraphicAttr& GetAttr() const { return maAttr; } + const Size& GetOutputSizePixel() const { return maOutSizePix; } + ULONG GetCacheSize() const { return mnCacheSize; } + const GraphicCacheEntry* GetReferencedCacheEntry() const { return mpRefCacheEntry; } + ULONG GetOutDevDrawMode() const { return mnOutDevDrawMode; } + USHORT GetOutDevBitCount() const { return mnOutDevBitCount; } + + void SetReleaseTime( const ::vos::TTimeValue& rReleaseTime ) { maReleaseTime = rReleaseTime; } + const ::vos::TTimeValue& GetReleaseTime() const { return maReleaseTime; } + + BOOL Matches( OutputDevice* pOut, const Point& /*rPtPixel*/, const Size& rSzPixel, + const GraphicCacheEntry* pCacheEntry, const GraphicAttr& rAttr ) const + { + // #i46805# Additional match + // criteria: outdev draw mode and + // bit count. One cannot reuse + // this cache object, if it's + // e.g. generated for + // DRAWMODE_GRAYBITMAP. + return( ( pCacheEntry == mpRefCacheEntry ) && + ( maAttr == rAttr ) && + ( ( maOutSizePix == rSzPixel ) || ( !maOutSizePix.Width() && !maOutSizePix.Height() ) ) && + ( pOut->GetBitCount() == mnOutDevBitCount ) && + ( pOut->GetDrawMode() == mnOutDevDrawMode ) ); + } + + void Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const; +}; + +// ----------------------------------------------------------------------------- + +ULONG GraphicDisplayCacheEntry::GetNeededSize( OutputDevice* pOut, const Point& /*rPt*/, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr ) +{ + const Graphic& rGraphic = rObj.GetGraphic(); + const GraphicType eType = rGraphic.GetType(); + ULONG nNeededSize; + + if( GRAPHIC_BITMAP == eType ) + { + const Size aOutSizePix( pOut->LogicToPixel( rSz ) ); + const long nBitCount = pOut->GetBitCount(); + + if( ( aOutSizePix.Width() > MAX_BMP_EXTENT ) || + ( aOutSizePix.Height() > MAX_BMP_EXTENT ) ) + { + nNeededSize = ULONG_MAX; + } + else if( nBitCount ) + { + nNeededSize = aOutSizePix.Width() * aOutSizePix.Height() * nBitCount / 8; + + if( rObj.IsTransparent() || ( rAttr.GetRotation() % 3600 ) ) + nNeededSize += nNeededSize / nBitCount; + } + else + { + DBG_ERROR( "GraphicDisplayCacheEntry::GetNeededSize(): pOut->GetBitCount() == 0" ); + nNeededSize = 256000; + } + } + else if( GRAPHIC_GDIMETAFILE == eType ) + nNeededSize = rGraphic.GetSizeBytes(); + else + nNeededSize = 0; + + return nNeededSize; +} + +// ----------------------------------------------------------------------------- + +GraphicDisplayCacheEntry::~GraphicDisplayCacheEntry() +{ + if( mpMtf ) + delete mpMtf; + + if( mpBmpEx ) + delete mpBmpEx; +} + +// ----------------------------------------------------------------------------- + +void GraphicDisplayCacheEntry::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz ) const +{ + if( mpMtf ) + GraphicManager::ImplDraw( pOut, rPt, rSz, *mpMtf, maAttr ); + else if( mpBmpEx ) + { + if( maAttr.IsRotated() ) + { + Polygon aPoly( Rectangle( rPt, rSz ) ); + + aPoly.Rotate( rPt, maAttr.GetRotation() % 3600 ); + const Rectangle aRotBoundRect( aPoly.GetBoundRect() ); + pOut->DrawBitmapEx( aRotBoundRect.TopLeft(), aRotBoundRect.GetSize(), *mpBmpEx ); + } + else + pOut->DrawBitmapEx( rPt, rSz, *mpBmpEx ); + } +} + +// ----------------------- +// - GraphicCache - +// ----------------------- + +GraphicCache::GraphicCache( GraphicManager& rMgr, ULONG nDisplayCacheSize, ULONG nMaxObjDisplayCacheSize ) : + mrMgr ( rMgr ), + mnReleaseTimeoutSeconds ( 0UL ), + mnMaxDisplaySize ( nDisplayCacheSize ), + mnMaxObjDisplaySize ( nMaxObjDisplayCacheSize ), + mnUsedDisplaySize ( 0UL ) +{ + maReleaseTimer.SetTimeoutHdl( LINK( this, GraphicCache, ReleaseTimeoutHdl ) ); + maReleaseTimer.SetTimeout( RELEASE_TIMEOUT ); + maReleaseTimer.Start(); +} + +// ----------------------------------------------------------------------------- + +GraphicCache::~GraphicCache() +{ + DBG_ASSERT( !maGraphicCache.Count(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in cache" ); + DBG_ASSERT( !maDisplayCache.Count(), "GraphicCache::~GraphicCache(): there are some GraphicObjects in display cache" ); +} + +// ----------------------------------------------------------------------------- + +void GraphicCache::AddGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute, + const ByteString* pID, const GraphicObject* pCopyObj ) +{ + BOOL bInserted = FALSE; + + if( !rObj.IsSwappedOut() && + ( pID || ( pCopyObj && ( pCopyObj->GetType() != GRAPHIC_NONE ) ) || ( rObj.GetType() != GRAPHIC_NONE ) ) ) + { + if( pCopyObj ) + { + GraphicCacheEntry* pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.First() ); + + while( !bInserted && pEntry ) + { + if( pEntry->HasGraphicObjectReference( *pCopyObj ) ) + { + pEntry->AddGraphicObjectReference( rObj, rSubstitute ); + bInserted = TRUE; + } + else + { + pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.Next() ); + } + } + } + + if( !bInserted ) + { + GraphicCacheEntry* pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.First() ); + const GraphicID aID( rObj ); + + while( !bInserted && pEntry ) + { + const GraphicID& rEntryID = pEntry->GetID(); + + if( pID ) + { + if( rEntryID.GetIDString() == *pID ) + { + pEntry->TryToSwapIn(); + + // since pEntry->TryToSwapIn can modify our current list, we have to + // iterate from beginning to add a reference to the appropriate + // CacheEntry object; after this, quickly jump out of the outer iteration + for( pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.First() ); + !bInserted && pEntry; + pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.Next() ) ) + { + const GraphicID& rID = pEntry->GetID(); + + if( rID.GetIDString() == *pID ) + { + pEntry->AddGraphicObjectReference( rObj, rSubstitute ); + bInserted = TRUE; + } + } + + if( !bInserted ) + { + maGraphicCache.Insert( new GraphicCacheEntry( rObj ), LIST_APPEND ); + bInserted = TRUE; + } + } + } + else if( rEntryID == aID ) + { + pEntry->AddGraphicObjectReference( rObj, rSubstitute ); + bInserted = TRUE; + } + + if( !bInserted ) + pEntry = static_cast< GraphicCacheEntry* >( maGraphicCache.Next() ); + } + } + } + + if( !bInserted ) + maGraphicCache.Insert( new GraphicCacheEntry( rObj ), LIST_APPEND ); +} + +// ----------------------------------------------------------------------------- + +void GraphicCache::ReleaseGraphicObject( const GraphicObject& rObj ) +{ + // Release cached object + GraphicCacheEntry* pEntry = (GraphicCacheEntry*) maGraphicCache.First(); + BOOL bRemoved = FALSE; + + while( !bRemoved && pEntry ) + { + bRemoved = pEntry->ReleaseGraphicObjectReference( rObj ); + + if( bRemoved ) + { + if( 0 == pEntry->GetGraphicObjectReferenceCount() ) + { + // if graphic cache entry has no more references, + // the corresponding display cache object can be removed + GraphicDisplayCacheEntry* pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First(); + + while( pDisplayEntry ) + { + if( pDisplayEntry->GetReferencedCacheEntry() == pEntry ) + { + mnUsedDisplaySize -= pDisplayEntry->GetCacheSize(); + maDisplayCache.Remove( pDisplayEntry ); + delete pDisplayEntry; + pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.GetCurObject(); + } + else + pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next(); + } + + // delete graphic cache entry + maGraphicCache.Remove( (void*) pEntry ); + delete pEntry; + } + } + else + pEntry = (GraphicCacheEntry*) maGraphicCache.Next(); + } + + DBG_ASSERT( bRemoved, "GraphicCache::ReleaseGraphicObject(...): GraphicObject not found in cache" ); +} + +// ----------------------------------------------------------------------------- + +void GraphicCache::GraphicObjectWasSwappedOut( const GraphicObject& rObj ) +{ + // notify cache that rObj is swapped out (and can thus be pruned + // from the cache) + GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj ); + + if( pEntry ) + pEntry->GraphicObjectWasSwappedOut( rObj ); +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCache::FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute ) +{ + GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj ); + + if( !pEntry ) + return FALSE; + + return pEntry->FillSwappedGraphicObject( rObj, rSubstitute ); +} + +// ----------------------------------------------------------------------------- + +void GraphicCache::GraphicObjectWasSwappedIn( const GraphicObject& rObj ) +{ + GraphicCacheEntry* pEntry = ImplGetCacheEntry( rObj ); + + if( pEntry ) + { + if( pEntry->GetID().IsEmpty() ) + { + ReleaseGraphicObject( rObj ); + AddGraphicObject( rObj, (Graphic&) rObj.GetGraphic(), NULL, NULL ); + } + else + pEntry->GraphicObjectWasSwappedIn( rObj ); + } +} + +// ----------------------------------------------------------------------------- + +void GraphicCache::SetMaxDisplayCacheSize( ULONG nNewCacheSize ) +{ + mnMaxDisplaySize = nNewCacheSize; + + if( GetMaxDisplayCacheSize() < GetUsedDisplayCacheSize() ) + ImplFreeDisplayCacheSpace( GetUsedDisplayCacheSize() - GetMaxDisplayCacheSize() ); +} + +// ----------------------------------------------------------------------------- + +void GraphicCache::SetMaxObjDisplayCacheSize( ULONG nNewMaxObjSize, BOOL bDestroyGreaterCached ) +{ + const BOOL bDestroy = ( bDestroyGreaterCached && ( nNewMaxObjSize < mnMaxObjDisplaySize ) ); + + mnMaxObjDisplaySize = Min( nNewMaxObjSize, mnMaxDisplaySize ); + + if( bDestroy ) + { + GraphicDisplayCacheEntry* pCacheObj = (GraphicDisplayCacheEntry*) maDisplayCache.First(); + + while( pCacheObj ) + { + if( pCacheObj->GetCacheSize() > mnMaxObjDisplaySize ) + { + mnUsedDisplaySize -= pCacheObj->GetCacheSize(); + maDisplayCache.Remove( pCacheObj ); + delete pCacheObj; + pCacheObj = (GraphicDisplayCacheEntry*) maDisplayCache.GetCurObject(); + } + else + pCacheObj = (GraphicDisplayCacheEntry*) maDisplayCache.Next(); + } + } +} + +// ----------------------------------------------------------------------------- + +void GraphicCache::SetCacheTimeout( ULONG nTimeoutSeconds ) +{ + if( mnReleaseTimeoutSeconds != nTimeoutSeconds ) + { + GraphicDisplayCacheEntry* pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First(); + ::vos::TTimeValue aReleaseTime; + + if( ( mnReleaseTimeoutSeconds = nTimeoutSeconds ) != 0 ) + { + osl_getSystemTime( &aReleaseTime ); + aReleaseTime.addTime( ::vos::TTimeValue( nTimeoutSeconds, 0 ) ); + } + + while( pDisplayEntry ) + { + pDisplayEntry->SetReleaseTime( aReleaseTime ); + pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next(); + } + } +} + +// ----------------------------------------------------------------------------- + +void GraphicCache::ClearDisplayCache() +{ + for( void* pObj = maDisplayCache.First(); pObj; pObj = maDisplayCache.Next() ) + delete (GraphicDisplayCacheEntry*) pObj; + + maDisplayCache.Clear(); + mnUsedDisplaySize = 0UL; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCache::IsDisplayCacheable( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr ) const +{ + return( GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr ) <= + GetMaxObjDisplayCacheSize() ); +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCache::IsInDisplayCache( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr ) const +{ + const Point aPtPixel( pOut->LogicToPixel( rPt ) ); + const Size aSzPixel( pOut->LogicToPixel( rSz ) ); + const GraphicCacheEntry* pCacheEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj ); + //GraphicDisplayCacheEntry* pDisplayEntry = (GraphicDisplayCacheEntry*) ( (GraphicCache*) this )->maDisplayCache.First(); // -Wall removed .... + BOOL bFound = FALSE; + + if( pCacheEntry ) + { + for( long i = 0, nCount = maDisplayCache.Count(); !bFound && ( i < nCount ); i++ ) + if( ( (GraphicDisplayCacheEntry*) maDisplayCache.GetObject( i ) )->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) ) + bFound = TRUE; + } + + return bFound; +} + +// ----------------------------------------------------------------------------- + +ByteString GraphicCache::GetUniqueID( const GraphicObject& rObj ) const +{ + ByteString aRet; + GraphicCacheEntry* pEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj ); + + // ensure that the entry is correctly initialized (it has to be read at least once) + if( pEntry && pEntry->GetID().IsEmpty() ) + pEntry->TryToSwapIn(); + + // do another call to ImplGetCacheEntry in case of modified entry list + pEntry = ( (GraphicCache*) this )->ImplGetCacheEntry( rObj ); + + if( pEntry ) + aRet = pEntry->GetID().GetIDString(); + + return aRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCache::CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr, + const BitmapEx& rBmpEx ) +{ + const ULONG nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr ); + BOOL bRet = FALSE; + + if( nNeededSize <= GetMaxObjDisplayCacheSize() ) + { + if( nNeededSize > GetFreeDisplayCacheSize() ) + ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() ); + + GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ), + pOut, rPt, rSz, rObj, rAttr, rBmpEx ); + + if( GetCacheTimeout() ) + { + ::vos::TTimeValue aReleaseTime; + + osl_getSystemTime( &aReleaseTime ); + aReleaseTime.addTime( ::vos::TTimeValue( GetCacheTimeout(), 0 ) ); + pNewEntry->SetReleaseTime( aReleaseTime ); + } + + maDisplayCache.Insert( pNewEntry, LIST_APPEND ); + mnUsedDisplaySize += pNewEntry->GetCacheSize(); + bRet = TRUE; + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCache::CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr, + const GDIMetaFile& rMtf ) +{ + const ULONG nNeededSize = GraphicDisplayCacheEntry::GetNeededSize( pOut, rPt, rSz, rObj, rAttr ); + BOOL bRet = FALSE; + + if( nNeededSize <= GetMaxObjDisplayCacheSize() ) + { + if( nNeededSize > GetFreeDisplayCacheSize() ) + ImplFreeDisplayCacheSpace( nNeededSize - GetFreeDisplayCacheSize() ); + + GraphicDisplayCacheEntry* pNewEntry = new GraphicDisplayCacheEntry( ImplGetCacheEntry( rObj ), + pOut, rPt, rSz, rObj, rAttr, rMtf ); + + if( GetCacheTimeout() ) + { + ::vos::TTimeValue aReleaseTime; + + osl_getSystemTime( &aReleaseTime ); + aReleaseTime.addTime( ::vos::TTimeValue( GetCacheTimeout(), 0 ) ); + pNewEntry->SetReleaseTime( aReleaseTime ); + } + + maDisplayCache.Insert( pNewEntry, LIST_APPEND ); + mnUsedDisplaySize += pNewEntry->GetCacheSize(); + bRet = TRUE; + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCache::DrawDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr ) +{ + const Point aPtPixel( pOut->LogicToPixel( rPt ) ); + const Size aSzPixel( pOut->LogicToPixel( rSz ) ); + const GraphicCacheEntry* pCacheEntry = ImplGetCacheEntry( rObj ); + GraphicDisplayCacheEntry* pDisplayCacheEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First(); + BOOL bRet = FALSE; + + while( !bRet && pDisplayCacheEntry ) + { + if( pDisplayCacheEntry->Matches( pOut, aPtPixel, aSzPixel, pCacheEntry, rAttr ) ) + { + ::vos::TTimeValue aReleaseTime; + + // put found object at last used position + maDisplayCache.Insert( maDisplayCache.Remove( pDisplayCacheEntry ), LIST_APPEND ); + + if( GetCacheTimeout() ) + { + osl_getSystemTime( &aReleaseTime ); + aReleaseTime.addTime( ::vos::TTimeValue( GetCacheTimeout(), 0 ) ); + } + + pDisplayCacheEntry->SetReleaseTime( aReleaseTime ); + bRet = TRUE; + } + else + pDisplayCacheEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next(); + } + + if( bRet ) + pDisplayCacheEntry->Draw( pOut, rPt, rSz ); + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicCache::ImplFreeDisplayCacheSpace( ULONG nSizeToFree ) +{ + ULONG nFreedSize = 0UL; + + if( nSizeToFree ) + { + void* pObj = maDisplayCache.First(); + + if( nSizeToFree > mnUsedDisplaySize ) + nSizeToFree = mnUsedDisplaySize; + + while( pObj ) + { + GraphicDisplayCacheEntry* pCacheObj = (GraphicDisplayCacheEntry*) pObj; + + nFreedSize += pCacheObj->GetCacheSize(); + mnUsedDisplaySize -= pCacheObj->GetCacheSize(); + maDisplayCache.Remove( pObj ); + delete pCacheObj; + + if( nFreedSize >= nSizeToFree ) + break; + else + pObj = maDisplayCache.GetCurObject(); + } + } + + return( nFreedSize >= nSizeToFree ); +} + +// ----------------------------------------------------------------------------- + +GraphicCacheEntry* GraphicCache::ImplGetCacheEntry( const GraphicObject& rObj ) +{ + GraphicCacheEntry* pRet = NULL; + + for( void* pObj = maGraphicCache.First(); !pRet && pObj; pObj = maGraphicCache.Next() ) + if( ( (GraphicCacheEntry*) pObj )->HasGraphicObjectReference( rObj ) ) + pRet = (GraphicCacheEntry*) pObj; + + return pRet; +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( GraphicCache, ReleaseTimeoutHdl, Timer*, pTimer ) +{ + pTimer->Stop(); + + ::vos::TTimeValue aCurTime; + GraphicDisplayCacheEntry* pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.First(); + + osl_getSystemTime( &aCurTime ); + + while( pDisplayEntry ) + { + const ::vos::TTimeValue& rReleaseTime = pDisplayEntry->GetReleaseTime(); + + if( !rReleaseTime.isEmpty() && ( rReleaseTime < aCurTime ) ) + { + mnUsedDisplaySize -= pDisplayEntry->GetCacheSize(); + maDisplayCache.Remove( pDisplayEntry ); + delete pDisplayEntry; + pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.GetCurObject(); + } + else + pDisplayEntry = (GraphicDisplayCacheEntry*) maDisplayCache.Next(); + } + + pTimer->Start(); + + return 0; +} diff --git a/svtools/source/graphic/grfcache.hxx b/svtools/source/graphic/grfcache.hxx new file mode 100644 index 000000000000..65391e12c656 --- /dev/null +++ b/svtools/source/graphic/grfcache.hxx @@ -0,0 +1,112 @@ +/************************************************************************* + * + * 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: grfcache.hxx,v $ + * $Revision: 1.4 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _GRFCACHE_HXX +#define _GRFCACHE_HXX + +#include <tools/list.hxx> +#include <vcl/graph.hxx> +#include <vcl/timer.hxx> +#include <svtools/grfmgr.hxx> + +// ----------------------- +// - GraphicManagerCache - +// ----------------------- + +class GraphicCacheEntry; + +class GraphicCache +{ +private: + + GraphicManager& mrMgr; + Timer maReleaseTimer; + List maGraphicCache; + List maDisplayCache; + ULONG mnReleaseTimeoutSeconds; + ULONG mnMaxDisplaySize; + ULONG mnMaxObjDisplaySize; + ULONG mnUsedDisplaySize; + + BOOL ImplFreeDisplayCacheSpace( ULONG nSizeToFree ); + GraphicCacheEntry* ImplGetCacheEntry( const GraphicObject& rObj ); + + + DECL_LINK( ReleaseTimeoutHdl, Timer* pTimer ); + +public: + + GraphicCache( GraphicManager& rMgr, + ULONG nDisplayCacheSize = 10000000UL, + ULONG nMaxObjDisplayCacheSize = 2400000UL ); + ~GraphicCache(); + +public: + + void AddGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute, + const ByteString* pID, const GraphicObject* pCopyObj ); + void ReleaseGraphicObject( const GraphicObject& rObj ); + + void GraphicObjectWasSwappedOut( const GraphicObject& rObj ); + BOOL FillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute ); + void GraphicObjectWasSwappedIn( const GraphicObject& rObj ); + + ByteString GetUniqueID( const GraphicObject& rObj ) const; + +public: + + void SetMaxDisplayCacheSize( ULONG nNewCacheSize ); + ULONG GetMaxDisplayCacheSize() const { return mnMaxDisplaySize; }; + + void SetMaxObjDisplayCacheSize( ULONG nNewMaxObjSize, BOOL bDestroyGreaterCached = FALSE ); + ULONG GetMaxObjDisplayCacheSize() const { return mnMaxObjDisplaySize; } + + ULONG GetUsedDisplayCacheSize() const { return mnUsedDisplaySize; } + ULONG GetFreeDisplayCacheSize() const { return( mnMaxDisplaySize - mnUsedDisplaySize ); } + + void SetCacheTimeout( ULONG nTimeoutSeconds ); + ULONG GetCacheTimeout() const { return mnReleaseTimeoutSeconds; } + + void ClearDisplayCache(); + BOOL IsDisplayCacheable( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr ) const; + BOOL IsInDisplayCache( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr ) const; + BOOL CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr, + const BitmapEx& rBmpEx ); + BOOL CreateDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr, + const GDIMetaFile& rMtf ); + BOOL DrawDisplayCacheObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicObject& rObj, const GraphicAttr& rAttr ); +}; + +#endif // _GRFCACHE_HXX diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx new file mode 100644 index 000000000000..cdac200810bc --- /dev/null +++ b/svtools/source/graphic/grfmgr.cxx @@ -0,0 +1,1319 @@ +/************************************************************************* + * + * 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: grfmgr.cxx,v $ + * $Revision: 1.36 $ + * + * 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" + +#define ENABLE_BYTESTRING_STREAM_OPERATORS + +#include <algorithm> + +#include <tools/vcompat.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/localfilehelper.hxx> +#include <unotools/tempfile.hxx> +#include <vcl/svapp.hxx> +#include <vcl/cvtgrf.hxx> +#include <vcl/metaact.hxx> +#include <vcl/virdev.hxx> +#include <vcl/salbtype.hxx> +#include <unotools/cacheoptions.hxx> +#include <svtools/grfmgr.hxx> + +// ----------- +// - Defines - +// ----------- + +#define WATERMARK_LUM_OFFSET 50 +#define WATERMARK_CON_OFFSET -70 + +// ----------- +// - statics - +// ----------- + +GraphicManager* GraphicObject::mpGlobalMgr = NULL; + +// --------------------- +// - GrfDirectCacheObj - +// --------------------- + +struct GrfSimpleCacheObj +{ + Graphic maGraphic; + GraphicAttr maAttr; + + GrfSimpleCacheObj( const Graphic& rGraphic, const GraphicAttr& rAttr ) : + maGraphic( rGraphic ), maAttr( rAttr ) {} +}; + +// ----------------- +// - GraphicObject - +// ----------------- + +TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream ); + +// ----------------------------------------------------------------------------- + +GraphicObject::GraphicObject( const GraphicManager* pMgr ) : + mpLink ( NULL ), + mpUserData ( NULL ) +{ + ImplConstruct(); + ImplAssignGraphicData(); + ImplSetGraphicManager( pMgr ); +} + +// ----------------------------------------------------------------------------- + +GraphicObject::GraphicObject( const Graphic& rGraphic, const GraphicManager* pMgr ) : + maGraphic ( rGraphic ), + mpLink ( NULL ), + mpUserData ( NULL ) +{ + ImplConstruct(); + ImplAssignGraphicData(); + ImplSetGraphicManager( pMgr ); +} + +// ----------------------------------------------------------------------------- + +GraphicObject::GraphicObject( const Graphic& rGraphic, const String& rLink, const GraphicManager* pMgr ) : + maGraphic ( rGraphic ), + mpLink ( rLink.Len() ? ( new String( rLink ) ) : NULL ), + mpUserData ( NULL ) +{ + ImplConstruct(); + ImplAssignGraphicData(); + ImplSetGraphicManager( pMgr ); +} + +// ----------------------------------------------------------------------------- + +GraphicObject::GraphicObject( const GraphicObject& rGraphicObj, const GraphicManager* pMgr ) : + SvDataCopyStream(), + maGraphic ( rGraphicObj.GetGraphic() ), + maAttr ( rGraphicObj.maAttr ), + mpLink ( rGraphicObj.mpLink ? ( new String( *rGraphicObj.mpLink ) ) : NULL ), + mpUserData ( rGraphicObj.mpUserData ? ( new String( *rGraphicObj.mpUserData ) ) : NULL ) +{ + ImplConstruct(); + ImplAssignGraphicData(); + ImplSetGraphicManager( pMgr, NULL, &rGraphicObj ); +} + +// ----------------------------------------------------------------------------- + +GraphicObject::GraphicObject( const ByteString& rUniqueID, const GraphicManager* pMgr ) : + mpLink ( NULL ), + mpUserData ( NULL ) +{ + ImplConstruct(); + + // assign default properties + ImplAssignGraphicData(); + + ImplSetGraphicManager( pMgr, &rUniqueID ); + + // update properties + ImplAssignGraphicData(); +} + +// ----------------------------------------------------------------------------- + +GraphicObject::~GraphicObject() +{ + if( mpMgr ) + { + mpMgr->ImplUnregisterObj( *this ); + + if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() ) + delete mpGlobalMgr, mpGlobalMgr = NULL; + } + + delete mpSwapOutTimer; + delete mpSwapStreamHdl; + delete mpLink; + delete mpUserData; + delete mpSimpleCache; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::ImplConstruct() +{ + mpMgr = NULL; + mpSwapStreamHdl = NULL; + mpSwapOutTimer = NULL; + mpSimpleCache = NULL; + mnAnimationLoopCount = 0; + mbAutoSwapped = FALSE; + mbIsInSwapIn = FALSE; + mbIsInSwapOut = FALSE; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::ImplAssignGraphicData() +{ + maPrefSize = maGraphic.GetPrefSize(); + maPrefMapMode = maGraphic.GetPrefMapMode(); + mnSizeBytes = maGraphic.GetSizeBytes(); + meType = maGraphic.GetType(); + mbTransparent = maGraphic.IsTransparent(); + mbAlpha = maGraphic.IsAlpha(); + mbAnimated = maGraphic.IsAnimated(); + mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 ); + + if( maGraphic.GetType() == GRAPHIC_GDIMETAFILE ) + { + const GDIMetaFile& rMtf = GetGraphic().GetGDIMetaFile(); + mbEPS = ( rMtf.GetActionCount() >= 1 ) && ( META_EPS_ACTION == rMtf.GetAction( 0 )->GetType() ); + } + else + mbEPS = FALSE; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::ImplSetGraphicManager( const GraphicManager* pMgr, const ByteString* pID, const GraphicObject* pCopyObj ) +{ + if( !mpMgr || ( pMgr != mpMgr ) ) + { + if( !pMgr && mpMgr && ( mpMgr == mpGlobalMgr ) ) + return; + else + { + if( mpMgr ) + { + mpMgr->ImplUnregisterObj( *this ); + + if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() ) + delete mpGlobalMgr, mpGlobalMgr = NULL; + } + + if( !pMgr ) + { + if( !mpGlobalMgr ) + { + SvtCacheOptions aCacheOptions; + + mpGlobalMgr = new GraphicManager( aCacheOptions.GetGraphicManagerTotalCacheSize(), + aCacheOptions.GetGraphicManagerObjectCacheSize() ); + mpGlobalMgr->SetCacheTimeout( aCacheOptions.GetGraphicManagerObjectReleaseTime() ); + } + + mpMgr = mpGlobalMgr; + } + else + mpMgr = (GraphicManager*) pMgr; + + mpMgr->ImplRegisterObj( *this, maGraphic, pID, pCopyObj ); + } + } +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::ImplAutoSwapIn() +{ + if( IsSwappedOut() ) + { + if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) ) + mbAutoSwapped = FALSE; + else + { + mbIsInSwapIn = TRUE; + + if( maGraphic.SwapIn() ) + mbAutoSwapped = FALSE; + else + { + SvStream* pStream = GetSwapStream(); + + if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream ) + { + if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream ) + { + if( HasLink() ) + { + String aURLStr; + + if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( GetLink(), aURLStr ) ) + { + SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aURLStr, STREAM_READ ); + + if( pIStm ) + { + (*pIStm) >> maGraphic; + mbAutoSwapped = ( maGraphic.GetType() != GRAPHIC_NONE ); + delete pIStm; + } + } + } + } + else if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream ) + mbAutoSwapped = !maGraphic.SwapIn(); + else if( GRFMGR_AUTOSWAPSTREAM_LOADED == pStream ) + mbAutoSwapped = maGraphic.IsSwapOut(); + else + { + mbAutoSwapped = !maGraphic.SwapIn( pStream ); + delete pStream; + } + } + else + { + DBG_ASSERT( ( GRAPHIC_NONE == meType ) || ( GRAPHIC_DEFAULT == meType ), + "GraphicObject::ImplAutoSwapIn: could not get stream to swap in graphic! (=>KA)" ); + } + } + + mbIsInSwapIn = FALSE; + + if( !mbAutoSwapped && mpMgr ) + mpMgr->ImplGraphicObjectWasSwappedIn( *this ); + } + } +} + +// ----------------------------------------------------------------------------- +BOOL GraphicObject::ImplGetCropParams( OutputDevice* pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr, + PolyPolygon& rClipPolyPoly, BOOL& bRectClipRegion ) const +{ + BOOL bRet = FALSE; + + if( GetType() != GRAPHIC_NONE ) + { + Polygon aClipPoly( Rectangle( rPt, rSz ) ); + const USHORT nRot10 = pAttr->GetRotation() % 3600; + const Point aOldOrigin( rPt ); + // --> OD 2005-09-30 #i54875# - It's not needed to get the graphic again. +// const Graphic& rGraphic = GetGraphic(); + // <-- + const MapMode aMap100( MAP_100TH_MM ); + Size aSize100; + long nTotalWidth, nTotalHeight; + long nNewLeft, nNewTop, nNewRight, nNewBottom; + double fScale; + + if( nRot10 ) + { + aClipPoly.Rotate( rPt, nRot10 ); + bRectClipRegion = FALSE; + } + else + bRectClipRegion = TRUE; + + rClipPolyPoly = aClipPoly; + + // --> OD 2005-09-30 #i54875# - directly access member <maGraphic> to + // get <PrefSize> and <PrefMapMode>. +// if( rGraphic.GetPrefMapMode() == MAP_PIXEL ) +// aSize100 = Application::GetDefaultDevice()->PixelToLogic( rGraphic.GetPrefSize(), aMap100 ); +// else +// aSize100 = pOut->LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), aMap100 ); + if( maGraphic.GetPrefMapMode() == MAP_PIXEL ) + aSize100 = Application::GetDefaultDevice()->PixelToLogic( maGraphic.GetPrefSize(), aMap100 ); + else + { + MapMode m(maGraphic.GetPrefMapMode()); + aSize100 = pOut->LogicToLogic( maGraphic.GetPrefSize(), &m, &aMap100 ); + } + // <-- + + nTotalWidth = aSize100.Width() - pAttr->GetLeftCrop() - pAttr->GetRightCrop(); + nTotalHeight = aSize100.Height() - pAttr->GetTopCrop() - pAttr->GetBottomCrop(); + + if( aSize100.Width() > 0 && aSize100.Height() > 0 && nTotalWidth > 0 && nTotalHeight > 0 ) + { + fScale = (double) aSize100.Width() / nTotalWidth; + nNewLeft = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_HORZ ) ? pAttr->GetRightCrop() : pAttr->GetLeftCrop() ) * fScale ); + nNewRight = nNewLeft + FRound( aSize100.Width() * fScale ) - 1; + + fScale = (double) rSz.Width() / aSize100.Width(); + rPt.X() += FRound( nNewLeft * fScale ); + rSz.Width() = FRound( ( nNewRight - nNewLeft + 1 ) * fScale ); + + fScale = (double) aSize100.Height() / nTotalHeight; + nNewTop = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_VERT ) ? pAttr->GetBottomCrop() : pAttr->GetTopCrop() ) * fScale ); + nNewBottom = nNewTop + FRound( aSize100.Height() * fScale ) - 1; + + fScale = (double) rSz.Height() / aSize100.Height(); + rPt.Y() += FRound( nNewTop * fScale ); + rSz.Height() = FRound( ( nNewBottom - nNewTop + 1 ) * fScale ); + + if( nRot10 ) + { + Polygon aOriginPoly( 1 ); + + aOriginPoly[ 0 ] = rPt; + aOriginPoly.Rotate( aOldOrigin, nRot10 ); + rPt = aOriginPoly[ 0 ]; + } + + bRet = TRUE; + } + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj ) +{ + if( &rGraphicObj != this ) + { + mpMgr->ImplUnregisterObj( *this ); + + delete mpSwapStreamHdl, mpSwapStreamHdl = NULL; + delete mpSimpleCache, mpSimpleCache = NULL; + delete mpLink; + delete mpUserData; + + maGraphic = rGraphicObj.GetGraphic(); + maAttr = rGraphicObj.maAttr; + mpLink = rGraphicObj.mpLink ? new String( *rGraphicObj.mpLink ) : NULL; + mpUserData = rGraphicObj.mpUserData ? new String( *rGraphicObj.mpUserData ) : NULL; + ImplAssignGraphicData(); + mbAutoSwapped = FALSE; + mpMgr = rGraphicObj.mpMgr; + + mpMgr->ImplRegisterObj( *this, maGraphic, NULL, &rGraphicObj ); + } + + return *this; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicObject::operator==( const GraphicObject& rGraphicObj ) const +{ + return( ( rGraphicObj.maGraphic == maGraphic ) && + ( rGraphicObj.maAttr == maAttr ) && + ( rGraphicObj.GetLink() == GetLink() ) ); +} + +// ------------------------------------------------------------------------ + +void GraphicObject::Load( SvStream& rIStm ) +{ + rIStm >> *this; +} + +// ------------------------------------------------------------------------ + +void GraphicObject::Save( SvStream& rOStm ) +{ + rOStm << *this; +} + +// ------------------------------------------------------------------------ + +void GraphicObject::Assign( const SvDataCopyStream& rCopyStream ) +{ + *this = (const GraphicObject& ) rCopyStream; +} + +// ----------------------------------------------------------------------------- + +ByteString GraphicObject::GetUniqueID() const +{ + if ( !IsInSwapIn() && IsEPS() ) + const_cast<GraphicObject*>(this)->FireSwapInRequest(); + + ByteString aRet; + + if( mpMgr ) + aRet = mpMgr->ImplGetUniqueID( *this ); + + return aRet; +} + +// ----------------------------------------------------------------------------- + +ULONG GraphicObject::GetChecksum() const +{ + return( ( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() ) ? maGraphic.GetChecksum() : 0 ); +} + +// ----------------------------------------------------------------------------- + +SvStream* GraphicObject::GetSwapStream() const +{ + return( HasSwapStreamHdl() ? (SvStream*) mpSwapStreamHdl->Call( (void*) this ) : GRFMGR_AUTOSWAPSTREAM_NONE ); +} + +// ----------------------------------------------------------------------------- + +// !!! to be removed +ULONG GraphicObject::GetReleaseFromCache() const +{ + return 0; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetAttr( const GraphicAttr& rAttr ) +{ + maAttr = rAttr; + + if( mpSimpleCache && ( mpSimpleCache->maAttr != rAttr ) ) + delete mpSimpleCache, mpSimpleCache = NULL; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetLink() +{ + if( mpLink ) + delete mpLink, mpLink = NULL; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetLink( const String& rLink ) +{ + delete mpLink, mpLink = new String( rLink ); +} + +// ----------------------------------------------------------------------------- + +String GraphicObject::GetLink() const +{ + if( mpLink ) + return *mpLink; + else + return String(); +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetUserData() +{ + if( mpUserData ) + delete mpUserData, mpUserData = NULL; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetUserData( const String& rUserData ) +{ + delete mpUserData, mpUserData = new String( rUserData ); +} + +// ----------------------------------------------------------------------------- + +String GraphicObject::GetUserData() const +{ + if( mpUserData ) + return *mpUserData; + else + return String(); +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetSwapStreamHdl() +{ + if( mpSwapStreamHdl ) + { + delete mpSwapOutTimer, mpSwapOutTimer = NULL; + delete mpSwapStreamHdl, mpSwapStreamHdl = NULL; + } +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetSwapStreamHdl( const Link& rHdl, const ULONG nSwapOutTimeout ) +{ + delete mpSwapStreamHdl, mpSwapStreamHdl = new Link( rHdl ); + + if( nSwapOutTimeout ) + { + if( !mpSwapOutTimer ) + { + mpSwapOutTimer = new Timer; + mpSwapOutTimer->SetTimeoutHdl( LINK( this, GraphicObject, ImplAutoSwapOutHdl ) ); + } + + mpSwapOutTimer->SetTimeout( nSwapOutTimeout ); + mpSwapOutTimer->Start(); + } + else + delete mpSwapOutTimer, mpSwapOutTimer = NULL; +} + +// ----------------------------------------------------------------------------- + +Link GraphicObject::GetSwapStreamHdl() const +{ + if( mpSwapStreamHdl ) + return *mpSwapStreamHdl; + else + return Link(); +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::FireSwapInRequest() +{ + ImplAutoSwapIn(); +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::FireSwapOutRequest() +{ + ImplAutoSwapOutHdl( NULL ); +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::GraphicManagerDestroyed() +{ + // we're alive, but our manager doesn't live anymore ==> connect to default manager + mpMgr = NULL; + ImplSetGraphicManager( NULL ); +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetGraphicManager( const GraphicManager& rMgr ) +{ + ImplSetGraphicManager( &rMgr ); +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicObject::IsCached( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicAttr* pAttr, ULONG nFlags ) const +{ + BOOL bRet; + + if( nFlags & GRFMGR_DRAW_CACHED ) + { + // --> OD 2005-10-11 #i54875# - Consider cropped graphics. + // Note: The graphic manager caches a cropped graphic with its + // uncropped position and size. +// bRet = mpMgr->IsInCache( pOut, rPt, rSz, *this, ( pAttr ? *pAttr : GetAttr() ) ); + Point aPt( rPt ); + Size aSz( rSz ); + if ( pAttr->IsCropped() ) + { + PolyPolygon aClipPolyPoly; + BOOL bRectClip; + ImplGetCropParams( pOut, aPt, aSz, pAttr, aClipPolyPoly, bRectClip ); + } + bRet = mpMgr->IsInCache( pOut, aPt, aSz, *this, ( pAttr ? *pAttr : GetAttr() ) ); + } + else + bRet = FALSE; + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::ReleaseFromCache() +{ + + mpMgr->ReleaseFromCache( *this ); +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetAnimationNotifyHdl( const Link& rLink ) +{ + maGraphic.SetAnimationNotifyHdl( rLink ); +} + +// ----------------------------------------------------------------------------- + +List* GraphicObject::GetAnimationInfoList() const +{ + return maGraphic.GetAnimationInfoList(); +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GraphicAttr* pAttr, ULONG nFlags ) +{ + GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() ); + Point aPt( rPt ); + Size aSz( rSz ); + const sal_uInt32 nOldDrawMode = pOut->GetDrawMode(); + BOOL bCropped = aAttr.IsCropped(); + BOOL bCached = FALSE; + BOOL bRet; + + // #i29534# Provide output rects for PDF writer + Rectangle aCropRect; + + if( !( GRFMGR_DRAW_USE_DRAWMODE_SETTINGS & nFlags ) ) + pOut->SetDrawMode( nOldDrawMode & ( ~( DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT ) ) ); + + // mirrored horizontically + if( aSz.Width() < 0L ) + { + aPt.X() += aSz.Width() + 1; + aSz.Width() = -aSz.Width(); + aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_HORZ ); + } + + // mirrored vertically + if( aSz.Height() < 0L ) + { + aPt.Y() += aSz.Height() + 1; + aSz.Height() = -aSz.Height(); + aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_VERT ); + } + + if( bCropped ) + { + PolyPolygon aClipPolyPoly; + BOOL bRectClip; + const BOOL bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip ); + + pOut->Push( PUSH_CLIPREGION ); + + if( bCrop ) + { + if( bRectClip ) + { + // #i29534# Store crop rect for later forwarding to + // PDF writer + aCropRect = aClipPolyPoly.GetBoundRect(); + pOut->IntersectClipRegion( aCropRect ); + } + else + { + pOut->IntersectClipRegion( aClipPolyPoly ); + } + } + } + + bRet = mpMgr->DrawObj( pOut, aPt, aSz, *this, aAttr, nFlags, bCached ); + + if( bCropped ) + pOut->Pop(); + + pOut->SetDrawMode( nOldDrawMode ); + + // #i29534# Moved below OutDev restoration, to avoid multiple swap-ins + // (code above needs to call GetGraphic twice) + if( bCached ) + { + if( mpSwapOutTimer ) + mpSwapOutTimer->Start(); + else + FireSwapOutRequest(); + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicObject::DrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSize, + const Size& rOffset, const GraphicAttr* pAttr, ULONG nFlags, int nTileCacheSize1D ) +{ + if( pOut == NULL || rSize.Width() == 0 || rSize.Height() == 0 ) + return FALSE; + + const MapMode aOutMapMode( pOut->GetMapMode() ); + const MapMode aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() ); + // #106258# Clamp size to 1 for zero values. This is okay, since + // logical size of zero is handled above already + const Size aOutTileSize( ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Width() ), + ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Height() ) ); + + //#i69780 clip final tile size to a sane max size + while (((sal_Int64)rSize.Width() * nTileCacheSize1D) > SAL_MAX_UINT16) + nTileCacheSize1D /= 2; + while (((sal_Int64)rSize.Height() * nTileCacheSize1D) > SAL_MAX_UINT16) + nTileCacheSize1D /= 2; + + return ImplDrawTiled( pOut, rArea, aOutTileSize, rOffset, pAttr, nFlags, nTileCacheSize1D ); +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicObject::StartAnimation( OutputDevice* pOut, const Point& rPt, const Size& rSz, + long nExtraData, const GraphicAttr* pAttr, ULONG /*nFlags*/, + OutputDevice* pFirstFrameOutDev ) +{ + BOOL bRet = FALSE; + + GetGraphic(); + + if( !IsSwappedOut() ) + { + const GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() ); + + if( mbAnimated ) + { + Point aPt( rPt ); + Size aSz( rSz ); + BOOL bCropped = aAttr.IsCropped(); + + if( bCropped ) + { + PolyPolygon aClipPolyPoly; + BOOL bRectClip; + const BOOL bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip ); + + pOut->Push( PUSH_CLIPREGION ); + + if( bCrop ) + { + if( bRectClip ) + pOut->IntersectClipRegion( aClipPolyPoly.GetBoundRect() ); + else + pOut->IntersectClipRegion( aClipPolyPoly ); + } + } + + if( !mpSimpleCache || ( mpSimpleCache->maAttr != aAttr ) || pFirstFrameOutDev ) + { + if( mpSimpleCache ) + delete mpSimpleCache; + + mpSimpleCache = new GrfSimpleCacheObj( GetTransformedGraphic( &aAttr ), aAttr ); + mpSimpleCache->maGraphic.SetAnimationNotifyHdl( GetAnimationNotifyHdl() ); + } + + mpSimpleCache->maGraphic.StartAnimation( pOut, aPt, aSz, nExtraData, pFirstFrameOutDev ); + + if( bCropped ) + pOut->Pop(); + + bRet = TRUE; + } + else + bRet = Draw( pOut, rPt, rSz, &aAttr, GRFMGR_DRAW_STANDARD ); + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData ) +{ + if( mpSimpleCache ) + mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData ); +} + +// ----------------------------------------------------------------------------- + +const Graphic& GraphicObject::GetGraphic() const +{ + if( mbAutoSwapped ) + ( (GraphicObject*) this )->ImplAutoSwapIn(); + + return maGraphic; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetGraphic( const Graphic& rGraphic ) +{ + mpMgr->ImplUnregisterObj( *this ); + + if( mpSwapOutTimer ) + mpSwapOutTimer->Stop(); + + maGraphic = rGraphic; + mbAutoSwapped = FALSE; + ImplAssignGraphicData(); + delete mpLink, mpLink = NULL; + delete mpSimpleCache, mpSimpleCache = NULL; + + mpMgr->ImplRegisterObj( *this, maGraphic ); + + if( mpSwapOutTimer ) + mpSwapOutTimer->Start(); +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetGraphic( const Graphic& rGraphic, const String& rLink ) +{ + SetGraphic( rGraphic ); + mpLink = new String( rLink ); +} + +// ----------------------------------------------------------------------------- + +Graphic GraphicObject::GetTransformedGraphic( const Size& rDestSize, const MapMode& rDestMap, const GraphicAttr& rAttr ) const +{ + // #104550# Extracted from svx/source/svdraw/svdograf.cxx + Graphic aTransGraphic( maGraphic ); + const GraphicType eType = GetType(); + const Size aSrcSize( aTransGraphic.GetPrefSize() ); + + // #104115# Convert the crop margins to graphic object mapmode + const MapMode aMapGraph( aTransGraphic.GetPrefMapMode() ); + const MapMode aMap100( MAP_100TH_MM ); + + Size aCropLeftTop; + Size aCropRightBottom; + + if( GRAPHIC_GDIMETAFILE == eType ) + { + GDIMetaFile aMtf( aTransGraphic.GetGDIMetaFile() ); + + if( aMapGraph == MAP_PIXEL ) + { + aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetLeftCrop(), + rAttr.GetTopCrop() ), + aMap100 ); + aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetRightCrop(), + rAttr.GetBottomCrop() ), + aMap100 ); + } + else + { + aCropLeftTop = OutputDevice::LogicToLogic( Size( rAttr.GetLeftCrop(), + rAttr.GetTopCrop() ), + aMap100, + aMapGraph ); + aCropRightBottom = OutputDevice::LogicToLogic( Size( rAttr.GetRightCrop(), + rAttr.GetBottomCrop() ), + aMap100, + aMapGraph ); + } + + // #104115# If the metafile is cropped, give it a special + // treatment: clip against the remaining area, scale up such + // that this area later fills the desired size, and move the + // origin to the upper left edge of that area. + if( rAttr.IsCropped() ) + { + const MapMode aMtfMapMode( aMtf.GetPrefMapMode() ); + + Rectangle aClipRect( aMtfMapMode.GetOrigin().X() + aCropLeftTop.Width(), + aMtfMapMode.GetOrigin().Y() + aCropLeftTop.Height(), + aMtfMapMode.GetOrigin().X() + aSrcSize.Width() - aCropRightBottom.Width(), + aMtfMapMode.GetOrigin().Y() + aSrcSize.Height() - aCropRightBottom.Height() ); + + // #104115# To correctly crop rotated metafiles, clip by view rectangle + aMtf.AddAction( new MetaISectRectClipRegionAction( aClipRect ), 0 ); + + // #104115# To crop the metafile, scale larger than the output rectangle + aMtf.Scale( (double)rDestSize.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()), + (double)rDestSize.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) ); + + // #104115# Adapt the pref size by hand (scale changes it + // proportionally, but we want it to be smaller than the + // former size, to crop the excess out) + aMtf.SetPrefSize( Size( (long)((double)rDestSize.Width() * (1.0 + (aCropLeftTop.Width() + aCropRightBottom.Width()) / aSrcSize.Width()) + .5), + (long)((double)rDestSize.Height() * (1.0 + (aCropLeftTop.Height() + aCropRightBottom.Height()) / aSrcSize.Height()) + .5) ) ); + + // #104115# Adapt the origin of the new mapmode, such that it + // is shifted to the place where the cropped output starts + Point aNewOrigin( (long)((double)aMtfMapMode.GetOrigin().X() + rDestSize.Width() * aCropLeftTop.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()) + .5), + (long)((double)aMtfMapMode.GetOrigin().Y() + rDestSize.Height() * aCropLeftTop.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) + .5) ); + MapMode aNewMap( rDestMap ); + aNewMap.SetOrigin( OutputDevice::LogicToLogic(aNewOrigin, aMtfMapMode, rDestMap) ); + aMtf.SetPrefMapMode( aNewMap ); + } + else + { + aMtf.Scale( Fraction( rDestSize.Width(), aSrcSize.Width() ), Fraction( rDestSize.Height(), aSrcSize.Height() ) ); + aMtf.SetPrefMapMode( rDestMap ); + } + + aTransGraphic = aMtf; + } + else if( GRAPHIC_BITMAP == eType ) + { + BitmapEx aBitmapEx( aTransGraphic.GetBitmapEx() ); + + // convert crops to pixel + aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetLeftCrop(), + rAttr.GetTopCrop() ), + aMap100 ); + aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetRightCrop(), + rAttr.GetBottomCrop() ), + aMap100 ); + + // convert from prefmapmode to pixel + const Size aSrcSizePixel( Application::GetDefaultDevice()->LogicToPixel( aSrcSize, + aMapGraph ) ); + + // setup crop rectangle in pixel + Rectangle aCropRect( aCropLeftTop.Width(), aCropLeftTop.Height(), + aSrcSizePixel.Width() - aCropRightBottom.Width(), + aSrcSizePixel.Height() - aCropRightBottom.Height() ); + + // #105641# Also crop animations + if( aTransGraphic.IsAnimated() ) + { + USHORT nFrame; + Animation aAnim( aTransGraphic.GetAnimation() ); + + for( nFrame=0; nFrame<aAnim.Count(); ++nFrame ) + { + AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) ); + + if( !aCropRect.IsInside( Rectangle(aAnimBmp.aPosPix, aAnimBmp.aSizePix) ) ) + { + // setup actual cropping (relative to frame position) + Rectangle aCropRectRel( aCropRect ); + aCropRectRel.Move( -aAnimBmp.aPosPix.X(), + -aAnimBmp.aPosPix.Y() ); + + // cropping affects this frame, apply it then + // do _not_ apply enlargement, this is done below + ImplTransformBitmap( aAnimBmp.aBmpEx, rAttr, Size(), Size(), + aCropRectRel, rDestSize, FALSE ); + + aAnim.Replace( aAnimBmp, nFrame ); + } + // else: bitmap completely within crop area, + // i.e. nothing is cropped away + } + + // now, apply enlargement (if any) through global animation size + if( aCropLeftTop.Width() < 0 || + aCropLeftTop.Height() < 0 || + aCropRightBottom.Width() < 0 || + aCropRightBottom.Height() < 0 ) + { + Size aNewSize( aAnim.GetDisplaySizePixel() ); + aNewSize.Width() += aCropRightBottom.Width() < 0 ? -aCropRightBottom.Width() : 0; + aNewSize.Width() += aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0; + aNewSize.Height() += aCropRightBottom.Height() < 0 ? -aCropRightBottom.Height() : 0; + aNewSize.Height() += aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0; + aAnim.SetDisplaySizePixel( aNewSize ); + } + + // if topleft has changed, we must move all frames to the + // right and bottom, resp. + if( aCropLeftTop.Width() < 0 || + aCropLeftTop.Height() < 0 ) + { + Point aPosOffset( aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0, + aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0 ); + + for( nFrame=0; nFrame<aAnim.Count(); ++nFrame ) + { + AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) ); + + aAnimBmp.aPosPix += aPosOffset; + + aAnim.Replace( aAnimBmp, nFrame ); + } + } + + aTransGraphic = aAnim; + } + else + { + BitmapEx aBmpEx( aTransGraphic.GetBitmapEx() ); + + ImplTransformBitmap( aBmpEx, rAttr, aCropLeftTop, aCropRightBottom, + aCropRect, rDestSize, TRUE ); + + aTransGraphic = aBmpEx; + } + + aTransGraphic.SetPrefSize( rDestSize ); + aTransGraphic.SetPrefMapMode( rDestMap ); + } + + GraphicObject aGrfObj( aTransGraphic ); + aTransGraphic = aGrfObj.GetTransformedGraphic( &rAttr ); + + return aTransGraphic; +} + +// ----------------------------------------------------------------------------- + +Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const // TODO: Change to Impl +{ + GetGraphic(); + + Graphic aGraphic; + GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() ); + + if( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() ) + { + if( aAttr.IsSpecialDrawMode() || aAttr.IsAdjusted() || aAttr.IsMirrored() || aAttr.IsRotated() || aAttr.IsTransparent() ) + { + if( GetType() == GRAPHIC_BITMAP ) + { + if( IsAnimated() ) + { + Animation aAnimation( maGraphic.GetAnimation() ); + GraphicManager::ImplAdjust( aAnimation, aAttr, ADJUSTMENT_ALL ); + aAnimation.SetLoopCount( mnAnimationLoopCount ); + aGraphic = aAnimation; + } + else + { + BitmapEx aBmpEx( maGraphic.GetBitmapEx() ); + GraphicManager::ImplAdjust( aBmpEx, aAttr, ADJUSTMENT_ALL ); + aGraphic = aBmpEx; + } + } + else + { + GDIMetaFile aMtf( maGraphic.GetGDIMetaFile() ); + GraphicManager::ImplAdjust( aMtf, aAttr, ADJUSTMENT_ALL ); + aGraphic = aMtf; + } + } + else + { + if( ( GetType() == GRAPHIC_BITMAP ) && IsAnimated() ) + { + Animation aAnimation( maGraphic.GetAnimation() ); + aAnimation.SetLoopCount( mnAnimationLoopCount ); + aGraphic = aAnimation; + } + else + aGraphic = maGraphic; + } + } + + return aGraphic; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::ResetAnimationLoopCount() +{ + if( IsAnimated() && !IsSwappedOut() ) + { + maGraphic.ResetAnimationLoopCount(); + + if( mpSimpleCache ) + mpSimpleCache->maGraphic.ResetAnimationLoopCount(); + } +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicObject::SwapOut() +{ + BOOL bRet = ( !mbAutoSwapped ? maGraphic.SwapOut() : FALSE ); + + if( bRet && mpMgr ) + mpMgr->ImplGraphicObjectWasSwappedOut( *this ); + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicObject::SwapOut( SvStream* pOStm ) +{ + BOOL bRet = ( !mbAutoSwapped ? maGraphic.SwapOut( pOStm ) : FALSE ); + + if( bRet && mpMgr ) + mpMgr->ImplGraphicObjectWasSwappedOut( *this ); + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicObject::SwapIn() +{ + BOOL bRet; + + if( mbAutoSwapped ) + { + ImplAutoSwapIn(); + bRet = TRUE; + } + else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) ) + bRet = TRUE; + else + { + bRet = maGraphic.SwapIn(); + + if( bRet && mpMgr ) + mpMgr->ImplGraphicObjectWasSwappedIn( *this ); + } + + if( bRet ) + ImplAssignGraphicData(); + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicObject::SwapIn( SvStream* pIStm ) +{ + BOOL bRet; + + if( mbAutoSwapped ) + { + ImplAutoSwapIn(); + bRet = TRUE; + } + else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) ) + bRet = TRUE; + else + { + bRet = maGraphic.SwapIn( pIStm ); + + if( bRet && mpMgr ) + mpMgr->ImplGraphicObjectWasSwappedIn( *this ); + } + + if( bRet ) + ImplAssignGraphicData(); + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::SetSwapState() +{ + if( !IsSwappedOut() ) + { + mbAutoSwapped = TRUE; + + if( mpMgr ) + mpMgr->ImplGraphicObjectWasSwappedOut( *this ); + } +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( GraphicObject, ImplAutoSwapOutHdl, void*, EMPTYARG ) +{ + if( !IsSwappedOut() ) + { + mbIsInSwapOut = TRUE; + + SvStream* pStream = GetSwapStream(); + + if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream ) + { + if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream ) + mbAutoSwapped = SwapOut( NULL ); + else + { + if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream ) + mbAutoSwapped = SwapOut(); + else + { + mbAutoSwapped = SwapOut( pStream ); + delete pStream; + } + } + } + + mbIsInSwapOut = FALSE; + } + + if( mpSwapOutTimer ) + mpSwapOutTimer->Start(); + + return 0L; +} + +// ------------------------------------------------------------------------ + +SvStream& operator>>( SvStream& rIStm, GraphicObject& rGraphicObj ) +{ + VersionCompat aCompat( rIStm, STREAM_READ ); + Graphic aGraphic; + GraphicAttr aAttr; + ByteString aLink; + BOOL bLink; + + rIStm >> aGraphic >> aAttr >> bLink; + + rGraphicObj.SetGraphic( aGraphic ); + rGraphicObj.SetAttr( aAttr ); + + if( bLink ) + { + rIStm >> aLink; + rGraphicObj.SetLink( UniString( aLink, RTL_TEXTENCODING_UTF8 ) ); + } + else + rGraphicObj.SetLink(); + + rGraphicObj.SetSwapStreamHdl(); + + return rIStm; +} + +// ------------------------------------------------------------------------ + +SvStream& operator<<( SvStream& rOStm, const GraphicObject& rGraphicObj ) +{ + VersionCompat aCompat( rOStm, STREAM_WRITE, 1 ); + const BOOL bLink = rGraphicObj.HasLink(); + + rOStm << rGraphicObj.GetGraphic() << rGraphicObj.GetAttr() << bLink; + + if( bLink ) + rOStm << ByteString( rGraphicObj.GetLink(), RTL_TEXTENCODING_UTF8 ); + + return rOStm; +} + +#define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:" + +GraphicObject GraphicObject::CreateGraphicObjectFromURL( const ::rtl::OUString &rURL ) +{ + const String aURL( rURL ), aPrefix( RTL_CONSTASCII_STRINGPARAM(UNO_NAME_GRAPHOBJ_URLPREFIX) ); + if( aURL.Search( aPrefix ) == 0 ) + { + // graphic manager url + ByteString aUniqueID( String(rURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 )), RTL_TEXTENCODING_UTF8 ); + return GraphicObject( aUniqueID ); + } + else + { + Graphic aGraphic; + if ( aURL.Len() ) + { + SvStream* pStream = utl::UcbStreamHelper::CreateStream( aURL, STREAM_READ ); + if( pStream ) + GraphicConverter::Import( *pStream, aGraphic ); + } + + return GraphicObject( aGraphic ); + } +} + diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx new file mode 100644 index 000000000000..03e88a7be6c4 --- /dev/null +++ b/svtools/source/graphic/grfmgr2.cxx @@ -0,0 +1,2385 @@ +/************************************************************************* + * + * 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: grfmgr2.cxx,v $ + * $Revision: 1.26 $ + * + * 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 <vos/macros.hxx> +#include <vcl/bmpacc.hxx> +#include <tools/poly.hxx> +#include <vcl/outdev.hxx> +#include <vcl/window.hxx> +#include <vcl/gdimtf.hxx> +#include <vcl/metaact.hxx> +#include <vcl/metric.hxx> +#include <vcl/animate.hxx> +#include <vcl/alpha.hxx> +#include <vcl/virdev.hxx> +#include "grfcache.hxx" +#include <svtools/grfmgr.hxx> + +// ----------- +// - defines - +// ----------- + +#define MAX_PRINTER_EXT 1024 +#define MAP( cVal0, cVal1, nFrac ) ((BYTE)((((long)(cVal0)<<20L)+nFrac*((long)(cVal1)-(cVal0)))>>20L)) +#define WATERMARK_LUM_OFFSET 50 +#define WATERMARK_CON_OFFSET -70 + +// ----------- +// - helpers - +// ----------- + +namespace { + +void muckWithBitmap( const Point& rDestPoint, + const Size& rDestSize, + const Size& rRefSize, + bool& o_rbNonBitmapActionEncountered ) +{ + const Point aEmptyPoint; + + if( aEmptyPoint != rDestPoint || + rDestSize != rRefSize ) + { + // non-fullscale, or offsetted bmp -> fallback to mtf + // rendering + o_rbNonBitmapActionEncountered = true; + } +} + +BitmapEx muckWithBitmap( const BitmapEx& rBmpEx, + const Point& rSrcPoint, + const Size& rSrcSize, + const Point& rDestPoint, + const Size& rDestSize, + const Size& rRefSize, + bool& o_rbNonBitmapActionEncountered ) +{ + BitmapEx aBmpEx; + + muckWithBitmap(rDestPoint, + rDestSize, + rRefSize, + o_rbNonBitmapActionEncountered); + + if( o_rbNonBitmapActionEncountered ) + return aBmpEx; + + aBmpEx = rBmpEx; + + if( (rSrcPoint.X() != 0 && rSrcPoint.Y() != 0) || + rSrcSize != rBmpEx.GetSizePixel() ) + { + // crop bitmap to given source rectangle (no + // need to copy and convert the whole bitmap) + const Rectangle aCropRect( rSrcPoint, + rSrcSize ); + aBmpEx.Crop( aCropRect ); + } + + return aBmpEx; +} + +} // namespace { + + +// ------------------ +// - GraphicManager - +// ------------------ + +GraphicManager::GraphicManager( ULONG nCacheSize, ULONG nMaxObjCacheSize ) : + mpCache( new GraphicCache( *this, nCacheSize, nMaxObjCacheSize ) ) +{ +} + +// ----------------------------------------------------------------------------- + +GraphicManager::~GraphicManager() +{ + for( void* pObj = maObjList.First(); pObj; pObj = maObjList.Next() ) + ( (GraphicObject*) pObj )->GraphicManagerDestroyed(); + + delete mpCache; +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::SetMaxCacheSize( ULONG nNewCacheSize ) +{ + mpCache->SetMaxDisplayCacheSize( nNewCacheSize ); +} + +// ----------------------------------------------------------------------------- + +ULONG GraphicManager::GetMaxCacheSize() const +{ + return mpCache->GetMaxDisplayCacheSize(); +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::SetMaxObjCacheSize( ULONG nNewMaxObjSize, BOOL bDestroyGreaterCached ) +{ + mpCache->SetMaxObjDisplayCacheSize( nNewMaxObjSize, bDestroyGreaterCached ); +} + +// ----------------------------------------------------------------------------- + +ULONG GraphicManager::GetMaxObjCacheSize() const +{ + return mpCache->GetMaxObjDisplayCacheSize(); +} + +// ----------------------------------------------------------------------------- + +ULONG GraphicManager::GetUsedCacheSize() const +{ + return mpCache->GetUsedDisplayCacheSize(); +} + +// ----------------------------------------------------------------------------- + +ULONG GraphicManager::GetFreeCacheSize() const +{ + return mpCache->GetFreeDisplayCacheSize(); +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::SetCacheTimeout( ULONG nTimeoutSeconds ) +{ + mpCache->SetCacheTimeout( nTimeoutSeconds ); +} + +// ----------------------------------------------------------------------------- + +ULONG GraphicManager::GetCacheTimeout() const +{ + return mpCache->GetCacheTimeout(); +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ClearCache() +{ + mpCache->ClearDisplayCache(); +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ReleaseFromCache( const GraphicObject& /*rObj*/ ) +{ + // !!! +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicManager::IsInCache( OutputDevice* pOut, const Point& rPt, + const Size& rSz, const GraphicObject& rObj, + const GraphicAttr& rAttr ) const +{ + return mpCache->IsInDisplayCache( pOut, rPt, rSz, rObj, rAttr ); +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicManager::DrawObj( OutputDevice* pOut, const Point& rPt, const Size& rSz, + GraphicObject& rObj, const GraphicAttr& rAttr, + const ULONG nFlags, BOOL& rCached ) +{ + Point aPt( rPt ); + Size aSz( rSz ); + BOOL bRet = FALSE; + + rCached = FALSE; + + if( ( rObj.GetType() == GRAPHIC_BITMAP ) || ( rObj.GetType() == GRAPHIC_GDIMETAFILE ) ) + { + // create output and fill cache + const Size aOutSize( pOut->GetOutputSizePixel() ); + + if( rObj.IsAnimated() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) || + ( !( nFlags & GRFMGR_DRAW_NO_SUBSTITUTE ) && + ( ( nFlags & GRFMGR_DRAW_SUBSTITUTE ) || + !( nFlags & GRFMGR_DRAW_CACHED ) || + ( pOut->GetConnectMetaFile() && !pOut->IsOutputEnabled() ) ) ) ) + { + // simple output of transformed graphic + const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) ); + + if( aGraphic.IsSupportedGraphic() ) + { + const USHORT nRot10 = rAttr.GetRotation() % 3600; + + if( nRot10 ) + { + Polygon aPoly( Rectangle( aPt, aSz ) ); + + aPoly.Rotate( aPt, nRot10 ); + const Rectangle aRotBoundRect( aPoly.GetBoundRect() ); + aPt = aRotBoundRect.TopLeft(); + aSz = aRotBoundRect.GetSize(); + } + + aGraphic.Draw( pOut, aPt, aSz ); + } + + bRet = TRUE; + } + + if( !bRet ) + { + // cached/direct drawing + if( !mpCache->DrawDisplayCacheObj( pOut, aPt, aSz, rObj, rAttr ) ) + bRet = ImplDraw( pOut, aPt, aSz, rObj, rAttr, nFlags, rCached ); + else + bRet = rCached = TRUE; + } + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ImplRegisterObj( const GraphicObject& rObj, Graphic& rSubstitute, + const ByteString* pID, const GraphicObject* pCopyObj ) +{ + maObjList.Insert( (void*) &rObj, LIST_APPEND ); + mpCache->AddGraphicObject( rObj, rSubstitute, pID, pCopyObj ); +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ImplUnregisterObj( const GraphicObject& rObj ) +{ + mpCache->ReleaseGraphicObject( rObj ); + maObjList.Remove( (void*) &rObj ); +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ImplGraphicObjectWasSwappedOut( const GraphicObject& rObj ) +{ + mpCache->GraphicObjectWasSwappedOut( rObj ); +} + +// ----------------------------------------------------------------------------- + +ByteString GraphicManager::ImplGetUniqueID( const GraphicObject& rObj ) const +{ + return mpCache->GetUniqueID( rObj ); +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicManager::ImplFillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute ) +{ + return( mpCache->FillSwappedGraphicObject( rObj, rSubstitute ) ); +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj ) +{ + mpCache->GraphicObjectWasSwappedIn( rObj ); +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt, + const Size& rSz, GraphicObject& rObj, + const GraphicAttr& rAttr, + const ULONG nFlags, BOOL& rCached ) +{ + const Graphic& rGraphic = rObj.GetGraphic(); + BOOL bRet = FALSE; + + if( rGraphic.IsSupportedGraphic() && !rGraphic.IsSwapOut() ) + { + if( GRAPHIC_BITMAP == rGraphic.GetType() ) + { + const BitmapEx aSrcBmpEx( rGraphic.GetBitmapEx() ); + + // #i46805# No point in caching a bitmap that is rendered + // via RectFill on the OutDev + if( !(pOut->GetDrawMode() & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP )) && + mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) ) + { + BitmapEx aDstBmpEx; + + if( ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr, nFlags, &aDstBmpEx ) ) + { + rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx ); + bRet = TRUE; + } + } + + if( !bRet ) + bRet = ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr, nFlags ); + } + else + { + const GDIMetaFile& rSrcMtf = rGraphic.GetGDIMetaFile(); + + if( mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) ) + { + GDIMetaFile aDstMtf; + BitmapEx aContainedBmpEx; + + if( ImplCreateOutput( pOut, rPt, rSz, rSrcMtf, rAttr, nFlags, aDstMtf, aContainedBmpEx ) ) + { + if( !!aContainedBmpEx ) + { + // #117889# Use bitmap output method, if + // metafile basically contains only a single + // bitmap + BitmapEx aDstBmpEx; + + if( ImplCreateOutput( pOut, rPt, rSz, aContainedBmpEx, rAttr, nFlags, &aDstBmpEx ) ) + { + rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx ); + bRet = TRUE; + } + } + else + { + rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstMtf ); + bRet = TRUE; + } + } + } + + if( !bRet ) + { + const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) ); + + if( aGraphic.IsSupportedGraphic() ) + { + aGraphic.Draw( pOut, rPt, rSz ); + bRet = TRUE; + } + } + } + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicManager::ImplCreateOutput( OutputDevice* pOut, + const Point& rPt, const Size& rSz, + const BitmapEx& rBmpEx, const GraphicAttr& rAttr, + const ULONG nFlags, BitmapEx* pBmpEx ) +{ + USHORT nRot10 = rAttr.GetRotation() % 3600; + Point aOutPtPix; + Size aOutSzPix; + Size aUnrotatedSzPix( pOut->LogicToPixel( rSz ) ); + BOOL bRet = FALSE; + + if( nRot10 ) + { + Polygon aPoly( Rectangle( rPt, rSz ) ); + + aPoly.Rotate( rPt, nRot10 ); + const Rectangle aRotBoundRect( aPoly.GetBoundRect() ); + aOutPtPix = pOut->LogicToPixel( aRotBoundRect.TopLeft() ); + aOutSzPix = pOut->LogicToPixel( aRotBoundRect.GetSize() ); + } + else + { + aOutPtPix = pOut->LogicToPixel( rPt ); + aOutSzPix = aUnrotatedSzPix; + } + + if( aUnrotatedSzPix.Width() && aUnrotatedSzPix.Height() ) + { + BitmapEx aBmpEx( rBmpEx ); + BitmapEx aOutBmpEx; + Point aOutPt; + Size aOutSz; + const Size& rBmpSzPix = rBmpEx.GetSizePixel(); + const long nW = rBmpSzPix.Width(); + const long nH = rBmpSzPix.Height(); + const long nNewW = aUnrotatedSzPix.Width(); + const long nNewH = aUnrotatedSzPix.Height(); + double fTmp; + long* pMapIX = new long[ nNewW ]; + long* pMapFX = new long[ nNewW ]; + long* pMapIY = new long[ nNewH ]; + long* pMapFY = new long[ nNewH ]; + long nStartX = -1, nStartY = -1, nEndX = -1, nEndY = -1; + long nX, nY, nTmp, nTmpX, nTmpY; + BOOL bHMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0; + BOOL bVMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0; + + if( nFlags & GRFMGR_DRAW_BILINEAR ) + { + const double fRevScaleX = ( nNewW > 1L ) ? ( (double) ( nW - 1L ) / ( nNewW - 1L ) ) : 0.0; + const double fRevScaleY = ( nNewH > 1L ) ? ( (double) ( nH - 1L ) / ( nNewH - 1L ) ) : 0.0; + + // create horizontal mapping table + for( nX = 0L, nTmpX = nW - 1L, nTmp = nW - 2L; nX < nNewW; nX++ ) + { + fTmp = nX * fRevScaleX; + + if( bHMirr ) + fTmp = nTmpX - fTmp; + + pMapFX[ nX ] = (long) ( ( fTmp - ( pMapIX[ nX ] = MinMax( (long) fTmp, 0, nTmp ) ) ) * 1048576. ); + } + + // create vertical mapping table + for( nY = 0L, nTmpY = nH - 1L, nTmp = nH - 2L; nY < nNewH; nY++ ) + { + fTmp = nY * fRevScaleY; + + if( bVMirr ) + fTmp = nTmpY - fTmp; + + pMapFY[ nY ] = (long) ( ( fTmp - ( pMapIY[ nY ] = MinMax( (long) fTmp, 0, nTmp ) ) ) * 1048576. ); + } + } + else + { + // #98290# Use a different mapping for non-interpolating mode, to avoid missing rows/columns + const double fRevScaleX = ( nNewW > 1L ) ? ( (double) nW / nNewW ) : 0.0; + const double fRevScaleY = ( nNewH > 1L ) ? ( (double) nH / nNewH ) : 0.0; + + // create horizontal mapping table + for( nX = 0L, nTmpX = nW - 1L, nTmp = nW - 2L; nX < nNewW; nX++ ) + { + fTmp = nX * fRevScaleX; + + if( bHMirr ) + fTmp = nTmpX - fTmp; + + // #98290# Do not use round to zero, otherwise last column will be missing + pMapIX[ nX ] = MinMax( (long) fTmp, 0, nTmp ); + pMapFX[ nX ] = fTmp >= nTmp+1 ? 1048576 : 0; + } + + // create vertical mapping table + for( nY = 0L, nTmpY = nH - 1L, nTmp = nH - 2L; nY < nNewH; nY++ ) + { + fTmp = nY * fRevScaleY; + + if( bVMirr ) + fTmp = nTmpY - fTmp; + + // #98290# Do not use round to zero, otherwise last row will be missing + pMapIY[ nY ] = MinMax( (long) fTmp, 0, nTmp ); + pMapFY[ nY ] = fTmp >= nTmp+1 ? 1048576 : 0; + } + } + + // calculate output sizes + if( !pBmpEx ) + { + Point aPt; + Rectangle aOutRect( aPt, pOut->GetOutputSizePixel() ); + Rectangle aBmpRect( aOutPtPix, aOutSzPix ); + + if( pOut->GetOutDevType() == OUTDEV_WINDOW ) + { + const Region aPaintRgn( ( (Window*) pOut )->GetPaintRegion() ); + if( !aPaintRgn.IsNull() ) + aOutRect.Intersection( pOut->LogicToPixel( aPaintRgn.GetBoundRect() ) ); + } + + aOutRect.Intersection( aBmpRect ); + + if( !aOutRect.IsEmpty() ) + { + aOutPt = pOut->PixelToLogic( aOutRect.TopLeft() ); + aOutSz = pOut->PixelToLogic( aOutRect.GetSize() ); + nStartX = aOutRect.Left() - aBmpRect.Left(); + nStartY = aOutRect.Top() - aBmpRect.Top(); + nEndX = aOutRect.Right() - aBmpRect.Left(); + nEndY = aOutRect.Bottom() - aBmpRect.Top(); + } + else + nStartX = -1L; // invalid + } + else + { + aOutPt = pOut->PixelToLogic( aOutPtPix ); + aOutSz = pOut->PixelToLogic( aOutSzPix ); + nStartX = nStartY = 0; + nEndX = aOutSzPix.Width() - 1L; + nEndY = aOutSzPix.Height() - 1L; + } + + // do transformation + if( nStartX >= 0L ) + { + const BOOL bSimple = ( 1 == nW || 1 == nH ); + + if( nRot10 ) + { + if( bSimple ) + { + bRet = ( aOutBmpEx = aBmpEx ).Scale( aUnrotatedSzPix ); + + if( bRet ) + aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT ); + } + else + { + bRet = ImplCreateRotatedScaled( aBmpEx, + nRot10, aOutSzPix, aUnrotatedSzPix, + pMapIX, pMapFX, pMapIY, pMapFY, nStartX, nEndX, nStartY, nEndY, + aOutBmpEx ); + } + } + else + { + // #105229# Don't scale if output size equals bitmap size + // #107226# Copy through only if we're not mirroring + if( !bHMirr && !bVMirr && aOutSzPix == rBmpSzPix ) + { + // #107226# Use original dimensions when just copying through + aOutPt = pOut->PixelToLogic( aOutPtPix ); + aOutSz = pOut->PixelToLogic( aOutSzPix ); + aOutBmpEx = aBmpEx; + bRet = TRUE; + } + else + { + if( bSimple ) + bRet = ( aOutBmpEx = aBmpEx ).Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ) ); + else + { + bRet = ImplCreateScaled( aBmpEx, + pMapIX, pMapFX, pMapIY, pMapFY, + nStartX, nEndX, nStartY, nEndY, + aOutBmpEx ); + } + } + } + + if( bRet ) + { + // attribute adjustment if neccessary + if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsTransparent() ) + ImplAdjust( aOutBmpEx, rAttr, ADJUSTMENT_DRAWMODE | ADJUSTMENT_COLORS | ADJUSTMENT_TRANSPARENCY ); + + // OutDev adjustment if neccessary + if( pOut->GetOutDevType() != OUTDEV_PRINTER && pOut->GetBitCount() <= 8 && aOutBmpEx.GetBitCount() >= 8 ) + aOutBmpEx.Dither( BMP_DITHER_MATRIX ); + } + } + + // delete lookup tables + delete[] pMapIX; + delete[] pMapFX; + delete[] pMapIY; + delete[] pMapFY; + + // create output + if( bRet ) + { + if( !pBmpEx ) + pOut->DrawBitmapEx( aOutPt, aOutSz, aOutBmpEx ); + else + { + if( !rAttr.IsTransparent() && !aOutBmpEx.IsAlpha() ) + aOutBmpEx = BitmapEx( aOutBmpEx.GetBitmap().CreateDisplayBitmap( pOut ), aOutBmpEx.GetMask() ); + + pOut->DrawBitmapEx( aOutPt, aOutSz, *pBmpEx = aOutBmpEx ); + } + } + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicManager::ImplCreateOutput( OutputDevice* pOut, + const Point& rPt, const Size& rSz, + const GDIMetaFile& rMtf, const GraphicAttr& rAttr, + const ULONG /*nFlags*/, GDIMetaFile& rOutMtf, BitmapEx& rOutBmpEx ) +{ + const Size aNewSize( rMtf.GetPrefSize() ); + + rOutMtf = rMtf; + + // #117889# count bitmap actions, and flag actions that paint, but + // are no bitmaps. + sal_Int32 nNumBitmaps(0); + bool bNonBitmapActionEncountered(false); + if( aNewSize.Width() && aNewSize.Height() && rSz.Width() && rSz.Height() ) + { + const double fGrfWH = (double) aNewSize.Width() / aNewSize.Height(); + const double fOutWH = (double) rSz.Width() / rSz.Height(); + + const double fScaleX = fOutWH / fGrfWH; + const double fScaleY = 1.0; + + const MapMode& rPrefMapMode( rMtf.GetPrefMapMode() ); + const Size& rSizePix( pOut->LogicToPixel( aNewSize, + rPrefMapMode ) ); + + // taking care of font width default if scaling metafile. + // #117889# use existing metafile scan, to determine whether + // the metafile basically displays a single bitmap. Note that + // the solution, as implemented here, is quite suboptimal (the + // cases where a mtf consisting basically of a single bitmap, + // that fail to pass the test below, are probably frequent). A + // better solution would involve FSAA, but that's currently + // expensive, and might trigger bugs on display drivers, if + // VDevs get bigger than the actual screen. + sal_uInt32 nCurPos; + MetaAction* pAct; + for( nCurPos = 0, pAct = (MetaAction*)rOutMtf.FirstAction(); pAct; + pAct = (MetaAction*)rOutMtf.NextAction(), nCurPos++ ) + { + MetaAction* pModAct = NULL; + switch( pAct->GetType() ) + { + case META_FONT_ACTION: + { + MetaFontAction* pA = (MetaFontAction*)pAct; + Font aFont( pA->GetFont() ); + if ( !aFont.GetWidth() ) + { + FontMetric aFontMetric( pOut->GetFontMetric( aFont ) ); + aFont.SetWidth( aFontMetric.GetWidth() ); + pModAct = new MetaFontAction( aFont ); + } + } + // FALLTHROUGH intended + case META_NULL_ACTION: + // FALLTHROUGH intended + + // OutDev state changes (which don't affect bitmap + // output) + case META_LINECOLOR_ACTION: + // FALLTHROUGH intended + case META_FILLCOLOR_ACTION: + // FALLTHROUGH intended + case META_TEXTCOLOR_ACTION: + // FALLTHROUGH intended + case META_TEXTFILLCOLOR_ACTION: + // FALLTHROUGH intended + case META_TEXTALIGN_ACTION: + // FALLTHROUGH intended + case META_TEXTLINECOLOR_ACTION: + // FALLTHROUGH intended + case META_TEXTLINE_ACTION: + // FALLTHROUGH intended + case META_PUSH_ACTION: + // FALLTHROUGH intended + case META_POP_ACTION: + // FALLTHROUGH intended + case META_LAYOUTMODE_ACTION: + // FALLTHROUGH intended + case META_TEXTLANGUAGE_ACTION: + // FALLTHROUGH intended + case META_COMMENT_ACTION: + break; + + // bitmap output methods + case META_BMP_ACTION: + if( !nNumBitmaps && !bNonBitmapActionEncountered ) + { + MetaBmpAction* pAction = (MetaBmpAction*)pAct; + + rOutBmpEx = BitmapEx( pAction->GetBitmap() ); + muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(), + rPrefMapMode ), + pAction->GetBitmap().GetSizePixel(), + rSizePix, + bNonBitmapActionEncountered ); + ++nNumBitmaps; + } + break; + + case META_BMPSCALE_ACTION: + if( !nNumBitmaps && !bNonBitmapActionEncountered ) + { + MetaBmpScaleAction* pAction = (MetaBmpScaleAction*)pAct; + + rOutBmpEx = BitmapEx( pAction->GetBitmap() ); + muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(), + rPrefMapMode ), + pOut->LogicToPixel( pAction->GetSize(), + rPrefMapMode ), + rSizePix, + bNonBitmapActionEncountered ); + ++nNumBitmaps; + } + break; + + case META_BMPSCALEPART_ACTION: + if( !nNumBitmaps && !bNonBitmapActionEncountered ) + { + MetaBmpScalePartAction* pAction = (MetaBmpScalePartAction*)pAct; + + rOutBmpEx = muckWithBitmap( BitmapEx( pAction->GetBitmap() ), + pAction->GetSrcPoint(), + pAction->GetSrcSize(), + pOut->LogicToPixel( pAction->GetDestPoint(), + rPrefMapMode ), + pOut->LogicToPixel( pAction->GetDestSize(), + rPrefMapMode ), + rSizePix, + bNonBitmapActionEncountered ); + ++nNumBitmaps; + } + break; + + case META_BMPEX_ACTION: + if( !nNumBitmaps && !bNonBitmapActionEncountered ) + { + MetaBmpExAction* pAction = (MetaBmpExAction*)pAct; + + rOutBmpEx = pAction->GetBitmapEx(); + muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(), + rPrefMapMode ), + pAction->GetBitmapEx().GetSizePixel(), + rSizePix, + bNonBitmapActionEncountered ); + ++nNumBitmaps; + } + break; + + case META_BMPEXSCALE_ACTION: + if( !nNumBitmaps && !bNonBitmapActionEncountered ) + { + MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*)pAct; + + rOutBmpEx = pAction->GetBitmapEx(); + muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(), + rPrefMapMode ), + pOut->LogicToPixel( pAction->GetSize(), + rPrefMapMode ), + rSizePix, + bNonBitmapActionEncountered ); + ++nNumBitmaps; + } + break; + + case META_BMPEXSCALEPART_ACTION: + if( !nNumBitmaps && !bNonBitmapActionEncountered ) + { + MetaBmpExScalePartAction* pAction = (MetaBmpExScalePartAction*)pAct; + + rOutBmpEx = muckWithBitmap( pAction->GetBitmapEx(), + pAction->GetSrcPoint(), + pAction->GetSrcSize(), + pOut->LogicToPixel( pAction->GetDestPoint(), + rPrefMapMode ), + pOut->LogicToPixel( pAction->GetDestSize(), + rPrefMapMode ), + rSizePix, + bNonBitmapActionEncountered ); + ++nNumBitmaps; + } + break; + + // these actions actually output something (that's + // different from a bitmap) + case META_RASTEROP_ACTION: + if( ((MetaRasterOpAction*)pAct)->GetRasterOp() == ROP_OVERPAINT ) + break; + // FALLTHROUGH intended + case META_PIXEL_ACTION: + // FALLTHROUGH intended + case META_POINT_ACTION: + // FALLTHROUGH intended + case META_LINE_ACTION: + // FALLTHROUGH intended + case META_RECT_ACTION: + // FALLTHROUGH intended + case META_ROUNDRECT_ACTION: + // FALLTHROUGH intended + case META_ELLIPSE_ACTION: + // FALLTHROUGH intended + case META_ARC_ACTION: + // FALLTHROUGH intended + case META_PIE_ACTION: + // FALLTHROUGH intended + case META_CHORD_ACTION: + // FALLTHROUGH intended + case META_POLYLINE_ACTION: + // FALLTHROUGH intended + case META_POLYGON_ACTION: + // FALLTHROUGH intended + case META_POLYPOLYGON_ACTION: + // FALLTHROUGH intended + + case META_TEXT_ACTION: + // FALLTHROUGH intended + case META_TEXTARRAY_ACTION: + // FALLTHROUGH intended + case META_STRETCHTEXT_ACTION: + // FALLTHROUGH intended + case META_TEXTRECT_ACTION: + // FALLTHROUGH intended + + case META_MASK_ACTION: + // FALLTHROUGH intended + case META_MASKSCALE_ACTION: + // FALLTHROUGH intended + case META_MASKSCALEPART_ACTION: + // FALLTHROUGH intended + + case META_GRADIENT_ACTION: + // FALLTHROUGH intended + case META_HATCH_ACTION: + // FALLTHROUGH intended + case META_WALLPAPER_ACTION: + // FALLTHROUGH intended + + case META_TRANSPARENT_ACTION: + // FALLTHROUGH intended + case META_EPS_ACTION: + // FALLTHROUGH intended + case META_FLOATTRANSPARENT_ACTION: + // FALLTHROUGH intended + case META_GRADIENTEX_ACTION: + // FALLTHROUGH intended + + // OutDev state changes that _do_ affect bitmap + // output + case META_CLIPREGION_ACTION: + // FALLTHROUGH intended + case META_ISECTRECTCLIPREGION_ACTION: + // FALLTHROUGH intended + case META_ISECTREGIONCLIPREGION_ACTION: + // FALLTHROUGH intended + case META_MOVECLIPREGION_ACTION: + // FALLTHROUGH intended + + case META_MAPMODE_ACTION: + // FALLTHROUGH intended + case META_REFPOINT_ACTION: + // FALLTHROUGH intended + default: + bNonBitmapActionEncountered = true; + break; + } + if ( pModAct ) + { + rOutMtf.ReplaceAction( pModAct, nCurPos ); + pAct->Delete(); + } + else + { + if( pAct->GetRefCount() > 1 ) + { + rOutMtf.ReplaceAction( pModAct = pAct->Clone(), nCurPos ); + pAct->Delete(); + } + else + pModAct = pAct; + } + pModAct->Scale( fScaleX, fScaleY ); + } + rOutMtf.SetPrefSize( Size( FRound( aNewSize.Width() * fScaleX ), + FRound( aNewSize.Height() * fScaleY ) ) ); + } + + if( nNumBitmaps != 1 || bNonBitmapActionEncountered ) + { + if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsMirrored() || rAttr.IsRotated() || rAttr.IsTransparent() ) + ImplAdjust( rOutMtf, rAttr, ADJUSTMENT_ALL ); + + ImplDraw( pOut, rPt, rSz, rOutMtf, rAttr ); + rOutBmpEx = BitmapEx(); + } + + return TRUE; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicManager::ImplCreateScaled( const BitmapEx& rBmpEx, + long* pMapIX, long* pMapFX, long* pMapIY, long* pMapFY, + long nStartX, long nEndX, long nStartY, long nEndY, + BitmapEx& rOutBmpEx ) +{ + Bitmap aBmp( rBmpEx.GetBitmap() ); + Bitmap aOutBmp; + BitmapReadAccess* pAcc = aBmp.AcquireReadAccess(); + BitmapWriteAccess* pWAcc; + BitmapColor aCol0, aCol1, aColRes; + const long nDstW = nEndX - nStartX + 1L; + const long nDstH = nEndY - nStartY + 1L; + long nX, nY, nTmpX, nTmpY, nTmpFX, nTmpFY; + long nXDst, nYDst; + BYTE cR0, cG0, cB0, cR1, cG1, cB1; + BOOL bRet = FALSE; + + DBG_ASSERT( aBmp.GetSizePixel() == rBmpEx.GetSizePixel(), + "GraphicManager::ImplCreateScaled(): bmp size inconsistent" ); + + if( pAcc ) + { + aOutBmp = Bitmap( Size( nDstW, nDstH ), 24 ); + pWAcc = aOutBmp.AcquireWriteAccess(); + + if( pWAcc ) + { + if( pAcc->HasPalette() ) + { + if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) + { + Scanline pLine0, pLine1; + + for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) + { + nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; + pLine0 = pAcc->GetScanline( nTmpY ); + pLine1 = pAcc->GetScanline( ++nTmpY ); + + for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) + { + nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; + + const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTmpX ] ); + const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTmpX ] ); + const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTmpX ] ); + const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTmpX ] ); + + cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTmpFX ); + cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTmpFX ); + cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTmpFX ); + + cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTmpFX ); + cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTmpFX ); + cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTmpFX ); + + aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); + aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); + aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); + pWAcc->SetPixel( nYDst, nXDst++, aColRes ); + } + } + } + else + { + for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) + { + nTmpY = pMapIY[ nY ], nTmpFY = pMapFY[ nY ]; + + for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) + { + nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; + + aCol0 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, nTmpX ) ); + aCol1 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, ++nTmpX ) ); + cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); + cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); + cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); + + aCol1 = pAcc->GetPaletteColor( pAcc->GetPixel( ++nTmpY, nTmpX ) ); + aCol0 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY--, --nTmpX ) ); + cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); + cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); + cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); + + aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); + aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); + aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); + pWAcc->SetPixel( nYDst, nXDst++, aColRes ); + } + } + } + } + else + { + if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR ) + { + Scanline pLine0, pLine1, pTmp0, pTmp1; + long nOff; + + for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) + { + nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; + pLine0 = pAcc->GetScanline( nTmpY ); + pLine1 = pAcc->GetScanline( ++nTmpY ); + + for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) + { + nOff = 3L * ( nTmpX = pMapIX[ nX ] ); + nTmpFX = pMapFX[ nX ]; + + pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L; + cB0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; + cG0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; + cR0 = MAP( *pTmp0, *pTmp1, nTmpFX ); + + pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L; + cB1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; + cG1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; + cR1 = MAP( *pTmp0, *pTmp1, nTmpFX ); + + aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); + aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); + aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); + pWAcc->SetPixel( nYDst, nXDst++, aColRes ); + } + } + } + else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB ) + { + Scanline pLine0, pLine1, pTmp0, pTmp1; + long nOff; + + for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) + { + nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; + pLine0 = pAcc->GetScanline( nTmpY ); + pLine1 = pAcc->GetScanline( ++nTmpY ); + + for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) + { + nOff = 3L * ( nTmpX = pMapIX[ nX ] ); + nTmpFX = pMapFX[ nX ]; + + pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L; + cR0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; + cG0 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; + cB0 = MAP( *pTmp0, *pTmp1, nTmpFX ); + + pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L; + cR1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; + cG1 = MAP( *pTmp0, *pTmp1, nTmpFX ); pTmp0++; pTmp1++; + cB1 = MAP( *pTmp0, *pTmp1, nTmpFX ); + + aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); + aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); + aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); + pWAcc->SetPixel( nYDst, nXDst++, aColRes ); + } + } + } + else + { + for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) + { + nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; + + for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) + { + nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; + + aCol0 = pAcc->GetPixel( nTmpY, nTmpX ); + aCol1 = pAcc->GetPixel( nTmpY, ++nTmpX ); + cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); + cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); + cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); + + aCol1 = pAcc->GetPixel( ++nTmpY, nTmpX ); + aCol0 = pAcc->GetPixel( nTmpY--, --nTmpX ); + cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); + cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); + cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); + + aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); + aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); + aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); + pWAcc->SetPixel( nYDst, nXDst++, aColRes ); + } + } + } + } + + aOutBmp.ReleaseAccess( pWAcc ); + bRet = TRUE; + } + + aBmp.ReleaseAccess( pAcc ); + } + + if( bRet && rBmpEx.IsTransparent() ) + { + bRet = FALSE; + + if( rBmpEx.IsAlpha() ) + { + DBG_ASSERT( rBmpEx.GetAlpha().GetSizePixel() == rBmpEx.GetSizePixel(), + "GraphicManager::ImplCreateScaled(): alpha mask size inconsistent" ); + + AlphaMask aAlpha( rBmpEx.GetAlpha() ); + AlphaMask aOutAlpha; + + pAcc = aAlpha.AcquireReadAccess(); + + if( pAcc ) + { + aOutAlpha = AlphaMask( Size( nDstW, nDstH ) ); + pWAcc = aOutAlpha.AcquireWriteAccess(); + + if( pWAcc ) + { + if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL && + pWAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) + { + Scanline pLine0, pLine1, pLineW; + + for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) + { + nTmpY = pMapIY[ nY ]; nTmpFY = pMapFY[ nY ]; + pLine0 = pAcc->GetScanline( nTmpY ); + pLine1 = pAcc->GetScanline( ++nTmpY ); + pLineW = pWAcc->GetScanline( nYDst ); + + for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++, nXDst++ ) + { + nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; + + const long nAlpha0 = pLine0[ nTmpX ]; + const long nAlpha2 = pLine1[ nTmpX ]; + const long nAlpha1 = pLine0[ ++nTmpX ]; + const long nAlpha3 = pLine1[ nTmpX ]; + const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); + const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); + + *pLineW++ = MAP( n0, n1, nTmpFY ); + } + } + } + else + { + BitmapColor aAlphaValue( 0 ); + + for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) + { + nTmpY = pMapIY[ nY ], nTmpFY = pMapFY[ nY ]; + + for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) + { + nTmpX = pMapIX[ nX ]; nTmpFX = pMapFX[ nX ]; + + long nAlpha0 = pAcc->GetPixel( nTmpY, nTmpX ).GetIndex(); + long nAlpha1 = pAcc->GetPixel( nTmpY, ++nTmpX ).GetIndex(); + const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); + + nAlpha1 = pAcc->GetPixel( ++nTmpY, nTmpX ).GetIndex(); + nAlpha0 = pAcc->GetPixel( nTmpY--, --nTmpX ).GetIndex(); + const long n1 = MAP( nAlpha0, nAlpha1, nTmpFX ); + + aAlphaValue.SetIndex( MAP( n0, n1, nTmpFY ) ); + pWAcc->SetPixel( nYDst, nXDst++, aAlphaValue ); + } + } + } + + aOutAlpha.ReleaseAccess( pWAcc ); + bRet = TRUE; + } + + aAlpha.ReleaseAccess( pAcc ); + + if( bRet ) + rOutBmpEx = BitmapEx( aOutBmp, aOutAlpha ); + } + } + else + { + DBG_ASSERT( rBmpEx.GetMask().GetSizePixel() == rBmpEx.GetSizePixel(), + "GraphicManager::ImplCreateScaled(): mask size inconsistent" ); + + Bitmap aMsk( rBmpEx.GetMask() ); + Bitmap aOutMsk; + + pAcc = aMsk.AcquireReadAccess(); + + if( pAcc ) + { + // #i40115# Use the same palette for destination + // bitmap. Otherwise, we'd have to color-map even the + // case below, when both masks are one bit deep. + if( pAcc->HasPalette() ) + aOutMsk = Bitmap( Size( nDstW, nDstH ), + 1, + &pAcc->GetPalette() ); + else + aOutMsk = Bitmap( Size( nDstW, nDstH ), 1 ); + + pWAcc = aOutMsk.AcquireWriteAccess(); + + if( pWAcc ) + { + long* pMapLX = new long[ nDstW ]; + long* pMapLY = new long[ nDstH ]; + + // create new horizontal mapping table + for( nX = 0UL, nTmpX = nStartX; nX < nDstW; nTmpX++ ) + pMapLX[ nX++ ] = FRound( (double) pMapIX[ nTmpX ] + pMapFX[ nTmpX ] / 1048576. ); + + // create new vertical mapping table + for( nY = 0UL, nTmpY = nStartY; nY < nDstH; nTmpY++ ) + pMapLY[ nY++ ] = FRound( (double) pMapIY[ nTmpY ] + pMapFY[ nTmpY ] / 1048576. ); + + // do normal scaling + if( pAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && + pWAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL ) + { + // optimized + for( nY = 0; nY < nDstH; nY++ ) + { + Scanline pSrc = pAcc->GetScanline( pMapLY[ nY ] ); + Scanline pDst = pWAcc->GetScanline( nY ); + + for( nX = 0L; nX < nDstW; nX++ ) + { + const long nSrcX = pMapLX[ nX ]; + + if( pSrc[ nSrcX >> 3 ] & ( 1 << ( 7 - ( nSrcX & 7 ) ) ) ) + pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) ); + else + pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) ); + } + } + } + else + { + const BitmapColor aB( pAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); + const BitmapColor aWB( pWAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); + const BitmapColor aWW( pWAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); + + if( pAcc->HasPalette() ) + { + for( nY = 0L; nY < nDstH; nY++ ) + { + for( nX = 0L; nX < nDstW; nX++ ) + { + if( pAcc->GetPaletteColor( (BYTE) pAcc->GetPixel( pMapLY[ nY ], pMapLX[ nX ] ) ) == aB ) + pWAcc->SetPixel( nY, nX, aWB ); + else + pWAcc->SetPixel( nY, nX, aWW ); + } + } + } + else + { + for( nY = 0L; nY < nDstH; nY++ ) + { + for( nX = 0L; nX < nDstW; nX++ ) + { + if( pAcc->GetPixel( pMapLY[ nY ], pMapLX[ nX ] ) == aB ) + pWAcc->SetPixel( nY, nX, aWB ); + else + pWAcc->SetPixel( nY, nX, aWW ); + } + } + } + } + + delete[] pMapLX; + delete[] pMapLY; + aOutMsk.ReleaseAccess( pWAcc ); + bRet = TRUE; + } + + aMsk.ReleaseAccess( pAcc ); + + if( bRet ) + rOutBmpEx = BitmapEx( aOutBmp, aOutMsk ); + } + } + + if( !bRet ) + rOutBmpEx = aOutBmp; + } + else + rOutBmpEx = aOutBmp; + + return bRet; +} + +// ----------------------------------------------------------------------------- + +BOOL GraphicManager::ImplCreateRotatedScaled( const BitmapEx& rBmpEx, + USHORT nRot10, const Size& /*rOutSzPix*/, const Size& rUnrotatedSzPix, + long* pMapIX, long* pMapFX, long* pMapIY, long* pMapFY, + long nStartX, long nEndX, long nStartY, long nEndY, + BitmapEx& rOutBmpEx ) +{ + Point aPt; + Bitmap aBmp( rBmpEx.GetBitmap() ); + Bitmap aOutBmp; + BitmapReadAccess* pAcc = aBmp.AcquireReadAccess(); + BitmapWriteAccess* pWAcc; + Polygon aPoly( Rectangle( aPt, rUnrotatedSzPix ) ); aPoly.Rotate( Point(), nRot10 ); + Rectangle aNewBound( aPoly.GetBoundRect() ); + const double fCosAngle = cos( nRot10 * F_PI1800 ), fSinAngle = sin( nRot10 * F_PI1800 ); + double fTmp; + const long nDstW = nEndX - nStartX + 1L; + const long nDstH = nEndY - nStartY + 1L; + const long nUnRotW = rUnrotatedSzPix.Width(); + const long nUnRotH = rUnrotatedSzPix.Height(); + long* pCosX = new long[ nDstW ]; + long* pSinX = new long[ nDstW ]; + long* pCosY = new long[ nDstH ]; + long* pSinY = new long[ nDstH ]; + long nX, nY, nTmpX, nTmpY, nTmpFX, nTmpFY, nUnRotX, nUnRotY, nSinY, nCosY; + BYTE cR0, cG0, cB0, cR1, cG1, cB1; + BOOL bRet = FALSE; + + // create horizontal mapping table + for( nX = 0L, nTmpX = aNewBound.Left() + nStartX; nX < nDstW; nX++ ) + { + pCosX[ nX ] = FRound( fCosAngle * ( fTmp = nTmpX++ << 8 ) ); + pSinX[ nX ] = FRound( fSinAngle * fTmp ); + } + + // create vertical mapping table + for( nY = 0L, nTmpY = aNewBound.Top() + nStartY; nY < nDstH; nY++ ) + { + pCosY[ nY ] = FRound( fCosAngle * ( fTmp = nTmpY++ << 8 ) ); + pSinY[ nY ] = FRound( fSinAngle * fTmp ); + } + + if( pAcc ) + { + aOutBmp = Bitmap( Size( nDstW, nDstH ), 24 ); + pWAcc = aOutBmp.AcquireWriteAccess(); + + if( pWAcc ) + { + BitmapColor aColRes; + + if( pAcc->HasPalette() ) + { + for( nY = 0; nY < nDstH; nY++ ) + { + nSinY = pSinY[ nY ]; + nCosY = pCosY[ nY ]; + + for( nX = 0; nX < nDstW; nX++ ) + { + nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; + + if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && + ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) + { + nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ]; + nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; + + const BitmapColor& rCol0 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, nTmpX ) ); + const BitmapColor& rCol1 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, ++nTmpX ) ); + cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTmpFX ); + cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTmpFX ); + cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTmpFX ); + + const BitmapColor& rCol3 = pAcc->GetPaletteColor( pAcc->GetPixel( ++nTmpY, nTmpX ) ); + const BitmapColor& rCol2 = pAcc->GetPaletteColor( pAcc->GetPixel( nTmpY, --nTmpX ) ); + cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTmpFX ); + cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTmpFX ); + cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTmpFX ); + + aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); + aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); + aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); + pWAcc->SetPixel( nY, nX, aColRes ); + } + } + } + } + else + { + BitmapColor aCol0, aCol1; + + for( nY = 0; nY < nDstH; nY++ ) + { + nSinY = pSinY[ nY ]; + nCosY = pCosY[ nY ]; + + for( nX = 0; nX < nDstW; nX++ ) + { + nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; + + if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && + ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) + { + nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ]; + nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; + + aCol0 = pAcc->GetPixel( nTmpY, nTmpX ); + aCol1 = pAcc->GetPixel( nTmpY, ++nTmpX ); + cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); + cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); + cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); + + aCol1 = pAcc->GetPixel( ++nTmpY, nTmpX ); + aCol0 = pAcc->GetPixel( nTmpY, --nTmpX ); + cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); + cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); + cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); + + aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); + aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); + aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); + pWAcc->SetPixel( nY, nX, aColRes ); + } + } + } + } + + aOutBmp.ReleaseAccess( pWAcc ); + bRet = TRUE; + } + + aBmp.ReleaseAccess( pAcc ); + } + + // mask processing + if( bRet && ( rBmpEx.IsTransparent() || ( nRot10 != 900 && nRot10 != 1800 && nRot10 != 2700 ) ) ) + { + bRet = FALSE; + + if( rBmpEx.IsAlpha() ) + { + AlphaMask aAlpha( rBmpEx.GetAlpha() ); + AlphaMask aOutAlpha; + + pAcc = aAlpha.AcquireReadAccess(); + + if( pAcc ) + { + aOutAlpha = AlphaMask( Size( nDstW, nDstH ) ); + pWAcc = aOutAlpha.AcquireWriteAccess(); + + if( pWAcc ) + { + if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL && + pWAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) + { + Scanline pLine0, pLine1, pLineW; + + for( nY = 0; nY < nDstH; nY++ ) + { + nSinY = pSinY[ nY ], nCosY = pCosY[ nY ]; + pLineW = pWAcc->GetScanline( nY ); + + for( nX = 0; nX < nDstW; nX++ ) + { + nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; + + if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && + ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) + { + nTmpX = pMapIX[ nUnRotX ], nTmpFX = pMapFX[ nUnRotX ]; + nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; + + pLine0 = pAcc->GetScanline( nTmpY++ ); + pLine1 = pAcc->GetScanline( nTmpY ); + + const long nAlpha0 = pLine0[ nTmpX ]; + const long nAlpha2 = pLine1[ nTmpX++ ]; + const long nAlpha1 = pLine0[ nTmpX ]; + const long nAlpha3 = pLine1[ nTmpX ]; + const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); + const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); + + *pLineW++ = MAP( n0, n1, nTmpFY ); + } + else + *pLineW++ = 255; + } + } + } + else + { + const BitmapColor aTrans( pWAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); + BitmapColor aAlphaVal( 0 ); + + for( nY = 0; nY < nDstH; nY++ ) + { + nSinY = pSinY[ nY ], nCosY = pCosY[ nY ]; + + for( nX = 0; nX < nDstW; nX++ ) + { + nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; + + if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && + ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) + { + nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ]; + nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; + + const long nAlpha0 = pAcc->GetPixel( nTmpY, nTmpX ).GetIndex(); + const long nAlpha1 = pAcc->GetPixel( nTmpY, ++nTmpX ).GetIndex(); + const long nAlpha3 = pAcc->GetPixel( ++nTmpY, nTmpX ).GetIndex(); + const long nAlpha2 = pAcc->GetPixel( nTmpY, --nTmpX ).GetIndex(); + const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); + const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); + + aAlphaVal.SetIndex( MAP( n0, n1, nTmpFY ) ); + pWAcc->SetPixel( nY, nX, aAlphaVal ); + } + else + pWAcc->SetPixel( nY, nX, aTrans ); + } + } + } + + aOutAlpha.ReleaseAccess( pWAcc ); + bRet = TRUE; + } + + aAlpha.ReleaseAccess( pAcc ); + } + + if( bRet ) + rOutBmpEx = BitmapEx( aOutBmp, aOutAlpha ); + } + else + { + Bitmap aOutMsk( Size( nDstW, nDstH ), 1 ); + pWAcc = aOutMsk.AcquireWriteAccess(); + + if( pWAcc ) + { + Bitmap aMsk( rBmpEx.GetMask() ); + const BitmapColor aB( pWAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); + const BitmapColor aW( pWAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); + BitmapReadAccess* pMAcc = NULL; + + if( !aMsk || ( ( pMAcc = aMsk.AcquireReadAccess() ) != NULL ) ) + { + long* pMapLX = new long[ nUnRotW ]; + long* pMapLY = new long[ nUnRotH ]; + BitmapColor aTestB; + + if( pMAcc ) + aTestB = pMAcc->GetBestMatchingColor( Color( COL_BLACK ) ); + + // create new horizontal mapping table + for( nX = 0UL; nX < nUnRotW; nX++ ) + pMapLX[ nX ] = FRound( (double) pMapIX[ nX ] + pMapFX[ nX ] / 1048576. ); + + // create new vertical mapping table + for( nY = 0UL; nY < nUnRotH; nY++ ) + pMapLY[ nY ] = FRound( (double) pMapIY[ nY ] + pMapFY[ nY ] / 1048576. ); + + // do mask rotation + for( nY = 0; nY < nDstH; nY++ ) + { + nSinY = pSinY[ nY ]; + nCosY = pCosY[ nY ]; + + for( nX = 0; nX < nDstW; nX++ ) + { + nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; + + if( ( nUnRotX >= 0L ) && ( nUnRotX < nUnRotW ) && + ( nUnRotY >= 0L ) && ( nUnRotY < nUnRotH ) ) + { + if( pMAcc ) + { + if( pMAcc->GetPixel( pMapLY[ nUnRotY ], pMapLX[ nUnRotX ] ) == aTestB ) + pWAcc->SetPixel( nY, nX, aB ); + else + pWAcc->SetPixel( nY, nX, aW ); + } + else + pWAcc->SetPixel( nY, nX, aB ); + } + else + pWAcc->SetPixel( nY, nX, aW ); + } + } + + delete[] pMapLX; + delete[] pMapLY; + + if( pMAcc ) + aMsk.ReleaseAccess( pMAcc ); + + bRet = TRUE; + } + + aOutMsk.ReleaseAccess( pWAcc ); + } + + if( bRet ) + rOutBmpEx = BitmapEx( aOutBmp, aOutMsk ); + } + + if( !bRet ) + rOutBmpEx = aOutBmp; + } + else + rOutBmpEx = aOutBmp; + + delete[] pSinX; + delete[] pCosX; + delete[] pSinY; + delete[] pCosY; + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ImplAdjust( BitmapEx& rBmpEx, const GraphicAttr& rAttr, ULONG nAdjustmentFlags ) +{ + GraphicAttr aAttr( rAttr ); + + if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() ) + { + switch( aAttr.GetDrawMode() ) + { + case( GRAPHICDRAWMODE_MONO ): + rBmpEx.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); + break; + + case( GRAPHICDRAWMODE_GREYS ): + rBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS ); + break; + + case( GRAPHICDRAWMODE_WATERMARK ): + { + aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); + aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); + } + break; + + default: + break; + } + } + + if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() ) + { + rBmpEx.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), + aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), + aAttr.GetGamma(), aAttr.IsInvert() ); + } + + if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() ) + { + rBmpEx.Mirror( aAttr.GetMirrorFlags() ); + } + + if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() ) + { + rBmpEx.Rotate( aAttr.GetRotation(), Color( COL_TRANSPARENT ) ); + } + + if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() ) + { + AlphaMask aAlpha; + BYTE cTrans = aAttr.GetTransparency(); + + if( !rBmpEx.IsTransparent() ) + aAlpha = AlphaMask( rBmpEx.GetSizePixel(), &cTrans ); + else if( !rBmpEx.IsAlpha() ) + { + aAlpha = rBmpEx.GetMask(); + aAlpha.Replace( 0, cTrans ); + } + else + { + aAlpha = rBmpEx.GetAlpha(); + BitmapWriteAccess* pA = aAlpha.AcquireWriteAccess(); + + if( pA ) + { + ULONG nTrans = cTrans, nNewTrans; + const long nWidth = pA->Width(), nHeight = pA->Height(); + + if( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) + { + for( long nY = 0; nY < nHeight; nY++ ) + { + Scanline pAScan = pA->GetScanline( nY ); + + for( long nX = 0; nX < nWidth; nX++ ) + { + nNewTrans = nTrans + *pAScan; + *pAScan++ = (BYTE) ( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans ); + } + } + } + else + { + BitmapColor aAlphaValue( 0 ); + + for( long nY = 0; nY < nHeight; nY++ ) + { + for( long nX = 0; nX < nWidth; nX++ ) + { + nNewTrans = nTrans + pA->GetPixel( nY, nX ).GetIndex(); + aAlphaValue.SetIndex( (BYTE) ( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans ) ); + pA->SetPixel( nY, nX, aAlphaValue ); + } + } + } + + aAlpha.ReleaseAccess( pA ); + } + } + + rBmpEx = BitmapEx( rBmpEx.GetBitmap(), aAlpha ); + } +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ImplAdjust( GDIMetaFile& rMtf, const GraphicAttr& rAttr, ULONG nAdjustmentFlags ) +{ + GraphicAttr aAttr( rAttr ); + + if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() ) + { + switch( aAttr.GetDrawMode() ) + { + case( GRAPHICDRAWMODE_MONO ): + rMtf.Convert( MTF_CONVERSION_1BIT_THRESHOLD ); + break; + + case( GRAPHICDRAWMODE_GREYS ): + rMtf.Convert( MTF_CONVERSION_8BIT_GREYS ); + break; + + case( GRAPHICDRAWMODE_WATERMARK ): + { + aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); + aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); + } + break; + + default: + break; + } + } + + if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() ) + { + rMtf.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), + aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), + aAttr.GetGamma(), aAttr.IsInvert() ); + } + + if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() ) + { + rMtf.Mirror( aAttr.GetMirrorFlags() ); + } + + if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() ) + { + rMtf.Rotate( aAttr.GetRotation() ); + } + + if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() ) + { + DBG_ERROR( "Missing implementation: Mtf-Transparency" ); + } +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ImplAdjust( Animation& rAnimation, const GraphicAttr& rAttr, ULONG nAdjustmentFlags ) +{ + GraphicAttr aAttr( rAttr ); + + if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() ) + { + switch( aAttr.GetDrawMode() ) + { + case( GRAPHICDRAWMODE_MONO ): + rAnimation.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); + break; + + case( GRAPHICDRAWMODE_GREYS ): + rAnimation.Convert( BMP_CONVERSION_8BIT_GREYS ); + break; + + case( GRAPHICDRAWMODE_WATERMARK ): + { + aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET ); + aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET ); + } + break; + + default: + break; + } + } + + if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() ) + { + rAnimation.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(), + aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(), + aAttr.GetGamma(), aAttr.IsInvert() ); + } + + if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() ) + { + rAnimation.Mirror( aAttr.GetMirrorFlags() ); + } + + if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() ) + { + DBG_ERROR( "Missing implementation: Animation-Rotation" ); + } + + if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() ) + { + DBG_ERROR( "Missing implementation: Animation-Transparency" ); + } +} + +// ----------------------------------------------------------------------------- + +void GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt, const Size& rSz, + const GDIMetaFile& rMtf, const GraphicAttr& rAttr ) +{ + USHORT nRot10 = rAttr.GetRotation() % 3600; + Point aOutPt( rPt ); + Size aOutSz( rSz ); + + if( nRot10 ) + { + Polygon aPoly( Rectangle( aOutPt, aOutSz ) ); + + aPoly.Rotate( aOutPt, nRot10 ); + const Rectangle aRotBoundRect( aPoly.GetBoundRect() ); + aOutPt = aRotBoundRect.TopLeft(); + aOutSz = aRotBoundRect.GetSize(); + } + + pOut->Push( PUSH_CLIPREGION ); + pOut->IntersectClipRegion( Rectangle( aOutPt, aOutSz ) ); + + ( (GDIMetaFile&) rMtf ).WindStart(); + ( (GDIMetaFile&) rMtf ).Play( pOut, aOutPt, aOutSz ); + ( (GDIMetaFile&) rMtf ).WindStart(); + + pOut->Pop(); +} + +// ----------------------------------------------------------------------------- + +struct ImplTileInfo +{ + ImplTileInfo() : aTileTopLeft(), aNextTileTopLeft(), aTileSizePixel(), nTilesEmptyX(0), nTilesEmptyY(0) {} + + Point aTileTopLeft; // top, left position of the rendered tile + Point aNextTileTopLeft; // top, left position for next recursion + // level's tile + Size aTileSizePixel; // size of the generated tile (might + // differ from + // aNextTileTopLeft-aTileTopLeft, because + // this is nExponent*prevTileSize. The + // generated tile is always nExponent + // times the previous tile, such that it + // can be used in the next stage. The + // required area coverage is often + // less. The extraneous area covered is + // later overwritten by the next stage) + int nTilesEmptyX; // number of original tiles empty right of + // this tile. This counts from + // aNextTileTopLeft, i.e. the additional + // area covered by aTileSizePixel is not + // considered here. This is for + // unification purposes, as the iterative + // calculation of the next level's empty + // tiles has to be based on this value. + int nTilesEmptyY; // as above, for Y +}; + + +bool GraphicObject::ImplRenderTempTile( VirtualDevice& rVDev, int nExponent, + int nNumTilesX, int nNumTilesY, + const Size& rTileSizePixel, + const GraphicAttr* pAttr, ULONG nFlags ) +{ + if( nExponent <= 1 ) + return false; + + // determine MSB factor + int nMSBFactor( 1 ); + while( nNumTilesX / nMSBFactor != 0 || + nNumTilesY / nMSBFactor != 0 ) + { + nMSBFactor *= nExponent; + } + + // one less + nMSBFactor /= nExponent; + + ImplTileInfo aTileInfo; + + // #105229# Switch off mapping (converting to logic and back to + // pixel might cause roundoff errors) + BOOL bOldMap( rVDev.IsMapModeEnabled() ); + rVDev.EnableMapMode( FALSE ); + + bool bRet( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor, nNumTilesX, nNumTilesY, + nNumTilesX, nNumTilesY, rTileSizePixel, pAttr, nFlags, aTileInfo ) ); + + rVDev.EnableMapMode( bOldMap ); + + return bRet; +} + +// ----------------------------------------------------------------------------- + +// define for debug drawings +//#define DBG_TEST + +// see header comment. this works similar to base conversion of a +// number, i.e. if the exponent is 10, then the number for every tile +// size is given by the decimal place of the corresponding decimal +// representation. +bool GraphicObject::ImplRenderTileRecursive( VirtualDevice& rVDev, int nExponent, int nMSBFactor, + int nNumOrigTilesX, int nNumOrigTilesY, + int nRemainderTilesX, int nRemainderTilesY, + const Size& rTileSizePixel, const GraphicAttr* pAttr, + ULONG nFlags, ImplTileInfo& rTileInfo ) +{ + // gets loaded with our tile bitmap + GraphicObject aTmpGraphic; + + // stores a flag that renders the zero'th tile position + // (i.e. (0,0)+rCurrPos) only if we're at the bottom of the + // recursion stack. All other position already have that tile + // rendered, because the lower levels painted their generated tile + // there. + bool bNoFirstTileDraw( false ); + + // what's left when we're done with our tile size + const int nNewRemainderX( nRemainderTilesX % nMSBFactor ); + const int nNewRemainderY( nRemainderTilesY % nMSBFactor ); + + // gets filled out from the recursive call with info of what's + // been generated + ImplTileInfo aTileInfo; + + // current output position while drawing + Point aCurrPos; + int nX, nY; + + // check for recursion's end condition: LSB place reached? + if( nMSBFactor == 1 ) + { + aTmpGraphic = *this; + + // set initial tile size -> orig size + aTileInfo.aTileSizePixel = rTileSizePixel; + aTileInfo.nTilesEmptyX = nNumOrigTilesX; + aTileInfo.nTilesEmptyY = nNumOrigTilesY; + } + else if( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor/nExponent, + nNumOrigTilesX, nNumOrigTilesY, + nNewRemainderX, nNewRemainderY, + rTileSizePixel, pAttr, nFlags, aTileInfo ) ) + { + // extract generated tile -> see comment on the first loop below + BitmapEx aTileBitmap( rVDev.GetBitmap( aTileInfo.aTileTopLeft, aTileInfo.aTileSizePixel ) ); + + aTmpGraphic = GraphicObject( aTileBitmap ); + + // fill stripes left over from upstream levels: + // + // x0000 + // 0 + // 0 + // 0 + // 0 + // + // where x denotes the place filled by our recursive predecessors + + // check whether we have to fill stripes here. Although not + // obvious, there is one case where we can skip this step: if + // the previous recursion level (the one who filled our + // aTileInfo) had zero area to fill, then there are no white + // stripes left, naturally. This happens if the digit + // associated to that level has a zero, and can be checked via + // aTileTopLeft==aNextTileTopLeft. + if( aTileInfo.aTileTopLeft != aTileInfo.aNextTileTopLeft ) + { + // now fill one row from aTileInfo.aNextTileTopLeft.X() all + // the way to the right + aCurrPos.X() = aTileInfo.aNextTileTopLeft.X(); + aCurrPos.Y() = aTileInfo.aTileTopLeft.Y(); + for( nX=0; nX < aTileInfo.nTilesEmptyX; nX += nMSBFactor ) + { + if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) ) + return false; + + aCurrPos.X() += aTileInfo.aTileSizePixel.Width(); + } + +#ifdef DBG_TEST +// rVDev.SetFillColor( COL_WHITE ); + rVDev.SetFillColor(); + rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) ); + rVDev.DrawEllipse( Rectangle(aTileInfo.aNextTileTopLeft.X(), aTileInfo.aTileTopLeft.Y(), + aTileInfo.aNextTileTopLeft.X() - 1 + (aTileInfo.nTilesEmptyX/nMSBFactor)*aTileInfo.aTileSizePixel.Width(), + aTileInfo.aTileTopLeft.Y() + aTileInfo.aTileSizePixel.Height() - 1) ); +#endif + + // now fill one column from aTileInfo.aNextTileTopLeft.Y() all + // the way to the bottom + aCurrPos.X() = aTileInfo.aTileTopLeft.X(); + aCurrPos.Y() = aTileInfo.aNextTileTopLeft.Y(); + for( nY=0; nY < aTileInfo.nTilesEmptyY; nY += nMSBFactor ) + { + if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) ) + return false; + + aCurrPos.Y() += aTileInfo.aTileSizePixel.Height(); + } + +#ifdef DBG_TEST + rVDev.DrawEllipse( Rectangle(aTileInfo.aTileTopLeft.X(), aTileInfo.aNextTileTopLeft.Y(), + aTileInfo.aTileTopLeft.X() + aTileInfo.aTileSizePixel.Width() - 1, + aTileInfo.aNextTileTopLeft.Y() - 1 + (aTileInfo.nTilesEmptyY/nMSBFactor)*aTileInfo.aTileSizePixel.Height()) ); +#endif + } + else + { + // Thought that aTileInfo.aNextTileTopLeft tile has always + // been drawn already, but that's wrong: typically, + // _parts_ of that tile have been drawn, since the + // previous level generated the tile there. But when + // aTileInfo.aNextTileTopLeft!=aTileInfo.aTileTopLeft, the + // difference between these two values is missing in the + // lower right corner of this first tile. So, can do that + // only here. + bNoFirstTileDraw = true; + } + } + else + { + return false; + } + + // calc number of original tiles in our drawing area without + // remainder + nRemainderTilesX -= nNewRemainderX; + nRemainderTilesY -= nNewRemainderY; + + // fill tile info for calling method + rTileInfo.aTileTopLeft = aTileInfo.aNextTileTopLeft; + rTileInfo.aNextTileTopLeft = Point( rTileInfo.aTileTopLeft.X() + rTileSizePixel.Width()*nRemainderTilesX, + rTileInfo.aTileTopLeft.Y() + rTileSizePixel.Height()*nRemainderTilesY ); + rTileInfo.aTileSizePixel = Size( rTileSizePixel.Width()*nMSBFactor*nExponent, + rTileSizePixel.Height()*nMSBFactor*nExponent ); + rTileInfo.nTilesEmptyX = aTileInfo.nTilesEmptyX - nRemainderTilesX; + rTileInfo.nTilesEmptyY = aTileInfo.nTilesEmptyY - nRemainderTilesY; + + // init output position + aCurrPos = aTileInfo.aNextTileTopLeft; + + // fill our drawing area. Fill possibly more, to create the next + // bigger tile size -> see bitmap extraction above. This does no + // harm, since everything right or below our actual area is + // overdrawn by our caller. Just in case we're in the last level, + // we don't draw beyond the right or bottom border. + for( nY=0; nY < aTileInfo.nTilesEmptyY && nY < nExponent*nMSBFactor; nY += nMSBFactor ) + { + aCurrPos.X() = aTileInfo.aNextTileTopLeft.X(); + + for( nX=0; nX < aTileInfo.nTilesEmptyX && nX < nExponent*nMSBFactor; nX += nMSBFactor ) + { + if( bNoFirstTileDraw ) + bNoFirstTileDraw = false; // don't draw first tile position + else if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) ) + return false; + + aCurrPos.X() += aTileInfo.aTileSizePixel.Width(); + } + + aCurrPos.Y() += aTileInfo.aTileSizePixel.Height(); + } + +#ifdef DBG_TEST +// rVDev.SetFillColor( COL_WHITE ); + rVDev.SetFillColor(); + rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) ); + rVDev.DrawRect( Rectangle((rTileInfo.aTileTopLeft.X())*rTileSizePixel.Width(), + (rTileInfo.aTileTopLeft.Y())*rTileSizePixel.Height(), + (rTileInfo.aNextTileTopLeft.X())*rTileSizePixel.Width()-1, + (rTileInfo.aNextTileTopLeft.Y())*rTileSizePixel.Height()-1) ); +#endif + + return true; +} + +// ----------------------------------------------------------------------------- + +bool GraphicObject::ImplDrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSizePixel, + const Size& rOffset, const GraphicAttr* pAttr, ULONG nFlags, int nTileCacheSize1D ) +{ + // how many tiles to generate per recursion step + enum{ SubdivisionExponent=2 }; + + const MapMode aOutMapMode( pOut->GetMapMode() ); + const MapMode aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() ); + bool bRet( false ); + + // #i42643# Casting to Int64, to avoid integer overflow for + // huge-DPI output devices + if( GetGraphic().GetType() == GRAPHIC_BITMAP && + static_cast<sal_Int64>(rSizePixel.Width()) * rSizePixel.Height() < + static_cast<sal_Int64>(nTileCacheSize1D)*nTileCacheSize1D ) + { + // First combine very small bitmaps into a larger tile + // =================================================== + + VirtualDevice aVDev; + const int nNumTilesInCacheX( (nTileCacheSize1D + rSizePixel.Width()-1) / rSizePixel.Width() ); + const int nNumTilesInCacheY( (nTileCacheSize1D + rSizePixel.Height()-1) / rSizePixel.Height() ); + + aVDev.SetOutputSizePixel( Size( nNumTilesInCacheX*rSizePixel.Width(), + nNumTilesInCacheY*rSizePixel.Height() ) ); + aVDev.SetMapMode( aMapMode ); + + // draw bitmap content + if( ImplRenderTempTile( aVDev, SubdivisionExponent, nNumTilesInCacheX, + nNumTilesInCacheY, rSizePixel, pAttr, nFlags ) ) + { + BitmapEx aTileBitmap( aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ) ); + + // draw alpha content, if any + if( IsTransparent() ) + { + GraphicObject aAlphaGraphic; + + if( GetGraphic().IsAlpha() ) + aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetAlpha().GetBitmap() ); + else + aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetMask() ); + + if( aAlphaGraphic.ImplRenderTempTile( aVDev, SubdivisionExponent, nNumTilesInCacheX, + nNumTilesInCacheY, rSizePixel, pAttr, nFlags ) ) + { + // Combine bitmap and alpha/mask + if( GetGraphic().IsAlpha() ) + aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(), + AlphaMask( aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ) ) ); + else + aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(), + aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ).CreateMask( Color(COL_WHITE) ) ); + } + } + + // paint generated tile + GraphicObject aTmpGraphic( aTileBitmap ); + bRet = aTmpGraphic.ImplDrawTiled( pOut, rArea, + aTileBitmap.GetSizePixel(), + rOffset, pAttr, nFlags, nTileCacheSize1D ); + } + } + else + { + const Size aOutOffset( pOut->LogicToPixel( rOffset, aOutMapMode ) ); + const Rectangle aOutArea( pOut->LogicToPixel( rArea, aOutMapMode ) ); + + // number of invisible (because out-of-area) tiles + int nInvisibleTilesX; + int nInvisibleTilesY; + + // round towards -infty for negative offset + if( aOutOffset.Width() < 0 ) + nInvisibleTilesX = (aOutOffset.Width() - rSizePixel.Width() + 1) / rSizePixel.Width(); + else + nInvisibleTilesX = aOutOffset.Width() / rSizePixel.Width(); + + // round towards -infty for negative offset + if( aOutOffset.Height() < 0 ) + nInvisibleTilesY = (aOutOffset.Height() - rSizePixel.Height() + 1) / rSizePixel.Height(); + else + nInvisibleTilesY = aOutOffset.Height() / rSizePixel.Height(); + + // origin from where to 'virtually' start drawing in pixel + const Point aOutOrigin( pOut->LogicToPixel( Point( rArea.Left() - rOffset.Width(), + rArea.Top() - rOffset.Height() ) ) ); + // position in pixel from where to really start output + const Point aOutStart( aOutOrigin.X() + nInvisibleTilesX*rSizePixel.Width(), + aOutOrigin.Y() + nInvisibleTilesY*rSizePixel.Height() ); + + pOut->Push( PUSH_CLIPREGION ); + pOut->IntersectClipRegion( rArea ); + + // Paint all tiles + // =============== + + bRet = ImplDrawTiled( *pOut, aOutStart, + (aOutArea.GetWidth() + aOutArea.Left() - aOutStart.X() + rSizePixel.Width() - 1) / rSizePixel.Width(), + (aOutArea.GetHeight() + aOutArea.Top() - aOutStart.Y() + rSizePixel.Height() - 1) / rSizePixel.Height(), + rSizePixel, pAttr, nFlags ); + + pOut->Pop(); + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +bool GraphicObject::ImplDrawTiled( OutputDevice& rOut, const Point& rPosPixel, + int nNumTilesX, int nNumTilesY, + const Size& rTileSizePixel, const GraphicAttr* pAttr, ULONG nFlags ) +{ + Point aCurrPos( rPosPixel ); + Size aTileSizeLogic( rOut.PixelToLogic( rTileSizePixel ) ); + int nX, nY; + + // #107607# Use logical coordinates for metafile playing, too + bool bDrawInPixel( rOut.GetConnectMetaFile() == NULL && GRAPHIC_BITMAP == GetType() ); + BOOL bRet( FALSE ); + + // #105229# Switch off mapping (converting to logic and back to + // pixel might cause roundoff errors) + BOOL bOldMap( rOut.IsMapModeEnabled() ); + + if( bDrawInPixel ) + rOut.EnableMapMode( FALSE ); + + for( nY=0; nY < nNumTilesY; ++nY ) + { + aCurrPos.X() = rPosPixel.X(); + + for( nX=0; nX < nNumTilesX; ++nX ) + { + // #105229# work with pixel coordinates here, mapping is disabled! + // #104004# don't disable mapping for metafile recordings + // #108412# don't quit the loop if one draw fails + + // update return value. This method should return true, if + // at least one of the looped Draws succeeded. + bRet |= Draw( &rOut, + bDrawInPixel ? aCurrPos : rOut.PixelToLogic( aCurrPos ), + bDrawInPixel ? rTileSizePixel : aTileSizeLogic, + pAttr, nFlags ); + + aCurrPos.X() += rTileSizePixel.Width(); + } + + aCurrPos.Y() += rTileSizePixel.Height(); + } + + if( bDrawInPixel ) + rOut.EnableMapMode( bOldMap ); + + return bRet; +} + +// ----------------------------------------------------------------------------- + +void GraphicObject::ImplTransformBitmap( BitmapEx& rBmpEx, + const GraphicAttr& rAttr, + const Size& rCropLeftTop, + const Size& rCropRightBottom, + const Rectangle& rCropRect, + const Size& rDstSize, + BOOL bEnlarge ) const +{ + // #107947# Extracted from svdograf.cxx + + // #104115# Crop the bitmap + if( rAttr.IsCropped() ) + { + rBmpEx.Crop( rCropRect ); + + // #104115# Negative crop sizes mean: enlarge bitmap and pad + if( bEnlarge && ( + rCropLeftTop.Width() < 0 || + rCropLeftTop.Height() < 0 || + rCropRightBottom.Width() < 0 || + rCropRightBottom.Height() < 0 ) ) + { + Size aBmpSize( rBmpEx.GetSizePixel() ); + sal_Int32 nPadLeft( rCropLeftTop.Width() < 0 ? -rCropLeftTop.Width() : 0 ); + sal_Int32 nPadTop( rCropLeftTop.Height() < 0 ? -rCropLeftTop.Height() : 0 ); + sal_Int32 nPadTotalWidth( aBmpSize.Width() + nPadLeft + (rCropRightBottom.Width() < 0 ? -rCropRightBottom.Width() : 0) ); + sal_Int32 nPadTotalHeight( aBmpSize.Height() + nPadTop + (rCropRightBottom.Height() < 0 ? -rCropRightBottom.Height() : 0) ); + + BitmapEx aBmpEx2; + + if( rBmpEx.IsTransparent() ) + { + if( rBmpEx.IsAlpha() ) + aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetAlpha() ); + else + aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetMask() ); + } + else + { + // #104115# Generate mask bitmap and init to zero + Bitmap aMask( aBmpSize, 1 ); + aMask.Erase( Color(0,0,0) ); + + // #104115# Always generate transparent bitmap, we need the border transparent + aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), aMask ); + + // #104115# Add opaque mask to source bitmap, otherwise the destination remains transparent + rBmpEx = aBmpEx2; + } + + aBmpEx2.SetSizePixel( Size(nPadTotalWidth, nPadTotalHeight) ); + aBmpEx2.Erase( Color(0xFF,0,0,0) ); + aBmpEx2.CopyPixel( Rectangle( Point(nPadLeft, nPadTop), aBmpSize ), Rectangle( Point(0, 0), aBmpSize ), &rBmpEx ); + rBmpEx = aBmpEx2; + } + } + + const Size aSizePixel( rBmpEx.GetSizePixel() ); + + if( rAttr.GetRotation() != 0 && !IsAnimated() ) + { + if( aSizePixel.Width() && aSizePixel.Height() && rDstSize.Width() && rDstSize.Height() ) + { + double fSrcWH = (double) aSizePixel.Width() / aSizePixel.Height(); + double fDstWH = (double) rDstSize.Width() / rDstSize.Height(); + double fScaleX = 1.0, fScaleY = 1.0; + + // always choose scaling to shrink bitmap + if( fSrcWH < fDstWH ) + fScaleY = aSizePixel.Width() / ( fDstWH * aSizePixel.Height() ); + else + fScaleX = fDstWH * aSizePixel.Height() / aSizePixel.Width(); + + rBmpEx.Scale( fScaleX, fScaleY ); + } + } +} + diff --git a/svtools/source/graphic/makefile.mk b/svtools/source/graphic/makefile.mk new file mode 100644 index 000000000000..ed985e142aa0 --- /dev/null +++ b/svtools/source/graphic/makefile.mk @@ -0,0 +1,70 @@ +#************************************************************************* +# +# 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: makefile.mk,v $ +# +# $Revision: 1.5 $ +# +# 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. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=svtools +TARGET=graphic + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/svt.pmk + +.IF "$(GUI)"=="WIN" +LINKFLAGS=$(LINKFLAGS) /PACKC:32768 +.ENDIF + +# --- Files -------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/grfattr.obj \ + $(SLO)$/grfmgr.obj \ + $(SLO)$/grfmgr2.obj \ + $(SLO)$/grfcache.obj \ + $(SLO)$/descriptor.obj \ + $(SLO)$/provider.obj \ + $(SLO)$/graphic.obj \ + $(SLO)$/renderer.obj \ + $(SLO)$/graphicunofactory.obj \ + $(SLO)$/transformer.obj + +EXCEPTIONSFILES= \ + $(SLO)$/descriptor.obj \ + $(SLO)$/provider.obj \ + $(SLO)$/graphic.obj \ + $(SLO)$/renderer.obj \ + $(SLO)$/graphicunofactory.obj \ + $(SLO)$/transformer.obj + +# --- Target ------------------------------------------------------- + +.INCLUDE : target.mk 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; + } +} + +} diff --git a/svtools/source/graphic/renderer.cxx b/svtools/source/graphic/renderer.cxx new file mode 100644 index 000000000000..39f45ad0f8f0 --- /dev/null +++ b/svtools/source/graphic/renderer.cxx @@ -0,0 +1,348 @@ +/************************************************************************* + * + * 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: renderer.cxx,v $ + * $Revision: 1.6 $ + * + * 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 <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <rtl/uuid.h> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <svl/itemprop.hxx> +#include <svtools/grfmgr.hxx> +#include "graphic.hxx" +#include "renderer.hxx" + +#define UNOGRAPHIC_DEVICE 1 +#define UNOGRAPHIC_DESTINATIONRECT 2 +#define UNOGRAPHIC_RENDERDATA 3 + +using namespace ::com::sun::star; + +namespace unographic { + +// --------------------- +// - GraphicRendererVCL - +// --------------------- + +uno::Reference< uno::XInterface > SAL_CALL GraphicRendererVCL_CreateInstance( const uno::Reference< lang::XMultiServiceFactory >& ) +{ + return SAL_STATIC_CAST( ::cppu::OWeakObject*, new GraphicRendererVCL ); +} + + +GraphicRendererVCL::GraphicRendererVCL() : + ::comphelper::PropertySetHelper( createPropertySetInfo() ), + mpOutDev( NULL ) +{ +} + +// ------------------------------------------------------------------------------ + +GraphicRendererVCL::~GraphicRendererVCL() + throw() +{ +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString GraphicRendererVCL::getImplementationName_Static() + throw() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.graphic.GraphicRendererVCL" ) ); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< ::rtl::OUString > GraphicRendererVCL::getSupportedServiceNames_Static() + throw( ) +{ + uno::Sequence< ::rtl::OUString > aSeq( 1 ); + + aSeq.getArray()[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.GraphicRendererVCL" ) ); + + return aSeq; +} + +// ------------------------------------------------------------------------------ + +uno::Any SAL_CALL GraphicRendererVCL::queryAggregation( const uno::Type & rType ) + throw( uno::RuntimeException ) +{ + uno::Any aAny; + + if( rType == ::getCppuType((const uno::Reference< lang::XServiceInfo >*)0) ) + aAny <<= uno::Reference< lang::XServiceInfo >(this); + else if( rType == ::getCppuType((const uno::Reference< lang::XTypeProvider >*)0) ) + aAny <<= uno::Reference< lang::XTypeProvider >(this); + else if( rType == ::getCppuType((const uno::Reference< beans::XPropertySet >*)0) ) + aAny <<= uno::Reference< beans::XPropertySet >(this); + else if( rType == ::getCppuType((const uno::Reference< beans::XPropertyState >*)0) ) + aAny <<= uno::Reference< beans::XPropertyState >(this); + else if( rType == ::getCppuType((const uno::Reference< beans::XMultiPropertySet >*)0) ) + aAny <<= uno::Reference< beans::XMultiPropertySet >(this); + else if( rType == ::getCppuType((const uno::Reference< graphic::XGraphicRenderer >*)0) ) + aAny <<= uno::Reference< graphic::XGraphicRenderer >(this); + else + aAny <<= OWeakAggObject::queryAggregation( rType ); + + return aAny; +} + +// ------------------------------------------------------------------------------ + +uno::Any SAL_CALL GraphicRendererVCL::queryInterface( const uno::Type & rType ) + throw( uno::RuntimeException ) +{ + return OWeakAggObject::queryInterface( rType ); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL GraphicRendererVCL::acquire() + throw() +{ + OWeakAggObject::acquire(); +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL GraphicRendererVCL::release() + throw() +{ + OWeakAggObject::release(); +} + +// ------------------------------------------------------------------------------ + +::rtl::OUString SAL_CALL GraphicRendererVCL::getImplementationName() + throw( uno::RuntimeException ) +{ + return getImplementationName_Static(); +} + +// ------------------------------------------------------------------------------ + +sal_Bool SAL_CALL GraphicRendererVCL::supportsService( const rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > aSNL( getSupportedServiceNames() ); + const ::rtl::OUString* pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return true; + + return false; +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< rtl::OUString > SAL_CALL GraphicRendererVCL::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return getSupportedServiceNames_Static(); +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< uno::Type > SAL_CALL GraphicRendererVCL::getTypes() + throw( uno::RuntimeException ) +{ + uno::Sequence< uno::Type > aTypes( 7 ); + uno::Type* pTypes = aTypes.getArray(); + + *pTypes++ = ::getCppuType((const uno::Reference< uno::XAggregation>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< lang::XServiceInfo>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< lang::XTypeProvider>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< beans::XPropertySet>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< beans::XPropertyState>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< beans::XMultiPropertySet>*)0); + *pTypes++ = ::getCppuType((const uno::Reference< graphic::XGraphicRenderer>*)0); + + return aTypes; +} + +// ------------------------------------------------------------------------------ + +uno::Sequence< sal_Int8 > SAL_CALL GraphicRendererVCL::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; +} + +// ------------------------------------------------------------------------------ + +::comphelper::PropertySetInfo* GraphicRendererVCL::createPropertySetInfo() +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + ::comphelper::PropertySetInfo* pRet = new ::comphelper::PropertySetInfo(); + + static ::comphelper::PropertyMapEntry aEntries[] = + { + { MAP_CHAR_LEN( "Device" ), UNOGRAPHIC_DEVICE, &::getCppuType( (const uno::Any*)(0)), 0, 0 }, + { MAP_CHAR_LEN( "DestinationRect" ), UNOGRAPHIC_DESTINATIONRECT, &::getCppuType( (const awt::Rectangle*)(0)), 0, 0 }, + { MAP_CHAR_LEN( "RenderData" ), UNOGRAPHIC_RENDERDATA, &::getCppuType( (const uno::Any*)(0)), 0, 0 }, + + { 0,0,0,0,0,0 } + }; + + pRet->acquire(); + pRet->add( aEntries ); + + return pRet; +} + +// ------------------------------------------------------------------------------ + +void GraphicRendererVCL::_setPropertyValues( const comphelper::PropertyMapEntry** ppEntries, const uno::Any* pValues ) + throw( beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + while( *ppEntries ) + { + switch( (*ppEntries)->mnHandle ) + { + case( UNOGRAPHIC_DEVICE ): + { + uno::Reference< awt::XDevice > xDevice; + + if( ( *pValues >>= xDevice ) && xDevice.is() ) + { + mxDevice = xDevice; + mpOutDev = VCLUnoHelper::GetOutputDevice( xDevice ); + } + else + { + mxDevice.clear(); + mpOutDev = NULL; + } + } + break; + + case( UNOGRAPHIC_DESTINATIONRECT ): + { + awt::Rectangle aAWTRect; + + if( *pValues >>= aAWTRect ) + { + maDestRect = Rectangle( Point( aAWTRect.X, aAWTRect.Y ), + Size( aAWTRect.Width, aAWTRect.Height ) ); + } + } + break; + + case( UNOGRAPHIC_RENDERDATA ): + { + *pValues >>= maRenderData; + } + break; + } + + ++ppEntries; + ++pValues; + } +} + +// ------------------------------------------------------------------------------ + +void GraphicRendererVCL::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, uno::Any* pValues ) + throw( beans::UnknownPropertyException, lang::WrappedTargetException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + while( *ppEntries ) + { + switch( (*ppEntries)->mnHandle ) + { + case( UNOGRAPHIC_DEVICE ): + { + if( mxDevice.is() ) + *pValues <<= mxDevice; + } + break; + + case( UNOGRAPHIC_DESTINATIONRECT ): + { + const awt::Rectangle aAWTRect( maDestRect.Left(), maDestRect.Top(), + maDestRect.GetWidth(), maDestRect.GetHeight() ); + + *pValues <<= aAWTRect; + } + break; + + case( UNOGRAPHIC_RENDERDATA ): + { + *pValues <<= maRenderData; + } + break; + } + + ++ppEntries; + ++pValues; + } +} + +// ------------------------------------------------------------------------------ + +void SAL_CALL GraphicRendererVCL::render( const uno::Reference< graphic::XGraphic >& rxGraphic ) + throw (uno::RuntimeException) +{ + if( mpOutDev && mxDevice.is() && rxGraphic.is() ) + { + const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY ); + const ::Graphic* pGraphic = ::unographic::Graphic::getImplementation( xIFace ); + + if( pGraphic ) + { + GraphicObject aGraphicObject( *pGraphic ); + aGraphicObject.Draw( mpOutDev, maDestRect.TopLeft(), maDestRect.GetSize() ); + } + } +} + +} diff --git a/svtools/source/graphic/transformer.cxx b/svtools/source/graphic/transformer.cxx new file mode 100644 index 000000000000..7cd9be15fca5 --- /dev/null +++ b/svtools/source/graphic/transformer.cxx @@ -0,0 +1,159 @@ +/************************************************************************* + * + * 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: transformer.cxx,v $ + * $Revision: 1.4 $ + * + * 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 <tools/rcid.h> +#include <tools/resid.hxx> +#include <tools/resmgr.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <svl/solar.hrc> +#include <vcl/salbtype.hxx> +#include <vcl/virdev.hxx> +#include <vcl/bmpacc.hxx> +#include <com/sun/star/text/GraphicCrop.hpp> + +#include "graphic.hxx" +#include "transformer.hxx" + +using namespace com::sun::star; + +namespace unographic { + +// ---------------------- +// - GraphicTransformer - +// ---------------------- + +GraphicTransformer::GraphicTransformer() +{ +} + +// ------------------------------------------------------------------------------ + +GraphicTransformer::~GraphicTransformer() +{ +} + +// ------------------------------------------------------------------------------ + +void setAlpha( Bitmap& rBitmap, AlphaMask& rAlpha, sal_Int32 nColorFrom, sal_Int8 nAlphaTo ) +{ + BitmapWriteAccess* pWriteAccess = rAlpha.AcquireWriteAccess(); + BitmapReadAccess* pReadAccess = rBitmap.AcquireReadAccess(); + BitmapColor aColorFrom( static_cast< sal_uInt8 >( nColorFrom >> 16 ), + static_cast< sal_uInt8 >( nColorFrom >> 8 ), + static_cast< sal_uInt8 >( nColorFrom ) ); + if ( pReadAccess && pWriteAccess ) + { + for ( sal_Int32 nY = 0; nY < pReadAccess->Height(); nY++ ) + { + for ( sal_Int32 nX = 0; nX < pReadAccess->Width(); nX++ ) + { + BitmapColor aColor( pReadAccess->GetPixel( nY, nX ) ); + if ( aColor == aColorFrom ) + pWriteAccess->SetPixel( nY, nX, nAlphaTo ); + } + } + } + rBitmap.ReleaseAccess( pReadAccess ); + rAlpha.ReleaseAccess( pWriteAccess ); +} + +// XGraphicTransformer +uno::Reference< graphic::XGraphic > SAL_CALL GraphicTransformer::colorChange( + const uno::Reference< graphic::XGraphic >& rxGraphic, sal_Int32 nColorFrom, sal_Int8 nTolerance, sal_Int32 nColorTo, sal_Int8 nAlphaTo ) + throw ( lang::IllegalArgumentException, uno::RuntimeException) +{ + const uno::Reference< uno::XInterface > xIFace( rxGraphic, uno::UNO_QUERY ); + ::Graphic aGraphic( *::unographic::Graphic::getImplementation( xIFace ) ); + + BitmapColor aColorFrom( static_cast< sal_uInt8 >( nColorFrom ), static_cast< sal_uInt8 >( nColorFrom >> 8 ), static_cast< sal_uInt8 >( nColorFrom >> 16 ) ); + BitmapColor aColorTo( static_cast< sal_uInt8 >( nColorTo ), static_cast< sal_uInt8 >( nColorTo >> 8 ), static_cast< sal_uInt8 >( nColorTo >> 16 ) ); + + if ( aGraphic.GetType() == GRAPHIC_BITMAP ) + { + BitmapEx aBitmapEx( aGraphic.GetBitmapEx() ); + Bitmap aBitmap( aBitmapEx.GetBitmap() ); + + if ( aBitmapEx.IsAlpha() ) + { + AlphaMask aAlphaMask( aBitmapEx.GetAlpha() ); + setAlpha( aBitmap, aAlphaMask, aColorFrom, nAlphaTo ); + aBitmap.Replace( aColorFrom, aColorTo, nTolerance ); + aGraphic = ::Graphic( BitmapEx( aBitmap, aAlphaMask ) ); + } + else if ( aBitmapEx.IsTransparent() ) + { + if ( ( nAlphaTo == 0 ) || ( nAlphaTo == sal::static_int_cast<sal_Int8>(0xff) ) ) + { + Bitmap aMask( aBitmapEx.GetMask() ); + Bitmap aMask2( aBitmap.CreateMask( aColorFrom, nTolerance ) ); + aMask.CombineSimple( aMask2, BMP_COMBINE_OR ); + aBitmap.Replace( aColorFrom, aColorTo, nTolerance ); + aGraphic = ::Graphic( BitmapEx( aBitmap, aMask ) ); + } + else + { + AlphaMask aAlphaMask( aBitmapEx.GetMask() ); + setAlpha( aBitmap, aAlphaMask, aColorFrom, nAlphaTo ); + aBitmap.Replace( aColorFrom, aColorTo, nTolerance ); + aGraphic = ::Graphic( BitmapEx( aBitmap, aAlphaMask ) ); + } + } + else + { + if ( ( nAlphaTo == 0 ) || ( nAlphaTo == sal::static_int_cast<sal_Int8>(0xff) ) ) + { + Bitmap aMask( aBitmap.CreateMask( aColorFrom, nTolerance ) ); + aBitmap.Replace( aColorFrom, aColorTo, nTolerance ); + aGraphic = ::Graphic( BitmapEx( aBitmap, aMask ) ); + } + else + { + AlphaMask aAlphaMask( aBitmapEx.GetSizePixel() ); + setAlpha( aBitmap, aAlphaMask, aColorFrom, nAlphaTo ); + aBitmap.Replace( aColorFrom, aColorTo, nTolerance ); + aGraphic = ::Graphic( BitmapEx( aBitmap, aAlphaMask ) ); + } + } + } + ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic(); + pUnoGraphic->init( aGraphic ); + uno::Reference< graphic::XGraphic > xRet( pUnoGraphic ); + return xRet; +} + +} diff --git a/svtools/source/graphic/transformer.hxx b/svtools/source/graphic/transformer.hxx new file mode 100644 index 000000000000..5de3acc7f2d5 --- /dev/null +++ b/svtools/source/graphic/transformer.hxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * 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: transformer.hxx,v $ + * $Revision: 1.3 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _GOODIES_GRAPHICTRANSFORMER_HXX +#define _GOODIES_GRAPHICTRANSFORMER_HXX + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/graphic/XGraphicTransformer.hpp> + +using namespace com::sun::star; + +namespace unographic { + +// ---------------------- +// - GraphicTransformer - +// ---------------------- + +typedef ::cppu::WeakAggImplHelper1< + ::com::sun::star::graphic::XGraphicTransformer + > GraphicTransformer_UnoImplHelper1; +class GraphicTransformer : public GraphicTransformer_UnoImplHelper1 +{ + public: + + GraphicTransformer(); + ~GraphicTransformer(); + + // XGraphicTransformer + virtual ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > SAL_CALL colorChange( + const ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >& rGraphic, + sal_Int32 nColorFrom, sal_Int8 nTolerance, sal_Int32 nColorTo, sal_Int8 nAlphaTo ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + +}; + +} + +#endif diff --git a/svtools/source/inc/provider.hxx b/svtools/source/inc/provider.hxx new file mode 100644 index 000000000000..d92866d1ed09 --- /dev/null +++ b/svtools/source/inc/provider.hxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * 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.hxx,v $ + * $Revision: 1.8 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _GOODIES_PROVIDER_HXX +#define _GOODIES_PROVIDER_HXX + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <com/sun/star/awt/XBitmap.hpp> + +using namespace com::sun::star; + +namespace unographic { + +// ------------------- +// - GraphicProvider - +// ------------------- + +class GraphicProvider : public ::cppu::WeakImplHelper1< ::com::sun::star::graphic::XGraphicProvider > +{ +public: + + GraphicProvider(); + ~GraphicProvider(); + + static ::rtl::OUString getImplementationName_Static() throw(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static() throw(); + +protected: + + // XServiceInfo + virtual rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException); + + // XGraphicProvider + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > SAL_CALL queryGraphicDescriptor( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& MediaProperties ) throw (::com::sun::star::io::IOException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > SAL_CALL queryGraphic( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& MediaProperties ) throw (::com::sun::star::io::IOException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL storeGraphic( const ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >& Graphic, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& MediaProperties ) throw (::com::sun::star::io::IOException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +private: + + ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > implLoadMemory( const ::rtl::OUString& rResourceURL ) const; + ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > implLoadGraphicObject( const ::rtl::OUString& rResourceURL ) const; + ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > implLoadResource( const ::rtl::OUString& rResourceURL ) const; + ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > implLoadRepositoryImage( const ::rtl::OUString& rResourceURL ) const; + ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > implLoadBitmap( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >& rBitmap ) const; + ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > implLoadStandardImage( const ::rtl::OUString& rResourceURL ) const; +}; + +} + +#endif diff --git a/svtools/source/inc/renderer.hxx b/svtools/source/inc/renderer.hxx new file mode 100644 index 000000000000..ebb4b2e3dca7 --- /dev/null +++ b/svtools/source/inc/renderer.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * 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: renderer.hxx,v $ + * $Revision: 1.4 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _GOODIES_RENDERER_HXX +#define _GOODIES_RENDERER_HXX + +#include <tools/gen.hxx> +#include <comphelper/propertysethelper.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/graphic/XGraphicRenderer.hpp> + + +using namespace com::sun::star; + +class OutputDevice; + +namespace unographic { + +// ------------------- +// - GraphicRenderer - +// ------------------- + +class GraphicRendererVCL : public ::cppu::OWeakAggObject, + public ::com::sun::star::lang::XServiceInfo, + public ::com::sun::star::lang::XTypeProvider, + public ::comphelper::PropertySetHelper, + public ::com::sun::star::graphic::XGraphicRenderer +{ +public: + + GraphicRendererVCL(); + ~GraphicRendererVCL() throw(); + + static ::rtl::OUString getImplementationName_Static() throw(); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static() throw(); + +protected: + + static ::comphelper::PropertySetInfo* createPropertySetInfo(); + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XServiceInfo + virtual rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException); + + // PropertySetHelper + virtual void _setPropertyValues( const comphelper::PropertyMapEntry** ppEntries, const ::com::sun::star::uno::Any* pValues ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException ); + virtual void _getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, ::com::sun::star::uno::Any* pValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException ); + + // XGraphicRenderer + virtual void SAL_CALL render( const ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >& Graphic ) throw (::com::sun::star::uno::RuntimeException); + +private: + + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice > mxDevice; + + OutputDevice* mpOutDev; + Rectangle maDestRect; + ::com::sun::star::uno::Any maRenderData; +}; + +} + +#endif diff --git a/svtools/source/uno/miscservices.cxx b/svtools/source/uno/miscservices.cxx index 0f7b79720179..ed1bd7451b41 100644 --- a/svtools/source/uno/miscservices.cxx +++ b/svtools/source/uno/miscservices.cxx @@ -37,13 +37,27 @@ #include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/registry/XRegistryKey.hpp> +#include <osl/diagnose.h> +#include <uno/mapping.hxx> +#include "provider.hxx" +#include "renderer.hxx" + +#include <com/sun/star/registry/XRegistryKey.hpp> +#include "comphelper/servicedecl.hxx" using namespace ::com::sun::star::uno; using namespace ::com::sun::star::registry; using namespace ::com::sun::star::lang; +using namespace unographic; using rtl::OUString; +namespace sdecl = comphelper::service_decl; + +namespace unographic { +extern sdecl::ServiceDecl const serviceDecl; +} + // ------------------------------------------------------------------------------------- // for CreateInstance functions implemented elsewhere @@ -60,10 +74,10 @@ using rtl::OUString; DECLARE_CREATEINSTANCE_NAMESPACE( svt, OAddressBookSourceDialogUno ) DECLARE_CREATEINSTANCE( SvFilterOptionsDialog ) -DECLARE_CREATEINSTANCE( PathService ) +DECLARE_CREATEINSTANCE_NAMESPACE( unographic, GraphicProvider ) +DECLARE_CREATEINSTANCE_NAMESPACE( unographic, GraphicRendererVCL ) // ------------------------------------------------------------------------------------- - extern "C" { @@ -74,13 +88,14 @@ SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment ( } SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo ( - void * /* _pServiceManager */, void * _pRegistryKey ) + void * pServiceManager, void * _pRegistryKey ) { if (_pRegistryKey) { Reference< XRegistryKey > xRegistryKey ( reinterpret_cast< XRegistryKey* >( _pRegistryKey )); Reference< XRegistryKey > xNewKey; + uno::Sequence< ::rtl::OUString > aServices; xNewKey = xRegistryKey->createKey ( OUString::createFromAscii( "/com.sun.star.comp.svtools.OAddressBookSourceDialogUno/UNO/SERVICES" ) ); @@ -92,13 +107,37 @@ SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo ( xNewKey->createKey ( OUString::createFromAscii( "com.sun.star.ui.dialogs.FilterOptionsDialog" ) ); + // GraphicProvider + xNewKey = reinterpret_cast< registry::XRegistryKey * >( _pRegistryKey )->createKey( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + + GraphicProvider::getImplementationName_Static() + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "/UNO/SERVICES") ) ); + + aServices = GraphicProvider::getSupportedServiceNames_Static(); + int i; + for( i = 0; i < aServices.getLength(); i++ ) + xNewKey->createKey( aServices.getConstArray()[ i ] ); + + // GraphicRendererVCL + xNewKey = reinterpret_cast< registry::XRegistryKey * >( _pRegistryKey )->createKey( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + + GraphicRendererVCL::getImplementationName_Static() + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "/UNO/SERVICES") ) ); + + aServices = ( GraphicRendererVCL::getSupportedServiceNames_Static() ); + for( i = 0; i < aServices.getLength(); i++ ) + xNewKey->createKey( aServices.getConstArray()[ i ] ); + + if ( !component_writeInfoHelper( reinterpret_cast< lang::XMultiServiceFactory* >( pServiceManager ), reinterpret_cast< registry::XRegistryKey* >( _pRegistryKey ), serviceDecl ) ) + return false; + return sal_True; } return sal_False; } SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory ( - const sal_Char * pImplementationName, void * _pServiceManager, void * /* _pRegistryKey */) + const sal_Char * pImplementationName, void * _pServiceManager, void * pRegistryKey) { void * pResult = 0; if ( _pServiceManager ) @@ -130,6 +169,27 @@ SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory ( SvFilterOptionsDialog_CreateInstance, aServiceNames); } + else if( 0 == GraphicProvider::getImplementationName_Static().compareToAscii( pImplementationName ) ) + { + xFactory = ::cppu::createOneInstanceFactory( + reinterpret_cast< lang::XMultiServiceFactory * >( _pServiceManager ), + GraphicProvider::getImplementationName_Static(), + GraphicProvider_CreateInstance, + GraphicProvider::getSupportedServiceNames_Static() ); + } + else if( 0 == GraphicRendererVCL::getImplementationName_Static().compareToAscii( pImplementationName ) ) + { + xFactory = ::cppu::createOneInstanceFactory( + reinterpret_cast< lang::XMultiServiceFactory * >( _pServiceManager ), + GraphicRendererVCL::getImplementationName_Static(), + GraphicRendererVCL_CreateInstance, + GraphicRendererVCL::getSupportedServiceNames_Static() ); + } + else + { + pResult = component_getFactoryHelper( pImplementationName, reinterpret_cast< lang::XMultiServiceFactory * >( _pServiceManager ),reinterpret_cast< registry::XRegistryKey* >( pRegistryKey ), serviceDecl ); + } + if ( xFactory.is() ) { xFactory->acquire(); |