1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: grfmgr.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_goodies.hxx"
34 #define ENABLE_BYTESTRING_STREAM_OPERATORS
38 #include <tools/vcompat.hxx>
39 #include <unotools/ucbstreamhelper.hxx>
40 #include <unotools/localfilehelper.hxx>
41 #include <unotools/tempfile.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/cvtgrf.hxx>
44 #include <vcl/metaact.hxx>
45 #include <vcl/virdev.hxx>
46 #include <vcl/salbtype.hxx>
47 #include <svtools/cacheoptions.hxx>
54 #define WATERMARK_LUM_OFFSET 50
55 #define WATERMARK_CON_OFFSET -70
61 GraphicManager
* GraphicObject::mpGlobalMgr
= NULL
;
63 // ---------------------
64 // - GrfDirectCacheObj -
65 // ---------------------
67 struct GrfSimpleCacheObj
72 GrfSimpleCacheObj( const Graphic
& rGraphic
, const GraphicAttr
& rAttr
) :
73 maGraphic( rGraphic
), maAttr( rAttr
) {}
80 TYPEINIT1_AUTOFACTORY( GraphicObject
, SvDataCopyStream
);
82 // -----------------------------------------------------------------------------
84 GraphicObject::GraphicObject( const GraphicManager
* pMgr
) :
89 ImplAssignGraphicData();
90 ImplSetGraphicManager( pMgr
);
93 // -----------------------------------------------------------------------------
95 GraphicObject::GraphicObject( const Graphic
& rGraphic
, const GraphicManager
* pMgr
) :
96 maGraphic ( rGraphic
),
101 ImplAssignGraphicData();
102 ImplSetGraphicManager( pMgr
);
105 // -----------------------------------------------------------------------------
107 GraphicObject::GraphicObject( const Graphic
& rGraphic
, const String
& rLink
, const GraphicManager
* pMgr
) :
108 maGraphic ( rGraphic
),
109 mpLink ( rLink
.Len() ? ( new String( rLink
) ) : NULL
),
113 ImplAssignGraphicData();
114 ImplSetGraphicManager( pMgr
);
117 // -----------------------------------------------------------------------------
119 GraphicObject::GraphicObject( const GraphicObject
& rGraphicObj
, const GraphicManager
* pMgr
) :
121 maGraphic ( rGraphicObj
.GetGraphic() ),
122 maAttr ( rGraphicObj
.maAttr
),
123 mpLink ( rGraphicObj
.mpLink
? ( new String( *rGraphicObj
.mpLink
) ) : NULL
),
124 mpUserData ( rGraphicObj
.mpUserData
? ( new String( *rGraphicObj
.mpUserData
) ) : NULL
)
127 ImplAssignGraphicData();
128 ImplSetGraphicManager( pMgr
, NULL
, &rGraphicObj
);
131 // -----------------------------------------------------------------------------
133 GraphicObject::GraphicObject( const ByteString
& rUniqueID
, const GraphicManager
* pMgr
) :
139 // assign default properties
140 ImplAssignGraphicData();
142 ImplSetGraphicManager( pMgr
, &rUniqueID
);
145 ImplAssignGraphicData();
148 // -----------------------------------------------------------------------------
150 GraphicObject::~GraphicObject()
154 mpMgr
->ImplUnregisterObj( *this );
156 if( ( mpMgr
== mpGlobalMgr
) && !mpGlobalMgr
->ImplHasObjects() )
157 delete mpGlobalMgr
, mpGlobalMgr
= NULL
;
160 delete mpSwapOutTimer
;
161 delete mpSwapStreamHdl
;
164 delete mpSimpleCache
;
167 // -----------------------------------------------------------------------------
169 void GraphicObject::ImplConstruct()
172 mpSwapStreamHdl
= NULL
;
173 mpSwapOutTimer
= NULL
;
174 mpSimpleCache
= NULL
;
175 mnAnimationLoopCount
= 0;
176 mbAutoSwapped
= FALSE
;
177 mbIsInSwapIn
= FALSE
;
178 mbIsInSwapOut
= FALSE
;
181 // -----------------------------------------------------------------------------
183 void GraphicObject::ImplAssignGraphicData()
185 maPrefSize
= maGraphic
.GetPrefSize();
186 maPrefMapMode
= maGraphic
.GetPrefMapMode();
187 mnSizeBytes
= maGraphic
.GetSizeBytes();
188 meType
= maGraphic
.GetType();
189 mbTransparent
= maGraphic
.IsTransparent();
190 mbAlpha
= maGraphic
.IsAlpha();
191 mbAnimated
= maGraphic
.IsAnimated();
192 mnAnimationLoopCount
= ( mbAnimated
? maGraphic
.GetAnimationLoopCount() : 0 );
194 if( maGraphic
.GetType() == GRAPHIC_GDIMETAFILE
)
196 const GDIMetaFile
& rMtf
= GetGraphic().GetGDIMetaFile();
197 mbEPS
= ( rMtf
.GetActionCount() >= 1 ) && ( META_EPS_ACTION
== rMtf
.GetAction( 0 )->GetType() );
203 // -----------------------------------------------------------------------------
205 void GraphicObject::ImplSetGraphicManager( const GraphicManager
* pMgr
, const ByteString
* pID
, const GraphicObject
* pCopyObj
)
207 if( !mpMgr
|| ( pMgr
!= mpMgr
) )
209 if( !pMgr
&& mpMgr
&& ( mpMgr
== mpGlobalMgr
) )
215 mpMgr
->ImplUnregisterObj( *this );
217 if( ( mpMgr
== mpGlobalMgr
) && !mpGlobalMgr
->ImplHasObjects() )
218 delete mpGlobalMgr
, mpGlobalMgr
= NULL
;
225 SvtCacheOptions aCacheOptions
;
227 mpGlobalMgr
= new GraphicManager( aCacheOptions
.GetGraphicManagerTotalCacheSize(),
228 aCacheOptions
.GetGraphicManagerObjectCacheSize() );
229 mpGlobalMgr
->SetCacheTimeout( aCacheOptions
.GetGraphicManagerObjectReleaseTime() );
235 mpMgr
= (GraphicManager
*) pMgr
;
237 mpMgr
->ImplRegisterObj( *this, maGraphic
, pID
, pCopyObj
);
242 // -----------------------------------------------------------------------------
244 void GraphicObject::ImplAutoSwapIn()
248 if( mpMgr
&& mpMgr
->ImplFillSwappedGraphicObject( *this, maGraphic
) )
249 mbAutoSwapped
= FALSE
;
254 if( maGraphic
.SwapIn() )
255 mbAutoSwapped
= FALSE
;
258 SvStream
* pStream
= GetSwapStream();
260 if( GRFMGR_AUTOSWAPSTREAM_NONE
!= pStream
)
262 if( GRFMGR_AUTOSWAPSTREAM_LINK
== pStream
)
268 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( GetLink(), aURLStr
) )
270 SvStream
* pIStm
= ::utl::UcbStreamHelper::CreateStream( aURLStr
, STREAM_READ
);
274 (*pIStm
) >> maGraphic
;
275 mbAutoSwapped
= ( maGraphic
.GetType() != GRAPHIC_NONE
);
281 else if( GRFMGR_AUTOSWAPSTREAM_TEMP
== pStream
)
282 mbAutoSwapped
= !maGraphic
.SwapIn();
283 else if( GRFMGR_AUTOSWAPSTREAM_LOADED
== pStream
)
284 mbAutoSwapped
= maGraphic
.IsSwapOut();
287 mbAutoSwapped
= !maGraphic
.SwapIn( pStream
);
293 DBG_ASSERT( ( GRAPHIC_NONE
== meType
) || ( GRAPHIC_DEFAULT
== meType
),
294 "GraphicObject::ImplAutoSwapIn: could not get stream to swap in graphic! (=>KA)" );
298 mbIsInSwapIn
= FALSE
;
300 if( !mbAutoSwapped
&& mpMgr
)
301 mpMgr
->ImplGraphicObjectWasSwappedIn( *this );
306 // -----------------------------------------------------------------------------
307 BOOL
GraphicObject::ImplGetCropParams( OutputDevice
* pOut
, Point
& rPt
, Size
& rSz
, const GraphicAttr
* pAttr
,
308 PolyPolygon
& rClipPolyPoly
, BOOL
& bRectClipRegion
) const
312 if( GetType() != GRAPHIC_NONE
)
314 Polygon
aClipPoly( Rectangle( rPt
, rSz
) );
315 const USHORT nRot10
= pAttr
->GetRotation() % 3600;
316 const Point
aOldOrigin( rPt
);
317 // --> OD 2005-09-30 #i54875# - It's not needed to get the graphic again.
318 // const Graphic& rGraphic = GetGraphic();
320 const MapMode
aMap100( MAP_100TH_MM
);
322 long nTotalWidth
, nTotalHeight
;
323 long nNewLeft
, nNewTop
, nNewRight
, nNewBottom
;
328 aClipPoly
.Rotate( rPt
, nRot10
);
329 bRectClipRegion
= FALSE
;
332 bRectClipRegion
= TRUE
;
334 rClipPolyPoly
= aClipPoly
;
336 // --> OD 2005-09-30 #i54875# - directly access member <maGraphic> to
337 // get <PrefSize> and <PrefMapMode>.
338 // if( rGraphic.GetPrefMapMode() == MAP_PIXEL )
339 // aSize100 = Application::GetDefaultDevice()->PixelToLogic( rGraphic.GetPrefSize(), aMap100 );
341 // aSize100 = pOut->LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), aMap100 );
342 if( maGraphic
.GetPrefMapMode() == MAP_PIXEL
)
343 aSize100
= Application::GetDefaultDevice()->PixelToLogic( maGraphic
.GetPrefSize(), aMap100
);
346 MapMode
m(maGraphic
.GetPrefMapMode());
347 aSize100
= pOut
->LogicToLogic( maGraphic
.GetPrefSize(), &m
, &aMap100
);
351 nTotalWidth
= aSize100
.Width() - pAttr
->GetLeftCrop() - pAttr
->GetRightCrop();
352 nTotalHeight
= aSize100
.Height() - pAttr
->GetTopCrop() - pAttr
->GetBottomCrop();
354 if( aSize100
.Width() > 0 && aSize100
.Height() > 0 && nTotalWidth
> 0 && nTotalHeight
> 0 )
356 fScale
= (double) aSize100
.Width() / nTotalWidth
;
357 nNewLeft
= -FRound( ( ( pAttr
->GetMirrorFlags() & BMP_MIRROR_HORZ
) ? pAttr
->GetRightCrop() : pAttr
->GetLeftCrop() ) * fScale
);
358 nNewRight
= nNewLeft
+ FRound( aSize100
.Width() * fScale
) - 1;
360 fScale
= (double) rSz
.Width() / aSize100
.Width();
361 rPt
.X() += FRound( nNewLeft
* fScale
);
362 rSz
.Width() = FRound( ( nNewRight
- nNewLeft
+ 1 ) * fScale
);
364 fScale
= (double) aSize100
.Height() / nTotalHeight
;
365 nNewTop
= -FRound( ( ( pAttr
->GetMirrorFlags() & BMP_MIRROR_VERT
) ? pAttr
->GetBottomCrop() : pAttr
->GetTopCrop() ) * fScale
);
366 nNewBottom
= nNewTop
+ FRound( aSize100
.Height() * fScale
) - 1;
368 fScale
= (double) rSz
.Height() / aSize100
.Height();
369 rPt
.Y() += FRound( nNewTop
* fScale
);
370 rSz
.Height() = FRound( ( nNewBottom
- nNewTop
+ 1 ) * fScale
);
374 Polygon
aOriginPoly( 1 );
376 aOriginPoly
[ 0 ] = rPt
;
377 aOriginPoly
.Rotate( aOldOrigin
, nRot10
);
378 rPt
= aOriginPoly
[ 0 ];
388 // -----------------------------------------------------------------------------
390 GraphicObject
& GraphicObject::operator=( const GraphicObject
& rGraphicObj
)
392 if( &rGraphicObj
!= this )
394 mpMgr
->ImplUnregisterObj( *this );
396 delete mpSwapStreamHdl
, mpSwapStreamHdl
= NULL
;
397 delete mpSimpleCache
, mpSimpleCache
= NULL
;
401 maGraphic
= rGraphicObj
.GetGraphic();
402 maAttr
= rGraphicObj
.maAttr
;
403 mpLink
= rGraphicObj
.mpLink
? new String( *rGraphicObj
.mpLink
) : NULL
;
404 mpUserData
= rGraphicObj
.mpUserData
? new String( *rGraphicObj
.mpUserData
) : NULL
;
405 ImplAssignGraphicData();
406 mbAutoSwapped
= FALSE
;
407 mpMgr
= rGraphicObj
.mpMgr
;
409 mpMgr
->ImplRegisterObj( *this, maGraphic
, NULL
, &rGraphicObj
);
415 // -----------------------------------------------------------------------------
417 BOOL
GraphicObject::operator==( const GraphicObject
& rGraphicObj
) const
419 return( ( rGraphicObj
.maGraphic
== maGraphic
) &&
420 ( rGraphicObj
.maAttr
== maAttr
) &&
421 ( rGraphicObj
.GetLink() == GetLink() ) );
424 // ------------------------------------------------------------------------
426 void GraphicObject::Load( SvStream
& rIStm
)
431 // ------------------------------------------------------------------------
433 void GraphicObject::Save( SvStream
& rOStm
)
438 // ------------------------------------------------------------------------
440 void GraphicObject::Assign( const SvDataCopyStream
& rCopyStream
)
442 *this = (const GraphicObject
& ) rCopyStream
;
445 // -----------------------------------------------------------------------------
447 ByteString
GraphicObject::GetUniqueID() const
449 if ( !IsInSwapIn() && IsEPS() )
450 const_cast<GraphicObject
*>(this)->FireSwapInRequest();
455 aRet
= mpMgr
->ImplGetUniqueID( *this );
460 // -----------------------------------------------------------------------------
462 ULONG
GraphicObject::GetChecksum() const
464 return( ( maGraphic
.IsSupportedGraphic() && !maGraphic
.IsSwapOut() ) ? maGraphic
.GetChecksum() : 0 );
467 // -----------------------------------------------------------------------------
469 SvStream
* GraphicObject::GetSwapStream() const
471 return( HasSwapStreamHdl() ? (SvStream
*) mpSwapStreamHdl
->Call( (void*) this ) : GRFMGR_AUTOSWAPSTREAM_NONE
);
474 // -----------------------------------------------------------------------------
477 ULONG
GraphicObject::GetReleaseFromCache() const
482 // -----------------------------------------------------------------------------
484 void GraphicObject::SetAttr( const GraphicAttr
& rAttr
)
488 if( mpSimpleCache
&& ( mpSimpleCache
->maAttr
!= rAttr
) )
489 delete mpSimpleCache
, mpSimpleCache
= NULL
;
492 // -----------------------------------------------------------------------------
494 void GraphicObject::SetLink()
497 delete mpLink
, mpLink
= NULL
;
500 // -----------------------------------------------------------------------------
502 void GraphicObject::SetLink( const String
& rLink
)
504 delete mpLink
, mpLink
= new String( rLink
);
507 // -----------------------------------------------------------------------------
509 String
GraphicObject::GetLink() const
517 // -----------------------------------------------------------------------------
519 void GraphicObject::SetUserData()
522 delete mpUserData
, mpUserData
= NULL
;
525 // -----------------------------------------------------------------------------
527 void GraphicObject::SetUserData( const String
& rUserData
)
529 delete mpUserData
, mpUserData
= new String( rUserData
);
532 // -----------------------------------------------------------------------------
534 String
GraphicObject::GetUserData() const
542 // -----------------------------------------------------------------------------
544 void GraphicObject::SetSwapStreamHdl()
546 if( mpSwapStreamHdl
)
548 delete mpSwapOutTimer
, mpSwapOutTimer
= NULL
;
549 delete mpSwapStreamHdl
, mpSwapStreamHdl
= NULL
;
553 // -----------------------------------------------------------------------------
555 void GraphicObject::SetSwapStreamHdl( const Link
& rHdl
, const ULONG nSwapOutTimeout
)
557 delete mpSwapStreamHdl
, mpSwapStreamHdl
= new Link( rHdl
);
559 if( nSwapOutTimeout
)
561 if( !mpSwapOutTimer
)
563 mpSwapOutTimer
= new Timer
;
564 mpSwapOutTimer
->SetTimeoutHdl( LINK( this, GraphicObject
, ImplAutoSwapOutHdl
) );
567 mpSwapOutTimer
->SetTimeout( nSwapOutTimeout
);
568 mpSwapOutTimer
->Start();
571 delete mpSwapOutTimer
, mpSwapOutTimer
= NULL
;
574 // -----------------------------------------------------------------------------
576 Link
GraphicObject::GetSwapStreamHdl() const
578 if( mpSwapStreamHdl
)
579 return *mpSwapStreamHdl
;
584 // -----------------------------------------------------------------------------
586 void GraphicObject::FireSwapInRequest()
591 // -----------------------------------------------------------------------------
593 void GraphicObject::FireSwapOutRequest()
595 ImplAutoSwapOutHdl( NULL
);
598 // -----------------------------------------------------------------------------
600 void GraphicObject::GraphicManagerDestroyed()
602 // we're alive, but our manager doesn't live anymore ==> connect to default manager
604 ImplSetGraphicManager( NULL
);
607 // -----------------------------------------------------------------------------
609 void GraphicObject::SetGraphicManager( const GraphicManager
& rMgr
)
611 ImplSetGraphicManager( &rMgr
);
614 // -----------------------------------------------------------------------------
616 BOOL
GraphicObject::IsCached( OutputDevice
* pOut
, const Point
& rPt
, const Size
& rSz
,
617 const GraphicAttr
* pAttr
, ULONG nFlags
) const
621 if( nFlags
& GRFMGR_DRAW_CACHED
)
623 // --> OD 2005-10-11 #i54875# - Consider cropped graphics.
624 // Note: The graphic manager caches a cropped graphic with its
625 // uncropped position and size.
626 // bRet = mpMgr->IsInCache( pOut, rPt, rSz, *this, ( pAttr ? *pAttr : GetAttr() ) );
629 if ( pAttr
->IsCropped() )
631 PolyPolygon aClipPolyPoly
;
633 ImplGetCropParams( pOut
, aPt
, aSz
, pAttr
, aClipPolyPoly
, bRectClip
);
635 bRet
= mpMgr
->IsInCache( pOut
, aPt
, aSz
, *this, ( pAttr
? *pAttr
: GetAttr() ) );
643 // -----------------------------------------------------------------------------
645 void GraphicObject::ReleaseFromCache()
648 mpMgr
->ReleaseFromCache( *this );
651 // -----------------------------------------------------------------------------
653 void GraphicObject::SetAnimationNotifyHdl( const Link
& rLink
)
655 maGraphic
.SetAnimationNotifyHdl( rLink
);
658 // -----------------------------------------------------------------------------
660 List
* GraphicObject::GetAnimationInfoList() const
662 return maGraphic
.GetAnimationInfoList();
665 // -----------------------------------------------------------------------------
667 BOOL
GraphicObject::Draw( OutputDevice
* pOut
, const Point
& rPt
, const Size
& rSz
,
668 const GraphicAttr
* pAttr
, ULONG nFlags
)
670 GraphicAttr
aAttr( pAttr
? *pAttr
: GetAttr() );
673 const sal_uInt32 nOldDrawMode
= pOut
->GetDrawMode();
674 BOOL bCropped
= aAttr
.IsCropped();
675 BOOL bCached
= FALSE
;
678 // #i29534# Provide output rects for PDF writer
681 if( !( GRFMGR_DRAW_USE_DRAWMODE_SETTINGS
& nFlags
) )
682 pOut
->SetDrawMode( nOldDrawMode
& ( ~( DRAWMODE_SETTINGSLINE
| DRAWMODE_SETTINGSFILL
| DRAWMODE_SETTINGSTEXT
| DRAWMODE_SETTINGSGRADIENT
) ) );
684 // mirrored horizontically
685 if( aSz
.Width() < 0L )
687 aPt
.X() += aSz
.Width() + 1;
688 aSz
.Width() = -aSz
.Width();
689 aAttr
.SetMirrorFlags( aAttr
.GetMirrorFlags() ^ BMP_MIRROR_HORZ
);
692 // mirrored vertically
693 if( aSz
.Height() < 0L )
695 aPt
.Y() += aSz
.Height() + 1;
696 aSz
.Height() = -aSz
.Height();
697 aAttr
.SetMirrorFlags( aAttr
.GetMirrorFlags() ^ BMP_MIRROR_VERT
);
702 PolyPolygon aClipPolyPoly
;
704 const BOOL bCrop
= ImplGetCropParams( pOut
, aPt
, aSz
, &aAttr
, aClipPolyPoly
, bRectClip
);
706 pOut
->Push( PUSH_CLIPREGION
);
712 // #i29534# Store crop rect for later forwarding to
714 aCropRect
= aClipPolyPoly
.GetBoundRect();
715 pOut
->IntersectClipRegion( aCropRect
);
719 pOut
->IntersectClipRegion( aClipPolyPoly
);
724 bRet
= mpMgr
->DrawObj( pOut
, aPt
, aSz
, *this, aAttr
, nFlags
, bCached
);
729 pOut
->SetDrawMode( nOldDrawMode
);
731 // #i29534# Moved below OutDev restoration, to avoid multiple swap-ins
732 // (code above needs to call GetGraphic twice)
736 mpSwapOutTimer
->Start();
738 FireSwapOutRequest();
744 // -----------------------------------------------------------------------------
746 BOOL
GraphicObject::DrawTiled( OutputDevice
* pOut
, const Rectangle
& rArea
, const Size
& rSize
,
747 const Size
& rOffset
, const GraphicAttr
* pAttr
, ULONG nFlags
, int nTileCacheSize1D
)
749 if( pOut
== NULL
|| rSize
.Width() == 0 || rSize
.Height() == 0 )
752 const MapMode
aOutMapMode( pOut
->GetMapMode() );
753 const MapMode
aMapMode( aOutMapMode
.GetMapUnit(), Point(), aOutMapMode
.GetScaleX(), aOutMapMode
.GetScaleY() );
754 // #106258# Clamp size to 1 for zero values. This is okay, since
755 // logical size of zero is handled above already
756 const Size
aOutTileSize( ::std::max( 1L, pOut
->LogicToPixel( rSize
, aOutMapMode
).Width() ),
757 ::std::max( 1L, pOut
->LogicToPixel( rSize
, aOutMapMode
).Height() ) );
759 //#i69780 clip final tile size to a sane max size
760 while (((sal_Int64
)rSize
.Width() * nTileCacheSize1D
) > SAL_MAX_UINT16
)
761 nTileCacheSize1D
/= 2;
762 while (((sal_Int64
)rSize
.Height() * nTileCacheSize1D
) > SAL_MAX_UINT16
)
763 nTileCacheSize1D
/= 2;
765 return ImplDrawTiled( pOut
, rArea
, aOutTileSize
, rOffset
, pAttr
, nFlags
, nTileCacheSize1D
);
768 // -----------------------------------------------------------------------------
770 BOOL
GraphicObject::StartAnimation( OutputDevice
* pOut
, const Point
& rPt
, const Size
& rSz
,
771 long nExtraData
, const GraphicAttr
* pAttr
, ULONG
/*nFlags*/,
772 OutputDevice
* pFirstFrameOutDev
)
778 if( !IsSwappedOut() )
780 const GraphicAttr
aAttr( pAttr
? *pAttr
: GetAttr() );
786 BOOL bCropped
= aAttr
.IsCropped();
790 PolyPolygon aClipPolyPoly
;
792 const BOOL bCrop
= ImplGetCropParams( pOut
, aPt
, aSz
, &aAttr
, aClipPolyPoly
, bRectClip
);
794 pOut
->Push( PUSH_CLIPREGION
);
799 pOut
->IntersectClipRegion( aClipPolyPoly
.GetBoundRect() );
801 pOut
->IntersectClipRegion( aClipPolyPoly
);
805 if( !mpSimpleCache
|| ( mpSimpleCache
->maAttr
!= aAttr
) || pFirstFrameOutDev
)
808 delete mpSimpleCache
;
810 mpSimpleCache
= new GrfSimpleCacheObj( GetTransformedGraphic( &aAttr
), aAttr
);
811 mpSimpleCache
->maGraphic
.SetAnimationNotifyHdl( GetAnimationNotifyHdl() );
814 mpSimpleCache
->maGraphic
.StartAnimation( pOut
, aPt
, aSz
, nExtraData
, pFirstFrameOutDev
);
822 bRet
= Draw( pOut
, rPt
, rSz
, &aAttr
, GRFMGR_DRAW_STANDARD
);
828 // -----------------------------------------------------------------------------
830 void GraphicObject::StopAnimation( OutputDevice
* pOut
, long nExtraData
)
833 mpSimpleCache
->maGraphic
.StopAnimation( pOut
, nExtraData
);
836 // -----------------------------------------------------------------------------
838 const Graphic
& GraphicObject::GetGraphic() const
841 ( (GraphicObject
*) this )->ImplAutoSwapIn();
846 // -----------------------------------------------------------------------------
848 void GraphicObject::SetGraphic( const Graphic
& rGraphic
)
850 mpMgr
->ImplUnregisterObj( *this );
853 mpSwapOutTimer
->Stop();
855 maGraphic
= rGraphic
;
856 mbAutoSwapped
= FALSE
;
857 ImplAssignGraphicData();
858 delete mpLink
, mpLink
= NULL
;
859 delete mpSimpleCache
, mpSimpleCache
= NULL
;
861 mpMgr
->ImplRegisterObj( *this, maGraphic
);
864 mpSwapOutTimer
->Start();
867 // -----------------------------------------------------------------------------
869 void GraphicObject::SetGraphic( const Graphic
& rGraphic
, const String
& rLink
)
871 SetGraphic( rGraphic
);
872 mpLink
= new String( rLink
);
875 // -----------------------------------------------------------------------------
877 Graphic
GraphicObject::GetTransformedGraphic( const Size
& rDestSize
, const MapMode
& rDestMap
, const GraphicAttr
& rAttr
) const
879 // #104550# Extracted from svx/source/svdraw/svdograf.cxx
880 Graphic
aTransGraphic( maGraphic
);
881 const GraphicType eType
= GetType();
882 const Size
aSrcSize( aTransGraphic
.GetPrefSize() );
884 // #104115# Convert the crop margins to graphic object mapmode
885 const MapMode
aMapGraph( aTransGraphic
.GetPrefMapMode() );
886 const MapMode
aMap100( MAP_100TH_MM
);
889 Size aCropRightBottom
;
891 if( GRAPHIC_GDIMETAFILE
== eType
)
893 GDIMetaFile
aMtf( aTransGraphic
.GetGDIMetaFile() );
895 if( aMapGraph
== MAP_PIXEL
)
897 aCropLeftTop
= Application::GetDefaultDevice()->LogicToPixel( Size( rAttr
.GetLeftCrop(),
898 rAttr
.GetTopCrop() ),
900 aCropRightBottom
= Application::GetDefaultDevice()->LogicToPixel( Size( rAttr
.GetRightCrop(),
901 rAttr
.GetBottomCrop() ),
906 aCropLeftTop
= OutputDevice::LogicToLogic( Size( rAttr
.GetLeftCrop(),
907 rAttr
.GetTopCrop() ),
910 aCropRightBottom
= OutputDevice::LogicToLogic( Size( rAttr
.GetRightCrop(),
911 rAttr
.GetBottomCrop() ),
916 // #104115# If the metafile is cropped, give it a special
917 // treatment: clip against the remaining area, scale up such
918 // that this area later fills the desired size, and move the
919 // origin to the upper left edge of that area.
920 if( rAttr
.IsCropped() )
922 const MapMode
aMtfMapMode( aMtf
.GetPrefMapMode() );
924 Rectangle
aClipRect( aMtfMapMode
.GetOrigin().X() + aCropLeftTop
.Width(),
925 aMtfMapMode
.GetOrigin().Y() + aCropLeftTop
.Height(),
926 aMtfMapMode
.GetOrigin().X() + aSrcSize
.Width() - aCropRightBottom
.Width(),
927 aMtfMapMode
.GetOrigin().Y() + aSrcSize
.Height() - aCropRightBottom
.Height() );
929 // #104115# To correctly crop rotated metafiles, clip by view rectangle
930 aMtf
.AddAction( new MetaISectRectClipRegionAction( aClipRect
), 0 );
932 // #104115# To crop the metafile, scale larger than the output rectangle
933 aMtf
.Scale( (double)rDestSize
.Width() / (aSrcSize
.Width() - aCropLeftTop
.Width() - aCropRightBottom
.Width()),
934 (double)rDestSize
.Height() / (aSrcSize
.Height() - aCropLeftTop
.Height() - aCropRightBottom
.Height()) );
936 // #104115# Adapt the pref size by hand (scale changes it
937 // proportionally, but we want it to be smaller than the
938 // former size, to crop the excess out)
939 aMtf
.SetPrefSize( Size( (long)((double)rDestSize
.Width() * (1.0 + (aCropLeftTop
.Width() + aCropRightBottom
.Width()) / aSrcSize
.Width()) + .5),
940 (long)((double)rDestSize
.Height() * (1.0 + (aCropLeftTop
.Height() + aCropRightBottom
.Height()) / aSrcSize
.Height()) + .5) ) );
942 // #104115# Adapt the origin of the new mapmode, such that it
943 // is shifted to the place where the cropped output starts
944 Point
aNewOrigin( (long)((double)aMtfMapMode
.GetOrigin().X() + rDestSize
.Width() * aCropLeftTop
.Width() / (aSrcSize
.Width() - aCropLeftTop
.Width() - aCropRightBottom
.Width()) + .5),
945 (long)((double)aMtfMapMode
.GetOrigin().Y() + rDestSize
.Height() * aCropLeftTop
.Height() / (aSrcSize
.Height() - aCropLeftTop
.Height() - aCropRightBottom
.Height()) + .5) );
946 MapMode
aNewMap( rDestMap
);
947 aNewMap
.SetOrigin( OutputDevice::LogicToLogic(aNewOrigin
, aMtfMapMode
, rDestMap
) );
948 aMtf
.SetPrefMapMode( aNewMap
);
952 aMtf
.Scale( Fraction( rDestSize
.Width(), aSrcSize
.Width() ), Fraction( rDestSize
.Height(), aSrcSize
.Height() ) );
953 aMtf
.SetPrefMapMode( rDestMap
);
956 aTransGraphic
= aMtf
;
958 else if( GRAPHIC_BITMAP
== eType
)
960 BitmapEx
aBitmapEx( aTransGraphic
.GetBitmapEx() );
962 // convert crops to pixel
963 aCropLeftTop
= Application::GetDefaultDevice()->LogicToPixel( Size( rAttr
.GetLeftCrop(),
964 rAttr
.GetTopCrop() ),
966 aCropRightBottom
= Application::GetDefaultDevice()->LogicToPixel( Size( rAttr
.GetRightCrop(),
967 rAttr
.GetBottomCrop() ),
970 // convert from prefmapmode to pixel
971 const Size
aSrcSizePixel( Application::GetDefaultDevice()->LogicToPixel( aSrcSize
,
974 // setup crop rectangle in pixel
975 Rectangle
aCropRect( aCropLeftTop
.Width(), aCropLeftTop
.Height(),
976 aSrcSizePixel
.Width() - aCropRightBottom
.Width(),
977 aSrcSizePixel
.Height() - aCropRightBottom
.Height() );
979 // #105641# Also crop animations
980 if( aTransGraphic
.IsAnimated() )
983 Animation
aAnim( aTransGraphic
.GetAnimation() );
985 for( nFrame
=0; nFrame
<aAnim
.Count(); ++nFrame
)
987 AnimationBitmap
aAnimBmp( aAnim
.Get( nFrame
) );
989 if( !aCropRect
.IsInside( Rectangle(aAnimBmp
.aPosPix
, aAnimBmp
.aSizePix
) ) )
991 // setup actual cropping (relative to frame position)
992 Rectangle
aCropRectRel( aCropRect
);
993 aCropRectRel
.Move( -aAnimBmp
.aPosPix
.X(),
994 -aAnimBmp
.aPosPix
.Y() );
996 // cropping affects this frame, apply it then
997 // do _not_ apply enlargement, this is done below
998 ImplTransformBitmap( aAnimBmp
.aBmpEx
, rAttr
, Size(), Size(),
999 aCropRectRel
, rDestSize
, FALSE
);
1001 aAnim
.Replace( aAnimBmp
, nFrame
);
1003 // else: bitmap completely within crop area,
1004 // i.e. nothing is cropped away
1007 // now, apply enlargement (if any) through global animation size
1008 if( aCropLeftTop
.Width() < 0 ||
1009 aCropLeftTop
.Height() < 0 ||
1010 aCropRightBottom
.Width() < 0 ||
1011 aCropRightBottom
.Height() < 0 )
1013 Size
aNewSize( aAnim
.GetDisplaySizePixel() );
1014 aNewSize
.Width() += aCropRightBottom
.Width() < 0 ? -aCropRightBottom
.Width() : 0;
1015 aNewSize
.Width() += aCropLeftTop
.Width() < 0 ? -aCropLeftTop
.Width() : 0;
1016 aNewSize
.Height() += aCropRightBottom
.Height() < 0 ? -aCropRightBottom
.Height() : 0;
1017 aNewSize
.Height() += aCropLeftTop
.Height() < 0 ? -aCropLeftTop
.Height() : 0;
1018 aAnim
.SetDisplaySizePixel( aNewSize
);
1021 // if topleft has changed, we must move all frames to the
1022 // right and bottom, resp.
1023 if( aCropLeftTop
.Width() < 0 ||
1024 aCropLeftTop
.Height() < 0 )
1026 Point
aPosOffset( aCropLeftTop
.Width() < 0 ? -aCropLeftTop
.Width() : 0,
1027 aCropLeftTop
.Height() < 0 ? -aCropLeftTop
.Height() : 0 );
1029 for( nFrame
=0; nFrame
<aAnim
.Count(); ++nFrame
)
1031 AnimationBitmap
aAnimBmp( aAnim
.Get( nFrame
) );
1033 aAnimBmp
.aPosPix
+= aPosOffset
;
1035 aAnim
.Replace( aAnimBmp
, nFrame
);
1039 aTransGraphic
= aAnim
;
1043 BitmapEx
aBmpEx( aTransGraphic
.GetBitmapEx() );
1045 ImplTransformBitmap( aBmpEx
, rAttr
, aCropLeftTop
, aCropRightBottom
,
1046 aCropRect
, rDestSize
, TRUE
);
1048 aTransGraphic
= aBmpEx
;
1051 aTransGraphic
.SetPrefSize( rDestSize
);
1052 aTransGraphic
.SetPrefMapMode( rDestMap
);
1055 GraphicObject
aGrfObj( aTransGraphic
);
1056 aTransGraphic
= aGrfObj
.GetTransformedGraphic( &rAttr
);
1058 return aTransGraphic
;
1061 // -----------------------------------------------------------------------------
1063 Graphic
GraphicObject::GetTransformedGraphic( const GraphicAttr
* pAttr
) const // TODO: Change to Impl
1068 GraphicAttr
aAttr( pAttr
? *pAttr
: GetAttr() );
1070 if( maGraphic
.IsSupportedGraphic() && !maGraphic
.IsSwapOut() )
1072 if( aAttr
.IsSpecialDrawMode() || aAttr
.IsAdjusted() || aAttr
.IsMirrored() || aAttr
.IsRotated() || aAttr
.IsTransparent() )
1074 if( GetType() == GRAPHIC_BITMAP
)
1078 Animation
aAnimation( maGraphic
.GetAnimation() );
1079 GraphicManager::ImplAdjust( aAnimation
, aAttr
, ADJUSTMENT_ALL
);
1080 aAnimation
.SetLoopCount( mnAnimationLoopCount
);
1081 aGraphic
= aAnimation
;
1085 BitmapEx
aBmpEx( maGraphic
.GetBitmapEx() );
1086 GraphicManager::ImplAdjust( aBmpEx
, aAttr
, ADJUSTMENT_ALL
);
1092 GDIMetaFile
aMtf( maGraphic
.GetGDIMetaFile() );
1093 GraphicManager::ImplAdjust( aMtf
, aAttr
, ADJUSTMENT_ALL
);
1099 if( ( GetType() == GRAPHIC_BITMAP
) && IsAnimated() )
1101 Animation
aAnimation( maGraphic
.GetAnimation() );
1102 aAnimation
.SetLoopCount( mnAnimationLoopCount
);
1103 aGraphic
= aAnimation
;
1106 aGraphic
= maGraphic
;
1113 // -----------------------------------------------------------------------------
1115 void GraphicObject::ResetAnimationLoopCount()
1117 if( IsAnimated() && !IsSwappedOut() )
1119 maGraphic
.ResetAnimationLoopCount();
1122 mpSimpleCache
->maGraphic
.ResetAnimationLoopCount();
1126 // -----------------------------------------------------------------------------
1128 BOOL
GraphicObject::SwapOut()
1130 BOOL bRet
= ( !mbAutoSwapped
? maGraphic
.SwapOut() : FALSE
);
1133 mpMgr
->ImplGraphicObjectWasSwappedOut( *this );
1138 // -----------------------------------------------------------------------------
1140 BOOL
GraphicObject::SwapOut( SvStream
* pOStm
)
1142 BOOL bRet
= ( !mbAutoSwapped
? maGraphic
.SwapOut( pOStm
) : FALSE
);
1145 mpMgr
->ImplGraphicObjectWasSwappedOut( *this );
1150 // -----------------------------------------------------------------------------
1152 BOOL
GraphicObject::SwapIn()
1161 else if( mpMgr
&& mpMgr
->ImplFillSwappedGraphicObject( *this, maGraphic
) )
1165 bRet
= maGraphic
.SwapIn();
1168 mpMgr
->ImplGraphicObjectWasSwappedIn( *this );
1172 ImplAssignGraphicData();
1177 // -----------------------------------------------------------------------------
1179 BOOL
GraphicObject::SwapIn( SvStream
* pIStm
)
1188 else if( mpMgr
&& mpMgr
->ImplFillSwappedGraphicObject( *this, maGraphic
) )
1192 bRet
= maGraphic
.SwapIn( pIStm
);
1195 mpMgr
->ImplGraphicObjectWasSwappedIn( *this );
1199 ImplAssignGraphicData();
1204 // -----------------------------------------------------------------------------
1206 void GraphicObject::SetSwapState()
1208 if( !IsSwappedOut() )
1210 mbAutoSwapped
= TRUE
;
1213 mpMgr
->ImplGraphicObjectWasSwappedOut( *this );
1217 // -----------------------------------------------------------------------------
1219 IMPL_LINK( GraphicObject
, ImplAutoSwapOutHdl
, void*, EMPTYARG
)
1221 if( !IsSwappedOut() )
1223 mbIsInSwapOut
= TRUE
;
1225 SvStream
* pStream
= GetSwapStream();
1227 if( GRFMGR_AUTOSWAPSTREAM_NONE
!= pStream
)
1229 if( GRFMGR_AUTOSWAPSTREAM_LINK
== pStream
)
1230 mbAutoSwapped
= SwapOut( NULL
);
1233 if( GRFMGR_AUTOSWAPSTREAM_TEMP
== pStream
)
1234 mbAutoSwapped
= SwapOut();
1237 mbAutoSwapped
= SwapOut( pStream
);
1243 mbIsInSwapOut
= FALSE
;
1246 if( mpSwapOutTimer
)
1247 mpSwapOutTimer
->Start();
1252 // ------------------------------------------------------------------------
1254 SvStream
& operator>>( SvStream
& rIStm
, GraphicObject
& rGraphicObj
)
1256 VersionCompat
aCompat( rIStm
, STREAM_READ
);
1262 rIStm
>> aGraphic
>> aAttr
>> bLink
;
1264 rGraphicObj
.SetGraphic( aGraphic
);
1265 rGraphicObj
.SetAttr( aAttr
);
1270 rGraphicObj
.SetLink( UniString( aLink
, RTL_TEXTENCODING_UTF8
) );
1273 rGraphicObj
.SetLink();
1275 rGraphicObj
.SetSwapStreamHdl();
1280 // ------------------------------------------------------------------------
1282 SvStream
& operator<<( SvStream
& rOStm
, const GraphicObject
& rGraphicObj
)
1284 VersionCompat
aCompat( rOStm
, STREAM_WRITE
, 1 );
1285 const BOOL bLink
= rGraphicObj
.HasLink();
1287 rOStm
<< rGraphicObj
.GetGraphic() << rGraphicObj
.GetAttr() << bLink
;
1290 rOStm
<< ByteString( rGraphicObj
.GetLink(), RTL_TEXTENCODING_UTF8
);