739e20ac58
Change-Id: I654e71e56d60bf629625df09eb93b21c9ef670e8
1214 lines
39 KiB
C++
1214 lines
39 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* 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.
|
|
*
|
|
************************************************************************/
|
|
|
|
#include "sal/config.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <officecfg/Office/Common.hxx>
|
|
#include <tools/vcompat.hxx>
|
|
#include <tools/helpers.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 <svtools/grfmgr.hxx>
|
|
|
|
#include <vcl/pdfextoutdevdata.hxx>
|
|
|
|
#include <com/sun/star/container/XNameContainer.hpp>
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
|
|
using com::sun::star::uno::Reference;
|
|
using com::sun::star::uno::XInterface;
|
|
using com::sun::star::uno::UNO_QUERY;
|
|
using com::sun::star::uno::Sequence;
|
|
using com::sun::star::container::XNameContainer;
|
|
using com::sun::star::beans::XPropertySet;
|
|
|
|
GraphicManager* GraphicObject::mpGlobalMgr = NULL;
|
|
|
|
struct GrfSimpleCacheObj
|
|
{
|
|
Graphic maGraphic;
|
|
GraphicAttr maAttr;
|
|
|
|
GrfSimpleCacheObj( const Graphic& rGraphic, const GraphicAttr& rAttr ) :
|
|
maGraphic( rGraphic ), maAttr( rAttr ) {}
|
|
};
|
|
|
|
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 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 rtl::OString& 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;
|
|
}
|
|
|
|
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();
|
|
mbIsRenderGraphic = maGraphic.IsRenderGraphic();
|
|
mbHasRenderGraphic = maGraphic.HasRenderGraphic();
|
|
mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 );
|
|
}
|
|
|
|
void GraphicObject::ImplSetGraphicManager( const GraphicManager* pMgr, const rtl::OString* 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 )
|
|
{
|
|
mpGlobalMgr = new GraphicManager(
|
|
(officecfg::Office::Common::Cache::GraphicManager::
|
|
TotalCacheSize::get()),
|
|
(officecfg::Office::Common::Cache::GraphicManager::
|
|
ObjectCacheSize::get()));
|
|
mpGlobalMgr->SetCacheTimeout(
|
|
officecfg::Office::Common::Cache::GraphicManager::
|
|
ObjectReleaseTime::get());
|
|
}
|
|
|
|
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() )
|
|
{
|
|
rtl::OUString 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 );
|
|
}
|
|
}
|
|
}
|
|
|
|
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 );
|
|
const MapMode aMap100( MAP_100TH_MM );
|
|
Size aSize100;
|
|
long nTotalWidth, nTotalHeight;
|
|
|
|
if( nRot10 )
|
|
{
|
|
aClipPoly.Rotate( rPt, nRot10 );
|
|
bRectClipRegion = sal_False;
|
|
}
|
|
else
|
|
bRectClipRegion = sal_True;
|
|
|
|
rClipPolyPoly = aClipPoly;
|
|
|
|
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 )
|
|
{
|
|
double fScale = (double) aSize100.Width() / nTotalWidth;
|
|
const long nNewLeft = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_HORZ ) ? pAttr->GetRightCrop() : pAttr->GetLeftCrop() ) * fScale );
|
|
const long 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;
|
|
const long nNewTop = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_VERT ) ? pAttr->GetBottomCrop() : pAttr->GetTopCrop() ) * fScale );
|
|
const long 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;
|
|
}
|
|
|
|
rtl::OString GraphicObject::GetUniqueID() const
|
|
{
|
|
if ( !IsInSwapIn() && ( IsEPS() || IsRenderGraphic() ) )
|
|
const_cast<GraphicObject*>(this)->FireSwapInRequest();
|
|
|
|
rtl::OString aRet;
|
|
|
|
if( mpMgr )
|
|
aRet = mpMgr->ImplGetUniqueID( *this );
|
|
|
|
return aRet;
|
|
}
|
|
|
|
SvStream* GraphicObject::GetSwapStream() const
|
|
{
|
|
return( HasSwapStreamHdl() ? (SvStream*) mpSwapStreamHdl->Call( (void*) this ) : GRFMGR_AUTOSWAPSTREAM_NONE );
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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 );
|
|
}
|
|
|
|
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 )
|
|
{
|
|
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 );
|
|
}
|
|
|
|
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;
|
|
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;
|
|
}
|
|
|
|
// #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();
|
|
}
|
|
|
|
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() )
|
|
{
|
|
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
|
|
{
|
|
BitmapEx aBmpEx( aTransGraphic.GetBitmapEx() );
|
|
|
|
ImplTransformBitmap( aBmpEx, rAttr, aCropLeftTop, aCropRightBottom,
|
|
aCropRect, rDestSize, sal_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;
|
|
}
|
|
|
|
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();
|
|
|
|
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();
|
|
|
|
return bRet;
|
|
}
|
|
|
|
void GraphicObject::SetSwapState()
|
|
{
|
|
if( !IsSwappedOut() )
|
|
{
|
|
mbAutoSwapped = sal_True;
|
|
|
|
if( mpMgr )
|
|
mpMgr->ImplGraphicObjectWasSwappedOut( *this );
|
|
}
|
|
}
|
|
|
|
IMPL_LINK_NOARG(GraphicObject, ImplAutoSwapOutHdl)
|
|
{
|
|
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;
|
|
sal_Bool bLink;
|
|
|
|
rIStm >> aGraphic >> aAttr >> bLink;
|
|
|
|
rGraphicObj.SetGraphic( aGraphic );
|
|
rGraphicObj.SetAttr( aAttr );
|
|
|
|
if( bLink )
|
|
{
|
|
rtl::OUString aLink = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(rIStm, RTL_TEXTENCODING_UTF8);
|
|
rGraphicObj.SetLink(aLink);
|
|
}
|
|
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 )
|
|
write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rOStm, 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_USTRINGPARAM(UNO_NAME_GRAPHOBJ_URLPREFIX) );
|
|
if( aURL.Search( aPrefix ) == 0 )
|
|
{
|
|
// graphic manager url
|
|
rtl::OString aUniqueID(rtl::OUStringToOString(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 );
|
|
}
|
|
}
|
|
|
|
void
|
|
GraphicObject::InspectForGraphicObjectImageURL( const Reference< XInterface >& xIf, std::vector< rtl::OUString >& rvEmbedImgUrls )
|
|
{
|
|
static rtl::OUString sImageURL(RTL_CONSTASCII_USTRINGPARAM( "ImageURL" ) );
|
|
Reference< XPropertySet > xProps( xIf, UNO_QUERY );
|
|
if ( xProps.is() )
|
|
{
|
|
|
|
if ( xProps->getPropertySetInfo()->hasPropertyByName( sImageURL ) )
|
|
{
|
|
rtl::OUString sURL;
|
|
xProps->getPropertyValue( sImageURL ) >>= sURL;
|
|
if ( !sURL.isEmpty() && sURL.compareToAscii( UNO_NAME_GRAPHOBJ_URLPREFIX, RTL_CONSTASCII_LENGTH( UNO_NAME_GRAPHOBJ_URLPREFIX ) ) == 0 )
|
|
rvEmbedImgUrls.push_back( sURL );
|
|
}
|
|
}
|
|
Reference< XNameContainer > xContainer( xIf, UNO_QUERY );
|
|
if ( xContainer.is() )
|
|
{
|
|
Sequence< rtl::OUString > sNames = xContainer->getElementNames();
|
|
sal_Int32 nContainees = sNames.getLength();
|
|
for ( sal_Int32 index = 0; index < nContainees; ++index )
|
|
{
|
|
Reference< XInterface > xCtrl;
|
|
xContainer->getByName( sNames[ index ] ) >>= xCtrl;
|
|
InspectForGraphicObjectImageURL( xCtrl, rvEmbedImgUrls );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|