xref: /aoo42x/main/svtools/source/graphic/grfmgr.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #define ENABLE_BYTESTRING_STREAM_OPERATORS
32 
33 #include <algorithm>
34 
35 #include <tools/vcompat.hxx>
36 #include <unotools/ucbstreamhelper.hxx>
37 #include <unotools/localfilehelper.hxx>
38 #include <unotools/tempfile.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/cvtgrf.hxx>
41 #include <vcl/metaact.hxx>
42 #include <vcl/virdev.hxx>
43 #include <vcl/salbtype.hxx>
44 #include <unotools/cacheoptions.hxx>
45 #include <svtools/grfmgr.hxx>
46 
47 // --> OD 2010-01-04 #i105243#
48 #include <vcl/pdfextoutdevdata.hxx>
49 // <--
50 
51 // -----------
52 // - Defines -
53 // -----------
54 
55 #define WATERMARK_LUM_OFFSET				50
56 #define WATERMARK_CON_OFFSET				-70
57 
58 // -----------
59 // - statics -
60 // -----------
61 
62 GraphicManager* GraphicObject::mpGlobalMgr = NULL;
63 
64 // ---------------------
65 // - GrfDirectCacheObj -
66 // ---------------------
67 
68 struct GrfSimpleCacheObj
69 {
70 	Graphic		maGraphic;
71 	GraphicAttr	maAttr;
72 
73 				GrfSimpleCacheObj( const Graphic& rGraphic, const GraphicAttr& rAttr ) :
74 					maGraphic( rGraphic ), maAttr( rAttr ) {}
75 };
76 
77 // -----------------
78 // - GraphicObject -
79 // -----------------
80 
81 TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream );
82 
83 // -----------------------------------------------------------------------------
84 
85 GraphicObject::GraphicObject( const GraphicManager* pMgr ) :
86 	mpLink		( NULL ),
87 	mpUserData	( NULL )
88 {
89 	ImplConstruct();
90 	ImplAssignGraphicData();
91 	ImplSetGraphicManager( pMgr );
92 }
93 
94 // -----------------------------------------------------------------------------
95 
96 GraphicObject::GraphicObject( const Graphic& rGraphic, const GraphicManager* pMgr ) :
97 	maGraphic	( rGraphic ),
98 	mpLink		( NULL ),
99 	mpUserData	( NULL )
100 {
101 	ImplConstruct();
102 	ImplAssignGraphicData();
103 	ImplSetGraphicManager( pMgr );
104 }
105 
106 // -----------------------------------------------------------------------------
107 
108 GraphicObject::GraphicObject( const Graphic& rGraphic, const String& rLink, const GraphicManager* pMgr ) :
109 	maGraphic	( rGraphic ),
110 	mpLink		( rLink.Len() ? ( new String( rLink ) ) : NULL ),
111 	mpUserData	( NULL )
112 {
113 	ImplConstruct();
114 	ImplAssignGraphicData();
115 	ImplSetGraphicManager( pMgr );
116 }
117 
118 // -----------------------------------------------------------------------------
119 
120 GraphicObject::GraphicObject( const GraphicObject& rGraphicObj, const GraphicManager* pMgr ) :
121     SvDataCopyStream(),
122 	maGraphic	( rGraphicObj.GetGraphic() ),
123 	maAttr		( rGraphicObj.maAttr ),
124 	mpLink		( rGraphicObj.mpLink ? ( new String( *rGraphicObj.mpLink ) ) : NULL ),
125 	mpUserData	( rGraphicObj.mpUserData ? ( new String( *rGraphicObj.mpUserData ) ) : NULL )
126 {
127 	ImplConstruct();
128 	ImplAssignGraphicData();
129 	ImplSetGraphicManager( pMgr, NULL, &rGraphicObj );
130 }
131 
132 // -----------------------------------------------------------------------------
133 
134 GraphicObject::GraphicObject( const ByteString& rUniqueID, const GraphicManager* pMgr ) :
135 	mpLink		( NULL ),
136 	mpUserData	( NULL )
137 {
138 	ImplConstruct();
139 
140 	// assign default properties
141 	ImplAssignGraphicData();
142 
143 	ImplSetGraphicManager( pMgr, &rUniqueID );
144 
145 	// update properties
146 	ImplAssignGraphicData();
147 }
148 
149 // -----------------------------------------------------------------------------
150 
151 GraphicObject::~GraphicObject()
152 {
153 	if( mpMgr )
154 	{
155 		mpMgr->ImplUnregisterObj( *this );
156 
157 		if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() )
158 			delete mpGlobalMgr, mpGlobalMgr = NULL;
159 	}
160 
161 	delete mpSwapOutTimer;
162 	delete mpSwapStreamHdl;
163 	delete mpLink;
164 	delete mpUserData;
165 	delete mpSimpleCache;
166 }
167 
168 // -----------------------------------------------------------------------------
169 
170 void GraphicObject::ImplConstruct()
171 {
172 	mpMgr = NULL;
173 	mpSwapStreamHdl = NULL;
174 	mpSwapOutTimer = NULL;
175 	mpSimpleCache = NULL;
176     mnAnimationLoopCount = 0;
177 	mbAutoSwapped = sal_False;
178 	mbIsInSwapIn = sal_False;
179 	mbIsInSwapOut = sal_False;
180 }
181 
182 // -----------------------------------------------------------------------------
183 
184 void GraphicObject::ImplAssignGraphicData()
185 {
186 	maPrefSize = maGraphic.GetPrefSize();
187 	maPrefMapMode = maGraphic.GetPrefMapMode();
188 	mnSizeBytes = maGraphic.GetSizeBytes();
189 	meType = maGraphic.GetType();
190 	mbTransparent = maGraphic.IsTransparent();
191 	mbAlpha = maGraphic.IsAlpha();
192 	mbAnimated = maGraphic.IsAnimated();
193 	mbEPS = maGraphic.IsEPS();
194 	mbIsRenderGraphic = maGraphic.IsRenderGraphic();
195 	mbHasRenderGraphic = maGraphic.HasRenderGraphic();
196     mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 );
197 }
198 
199 // -----------------------------------------------------------------------------
200 
201 void GraphicObject::ImplSetGraphicManager( const GraphicManager* pMgr, const ByteString* pID, const GraphicObject* pCopyObj )
202 {
203 	if( !mpMgr || ( pMgr != mpMgr ) )
204 	{
205 		if( !pMgr && mpMgr && ( mpMgr == mpGlobalMgr ) )
206 			return;
207 		else
208 		{
209 			if( mpMgr )
210 			{
211 				mpMgr->ImplUnregisterObj( *this );
212 
213 				if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() )
214 					delete mpGlobalMgr, mpGlobalMgr = NULL;
215 			}
216 
217 			if( !pMgr )
218 			{
219 				if( !mpGlobalMgr )
220 				{
221                     SvtCacheOptions aCacheOptions;
222 
223 					mpGlobalMgr = new GraphicManager( aCacheOptions.GetGraphicManagerTotalCacheSize(),
224                                                       aCacheOptions.GetGraphicManagerObjectCacheSize() );
225                     mpGlobalMgr->SetCacheTimeout( aCacheOptions.GetGraphicManagerObjectReleaseTime() );
226 				}
227 
228 				mpMgr = mpGlobalMgr;
229 			}
230 			else
231 				mpMgr = (GraphicManager*) pMgr;
232 
233 			mpMgr->ImplRegisterObj( *this, maGraphic, pID, pCopyObj );
234 		}
235 	}
236 }
237 
238 // -----------------------------------------------------------------------------
239 
240 void GraphicObject::ImplAutoSwapIn()
241 {
242 	if( IsSwappedOut() )
243 	{
244 		if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
245 			mbAutoSwapped = sal_False;
246 		else
247 		{
248 			mbIsInSwapIn = sal_True;
249 
250 			if( maGraphic.SwapIn() )
251 				mbAutoSwapped = sal_False;
252 			else
253 			{
254 				SvStream* pStream = GetSwapStream();
255 
256 				if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
257 				{
258 					if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
259 					{
260 						if( HasLink() )
261 						{
262 							String aURLStr;
263 
264 							if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( GetLink(), aURLStr ) )
265 							{
266 								SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aURLStr, STREAM_READ );
267 
268 								if( pIStm )
269 								{
270 									(*pIStm) >> maGraphic;
271 									mbAutoSwapped = ( maGraphic.GetType() != GRAPHIC_NONE );
272 									delete pIStm;
273 								}
274 							}
275 						}
276 					}
277 					else if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
278 						mbAutoSwapped = !maGraphic.SwapIn();
279 					else if( GRFMGR_AUTOSWAPSTREAM_LOADED == pStream )
280 						mbAutoSwapped = maGraphic.IsSwapOut();
281 					else
282 					{
283 						mbAutoSwapped = !maGraphic.SwapIn( pStream );
284 						delete pStream;
285 					}
286 				}
287 				else
288 				{
289 					DBG_ASSERT( ( GRAPHIC_NONE == meType ) || ( GRAPHIC_DEFAULT == meType ),
290 								"GraphicObject::ImplAutoSwapIn: could not get stream to swap in graphic! (=>KA)" );
291 				}
292 			}
293 
294 			mbIsInSwapIn = sal_False;
295 
296 			if( !mbAutoSwapped && mpMgr )
297 				mpMgr->ImplGraphicObjectWasSwappedIn( *this );
298 		}
299 	}
300 }
301 
302 // -----------------------------------------------------------------------------
303 sal_Bool GraphicObject::ImplGetCropParams( OutputDevice* pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr,
304 									   PolyPolygon& rClipPolyPoly, sal_Bool& bRectClipRegion ) const
305 {
306 	sal_Bool bRet = sal_False;
307 
308 	if( GetType() != GRAPHIC_NONE )
309 	{
310 		Polygon			aClipPoly( Rectangle( rPt, rSz ) );
311 		const sal_uInt16	nRot10 = pAttr->GetRotation() % 3600;
312 		const Point		aOldOrigin( rPt );
313         // --> OD 2005-09-30 #i54875# - It's not needed to get the graphic again.
314 //        const Graphic&  rGraphic = GetGraphic();
315         // <--
316 		const MapMode	aMap100( MAP_100TH_MM );
317 		Size			aSize100;
318 		long			nTotalWidth, nTotalHeight;
319 		long			nNewLeft, nNewTop, nNewRight, nNewBottom;
320 		double			fScale;
321 
322 		if( nRot10 )
323 		{
324 			aClipPoly.Rotate( rPt, nRot10 );
325 			bRectClipRegion = sal_False;
326 		}
327 		else
328 			bRectClipRegion = sal_True;
329 
330 		rClipPolyPoly = aClipPoly;
331 
332         // --> OD 2005-09-30 #i54875# - directly access member <maGraphic> to
333         // get <PrefSize> and <PrefMapMode>.
334 //        if( rGraphic.GetPrefMapMode() == MAP_PIXEL )
335 //            aSize100 = Application::GetDefaultDevice()->PixelToLogic( rGraphic.GetPrefSize(), aMap100 );
336 //        else
337 //            aSize100 = pOut->LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), aMap100 );
338         if( maGraphic.GetPrefMapMode() == MAP_PIXEL )
339             aSize100 = Application::GetDefaultDevice()->PixelToLogic( maGraphic.GetPrefSize(), aMap100 );
340         else
341         {
342             MapMode m(maGraphic.GetPrefMapMode());
343             aSize100 = pOut->LogicToLogic( maGraphic.GetPrefSize(), &m, &aMap100 );
344         }
345         // <--
346 
347 		nTotalWidth = aSize100.Width() - pAttr->GetLeftCrop() - pAttr->GetRightCrop();
348 		nTotalHeight = aSize100.Height() - pAttr->GetTopCrop() - pAttr->GetBottomCrop();
349 
350 		if( aSize100.Width() > 0 && aSize100.Height() > 0 && nTotalWidth > 0 && nTotalHeight > 0 )
351 		{
352 			fScale = (double) aSize100.Width() / nTotalWidth;
353 			nNewLeft = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_HORZ ) ? pAttr->GetRightCrop() : pAttr->GetLeftCrop() ) * fScale );
354 			nNewRight = nNewLeft + FRound( aSize100.Width() * fScale ) - 1;
355 
356 			fScale = (double) rSz.Width() / aSize100.Width();
357 			rPt.X() += FRound( nNewLeft * fScale );
358 			rSz.Width() = FRound( ( nNewRight - nNewLeft + 1 ) * fScale );
359 
360 			fScale = (double) aSize100.Height() / nTotalHeight;
361 			nNewTop = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_VERT ) ? pAttr->GetBottomCrop() : pAttr->GetTopCrop() ) * fScale );
362 			nNewBottom = nNewTop + FRound( aSize100.Height() * fScale ) - 1;
363 
364 			fScale = (double) rSz.Height() / aSize100.Height();
365 			rPt.Y() += FRound( nNewTop * fScale );
366 			rSz.Height() = FRound( ( nNewBottom - nNewTop + 1 ) * fScale );
367 
368 			if( nRot10 )
369 			{
370 				Polygon aOriginPoly( 1 );
371 
372 				aOriginPoly[ 0 ] = rPt;
373 				aOriginPoly.Rotate( aOldOrigin, nRot10 );
374 				rPt = aOriginPoly[ 0 ];
375 			}
376 
377 			bRet = sal_True;
378 		}
379 	}
380 
381 	return bRet;
382 }
383 
384 // -----------------------------------------------------------------------------
385 
386 GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj )
387 {
388 	if( &rGraphicObj != this )
389 	{
390 		mpMgr->ImplUnregisterObj( *this );
391 
392 		delete mpSwapStreamHdl, mpSwapStreamHdl = NULL;
393 		delete mpSimpleCache, mpSimpleCache = NULL;
394 		delete mpLink;
395 		delete mpUserData;
396 
397 		maGraphic = rGraphicObj.GetGraphic();
398 		maAttr = rGraphicObj.maAttr;
399 		mpLink = rGraphicObj.mpLink ? new String( *rGraphicObj.mpLink ) : NULL;
400 		mpUserData = rGraphicObj.mpUserData ? new String( *rGraphicObj.mpUserData ) : NULL;
401 		ImplAssignGraphicData();
402 		mbAutoSwapped = sal_False;
403 		mpMgr = rGraphicObj.mpMgr;
404 
405 		mpMgr->ImplRegisterObj( *this, maGraphic, NULL, &rGraphicObj );
406 	}
407 
408 	return *this;
409 }
410 
411 // -----------------------------------------------------------------------------
412 
413 sal_Bool GraphicObject::operator==( const GraphicObject& rGraphicObj ) const
414 {
415 	return(	( rGraphicObj.maGraphic == maGraphic ) &&
416 			( rGraphicObj.maAttr == maAttr ) &&
417 			( rGraphicObj.GetLink() == GetLink() ) );
418 }
419 
420 // ------------------------------------------------------------------------
421 
422 void GraphicObject::Load( SvStream& rIStm )
423 {
424     rIStm >> *this;
425 }
426 
427 // ------------------------------------------------------------------------
428 
429 void GraphicObject::Save( SvStream& rOStm )
430 {
431     rOStm << *this;
432 }
433 
434 // ------------------------------------------------------------------------
435 
436 void GraphicObject::Assign( const SvDataCopyStream& rCopyStream )
437 {
438     *this = (const GraphicObject& ) rCopyStream;
439 }
440 
441 // -----------------------------------------------------------------------------
442 
443 ByteString GraphicObject::GetUniqueID() const
444 {
445 	if ( !IsInSwapIn() && ( IsEPS() || IsRenderGraphic() ) )
446 		const_cast<GraphicObject*>(this)->FireSwapInRequest();
447 
448 	ByteString aRet;
449 
450 	if( mpMgr )
451 		aRet = mpMgr->ImplGetUniqueID( *this );
452 
453 	return aRet;
454 }
455 
456 // -----------------------------------------------------------------------------
457 
458 sal_uLong GraphicObject::GetChecksum() const
459 {
460 	return( ( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() ) ? maGraphic.GetChecksum() : 0 );
461 }
462 
463 // -----------------------------------------------------------------------------
464 
465 SvStream* GraphicObject::GetSwapStream() const
466 {
467 	return( HasSwapStreamHdl() ? (SvStream*) mpSwapStreamHdl->Call( (void*) this ) : GRFMGR_AUTOSWAPSTREAM_NONE );
468 }
469 
470 // -----------------------------------------------------------------------------
471 
472 // !!! to be removed
473 sal_uLong GraphicObject::GetReleaseFromCache() const
474 {
475 	return 0;
476 }
477 
478 // -----------------------------------------------------------------------------
479 
480 void GraphicObject::SetAttr( const GraphicAttr& rAttr )
481 {
482 	maAttr = rAttr;
483 
484 	if( mpSimpleCache && ( mpSimpleCache->maAttr != rAttr ) )
485 		delete mpSimpleCache, mpSimpleCache = NULL;
486 }
487 
488 // -----------------------------------------------------------------------------
489 
490 void GraphicObject::SetLink()
491 {
492 	if( mpLink )
493 		delete mpLink, mpLink = NULL;
494 }
495 
496 // -----------------------------------------------------------------------------
497 
498 void GraphicObject::SetLink( const String& rLink )
499 {
500 	delete mpLink, mpLink = new String( rLink );
501 }
502 
503 // -----------------------------------------------------------------------------
504 
505 String GraphicObject::GetLink() const
506 {
507 	if( mpLink )
508 		return *mpLink;
509 	else
510 		return String();
511 }
512 
513 // -----------------------------------------------------------------------------
514 
515 void GraphicObject::SetUserData()
516 {
517 	if( mpUserData )
518 		delete mpUserData, mpUserData = NULL;
519 }
520 
521 // -----------------------------------------------------------------------------
522 
523 void GraphicObject::SetUserData( const String& rUserData )
524 {
525 	delete mpUserData, mpUserData = new String( rUserData );
526 }
527 
528 // -----------------------------------------------------------------------------
529 
530 String GraphicObject::GetUserData() const
531 {
532 	if( mpUserData )
533 		return *mpUserData;
534 	else
535 		return String();
536 }
537 
538 // -----------------------------------------------------------------------------
539 
540 void GraphicObject::SetSwapStreamHdl()
541 {
542 	if( mpSwapStreamHdl )
543 	{
544 		delete mpSwapOutTimer, mpSwapOutTimer = NULL;
545 		delete mpSwapStreamHdl, mpSwapStreamHdl = NULL;
546 	}
547 }
548 
549 // -----------------------------------------------------------------------------
550 
551 void GraphicObject::SetSwapStreamHdl( const Link& rHdl, const sal_uLong nSwapOutTimeout )
552 {
553 	delete mpSwapStreamHdl,	mpSwapStreamHdl = new Link( rHdl );
554 
555 	if( nSwapOutTimeout )
556 	{
557 		if( !mpSwapOutTimer )
558 		{
559 			mpSwapOutTimer = new Timer;
560 			mpSwapOutTimer->SetTimeoutHdl( LINK( this, GraphicObject, ImplAutoSwapOutHdl ) );
561 		}
562 
563 		mpSwapOutTimer->SetTimeout( nSwapOutTimeout );
564 		mpSwapOutTimer->Start();
565 	}
566 	else
567 		delete mpSwapOutTimer, mpSwapOutTimer = NULL;
568 }
569 
570 // -----------------------------------------------------------------------------
571 
572 Link GraphicObject::GetSwapStreamHdl() const
573 {
574 	if( mpSwapStreamHdl )
575 		return *mpSwapStreamHdl;
576 	else
577 		return Link();
578 }
579 
580 // -----------------------------------------------------------------------------
581 
582 void GraphicObject::FireSwapInRequest()
583 {
584 	ImplAutoSwapIn();
585 }
586 
587 // -----------------------------------------------------------------------------
588 
589 void GraphicObject::FireSwapOutRequest()
590 {
591 	ImplAutoSwapOutHdl( NULL );
592 }
593 
594 // -----------------------------------------------------------------------------
595 
596 void GraphicObject::GraphicManagerDestroyed()
597 {
598 	// we're alive, but our manager doesn't live anymore ==> connect to default manager
599 	mpMgr = NULL;
600 	ImplSetGraphicManager( NULL );
601 }
602 
603 // -----------------------------------------------------------------------------
604 
605 void GraphicObject::SetGraphicManager( const GraphicManager& rMgr )
606 {
607 	ImplSetGraphicManager( &rMgr );
608 }
609 
610 // -----------------------------------------------------------------------------
611 
612 sal_Bool GraphicObject::IsCached( OutputDevice* pOut, const Point& rPt, const Size& rSz,
613 							  const GraphicAttr* pAttr, sal_uLong nFlags ) const
614 {
615 	sal_Bool bRet;
616 
617 	if( nFlags & GRFMGR_DRAW_CACHED )
618     {
619         // --> OD 2005-10-11 #i54875# - Consider cropped graphics.
620         // Note: The graphic manager caches a cropped graphic with its
621         //       uncropped position and size.
622 //        bRet = mpMgr->IsInCache( pOut, rPt, rSz, *this, ( pAttr ? *pAttr : GetAttr() ) );
623         Point aPt( rPt );
624         Size aSz( rSz );
625         if ( pAttr->IsCropped() )
626         {
627             PolyPolygon aClipPolyPoly;
628             sal_Bool        bRectClip;
629             ImplGetCropParams( pOut, aPt, aSz, pAttr, aClipPolyPoly, bRectClip );
630         }
631         bRet = mpMgr->IsInCache( pOut, aPt, aSz, *this, ( pAttr ? *pAttr : GetAttr() ) );
632     }
633 	else
634 		bRet = sal_False;
635 
636 	return bRet;
637 }
638 
639 // -----------------------------------------------------------------------------
640 
641 void GraphicObject::ReleaseFromCache()
642 {
643 
644 	mpMgr->ReleaseFromCache( *this );
645 }
646 
647 // -----------------------------------------------------------------------------
648 
649 void GraphicObject::SetAnimationNotifyHdl( const Link& rLink )
650 {
651 	maGraphic.SetAnimationNotifyHdl( rLink );
652 }
653 
654 // -----------------------------------------------------------------------------
655 
656 List* GraphicObject::GetAnimationInfoList() const
657 {
658 	return maGraphic.GetAnimationInfoList();
659 }
660 
661 // -----------------------------------------------------------------------------
662 
663 sal_Bool GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz,
664 						  const GraphicAttr* pAttr, sal_uLong nFlags )
665 {
666 	GraphicAttr	        aAttr( pAttr ? *pAttr : GetAttr() );
667 	Point 		        aPt( rPt );
668 	Size  	            aSz( rSz );
669     const sal_uInt32    nOldDrawMode = pOut->GetDrawMode();
670 	sal_Bool		        bCropped = aAttr.IsCropped();
671 	sal_Bool		        bCached = sal_False;
672 	sal_Bool		        bRet;
673 
674     // #i29534# Provide output rects for PDF writer
675     Rectangle			aCropRect;
676 
677     if( !( GRFMGR_DRAW_USE_DRAWMODE_SETTINGS & nFlags ) )
678         pOut->SetDrawMode( nOldDrawMode & ( ~( DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT ) ) );
679 
680 	// mirrored horizontically
681 	if( aSz.Width() < 0L )
682 	{
683 		aPt.X() += aSz.Width() + 1;
684 		aSz.Width() = -aSz.Width();
685 		aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_HORZ );
686 	}
687 
688 	// mirrored vertically
689 	if( aSz.Height() < 0L )
690 	{
691 		aPt.Y() += aSz.Height() + 1;
692 		aSz.Height() = -aSz.Height();
693 		aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_VERT );
694 	}
695 
696 	if( bCropped )
697 	{
698 		PolyPolygon aClipPolyPoly;
699 		sal_Bool		bRectClip;
700 		const sal_Bool	bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
701 
702 		pOut->Push( PUSH_CLIPREGION );
703 
704 		if( bCrop )
705 		{
706 			if( bRectClip )
707             {
708                 // #i29534# Store crop rect for later forwarding to
709                 // PDF writer
710                 aCropRect = aClipPolyPoly.GetBoundRect();
711 				pOut->IntersectClipRegion( aCropRect );
712             }
713 			else
714             {
715 				pOut->IntersectClipRegion( aClipPolyPoly );
716             }
717 		}
718 	}
719 
720 	bRet = mpMgr->DrawObj( pOut, aPt, aSz, *this, aAttr, nFlags, bCached );
721 
722 	if( bCropped )
723 		pOut->Pop();
724 
725     pOut->SetDrawMode( nOldDrawMode );
726 
727     // #i29534# Moved below OutDev restoration, to avoid multiple swap-ins
728     // (code above needs to call GetGraphic twice)
729 	if( bCached )
730 	{
731 		if( mpSwapOutTimer )
732 			mpSwapOutTimer->Start();
733 		else
734 			FireSwapOutRequest();
735 	}
736 
737 	return bRet;
738 }
739 
740 // --> OD 2010-01-04 #i105243#
741 sal_Bool GraphicObject::DrawWithPDFHandling( OutputDevice& rOutDev,
742                                          const Point& rPt, const Size& rSz,
743                                          const GraphicAttr* pGrfAttr,
744                                          const sal_uLong nFlags )
745 {
746     const GraphicAttr aGrfAttr( pGrfAttr ? *pGrfAttr : GetAttr() );
747 
748     // Notify PDF writer about linked graphic (if any)
749     sal_Bool bWritingPdfLinkedGraphic( sal_False );
750     Point aPt( rPt );
751     Size aSz( rSz );
752     Rectangle aCropRect;
753     vcl::PDFExtOutDevData* pPDFExtOutDevData =
754             dynamic_cast<vcl::PDFExtOutDevData*>(rOutDev.GetExtOutDevData());
755     if( pPDFExtOutDevData )
756     {
757         // only delegate image handling to PDF, if no special treatment is necessary
758         if( GetGraphic().IsLink() &&
759             rSz.Width() > 0L &&
760             rSz.Height() > 0L &&
761             !aGrfAttr.IsSpecialDrawMode() &&
762             !aGrfAttr.IsMirrored() &&
763             !aGrfAttr.IsRotated() &&
764             !aGrfAttr.IsAdjusted() )
765         {
766             bWritingPdfLinkedGraphic = true;
767 
768             if( aGrfAttr.IsCropped() )
769             {
770                 PolyPolygon aClipPolyPoly;
771                 sal_Bool bRectClip;
772                 const sal_Bool bCrop = ImplGetCropParams( &rOutDev,
773                                                       aPt, aSz,
774                                                       &aGrfAttr,
775                                                       aClipPolyPoly,
776                                                       bRectClip );
777                 if ( bCrop && bRectClip )
778                 {
779                     aCropRect = aClipPolyPoly.GetBoundRect();
780                 }
781             }
782 
783             pPDFExtOutDevData->BeginGroup();
784         }
785     }
786 
787     sal_Bool bRet = Draw( &rOutDev, rPt, rSz, &aGrfAttr, nFlags );
788 
789     // Notify PDF writer about linked graphic (if any)
790     if( bWritingPdfLinkedGraphic )
791     {
792         pPDFExtOutDevData->EndGroup( const_cast< Graphic& >(GetGraphic()),
793                                      aGrfAttr.GetTransparency(),
794                                      Rectangle( aPt, aSz ),
795                                      aCropRect );
796     }
797 
798     return bRet;
799 }
800 // <--
801 
802 // -----------------------------------------------------------------------------
803 
804 sal_Bool GraphicObject::DrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSize,
805                                const Size& rOffset, const GraphicAttr* pAttr, sal_uLong nFlags, int nTileCacheSize1D )
806 {
807     if( pOut == NULL || rSize.Width() == 0 || rSize.Height() == 0 )
808         return sal_False;
809 
810     const MapMode 	aOutMapMode( pOut->GetMapMode() );
811     const MapMode	aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() );
812     // #106258# Clamp size to 1 for zero values. This is okay, since
813     // logical size of zero is handled above already
814     const Size		aOutTileSize( ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Width() ),
815                                   ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Height() ) );
816 
817 	//#i69780 clip final tile size to a sane max size
818     while (((sal_Int64)rSize.Width() * nTileCacheSize1D) > SAL_MAX_UINT16)
819         nTileCacheSize1D /= 2;
820     while (((sal_Int64)rSize.Height() * nTileCacheSize1D) > SAL_MAX_UINT16)
821         nTileCacheSize1D /= 2;
822 
823     return ImplDrawTiled( pOut, rArea, aOutTileSize, rOffset, pAttr, nFlags, nTileCacheSize1D );
824 }
825 
826 // -----------------------------------------------------------------------------
827 
828 sal_Bool GraphicObject::StartAnimation( OutputDevice* pOut, const Point& rPt, const Size& rSz,
829 									long nExtraData, const GraphicAttr* pAttr, sal_uLong /*nFlags*/,
830 									OutputDevice* pFirstFrameOutDev )
831 {
832 	sal_Bool bRet = sal_False;
833 
834 	GetGraphic();
835 
836 	if( !IsSwappedOut() )
837 	{
838     	const GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
839 
840 		if( mbAnimated )
841 		{
842 			Point   aPt( rPt );
843 			Size	aSz( rSz );
844 			sal_Bool	bCropped = aAttr.IsCropped();
845 
846 			if( bCropped )
847 			{
848 				PolyPolygon aClipPolyPoly;
849 				sal_Bool		bRectClip;
850 				const sal_Bool	bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
851 
852 				pOut->Push( PUSH_CLIPREGION );
853 
854 				if( bCrop )
855 				{
856 					if( bRectClip )
857 						pOut->IntersectClipRegion( aClipPolyPoly.GetBoundRect() );
858 					else
859 						pOut->IntersectClipRegion( aClipPolyPoly );
860 				}
861 			}
862 
863 			if( !mpSimpleCache || ( mpSimpleCache->maAttr != aAttr ) || pFirstFrameOutDev )
864 			{
865 				if( mpSimpleCache )
866 					delete mpSimpleCache;
867 
868 				mpSimpleCache = new GrfSimpleCacheObj( GetTransformedGraphic( &aAttr ), aAttr );
869 				mpSimpleCache->maGraphic.SetAnimationNotifyHdl( GetAnimationNotifyHdl() );
870 			}
871 
872 			mpSimpleCache->maGraphic.StartAnimation( pOut, aPt, aSz, nExtraData, pFirstFrameOutDev );
873 
874 			if( bCropped )
875 				pOut->Pop();
876 
877 			bRet = sal_True;
878 		}
879 		else
880 			bRet = Draw( pOut, rPt, rSz, &aAttr, GRFMGR_DRAW_STANDARD );
881 	}
882 
883 	return bRet;
884 }
885 
886 // -----------------------------------------------------------------------------
887 
888 void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData )
889 {
890 	if( mpSimpleCache )
891 		mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData );
892 }
893 
894 // -----------------------------------------------------------------------------
895 
896 const Graphic& GraphicObject::GetGraphic() const
897 {
898 	if( mbAutoSwapped )
899 		( (GraphicObject*) this )->ImplAutoSwapIn();
900 
901 	return maGraphic;
902 }
903 
904 // -----------------------------------------------------------------------------
905 
906 void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pCopyObj )
907 {
908 	mpMgr->ImplUnregisterObj( *this );
909 
910 	if( mpSwapOutTimer )
911 		mpSwapOutTimer->Stop();
912 
913 	maGraphic = rGraphic;
914 	mbAutoSwapped = sal_False;
915 	ImplAssignGraphicData();
916 	delete mpLink, mpLink = NULL;
917 	delete mpSimpleCache, mpSimpleCache = NULL;
918 
919 	mpMgr->ImplRegisterObj( *this, maGraphic, 0, pCopyObj);
920 
921 	if( mpSwapOutTimer )
922 		mpSwapOutTimer->Start();
923 }
924 
925 // -----------------------------------------------------------------------------
926 
927 void GraphicObject::SetGraphic( const Graphic& rGraphic, const String& rLink )
928 {
929 	SetGraphic( rGraphic );
930 	mpLink = new String( rLink );
931 }
932 
933 // -----------------------------------------------------------------------------
934 
935 Graphic GraphicObject::GetTransformedGraphic( const Size& rDestSize, const MapMode& rDestMap, const GraphicAttr& rAttr ) const
936 {
937     // #104550# Extracted from svx/source/svdraw/svdograf.cxx
938 	Graphic		    	aTransGraphic( maGraphic );
939 	const GraphicType	eType = GetType();
940     const Size      	aSrcSize( aTransGraphic.GetPrefSize() );
941 
942     // #104115# Convert the crop margins to graphic object mapmode
943     const MapMode aMapGraph( aTransGraphic.GetPrefMapMode() );
944     const MapMode aMap100( MAP_100TH_MM );
945 
946     Size aCropLeftTop;
947     Size aCropRightBottom;
948 
949     if( GRAPHIC_GDIMETAFILE == eType )
950     {
951         GDIMetaFile aMtf( aTransGraphic.GetGDIMetaFile() );
952 
953         if( aMapGraph == MAP_PIXEL )
954         {
955             aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetLeftCrop(),
956                                                                                 rAttr.GetTopCrop() ),
957                                                                           aMap100 );
958             aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetRightCrop(),
959                                                                                     rAttr.GetBottomCrop() ),
960                                                                               aMap100 );
961         }
962         else
963         {
964             aCropLeftTop = OutputDevice::LogicToLogic( Size( rAttr.GetLeftCrop(),
965                                                              rAttr.GetTopCrop() ),
966                                                        aMap100,
967                                                        aMapGraph );
968             aCropRightBottom = OutputDevice::LogicToLogic( Size( rAttr.GetRightCrop(),
969                                                                  rAttr.GetBottomCrop() ),
970                                                            aMap100,
971                                                            aMapGraph );
972         }
973 
974         // #104115# If the metafile is cropped, give it a special
975         // treatment: clip against the remaining area, scale up such
976         // that this area later fills the desired size, and move the
977         // origin to the upper left edge of that area.
978         if( rAttr.IsCropped() )
979         {
980             const MapMode aMtfMapMode( aMtf.GetPrefMapMode() );
981 
982             Rectangle aClipRect( aMtfMapMode.GetOrigin().X() + aCropLeftTop.Width(),
983                                  aMtfMapMode.GetOrigin().Y() + aCropLeftTop.Height(),
984                                  aMtfMapMode.GetOrigin().X() + aSrcSize.Width() - aCropRightBottom.Width(),
985                                  aMtfMapMode.GetOrigin().Y() + aSrcSize.Height() - aCropRightBottom.Height() );
986 
987             // #104115# To correctly crop rotated metafiles, clip by view rectangle
988             aMtf.AddAction( new MetaISectRectClipRegionAction( aClipRect ), 0 );
989 
990             // #104115# To crop the metafile, scale larger than the output rectangle
991             aMtf.Scale( (double)rDestSize.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()),
992                         (double)rDestSize.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) );
993 
994             // #104115# Adapt the pref size by hand (scale changes it
995             // proportionally, but we want it to be smaller than the
996             // former size, to crop the excess out)
997             aMtf.SetPrefSize( Size( (long)((double)rDestSize.Width() *  (1.0 + (aCropLeftTop.Width() + aCropRightBottom.Width()) / aSrcSize.Width())  + .5),
998                                     (long)((double)rDestSize.Height() * (1.0 + (aCropLeftTop.Height() + aCropRightBottom.Height()) / aSrcSize.Height()) + .5) ) );
999 
1000             // #104115# Adapt the origin of the new mapmode, such that it
1001             // is shifted to the place where the cropped output starts
1002             Point aNewOrigin( (long)((double)aMtfMapMode.GetOrigin().X() + rDestSize.Width() * aCropLeftTop.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()) + .5),
1003                               (long)((double)aMtfMapMode.GetOrigin().Y() + rDestSize.Height() * aCropLeftTop.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) + .5) );
1004             MapMode aNewMap( rDestMap );
1005             aNewMap.SetOrigin( OutputDevice::LogicToLogic(aNewOrigin, aMtfMapMode, rDestMap) );
1006             aMtf.SetPrefMapMode( aNewMap );
1007         }
1008         else
1009         {
1010             aMtf.Scale( Fraction( rDestSize.Width(), aSrcSize.Width() ), Fraction( rDestSize.Height(), aSrcSize.Height() ) );
1011             aMtf.SetPrefMapMode( rDestMap );
1012         }
1013 
1014         aTransGraphic = aMtf;
1015     }
1016     else if( GRAPHIC_BITMAP == eType )
1017     {
1018         BitmapEx    aBitmapEx( aTransGraphic.GetBitmapEx() );
1019 
1020         // convert crops to pixel
1021         aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetLeftCrop(),
1022                                                                             rAttr.GetTopCrop() ),
1023                                                                       aMap100 );
1024         aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetRightCrop(),
1025                                                                                 rAttr.GetBottomCrop() ),
1026                                                                           aMap100 );
1027 
1028         // convert from prefmapmode to pixel
1029         const Size aSrcSizePixel( Application::GetDefaultDevice()->LogicToPixel( aSrcSize,
1030                                                                                  aMapGraph ) );
1031 
1032         // setup crop rectangle in pixel
1033         Rectangle aCropRect( aCropLeftTop.Width(), aCropLeftTop.Height(),
1034                              aSrcSizePixel.Width() - aCropRightBottom.Width(),
1035                              aSrcSizePixel.Height() - aCropRightBottom.Height() );
1036 
1037         // #105641# Also crop animations
1038         if( aTransGraphic.IsAnimated() )
1039         {
1040             sal_uInt16 nFrame;
1041             Animation aAnim( aTransGraphic.GetAnimation() );
1042 
1043             for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
1044             {
1045                 AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
1046 
1047                 if( !aCropRect.IsInside( Rectangle(aAnimBmp.aPosPix, aAnimBmp.aSizePix) ) )
1048                 {
1049                     // setup actual cropping (relative to frame position)
1050                     Rectangle aCropRectRel( aCropRect );
1051                     aCropRectRel.Move( -aAnimBmp.aPosPix.X(),
1052                                        -aAnimBmp.aPosPix.Y() );
1053 
1054                     // cropping affects this frame, apply it then
1055                     // do _not_ apply enlargement, this is done below
1056                     ImplTransformBitmap( aAnimBmp.aBmpEx, rAttr, Size(), Size(),
1057                                          aCropRectRel, rDestSize, sal_False );
1058 
1059                     aAnim.Replace( aAnimBmp, nFrame );
1060                 }
1061                 // else: bitmap completely within crop area,
1062                 // i.e. nothing is cropped away
1063             }
1064 
1065             // now, apply enlargement (if any) through global animation size
1066             if( aCropLeftTop.Width() < 0 ||
1067                 aCropLeftTop.Height() < 0 ||
1068                 aCropRightBottom.Width() < 0 ||
1069                 aCropRightBottom.Height() < 0 )
1070             {
1071                 Size aNewSize( aAnim.GetDisplaySizePixel() );
1072                 aNewSize.Width() += aCropRightBottom.Width() < 0 ? -aCropRightBottom.Width() : 0;
1073                 aNewSize.Width() += aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0;
1074                 aNewSize.Height() += aCropRightBottom.Height() < 0 ? -aCropRightBottom.Height() : 0;
1075                 aNewSize.Height() += aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0;
1076                 aAnim.SetDisplaySizePixel( aNewSize );
1077             }
1078 
1079             // if topleft has changed, we must move all frames to the
1080             // right and bottom, resp.
1081             if( aCropLeftTop.Width() < 0 ||
1082                 aCropLeftTop.Height() < 0 )
1083             {
1084                 Point aPosOffset( aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0,
1085                                   aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0 );
1086 
1087                 for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
1088                 {
1089                     AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
1090 
1091                     aAnimBmp.aPosPix += aPosOffset;
1092 
1093                     aAnim.Replace( aAnimBmp, nFrame );
1094                 }
1095             }
1096 
1097             aTransGraphic = aAnim;
1098         }
1099         else
1100         {
1101             BitmapEx aBmpEx( aTransGraphic.GetBitmapEx() );
1102 
1103             ImplTransformBitmap( aBmpEx, rAttr, aCropLeftTop, aCropRightBottom,
1104                                  aCropRect, rDestSize, sal_True );
1105 
1106             aTransGraphic = aBmpEx;
1107         }
1108 
1109         aTransGraphic.SetPrefSize( rDestSize );
1110         aTransGraphic.SetPrefMapMode( rDestMap );
1111     }
1112 
1113     GraphicObject aGrfObj( aTransGraphic );
1114     aTransGraphic = aGrfObj.GetTransformedGraphic( &rAttr );
1115 
1116 	return aTransGraphic;
1117 }
1118 
1119 // -----------------------------------------------------------------------------
1120 
1121 Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const // TODO: Change to Impl
1122 {
1123 	GetGraphic();
1124 
1125 	Graphic     aGraphic;
1126     GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
1127 
1128 	if( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() )
1129 	{
1130 		if( aAttr.IsSpecialDrawMode() || aAttr.IsAdjusted() || aAttr.IsMirrored() || aAttr.IsRotated() || aAttr.IsTransparent() )
1131 		{
1132 			if( GetType() == GRAPHIC_BITMAP )
1133 			{
1134 				if( IsAnimated() )
1135 				{
1136 					Animation aAnimation( maGraphic.GetAnimation() );
1137 					GraphicManager::ImplAdjust( aAnimation, aAttr, ADJUSTMENT_ALL );
1138                     aAnimation.SetLoopCount( mnAnimationLoopCount );
1139 					aGraphic = aAnimation;
1140 				}
1141 				else
1142 				{
1143 					BitmapEx aBmpEx( maGraphic.GetBitmapEx() );
1144 					GraphicManager::ImplAdjust( aBmpEx, aAttr, ADJUSTMENT_ALL );
1145 					aGraphic = aBmpEx;
1146 				}
1147 			}
1148 			else
1149 			{
1150 				GDIMetaFile aMtf( maGraphic.GetGDIMetaFile() );
1151 				GraphicManager::ImplAdjust( aMtf, aAttr, ADJUSTMENT_ALL );
1152 				aGraphic = aMtf;
1153 			}
1154 		}
1155 		else
1156         {
1157 			if( ( GetType() == GRAPHIC_BITMAP ) && IsAnimated() )
1158 			{
1159 				Animation aAnimation( maGraphic.GetAnimation() );
1160                 aAnimation.SetLoopCount( mnAnimationLoopCount );
1161 				aGraphic = aAnimation;
1162 			}
1163             else
1164 			    aGraphic = maGraphic;
1165         }
1166 	}
1167 
1168 	return aGraphic;
1169 }
1170 
1171 // -----------------------------------------------------------------------------
1172 
1173 void GraphicObject::ResetAnimationLoopCount()
1174 {
1175 	if( IsAnimated() && !IsSwappedOut() )
1176 	{
1177 		maGraphic.ResetAnimationLoopCount();
1178 
1179 		if( mpSimpleCache )
1180 			mpSimpleCache->maGraphic.ResetAnimationLoopCount();
1181 	}
1182 }
1183 
1184 // -----------------------------------------------------------------------------
1185 
1186 sal_Bool GraphicObject::SwapOut()
1187 {
1188 	sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut() : sal_False );
1189 
1190 	if( bRet && mpMgr )
1191 		mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1192 
1193 	return bRet;
1194 }
1195 
1196 // -----------------------------------------------------------------------------
1197 
1198 sal_Bool GraphicObject::SwapOut( SvStream* pOStm )
1199 {
1200 	sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut( pOStm ) : sal_False );
1201 
1202 	if( bRet && mpMgr )
1203 		mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1204 
1205 	return bRet;
1206 }
1207 
1208 // -----------------------------------------------------------------------------
1209 
1210 sal_Bool GraphicObject::SwapIn()
1211 {
1212 	sal_Bool bRet;
1213 
1214 	if( mbAutoSwapped )
1215 	{
1216 		ImplAutoSwapIn();
1217 		bRet = sal_True;
1218 	}
1219 	else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
1220 		bRet = sal_True;
1221 	else
1222 	{
1223 		bRet = maGraphic.SwapIn();
1224 
1225 		if( bRet && mpMgr )
1226 			mpMgr->ImplGraphicObjectWasSwappedIn( *this );
1227 	}
1228 
1229 	if( bRet )
1230 		ImplAssignGraphicData();
1231 
1232 	return bRet;
1233 }
1234 
1235 // -----------------------------------------------------------------------------
1236 
1237 sal_Bool GraphicObject::SwapIn( SvStream* pIStm )
1238 {
1239 	sal_Bool bRet;
1240 
1241 	if( mbAutoSwapped )
1242 	{
1243 		ImplAutoSwapIn();
1244 		bRet = sal_True;
1245 	}
1246 	else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
1247 		bRet = sal_True;
1248 	else
1249 	{
1250 		bRet = maGraphic.SwapIn( pIStm );
1251 
1252 		if( bRet && mpMgr )
1253 			mpMgr->ImplGraphicObjectWasSwappedIn( *this );
1254 	}
1255 
1256 	if( bRet )
1257 		ImplAssignGraphicData();
1258 
1259 	return bRet;
1260 }
1261 
1262 // -----------------------------------------------------------------------------
1263 
1264 void GraphicObject::SetSwapState()
1265 {
1266 	if( !IsSwappedOut() )
1267 	{
1268 		mbAutoSwapped = sal_True;
1269 
1270 		if( mpMgr )
1271 			mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1272 	}
1273 }
1274 
1275 // -----------------------------------------------------------------------------
1276 
1277 IMPL_LINK( GraphicObject, ImplAutoSwapOutHdl, void*, EMPTYARG )
1278 {
1279 	if( !IsSwappedOut() )
1280 	{
1281 		mbIsInSwapOut = sal_True;
1282 
1283 		SvStream* pStream = GetSwapStream();
1284 
1285 		if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
1286 		{
1287 			if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
1288 				mbAutoSwapped = SwapOut( NULL );
1289 			else
1290 			{
1291 				if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
1292 					mbAutoSwapped = SwapOut();
1293 				else
1294 				{
1295 					mbAutoSwapped = SwapOut( pStream );
1296 					delete pStream;
1297 				}
1298 			}
1299 		}
1300 
1301 		mbIsInSwapOut = sal_False;
1302 	}
1303 
1304 	if( mpSwapOutTimer )
1305 		mpSwapOutTimer->Start();
1306 
1307 	return 0L;
1308 }
1309 
1310 // ------------------------------------------------------------------------
1311 
1312 SvStream& operator>>( SvStream& rIStm, GraphicObject& rGraphicObj )
1313 {
1314 	VersionCompat	aCompat( rIStm, STREAM_READ );
1315 	Graphic			aGraphic;
1316 	GraphicAttr		aAttr;
1317 	ByteString		aLink;
1318 	sal_Bool			bLink;
1319 
1320 	rIStm >> aGraphic >> aAttr >> bLink;
1321 
1322 	rGraphicObj.SetGraphic( aGraphic );
1323 	rGraphicObj.SetAttr( aAttr );
1324 
1325 	if( bLink )
1326 	{
1327 		rIStm >> aLink;
1328 		rGraphicObj.SetLink( UniString( aLink, RTL_TEXTENCODING_UTF8 ) );
1329 	}
1330 	else
1331 		rGraphicObj.SetLink();
1332 
1333 	rGraphicObj.SetSwapStreamHdl();
1334 
1335 	return rIStm;
1336 }
1337 
1338 // ------------------------------------------------------------------------
1339 
1340 SvStream& operator<<( SvStream& rOStm, const GraphicObject& rGraphicObj )
1341 {
1342 	VersionCompat	aCompat( rOStm, STREAM_WRITE, 1 );
1343 	const sal_Bool		bLink =  rGraphicObj.HasLink();
1344 
1345 	rOStm << rGraphicObj.GetGraphic() << rGraphicObj.GetAttr() << bLink;
1346 
1347 	if( bLink )
1348 		rOStm << ByteString( rGraphicObj.GetLink(), RTL_TEXTENCODING_UTF8 );
1349 
1350 	return rOStm;
1351 }
1352 
1353 #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:"
1354 
1355 GraphicObject GraphicObject::CreateGraphicObjectFromURL( const ::rtl::OUString &rURL )
1356 {
1357 	const String aURL( rURL ), aPrefix( RTL_CONSTASCII_STRINGPARAM(UNO_NAME_GRAPHOBJ_URLPREFIX) );
1358 	if( aURL.Search( aPrefix ) == 0 )
1359 	{
1360 		// graphic manager url
1361 		ByteString aUniqueID( String(rURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 )), RTL_TEXTENCODING_UTF8 );
1362 		return GraphicObject( aUniqueID );
1363 	}
1364 	else
1365 	{
1366 		Graphic		aGraphic;
1367 		if ( aURL.Len() )
1368 		{
1369 			SvStream*	pStream = utl::UcbStreamHelper::CreateStream( aURL, STREAM_READ );
1370 			if( pStream )
1371 				GraphicConverter::Import( *pStream, aGraphic );
1372 		}
1373 
1374 		return GraphicObject( aGraphic );
1375 	}
1376 }
1377