/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the 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>

// --> OD 2010-01-04 #i105243#
#include <vcl/pdfextoutdevdata.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 );

// unique increasing ID for being able to detect the GraphicObject with the
// oldest last data changes
static sal_uLong aIncrementingTimeOfLastDataChange = 1;

void GraphicObject::ImplAfterDataChange()
{
    // set unique timestamp ID of last data change
    mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;

    // check memory footprint of all GraphicObjects managed and evtl. take action
    GetGraphicManager().ImplCheckSizeOfSwappedInGraphics();
}

// -----------------------------------------------------------------------------

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 = sal_False;
	mbIsInSwapIn = sal_False;
	mbIsInSwapOut = sal_False;

    // Init with a unique, increasing ID
    mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;
}

// -----------------------------------------------------------------------------

void GraphicObject::ImplAssignGraphicData()
{
	maPrefSize = maGraphic.GetPrefSize();
	maPrefMapMode = maGraphic.GetPrefMapMode();
	mnSizeBytes = maGraphic.GetSizeBytes();
	meType = maGraphic.GetType();
	mbTransparent = maGraphic.IsTransparent();
	mbAlpha = maGraphic.IsAlpha();
	mbAnimated = maGraphic.IsAnimated();
	mbEPS = maGraphic.IsEPS();
    mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 );
}

// -----------------------------------------------------------------------------

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 = sal_False;
		else
		{
			mbIsInSwapIn = sal_True;

			if( maGraphic.SwapIn() )
				mbAutoSwapped = sal_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 = sal_False;

			if( !mbAutoSwapped && mpMgr )
				mpMgr->ImplGraphicObjectWasSwappedIn( *this );
		}

        // Handle evtl. needed AfterDataChanges
        ImplAfterDataChange();
	}
}

// -----------------------------------------------------------------------------
sal_Bool GraphicObject::ImplGetCropParams( OutputDevice* pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr,
									   PolyPolygon& rClipPolyPoly, sal_Bool& bRectClipRegion ) const
{
	sal_Bool bRet = sal_False;

	if( GetType() != GRAPHIC_NONE )
	{
		Polygon			aClipPoly( Rectangle( rPt, rSz ) );
		const sal_uInt16	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 = sal_False;
		}
		else
			bRectClipRegion = sal_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 = sal_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 = sal_False;
		mpMgr = rGraphicObj.mpMgr;

		mpMgr->ImplRegisterObj( *this, maGraphic, NULL, &rGraphicObj );
	}

	return *this;
}

// -----------------------------------------------------------------------------

sal_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;
}

// -----------------------------------------------------------------------------

sal_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
sal_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 sal_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 );
}

// -----------------------------------------------------------------------------

sal_Bool GraphicObject::IsCached( OutputDevice* pOut, const Point& rPt, const Size& rSz,
							  const GraphicAttr* pAttr, sal_uLong nFlags ) const
{
	sal_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;
            sal_Bool        bRectClip;
            ImplGetCropParams( pOut, aPt, aSz, pAttr, aClipPolyPoly, bRectClip );
        }
        bRet = mpMgr->IsInCache( pOut, aPt, aSz, *this, ( pAttr ? *pAttr : GetAttr() ) );
    }
	else
		bRet = sal_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();
}

// -----------------------------------------------------------------------------

sal_Bool GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz,
						  const GraphicAttr* pAttr, sal_uLong nFlags )
{
	GraphicAttr	        aAttr( pAttr ? *pAttr : GetAttr() );
	Point 		        aPt( rPt );
	Size  	            aSz( rSz );
    const sal_uInt32    nOldDrawMode = pOut->GetDrawMode();
	sal_Bool		        bCropped = aAttr.IsCropped();
	sal_Bool		        bCached = sal_False;
	sal_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;
		sal_Bool		bRectClip;
		const sal_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;
}

// --> OD 2010-01-04 #i105243#
sal_Bool GraphicObject::DrawWithPDFHandling( OutputDevice& rOutDev,
                                         const Point& rPt, const Size& rSz,
                                         const GraphicAttr* pGrfAttr,
                                         const sal_uLong nFlags )
{
    const GraphicAttr aGrfAttr( pGrfAttr ? *pGrfAttr : GetAttr() );

    // Notify PDF writer about linked graphic (if any)
    sal_Bool bWritingPdfLinkedGraphic( sal_False );
    Point aPt( rPt );
    Size aSz( rSz );
    Rectangle aCropRect;
    vcl::PDFExtOutDevData* pPDFExtOutDevData =
            dynamic_cast<vcl::PDFExtOutDevData*>(rOutDev.GetExtOutDevData());
    if( pPDFExtOutDevData )
    {
        // only delegate image handling to PDF, if no special treatment is necessary
        if( GetGraphic().IsLink() &&
            rSz.Width() > 0L &&
            rSz.Height() > 0L &&
            !aGrfAttr.IsSpecialDrawMode() &&
            !aGrfAttr.IsMirrored() &&
            !aGrfAttr.IsRotated() &&
            !aGrfAttr.IsAdjusted() )
        {
            bWritingPdfLinkedGraphic = true;

            if( aGrfAttr.IsCropped() )
            {
                PolyPolygon aClipPolyPoly;
                sal_Bool bRectClip;
                const sal_Bool bCrop = ImplGetCropParams( &rOutDev,
                                                      aPt, aSz,
                                                      &aGrfAttr,
                                                      aClipPolyPoly,
                                                      bRectClip );
                if ( bCrop && bRectClip )
                {
                    aCropRect = aClipPolyPoly.GetBoundRect();
                }
            }

            pPDFExtOutDevData->BeginGroup();
        }
    }

    sal_Bool bRet = Draw( &rOutDev, rPt, rSz, &aGrfAttr, nFlags );

    // Notify PDF writer about linked graphic (if any)
    if( bWritingPdfLinkedGraphic )
    {
        pPDFExtOutDevData->EndGroup( const_cast< Graphic& >(GetGraphic()),
                                     aGrfAttr.GetTransparency(),
                                     Rectangle( aPt, aSz ),
                                     aCropRect );
    }

    return bRet;
}
// <--

