summaryrefslogtreecommitdiff
path: root/svtools/source/graphic/grfmgr.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/graphic/grfmgr.cxx')
-rw-r--r--svtools/source/graphic/grfmgr.cxx1316
1 files changed, 1316 insertions, 0 deletions
diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx
new file mode 100644
index 000000000000..53f4a3ed2515
--- /dev/null
+++ b/svtools/source/graphic/grfmgr.cxx
@@ -0,0 +1,1316 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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, const GraphicObject* pCopyObj )
+{
+ mpMgr->ImplUnregisterObj( *this );
+
+ if( mpSwapOutTimer )
+ mpSwapOutTimer->Stop();
+
+ maGraphic = rGraphic;
+ mbAutoSwapped = FALSE;
+ ImplAssignGraphicData();
+ delete mpLink, mpLink = NULL;
+ delete mpSimpleCache, mpSimpleCache = NULL;
+
+ mpMgr->ImplRegisterObj( *this, maGraphic, 0, pCopyObj);
+
+ 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 );
+ }
+}
+