merge the formfield patch from ooo-build
[ooovba.git] / goodies / source / graphic / grfmgr.cxx
blobbd9dd3c7ced1cceca7fd8d38087d00b9325a7540
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: grfmgr.cxx,v $
10 * $Revision: 1.36 $
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
36 #include <algorithm>
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>
48 #include "grfmgr.hxx"
50 // -----------
51 // - Defines -
52 // -----------
54 #define WATERMARK_LUM_OFFSET 50
55 #define WATERMARK_CON_OFFSET -70
57 // -----------
58 // - statics -
59 // -----------
61 GraphicManager* GraphicObject::mpGlobalMgr = NULL;
63 // ---------------------
64 // - GrfDirectCacheObj -
65 // ---------------------
67 struct GrfSimpleCacheObj
69 Graphic maGraphic;
70 GraphicAttr maAttr;
72 GrfSimpleCacheObj( const Graphic& rGraphic, const GraphicAttr& rAttr ) :
73 maGraphic( rGraphic ), maAttr( rAttr ) {}
76 // -----------------
77 // - GraphicObject -
78 // -----------------
80 TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream );
82 // -----------------------------------------------------------------------------
84 GraphicObject::GraphicObject( const GraphicManager* pMgr ) :
85 mpLink ( NULL ),
86 mpUserData ( NULL )
88 ImplConstruct();
89 ImplAssignGraphicData();
90 ImplSetGraphicManager( pMgr );
93 // -----------------------------------------------------------------------------
95 GraphicObject::GraphicObject( const Graphic& rGraphic, const GraphicManager* pMgr ) :
96 maGraphic ( rGraphic ),
97 mpLink ( NULL ),
98 mpUserData ( NULL )
100 ImplConstruct();
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 ),
110 mpUserData ( NULL )
112 ImplConstruct();
113 ImplAssignGraphicData();
114 ImplSetGraphicManager( pMgr );
117 // -----------------------------------------------------------------------------
119 GraphicObject::GraphicObject( const GraphicObject& rGraphicObj, const GraphicManager* pMgr ) :
120 SvDataCopyStream(),
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 )
126 ImplConstruct();
127 ImplAssignGraphicData();
128 ImplSetGraphicManager( pMgr, NULL, &rGraphicObj );
131 // -----------------------------------------------------------------------------
133 GraphicObject::GraphicObject( const ByteString& rUniqueID, const GraphicManager* pMgr ) :
134 mpLink ( NULL ),
135 mpUserData ( NULL )
137 ImplConstruct();
139 // assign default properties
140 ImplAssignGraphicData();
142 ImplSetGraphicManager( pMgr, &rUniqueID );
144 // update properties
145 ImplAssignGraphicData();
148 // -----------------------------------------------------------------------------
150 GraphicObject::~GraphicObject()
152 if( mpMgr )
154 mpMgr->ImplUnregisterObj( *this );
156 if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() )
157 delete mpGlobalMgr, mpGlobalMgr = NULL;
160 delete mpSwapOutTimer;
161 delete mpSwapStreamHdl;
162 delete mpLink;
163 delete mpUserData;
164 delete mpSimpleCache;
167 // -----------------------------------------------------------------------------
169 void GraphicObject::ImplConstruct()
171 mpMgr = NULL;
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() );
199 else
200 mbEPS = FALSE;
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 ) )
210 return;
211 else
213 if( mpMgr )
215 mpMgr->ImplUnregisterObj( *this );
217 if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() )
218 delete mpGlobalMgr, mpGlobalMgr = NULL;
221 if( !pMgr )
223 if( !mpGlobalMgr )
225 SvtCacheOptions aCacheOptions;
227 mpGlobalMgr = new GraphicManager( aCacheOptions.GetGraphicManagerTotalCacheSize(),
228 aCacheOptions.GetGraphicManagerObjectCacheSize() );
229 mpGlobalMgr->SetCacheTimeout( aCacheOptions.GetGraphicManagerObjectReleaseTime() );
232 mpMgr = mpGlobalMgr;
234 else
235 mpMgr = (GraphicManager*) pMgr;
237 mpMgr->ImplRegisterObj( *this, maGraphic, pID, pCopyObj );
242 // -----------------------------------------------------------------------------
244 void GraphicObject::ImplAutoSwapIn()
246 if( IsSwappedOut() )
248 if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
249 mbAutoSwapped = FALSE;
250 else
252 mbIsInSwapIn = TRUE;
254 if( maGraphic.SwapIn() )
255 mbAutoSwapped = FALSE;
256 else
258 SvStream* pStream = GetSwapStream();
260 if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
262 if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
264 if( HasLink() )
266 String aURLStr;
268 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( GetLink(), aURLStr ) )
270 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aURLStr, STREAM_READ );
272 if( pIStm )
274 (*pIStm) >> maGraphic;
275 mbAutoSwapped = ( maGraphic.GetType() != GRAPHIC_NONE );
276 delete pIStm;
281 else if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
282 mbAutoSwapped = !maGraphic.SwapIn();
283 else if( GRFMGR_AUTOSWAPSTREAM_LOADED == pStream )
284 mbAutoSwapped = maGraphic.IsSwapOut();
285 else
287 mbAutoSwapped = !maGraphic.SwapIn( pStream );
288 delete pStream;
291 else
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
310 BOOL bRet = FALSE;
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();
319 // <--
320 const MapMode aMap100( MAP_100TH_MM );
321 Size aSize100;
322 long nTotalWidth, nTotalHeight;
323 long nNewLeft, nNewTop, nNewRight, nNewBottom;
324 double fScale;
326 if( nRot10 )
328 aClipPoly.Rotate( rPt, nRot10 );
329 bRectClipRegion = FALSE;
331 else
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 );
340 // else
341 // aSize100 = pOut->LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), aMap100 );
342 if( maGraphic.GetPrefMapMode() == MAP_PIXEL )
343 aSize100 = Application::GetDefaultDevice()->PixelToLogic( maGraphic.GetPrefSize(), aMap100 );
344 else
346 MapMode m(maGraphic.GetPrefMapMode());
347 aSize100 = pOut->LogicToLogic( maGraphic.GetPrefSize(), &m, &aMap100 );
349 // <--
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 );
372 if( nRot10 )
374 Polygon aOriginPoly( 1 );
376 aOriginPoly[ 0 ] = rPt;
377 aOriginPoly.Rotate( aOldOrigin, nRot10 );
378 rPt = aOriginPoly[ 0 ];
381 bRet = TRUE;
385 return bRet;
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;
398 delete mpLink;
399 delete mpUserData;
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 );
412 return *this;
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 )
428 rIStm >> *this;
431 // ------------------------------------------------------------------------
433 void GraphicObject::Save( SvStream& rOStm )
435 rOStm << *this;
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();
452 ByteString aRet;
454 if( mpMgr )
455 aRet = mpMgr->ImplGetUniqueID( *this );
457 return aRet;
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 // -----------------------------------------------------------------------------
476 // !!! to be removed
477 ULONG GraphicObject::GetReleaseFromCache() const
479 return 0;
482 // -----------------------------------------------------------------------------
484 void GraphicObject::SetAttr( const GraphicAttr& rAttr )
486 maAttr = rAttr;
488 if( mpSimpleCache && ( mpSimpleCache->maAttr != rAttr ) )
489 delete mpSimpleCache, mpSimpleCache = NULL;
492 // -----------------------------------------------------------------------------
494 void GraphicObject::SetLink()
496 if( mpLink )
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
511 if( mpLink )
512 return *mpLink;
513 else
514 return String();
517 // -----------------------------------------------------------------------------
519 void GraphicObject::SetUserData()
521 if( mpUserData )
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
536 if( mpUserData )
537 return *mpUserData;
538 else
539 return String();
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();
570 else
571 delete mpSwapOutTimer, mpSwapOutTimer = NULL;
574 // -----------------------------------------------------------------------------
576 Link GraphicObject::GetSwapStreamHdl() const
578 if( mpSwapStreamHdl )
579 return *mpSwapStreamHdl;
580 else
581 return Link();
584 // -----------------------------------------------------------------------------
586 void GraphicObject::FireSwapInRequest()
588 ImplAutoSwapIn();
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
603 mpMgr = NULL;
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
619 BOOL bRet;
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() ) );
627 Point aPt( rPt );
628 Size aSz( rSz );
629 if ( pAttr->IsCropped() )
631 PolyPolygon aClipPolyPoly;
632 BOOL bRectClip;
633 ImplGetCropParams( pOut, aPt, aSz, pAttr, aClipPolyPoly, bRectClip );
635 bRet = mpMgr->IsInCache( pOut, aPt, aSz, *this, ( pAttr ? *pAttr : GetAttr() ) );
637 else
638 bRet = FALSE;
640 return bRet;
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() );
671 Point aPt( rPt );
672 Size aSz( rSz );
673 const sal_uInt32 nOldDrawMode = pOut->GetDrawMode();
674 BOOL bCropped = aAttr.IsCropped();
675 BOOL bCached = FALSE;
676 BOOL bRet;
678 // #i29534# Provide output rects for PDF writer
679 Rectangle aCropRect;
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 );
700 if( bCropped )
702 PolyPolygon aClipPolyPoly;
703 BOOL bRectClip;
704 const BOOL bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
706 pOut->Push( PUSH_CLIPREGION );
708 if( bCrop )
710 if( bRectClip )
712 // #i29534# Store crop rect for later forwarding to
713 // PDF writer
714 aCropRect = aClipPolyPoly.GetBoundRect();
715 pOut->IntersectClipRegion( aCropRect );
717 else
719 pOut->IntersectClipRegion( aClipPolyPoly );
724 bRet = mpMgr->DrawObj( pOut, aPt, aSz, *this, aAttr, nFlags, bCached );
726 if( bCropped )
727 pOut->Pop();
729 pOut->SetDrawMode( nOldDrawMode );
731 // #i29534# Moved below OutDev restoration, to avoid multiple swap-ins
732 // (code above needs to call GetGraphic twice)
733 if( bCached )
735 if( mpSwapOutTimer )
736 mpSwapOutTimer->Start();
737 else
738 FireSwapOutRequest();
741 return bRet;
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 )
750 return FALSE;
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 )
774 BOOL bRet = FALSE;
776 GetGraphic();
778 if( !IsSwappedOut() )
780 const GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
782 if( mbAnimated )
784 Point aPt( rPt );
785 Size aSz( rSz );
786 BOOL bCropped = aAttr.IsCropped();
788 if( bCropped )
790 PolyPolygon aClipPolyPoly;
791 BOOL bRectClip;
792 const BOOL bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
794 pOut->Push( PUSH_CLIPREGION );
796 if( bCrop )
798 if( bRectClip )
799 pOut->IntersectClipRegion( aClipPolyPoly.GetBoundRect() );
800 else
801 pOut->IntersectClipRegion( aClipPolyPoly );
805 if( !mpSimpleCache || ( mpSimpleCache->maAttr != aAttr ) || pFirstFrameOutDev )
807 if( mpSimpleCache )
808 delete mpSimpleCache;
810 mpSimpleCache = new GrfSimpleCacheObj( GetTransformedGraphic( &aAttr ), aAttr );
811 mpSimpleCache->maGraphic.SetAnimationNotifyHdl( GetAnimationNotifyHdl() );
814 mpSimpleCache->maGraphic.StartAnimation( pOut, aPt, aSz, nExtraData, pFirstFrameOutDev );
816 if( bCropped )
817 pOut->Pop();
819 bRet = TRUE;
821 else
822 bRet = Draw( pOut, rPt, rSz, &aAttr, GRFMGR_DRAW_STANDARD );
825 return bRet;
828 // -----------------------------------------------------------------------------
830 void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData )
832 if( mpSimpleCache )
833 mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData );
836 // -----------------------------------------------------------------------------
838 const Graphic& GraphicObject::GetGraphic() const
840 if( mbAutoSwapped )
841 ( (GraphicObject*) this )->ImplAutoSwapIn();
843 return maGraphic;
846 // -----------------------------------------------------------------------------
848 void GraphicObject::SetGraphic( const Graphic& rGraphic )
850 mpMgr->ImplUnregisterObj( *this );
852 if( mpSwapOutTimer )
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 );
863 if( mpSwapOutTimer )
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 );
888 Size aCropLeftTop;
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() ),
899 aMap100 );
900 aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetRightCrop(),
901 rAttr.GetBottomCrop() ),
902 aMap100 );
904 else
906 aCropLeftTop = OutputDevice::LogicToLogic( Size( rAttr.GetLeftCrop(),
907 rAttr.GetTopCrop() ),
908 aMap100,
909 aMapGraph );
910 aCropRightBottom = OutputDevice::LogicToLogic( Size( rAttr.GetRightCrop(),
911 rAttr.GetBottomCrop() ),
912 aMap100,
913 aMapGraph );
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 );
950 else
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() ),
965 aMap100 );
966 aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetRightCrop(),
967 rAttr.GetBottomCrop() ),
968 aMap100 );
970 // convert from prefmapmode to pixel
971 const Size aSrcSizePixel( Application::GetDefaultDevice()->LogicToPixel( aSrcSize,
972 aMapGraph ) );
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() )
982 USHORT nFrame;
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;
1041 else
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
1065 GetGraphic();
1067 Graphic aGraphic;
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 )
1076 if( IsAnimated() )
1078 Animation aAnimation( maGraphic.GetAnimation() );
1079 GraphicManager::ImplAdjust( aAnimation, aAttr, ADJUSTMENT_ALL );
1080 aAnimation.SetLoopCount( mnAnimationLoopCount );
1081 aGraphic = aAnimation;
1083 else
1085 BitmapEx aBmpEx( maGraphic.GetBitmapEx() );
1086 GraphicManager::ImplAdjust( aBmpEx, aAttr, ADJUSTMENT_ALL );
1087 aGraphic = aBmpEx;
1090 else
1092 GDIMetaFile aMtf( maGraphic.GetGDIMetaFile() );
1093 GraphicManager::ImplAdjust( aMtf, aAttr, ADJUSTMENT_ALL );
1094 aGraphic = aMtf;
1097 else
1099 if( ( GetType() == GRAPHIC_BITMAP ) && IsAnimated() )
1101 Animation aAnimation( maGraphic.GetAnimation() );
1102 aAnimation.SetLoopCount( mnAnimationLoopCount );
1103 aGraphic = aAnimation;
1105 else
1106 aGraphic = maGraphic;
1110 return aGraphic;
1113 // -----------------------------------------------------------------------------
1115 void GraphicObject::ResetAnimationLoopCount()
1117 if( IsAnimated() && !IsSwappedOut() )
1119 maGraphic.ResetAnimationLoopCount();
1121 if( mpSimpleCache )
1122 mpSimpleCache->maGraphic.ResetAnimationLoopCount();
1126 // -----------------------------------------------------------------------------
1128 BOOL GraphicObject::SwapOut()
1130 BOOL bRet = ( !mbAutoSwapped ? maGraphic.SwapOut() : FALSE );
1132 if( bRet && mpMgr )
1133 mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1135 return bRet;
1138 // -----------------------------------------------------------------------------
1140 BOOL GraphicObject::SwapOut( SvStream* pOStm )
1142 BOOL bRet = ( !mbAutoSwapped ? maGraphic.SwapOut( pOStm ) : FALSE );
1144 if( bRet && mpMgr )
1145 mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1147 return bRet;
1150 // -----------------------------------------------------------------------------
1152 BOOL GraphicObject::SwapIn()
1154 BOOL bRet;
1156 if( mbAutoSwapped )
1158 ImplAutoSwapIn();
1159 bRet = TRUE;
1161 else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
1162 bRet = TRUE;
1163 else
1165 bRet = maGraphic.SwapIn();
1167 if( bRet && mpMgr )
1168 mpMgr->ImplGraphicObjectWasSwappedIn( *this );
1171 if( bRet )
1172 ImplAssignGraphicData();
1174 return bRet;
1177 // -----------------------------------------------------------------------------
1179 BOOL GraphicObject::SwapIn( SvStream* pIStm )
1181 BOOL bRet;
1183 if( mbAutoSwapped )
1185 ImplAutoSwapIn();
1186 bRet = TRUE;
1188 else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
1189 bRet = TRUE;
1190 else
1192 bRet = maGraphic.SwapIn( pIStm );
1194 if( bRet && mpMgr )
1195 mpMgr->ImplGraphicObjectWasSwappedIn( *this );
1198 if( bRet )
1199 ImplAssignGraphicData();
1201 return bRet;
1204 // -----------------------------------------------------------------------------
1206 void GraphicObject::SetSwapState()
1208 if( !IsSwappedOut() )
1210 mbAutoSwapped = TRUE;
1212 if( mpMgr )
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 );
1231 else
1233 if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
1234 mbAutoSwapped = SwapOut();
1235 else
1237 mbAutoSwapped = SwapOut( pStream );
1238 delete pStream;
1243 mbIsInSwapOut = FALSE;
1246 if( mpSwapOutTimer )
1247 mpSwapOutTimer->Start();
1249 return 0L;
1252 // ------------------------------------------------------------------------
1254 SvStream& operator>>( SvStream& rIStm, GraphicObject& rGraphicObj )
1256 VersionCompat aCompat( rIStm, STREAM_READ );
1257 Graphic aGraphic;
1258 GraphicAttr aAttr;
1259 ByteString aLink;
1260 BOOL bLink;
1262 rIStm >> aGraphic >> aAttr >> bLink;
1264 rGraphicObj.SetGraphic( aGraphic );
1265 rGraphicObj.SetAttr( aAttr );
1267 if( bLink )
1269 rIStm >> aLink;
1270 rGraphicObj.SetLink( UniString( aLink, RTL_TEXTENCODING_UTF8 ) );
1272 else
1273 rGraphicObj.SetLink();
1275 rGraphicObj.SetSwapStreamHdl();
1277 return rIStm;
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;
1289 if( bLink )
1290 rOStm << ByteString( rGraphicObj.GetLink(), RTL_TEXTENCODING_UTF8 );
1292 return rOStm;