// -----------------------------------------------------------------------------

sal_Bool GraphicObject::DrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSize,
                               const Size& rOffset, const GraphicAttr* pAttr, sal_uLong nFlags, int nTileCacheSize1D )
{
    if( pOut == NULL || rSize.Width() == 0 || rSize.Height() == 0 )
        return sal_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 );
}

// -----------------------------------------------------------------------------

sal_Bool GraphicObject::StartAnimation( OutputDevice* pOut, const Point& rPt, const Size& rSz,
									long nExtraData, const GraphicAttr* pAttr, sal_uLong /*nFlags*/,
									OutputDevice* pFirstFrameOutDev )
{
	sal_Bool bRet = sal_False;

	GetGraphic();

	if( !IsSwappedOut() )
	{
    	const GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );

		if( mbAnimated )
		{
			Point   aPt( rPt );
			Size	aSz( rSz );
			sal_Bool	bCropped = aAttr.IsCropped();

			if( bCropped )
			{
				PolyPolygon aClipPolyPoly;
				sal_Bool		bRectClip;
				const sal_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 = sal_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 = sal_False;
	ImplAssignGraphicData();
	delete mpLink, mpLink = NULL;
	delete mpSimpleCache, mpSimpleCache = NULL;

	mpMgr->ImplRegisterObj( *this, maGraphic, 0, pCopyObj);

	if( mpSwapOutTimer )
		mpSwapOutTimer->Start();

    // Handle evtl. needed AfterDataChanges
    ImplAfterDataChange();
}

// -----------------------------------------------------------------------------

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 )
        {
            // crops are in 1/100th mm -> to aMapGraph -> to MAP_PIXEL
            aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( 
                Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()), 
                aMap100);
            aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( 
                Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
                aMap100);
        }
        else
        {
            // crops are in GraphicObject units -> to aMapGraph
            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() );
        Rectangle aCropRect;

        // convert crops to pixel
        if(rAttr.IsCropped())
        {
            if( aMapGraph == MAP_PIXEL )
            {
                // crops are in 1/100th mm -> to MAP_PIXEL
                aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( 
                    Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
                    aMap100);
                aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( 
                    Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
                    aMap100);
            }
            else
            {
                // crops are in GraphicObject units -> to MAP_PIXEL
                aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( 
                    Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
                    aMapGraph);
                aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( 
                    Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
                    aMapGraph);
            }

            // convert from prefmapmode to pixel
            Size aSrcSizePixel(
                Application::GetDefaultDevice()->LogicToPixel( 
                    aSrcSize,
                    aMapGraph));

            if(rAttr.IsCropped() 
                && (aSrcSizePixel.Width() != aBitmapEx.GetSizePixel().Width() || aSrcSizePixel.Height() != aBitmapEx.GetSizePixel().Height())
                && aSrcSizePixel.Width())
            {
                // the size in pixels calculated from Graphic's internal MapMode (aTransGraphic.GetPrefMapMode())
                // and it's internal size (aTransGraphic.GetPrefSize()) is different from it's real pixel size.
                // This can be interpreted as this values to be set wrong, but needs to be corrected since e.g.
                // existing cropping is calculated based on this logic values already.
                // aBitmapEx.Scale(aSrcSizePixel);

                // another possibility is to adapt the values created so far with a factor; this
                // will keep the original Bitmap untouched and thus quality will not change
                // caution: convert to double first, else pretty big errors may occurr
                const double fFactorX((double)aBitmapEx.GetSizePixel().Width() / aSrcSizePixel.Width());
                const double fFactorY((double)aBitmapEx.GetSizePixel().Height() / aSrcSizePixel.Height());

                aCropLeftTop.Width() = basegfx::fround(aCropLeftTop.Width() * fFactorX);
                aCropLeftTop.Height() = basegfx::fround(aCropLeftTop.Height() * fFactorY);
                aCropRightBottom.Width() = basegfx::fround(aCropRightBottom.Width() * fFactorX);
                aCropRightBottom.Height() = basegfx::fround(aCropRightBottom.Height() * fFactorY);

                aSrcSizePixel = aBitmapEx.GetSizePixel();
            }

            // setup crop rectangle in pixel
            aCropRect = Rectangle( aCropLeftTop.Width(), aCropLeftTop.Height(),
                                 aSrcSizePixel.Width() - aCropRightBottom.Width(),
                                 aSrcSizePixel.Height() - aCropRightBottom.Height() );
        }

        // #105641# Also crop animations
        if( aTransGraphic.IsAnimated() )
        {
            sal_uInt16 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, sal_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
        {
            ImplTransformBitmap( aBitmapEx, rAttr, aCropLeftTop, aCropRightBottom,
                                 aCropRect, rDestSize, sal_True );

            aTransGraphic = aBitmapEx;
        }

        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();
	}
}

