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