summaryrefslogtreecommitdiff
path: root/svtools/source/graphic
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/graphic')
-rw-r--r--svtools/source/graphic/descriptor.cxx501
-rw-r--r--svtools/source/graphic/descriptor.hxx143
-rw-r--r--svtools/source/graphic/graphic.cxx303
-rw-r--r--svtools/source/graphic/graphic.hxx106
-rw-r--r--svtools/source/graphic/graphicunofactory.cxx106
-rw-r--r--svtools/source/graphic/grfattr.cxx121
-rw-r--r--svtools/source/graphic/grfcache.cxx1055
-rw-r--r--svtools/source/graphic/grfcache.hxx112
-rw-r--r--svtools/source/graphic/grfmgr.cxx1319
-rw-r--r--svtools/source/graphic/grfmgr2.cxx2385
-rw-r--r--svtools/source/graphic/makefile.mk70
-rw-r--r--svtools/source/graphic/provider.cxx864
-rw-r--r--svtools/source/graphic/renderer.cxx348
-rw-r--r--svtools/source/graphic/transformer.cxx159
-rw-r--r--svtools/source/graphic/transformer.hxx66
15 files changed, 7658 insertions, 0 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