// -----------------------------------------------------------------------------

sal_Bool GraphicObject::SwapOut()
{
	sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut() : sal_False );

	if( bRet && mpMgr )
		mpMgr->ImplGraphicObjectWasSwappedOut( *this );

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GraphicObject::SwapOut( SvStream* pOStm )
{
	sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut( pOStm ) : sal_False );

	if( bRet && mpMgr )
		mpMgr->ImplGraphicObjectWasSwappedOut( *this );

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GraphicObject::SwapIn()
{
	sal_Bool bRet;

	if( mbAutoSwapped )
	{
		ImplAutoSwapIn();
		bRet = sal_True;
	}
	else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
    {
		bRet = sal_True;
    }
	else
	{
		bRet = maGraphic.SwapIn();

		if( bRet && mpMgr )
			mpMgr->ImplGraphicObjectWasSwappedIn( *this );
	}

	if( bRet )
    {
		ImplAssignGraphicData();

        // Handle evtl. needed AfterDataChanges
        ImplAfterDataChange();
    }

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GraphicObject::SwapIn( SvStream* pIStm )
{
	sal_Bool bRet;

	if( mbAutoSwapped )
	{
		ImplAutoSwapIn();
		bRet = sal_True;
	}
	else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
    {
		bRet = sal_True;
    }
	else
	{
		bRet = maGraphic.SwapIn( pIStm );

		if( bRet && mpMgr )
			mpMgr->ImplGraphicObjectWasSwappedIn( *this );
	}

	if( bRet )
    {
		ImplAssignGraphicData();

        //
        ImplAfterDataChange();
    }

	return bRet;
}

// -----------------------------------------------------------------------------

void GraphicObject::SetSwapState()
{
	if( !IsSwappedOut() )
	{
		mbAutoSwapped = sal_True;

		if( mpMgr )
			mpMgr->ImplGraphicObjectWasSwappedOut( *this );
	}
}

// -----------------------------------------------------------------------------

IMPL_LINK( GraphicObject, ImplAutoSwapOutHdl, void*, EMPTYARG )
{
	if( !IsSwappedOut() )
	{
		mbIsInSwapOut = sal_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 = sal_False;
	}

	if( mpSwapOutTimer )
		mpSwapOutTimer->Start();

	return 0L;
}

// ------------------------------------------------------------------------

SvStream& operator>>( SvStream& rIStm, GraphicObject& rGraphicObj )
{
	VersionCompat	aCompat( rIStm, STREAM_READ );
	Graphic			aGraphic;
	GraphicAttr		aAttr;
	ByteString		aLink;
	sal_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 sal_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 );
	}
}

// calculate scalings between real image size and logic object size. This
// is necessary since the crop values are relative to original bitmap size
basegfx::B2DVector GraphicObject::calculateCropScaling(
    double fWidth,
    double fHeight,
    double fLeftCrop, 
    double fTopCrop, 
    double fRightCrop, 
    double fBottomCrop) const
{
    const MapMode aMapMode100thmm(MAP_100TH_MM);
    Size aBitmapSize(GetPrefSize());
    double fFactorX(1.0);
    double fFactorY(1.0);

    if(MAP_PIXEL == GetPrefMapMode().GetMapUnit())
    {
        aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm);
    }
    else
    {
        aBitmapSize = Application::GetDefaultDevice()->LogicToLogic(aBitmapSize, GetPrefMapMode(), aMapMode100thmm);
    }

    const double fDivX(aBitmapSize.Width() - fLeftCrop - fRightCrop);
    const double fDivY(aBitmapSize.Height() - fTopCrop - fBottomCrop);

    if(!basegfx::fTools::equalZero(fDivX))
    {
        fFactorX = fabs(fWidth) / fDivX;
    }

    if(!basegfx::fTools::equalZero(fDivY))
    {
        fFactorY = fabs(fHeight) / fDivY;
    }

    return basegfx::B2DVector(fFactorX,fFactorY);
}

// ------------------------------------------------------------------------
// restart SwapOut timer

void GraphicObject::restartSwapOutTimer() const
{
    if( mpSwapOutTimer && mpSwapOutTimer->IsActive() )
    {
        mpSwapOutTimer->Start();
    }
}

// eof
