xref: /aoo42x/main/svtools/source/graphic/grfmgr.cxx (revision a409c94e)
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     mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 );
191 }
192 
193 // -----------------------------------------------------------------------------
194 
195 void GraphicObject::ImplSetGraphicManager( const GraphicManager* pMgr, const ByteString* pID, const GraphicObject* pCopyObj )
196 {
197 	if( !mpMgr || ( pMgr != mpMgr ) )
198 	{
199 		if( !pMgr && mpMgr && ( mpMgr == mpGlobalMgr ) )
200 			return;
201 		else
202 		{
203 			if( mpMgr )
204 			{
205 				mpMgr->ImplUnregisterObj( *this );
206 
207 				if( ( mpMgr == mpGlobalMgr ) && !mpGlobalMgr->ImplHasObjects() )
208 					delete mpGlobalMgr, mpGlobalMgr = NULL;
209 			}
210 
211 			if( !pMgr )
212 			{
213 				if( !mpGlobalMgr )
214 				{
215                     SvtCacheOptions aCacheOptions;
216 
217 					mpGlobalMgr = new GraphicManager( aCacheOptions.GetGraphicManagerTotalCacheSize(),
218                                                       aCacheOptions.GetGraphicManagerObjectCacheSize() );
219                     mpGlobalMgr->SetCacheTimeout( aCacheOptions.GetGraphicManagerObjectReleaseTime() );
220 				}
221 
222 				mpMgr = mpGlobalMgr;
223 			}
224 			else
225 				mpMgr = (GraphicManager*) pMgr;
226 
227 			mpMgr->ImplRegisterObj( *this, maGraphic, pID, pCopyObj );
228 		}
229 	}
230 }
231 
232 // -----------------------------------------------------------------------------
233 
234 void GraphicObject::ImplAutoSwapIn()
235 {
236 	if( IsSwappedOut() )
237 	{
238 		if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
239 			mbAutoSwapped = sal_False;
240 		else
241 		{
242 			mbIsInSwapIn = sal_True;
243 
244 			if( maGraphic.SwapIn() )
245 				mbAutoSwapped = sal_False;
246 			else
247 			{
248 				SvStream* pStream = GetSwapStream();
249 
250 				if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
251 				{
252 					if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
253 					{
254 						if( HasLink() )
255 						{
256 							String aURLStr;
257 
258 							if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( GetLink(), aURLStr ) )
259 							{
260 								SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aURLStr, STREAM_READ );
261 
262 								if( pIStm )
263 								{
264 									(*pIStm) >> maGraphic;
265 									mbAutoSwapped = ( maGraphic.GetType() != GRAPHIC_NONE );
266 									delete pIStm;
267 								}
268 							}
269 						}
270 					}
271 					else if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
272 						mbAutoSwapped = !maGraphic.SwapIn();
273 					else if( GRFMGR_AUTOSWAPSTREAM_LOADED == pStream )
274 						mbAutoSwapped = maGraphic.IsSwapOut();
275 					else
276 					{
277 						mbAutoSwapped = !maGraphic.SwapIn( pStream );
278 						delete pStream;
279 					}
280 				}
281 				else
282 				{
283 					DBG_ASSERT( ( GRAPHIC_NONE == meType ) || ( GRAPHIC_DEFAULT == meType ),
284 								"GraphicObject::ImplAutoSwapIn: could not get stream to swap in graphic! (=>KA)" );
285 				}
286 			}
287 
288 			mbIsInSwapIn = sal_False;
289 
290 			if( !mbAutoSwapped && mpMgr )
291 				mpMgr->ImplGraphicObjectWasSwappedIn( *this );
292 		}
293 	}
294 }
295 
296 // -----------------------------------------------------------------------------
297 sal_Bool GraphicObject::ImplGetCropParams( OutputDevice* pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr,
298 									   PolyPolygon& rClipPolyPoly, sal_Bool& bRectClipRegion ) const
299 {
300 	sal_Bool bRet = sal_False;
301 
302 	if( GetType() != GRAPHIC_NONE )
303 	{
304 		Polygon			aClipPoly( Rectangle( rPt, rSz ) );
305 		const sal_uInt16	nRot10 = pAttr->GetRotation() % 3600;
306 		const Point		aOldOrigin( rPt );
307         // --> OD 2005-09-30 #i54875# - It's not needed to get the graphic again.
308 //        const Graphic&  rGraphic = GetGraphic();
309         // <--
310 		const MapMode	aMap100( MAP_100TH_MM );
311 		Size			aSize100;
312 		long			nTotalWidth, nTotalHeight;
313 		long			nNewLeft, nNewTop, nNewRight, nNewBottom;
314 		double			fScale;
315 
316 		if( nRot10 )
317 		{
318 			aClipPoly.Rotate( rPt, nRot10 );
319 			bRectClipRegion = sal_False;
320 		}
321 		else
322 			bRectClipRegion = sal_True;
323 
324 		rClipPolyPoly = aClipPoly;
325 
326         // --> OD 2005-09-30 #i54875# - directly access member <maGraphic> to
327         // get <PrefSize> and <PrefMapMode>.
328 //        if( rGraphic.GetPrefMapMode() == MAP_PIXEL )
329 //            aSize100 = Application::GetDefaultDevice()->PixelToLogic( rGraphic.GetPrefSize(), aMap100 );
330 //        else
331 //            aSize100 = pOut->LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), aMap100 );
332         if( maGraphic.GetPrefMapMode() == MAP_PIXEL )
333             aSize100 = Application::GetDefaultDevice()->PixelToLogic( maGraphic.GetPrefSize(), aMap100 );
334         else
335         {
336             MapMode m(maGraphic.GetPrefMapMode());
337             aSize100 = pOut->LogicToLogic( maGraphic.GetPrefSize(), &m, &aMap100 );
338         }
339         // <--
340 
341 		nTotalWidth = aSize100.Width() - pAttr->GetLeftCrop() - pAttr->GetRightCrop();
342 		nTotalHeight = aSize100.Height() - pAttr->GetTopCrop() - pAttr->GetBottomCrop();
343 
344 		if( aSize100.Width() > 0 && aSize100.Height() > 0 && nTotalWidth > 0 && nTotalHeight > 0 )
345 		{
346 			fScale = (double) aSize100.Width() / nTotalWidth;
347 			nNewLeft = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_HORZ ) ? pAttr->GetRightCrop() : pAttr->GetLeftCrop() ) * fScale );
348 			nNewRight = nNewLeft + FRound( aSize100.Width() * fScale ) - 1;
349 
350 			fScale = (double) rSz.Width() / aSize100.Width();
351 			rPt.X() += FRound( nNewLeft * fScale );
352 			rSz.Width() = FRound( ( nNewRight - nNewLeft + 1 ) * fScale );
353 
354 			fScale = (double) aSize100.Height() / nTotalHeight;
355 			nNewTop = -FRound( ( ( pAttr->GetMirrorFlags() & BMP_MIRROR_VERT ) ? pAttr->GetBottomCrop() : pAttr->GetTopCrop() ) * fScale );
356 			nNewBottom = nNewTop + FRound( aSize100.Height() * fScale ) - 1;
357 
358 			fScale = (double) rSz.Height() / aSize100.Height();
359 			rPt.Y() += FRound( nNewTop * fScale );
360 			rSz.Height() = FRound( ( nNewBottom - nNewTop + 1 ) * fScale );
361 
362 			if( nRot10 )
363 			{
364 				Polygon aOriginPoly( 1 );
365 
366 				aOriginPoly[ 0 ] = rPt;
367 				aOriginPoly.Rotate( aOldOrigin, nRot10 );
368 				rPt = aOriginPoly[ 0 ];
369 			}
370 
371 			bRet = sal_True;
372 		}
373 	}
374 
375 	return bRet;
376 }
377 
378 // -----------------------------------------------------------------------------
379 
380 GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj )
381 {
382 	if( &rGraphicObj != this )
383 	{
384 		mpMgr->ImplUnregisterObj( *this );
385 
386 		delete mpSwapStreamHdl, mpSwapStreamHdl = NULL;
387 		delete mpSimpleCache, mpSimpleCache = NULL;
388 		delete mpLink;
389 		delete mpUserData;
390 
391 		maGraphic = rGraphicObj.GetGraphic();
392 		maAttr = rGraphicObj.maAttr;
393 		mpLink = rGraphicObj.mpLink ? new String( *rGraphicObj.mpLink ) : NULL;
394 		mpUserData = rGraphicObj.mpUserData ? new String( *rGraphicObj.mpUserData ) : NULL;
395 		ImplAssignGraphicData();
396 		mbAutoSwapped = sal_False;
397 		mpMgr = rGraphicObj.mpMgr;
398 
399 		mpMgr->ImplRegisterObj( *this, maGraphic, NULL, &rGraphicObj );
400 	}
401 
402 	return *this;
403 }
404 
405 // -----------------------------------------------------------------------------
406 
407 sal_Bool GraphicObject::operator==( const GraphicObject& rGraphicObj ) const
408 {
409 	return(	( rGraphicObj.maGraphic == maGraphic ) &&
410 			( rGraphicObj.maAttr == maAttr ) &&
411 			( rGraphicObj.GetLink() == GetLink() ) );
412 }
413 
414 // ------------------------------------------------------------------------
415 
416 void GraphicObject::Load( SvStream& rIStm )
417 {
418     rIStm >> *this;
419 }
420 
421 // ------------------------------------------------------------------------
422 
423 void GraphicObject::Save( SvStream& rOStm )
424 {
425     rOStm << *this;
426 }
427 
428 // ------------------------------------------------------------------------
429 
430 void GraphicObject::Assign( const SvDataCopyStream& rCopyStream )
431 {
432     *this = (const GraphicObject& ) rCopyStream;
433 }
434 
435 // -----------------------------------------------------------------------------
436 
437 ByteString GraphicObject::GetUniqueID() const
438 {
439 	if ( !IsInSwapIn() && IsEPS() )
440 		const_cast<GraphicObject*>(this)->FireSwapInRequest();
441 
442 	ByteString aRet;
443 
444 	if( mpMgr )
445 		aRet = mpMgr->ImplGetUniqueID( *this );
446 
447 	return aRet;
448 }
449 
450 // -----------------------------------------------------------------------------
451 
452 sal_uLong GraphicObject::GetChecksum() const
453 {
454 	return( ( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() ) ? maGraphic.GetChecksum() : 0 );
455 }
456 
457 // -----------------------------------------------------------------------------
458 
459 SvStream* GraphicObject::GetSwapStream() const
460 {
461 	return( HasSwapStreamHdl() ? (SvStream*) mpSwapStreamHdl->Call( (void*) this ) : GRFMGR_AUTOSWAPSTREAM_NONE );
462 }
463 
464 // -----------------------------------------------------------------------------
465 
466 // !!! to be removed
467 sal_uLong GraphicObject::GetReleaseFromCache() const
468 {
469 	return 0;
470 }
471 
472 // -----------------------------------------------------------------------------
473 
474 void GraphicObject::SetAttr( const GraphicAttr& rAttr )
475 {
476 	maAttr = rAttr;
477 
478 	if( mpSimpleCache && ( mpSimpleCache->maAttr != rAttr ) )
479 		delete mpSimpleCache, mpSimpleCache = NULL;
480 }
481 
482 // -----------------------------------------------------------------------------
483 
484 void GraphicObject::SetLink()
485 {
486 	if( mpLink )
487 		delete mpLink, mpLink = NULL;
488 }
489 
490 // -----------------------------------------------------------------------------
491 
492 void GraphicObject::SetLink( const String& rLink )
493 {
494 	delete mpLink, mpLink = new String( rLink );
495 }
496 
497 // -----------------------------------------------------------------------------
498 
499 String GraphicObject::GetLink() const
500 {
501 	if( mpLink )
502 		return *mpLink;
503 	else
504 		return String();
505 }
506 
507 // -----------------------------------------------------------------------------
508 
509 void GraphicObject::SetUserData()
510 {
511 	if( mpUserData )
512 		delete mpUserData, mpUserData = NULL;
513 }
514 
515 // -----------------------------------------------------------------------------
516 
517 void GraphicObject::SetUserData( const String& rUserData )
518 {
519 	delete mpUserData, mpUserData = new String( rUserData );
520 }
521 
522 // -----------------------------------------------------------------------------
523 
524 String GraphicObject::GetUserData() const
525 {
526 	if( mpUserData )
527 		return *mpUserData;
528 	else
529 		return String();
530 }
531 
532 // -----------------------------------------------------------------------------
533 
534 void GraphicObject::SetSwapStreamHdl()
535 {
536 	if( mpSwapStreamHdl )
537 	{
538 		delete mpSwapOutTimer, mpSwapOutTimer = NULL;
539 		delete mpSwapStreamHdl, mpSwapStreamHdl = NULL;
540 	}
541 }
542 
543 // -----------------------------------------------------------------------------
544 
545 void GraphicObject::SetSwapStreamHdl( const Link& rHdl, const sal_uLong nSwapOutTimeout )
546 {
547 	delete mpSwapStreamHdl,	mpSwapStreamHdl = new Link( rHdl );
548 
549 	if( nSwapOutTimeout )
550 	{
551 		if( !mpSwapOutTimer )
552 		{
553 			mpSwapOutTimer = new Timer;
554 			mpSwapOutTimer->SetTimeoutHdl( LINK( this, GraphicObject, ImplAutoSwapOutHdl ) );
555 		}
556 
557 		mpSwapOutTimer->SetTimeout( nSwapOutTimeout );
558 		mpSwapOutTimer->Start();
559 	}
560 	else
561 		delete mpSwapOutTimer, mpSwapOutTimer = NULL;
562 }
563 
564 // -----------------------------------------------------------------------------
565 
566 Link GraphicObject::GetSwapStreamHdl() const
567 {
568 	if( mpSwapStreamHdl )
569 		return *mpSwapStreamHdl;
570 	else
571 		return Link();
572 }
573 
574 // -----------------------------------------------------------------------------
575 
576 void GraphicObject::FireSwapInRequest()
577 {
578 	ImplAutoSwapIn();
579 }
580 
581 // -----------------------------------------------------------------------------
582 
583 void GraphicObject::FireSwapOutRequest()
584 {
585 	ImplAutoSwapOutHdl( NULL );
586 }
587 
588 // -----------------------------------------------------------------------------
589 
590 void GraphicObject::GraphicManagerDestroyed()
591 {
592 	// we're alive, but our manager doesn't live anymore ==> connect to default manager
593 	mpMgr = NULL;
594 	ImplSetGraphicManager( NULL );
595 }
596 
597 // -----------------------------------------------------------------------------
598 
599 void GraphicObject::SetGraphicManager( const GraphicManager& rMgr )
600 {
601 	ImplSetGraphicManager( &rMgr );
602 }
603 
604 // -----------------------------------------------------------------------------
605 
606 sal_Bool GraphicObject::IsCached( OutputDevice* pOut, const Point& rPt, const Size& rSz,
607 							  const GraphicAttr* pAttr, sal_uLong nFlags ) const
608 {
609 	sal_Bool bRet;
610 
611 	if( nFlags & GRFMGR_DRAW_CACHED )
612     {
613         // --> OD 2005-10-11 #i54875# - Consider cropped graphics.
614         // Note: The graphic manager caches a cropped graphic with its
615         //       uncropped position and size.
616 //        bRet = mpMgr->IsInCache( pOut, rPt, rSz, *this, ( pAttr ? *pAttr : GetAttr() ) );
617         Point aPt( rPt );
618         Size aSz( rSz );
619         if ( pAttr->IsCropped() )
620         {
621             PolyPolygon aClipPolyPoly;
622             sal_Bool        bRectClip;
623             ImplGetCropParams( pOut, aPt, aSz, pAttr, aClipPolyPoly, bRectClip );
624         }
625         bRet = mpMgr->IsInCache( pOut, aPt, aSz, *this, ( pAttr ? *pAttr : GetAttr() ) );
626     }
627 	else
628 		bRet = sal_False;
629 
630 	return bRet;
631 }
632 
633 // -----------------------------------------------------------------------------
634 
635 void GraphicObject::ReleaseFromCache()
636 {
637 
638 	mpMgr->ReleaseFromCache( *this );
639 }
640 
641 // -----------------------------------------------------------------------------
642 
643 void GraphicObject::SetAnimationNotifyHdl( const Link& rLink )
644 {
645 	maGraphic.SetAnimationNotifyHdl( rLink );
646 }
647 
648 // -----------------------------------------------------------------------------
649 
650 List* GraphicObject::GetAnimationInfoList() const
651 {
652 	return maGraphic.GetAnimationInfoList();
653 }
654 
655 // -----------------------------------------------------------------------------
656 
657 sal_Bool GraphicObject::Draw( OutputDevice* pOut, const Point& rPt, const Size& rSz,
658 						  const GraphicAttr* pAttr, sal_uLong nFlags )
659 {
660 	GraphicAttr	        aAttr( pAttr ? *pAttr : GetAttr() );
661 	Point 		        aPt( rPt );
662 	Size  	            aSz( rSz );
663     const sal_uInt32    nOldDrawMode = pOut->GetDrawMode();
664 	sal_Bool		        bCropped = aAttr.IsCropped();
665 	sal_Bool		        bCached = sal_False;
666 	sal_Bool		        bRet;
667 
668     // #i29534# Provide output rects for PDF writer
669     Rectangle			aCropRect;
670 
671     if( !( GRFMGR_DRAW_USE_DRAWMODE_SETTINGS & nFlags ) )
672         pOut->SetDrawMode( nOldDrawMode & ( ~( DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT ) ) );
673 
674 	// mirrored horizontically
675 	if( aSz.Width() < 0L )
676 	{
677 		aPt.X() += aSz.Width() + 1;
678 		aSz.Width() = -aSz.Width();
679 		aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_HORZ );
680 	}
681 
682 	// mirrored vertically
683 	if( aSz.Height() < 0L )
684 	{
685 		aPt.Y() += aSz.Height() + 1;
686 		aSz.Height() = -aSz.Height();
687 		aAttr.SetMirrorFlags( aAttr.GetMirrorFlags() ^ BMP_MIRROR_VERT );
688 	}
689 
690 	if( bCropped )
691 	{
692 		PolyPolygon aClipPolyPoly;
693 		sal_Bool		bRectClip;
694 		const sal_Bool	bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
695 
696 		pOut->Push( PUSH_CLIPREGION );
697 
698 		if( bCrop )
699 		{
700 			if( bRectClip )
701             {
702                 // #i29534# Store crop rect for later forwarding to
703                 // PDF writer
704                 aCropRect = aClipPolyPoly.GetBoundRect();
705 				pOut->IntersectClipRegion( aCropRect );
706             }
707 			else
708             {
709 				pOut->IntersectClipRegion( aClipPolyPoly );
710             }
711 		}
712 	}
713 
714 	bRet = mpMgr->DrawObj( pOut, aPt, aSz, *this, aAttr, nFlags, bCached );
715 
716 	if( bCropped )
717 		pOut->Pop();
718 
719     pOut->SetDrawMode( nOldDrawMode );
720 
721     // #i29534# Moved below OutDev restoration, to avoid multiple swap-ins
722     // (code above needs to call GetGraphic twice)
723 	if( bCached )
724 	{
725 		if( mpSwapOutTimer )
726 			mpSwapOutTimer->Start();
727 		else
728 			FireSwapOutRequest();
729 	}
730 
731 	return bRet;
732 }
733 
734 // --> OD 2010-01-04 #i105243#
735 sal_Bool GraphicObject::DrawWithPDFHandling( OutputDevice& rOutDev,
736                                          const Point& rPt, const Size& rSz,
737                                          const GraphicAttr* pGrfAttr,
738                                          const sal_uLong nFlags )
739 {
740     const GraphicAttr aGrfAttr( pGrfAttr ? *pGrfAttr : GetAttr() );
741 
742     // Notify PDF writer about linked graphic (if any)
743     sal_Bool bWritingPdfLinkedGraphic( sal_False );
744     Point aPt( rPt );
745     Size aSz( rSz );
746     Rectangle aCropRect;
747     vcl::PDFExtOutDevData* pPDFExtOutDevData =
748             dynamic_cast<vcl::PDFExtOutDevData*>(rOutDev.GetExtOutDevData());
749     if( pPDFExtOutDevData )
750     {
751         // only delegate image handling to PDF, if no special treatment is necessary
752         if( GetGraphic().IsLink() &&
753             rSz.Width() > 0L &&
754             rSz.Height() > 0L &&
755             !aGrfAttr.IsSpecialDrawMode() &&
756             !aGrfAttr.IsMirrored() &&
757             !aGrfAttr.IsRotated() &&
758             !aGrfAttr.IsAdjusted() )
759         {
760             bWritingPdfLinkedGraphic = true;
761 
762             if( aGrfAttr.IsCropped() )
763             {
764                 PolyPolygon aClipPolyPoly;
765                 sal_Bool bRectClip;
766                 const sal_Bool bCrop = ImplGetCropParams( &rOutDev,
767                                                       aPt, aSz,
768                                                       &aGrfAttr,
769                                                       aClipPolyPoly,
770                                                       bRectClip );
771                 if ( bCrop && bRectClip )
772                 {
773                     aCropRect = aClipPolyPoly.GetBoundRect();
774                 }
775             }
776 
777             pPDFExtOutDevData->BeginGroup();
778         }
779     }
780 
781     sal_Bool bRet = Draw( &rOutDev, rPt, rSz, &aGrfAttr, nFlags );
782 
783     // Notify PDF writer about linked graphic (if any)
784     if( bWritingPdfLinkedGraphic )
785     {
786         pPDFExtOutDevData->EndGroup( const_cast< Graphic& >(GetGraphic()),
787                                      aGrfAttr.GetTransparency(),
788                                      Rectangle( aPt, aSz ),
789                                      aCropRect );
790     }
791 
792     return bRet;
793 }
794 // <--
795 
796 // -----------------------------------------------------------------------------
797 
798 sal_Bool GraphicObject::DrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSize,
799                                const Size& rOffset, const GraphicAttr* pAttr, sal_uLong nFlags, int nTileCacheSize1D )
800 {
801     if( pOut == NULL || rSize.Width() == 0 || rSize.Height() == 0 )
802         return sal_False;
803 
804     const MapMode 	aOutMapMode( pOut->GetMapMode() );
805     const MapMode	aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() );
806     // #106258# Clamp size to 1 for zero values. This is okay, since
807     // logical size of zero is handled above already
808     const Size		aOutTileSize( ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Width() ),
809                                   ::std::max( 1L, pOut->LogicToPixel( rSize, aOutMapMode ).Height() ) );
810 
811 	//#i69780 clip final tile size to a sane max size
812     while (((sal_Int64)rSize.Width() * nTileCacheSize1D) > SAL_MAX_UINT16)
813         nTileCacheSize1D /= 2;
814     while (((sal_Int64)rSize.Height() * nTileCacheSize1D) > SAL_MAX_UINT16)
815         nTileCacheSize1D /= 2;
816 
817     return ImplDrawTiled( pOut, rArea, aOutTileSize, rOffset, pAttr, nFlags, nTileCacheSize1D );
818 }
819 
820 // -----------------------------------------------------------------------------
821 
822 sal_Bool GraphicObject::StartAnimation( OutputDevice* pOut, const Point& rPt, const Size& rSz,
823 									long nExtraData, const GraphicAttr* pAttr, sal_uLong /*nFlags*/,
824 									OutputDevice* pFirstFrameOutDev )
825 {
826 	sal_Bool bRet = sal_False;
827 
828 	GetGraphic();
829 
830 	if( !IsSwappedOut() )
831 	{
832     	const GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
833 
834 		if( mbAnimated )
835 		{
836 			Point   aPt( rPt );
837 			Size	aSz( rSz );
838 			sal_Bool	bCropped = aAttr.IsCropped();
839 
840 			if( bCropped )
841 			{
842 				PolyPolygon aClipPolyPoly;
843 				sal_Bool		bRectClip;
844 				const sal_Bool	bCrop = ImplGetCropParams( pOut, aPt, aSz, &aAttr, aClipPolyPoly, bRectClip );
845 
846 				pOut->Push( PUSH_CLIPREGION );
847 
848 				if( bCrop )
849 				{
850 					if( bRectClip )
851 						pOut->IntersectClipRegion( aClipPolyPoly.GetBoundRect() );
852 					else
853 						pOut->IntersectClipRegion( aClipPolyPoly );
854 				}
855 			}
856 
857 			if( !mpSimpleCache || ( mpSimpleCache->maAttr != aAttr ) || pFirstFrameOutDev )
858 			{
859 				if( mpSimpleCache )
860 					delete mpSimpleCache;
861 
862 				mpSimpleCache = new GrfSimpleCacheObj( GetTransformedGraphic( &aAttr ), aAttr );
863 				mpSimpleCache->maGraphic.SetAnimationNotifyHdl( GetAnimationNotifyHdl() );
864 			}
865 
866 			mpSimpleCache->maGraphic.StartAnimation( pOut, aPt, aSz, nExtraData, pFirstFrameOutDev );
867 
868 			if( bCropped )
869 				pOut->Pop();
870 
871 			bRet = sal_True;
872 		}
873 		else
874 			bRet = Draw( pOut, rPt, rSz, &aAttr, GRFMGR_DRAW_STANDARD );
875 	}
876 
877 	return bRet;
878 }
879 
880 // -----------------------------------------------------------------------------
881 
882 void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData )
883 {
884 	if( mpSimpleCache )
885 		mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData );
886 }
887 
888 // -----------------------------------------------------------------------------
889 
890 const Graphic& GraphicObject::GetGraphic() const
891 {
892 	if( mbAutoSwapped )
893 		( (GraphicObject*) this )->ImplAutoSwapIn();
894 
895 	return maGraphic;
896 }
897 
898 // -----------------------------------------------------------------------------
899 
900 void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pCopyObj )
901 {
902 	mpMgr->ImplUnregisterObj( *this );
903 
904 	if( mpSwapOutTimer )
905 		mpSwapOutTimer->Stop();
906 
907 	maGraphic = rGraphic;
908 	mbAutoSwapped = sal_False;
909 	ImplAssignGraphicData();
910 	delete mpLink, mpLink = NULL;
911 	delete mpSimpleCache, mpSimpleCache = NULL;
912 
913 	mpMgr->ImplRegisterObj( *this, maGraphic, 0, pCopyObj);
914 
915 	if( mpSwapOutTimer )
916 		mpSwapOutTimer->Start();
917 }
918 
919 // -----------------------------------------------------------------------------
920 
921 void GraphicObject::SetGraphic( const Graphic& rGraphic, const String& rLink )
922 {
923 	SetGraphic( rGraphic );
924 	mpLink = new String( rLink );
925 }
926 
927 // -----------------------------------------------------------------------------
928 
929 Graphic GraphicObject::GetTransformedGraphic( const Size& rDestSize, const MapMode& rDestMap, const GraphicAttr& rAttr ) const
930 {
931     // #104550# Extracted from svx/source/svdraw/svdograf.cxx
932 	Graphic		    	aTransGraphic( maGraphic );
933 	const GraphicType	eType = GetType();
934     const Size      	aSrcSize( aTransGraphic.GetPrefSize() );
935 
936     // #104115# Convert the crop margins to graphic object mapmode
937     const MapMode aMapGraph( aTransGraphic.GetPrefMapMode() );
938     const MapMode aMap100( MAP_100TH_MM );
939 
940     Size aCropLeftTop;
941     Size aCropRightBottom;
942 
943     if( GRAPHIC_GDIMETAFILE == eType )
944     {
945         GDIMetaFile aMtf( aTransGraphic.GetGDIMetaFile() );
946 
947         if( aMapGraph == MAP_PIXEL )
948         {
949             // crops are in 1/100th mm -> to aMapGraph -> to MAP_PIXEL
950             aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
951                 Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
952                 aMap100);
953             aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
954                 Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
955                 aMap100);
956         }
957         else
958         {
959             // crops are in GraphicObject units -> to aMapGraph
960             aCropLeftTop = OutputDevice::LogicToLogic(
961                 Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
962                 aMap100,
963                 aMapGraph);
964             aCropRightBottom = OutputDevice::LogicToLogic(
965                 Size(rAttr.GetRightCrop(), 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         Rectangle aCropRect;
1016 
1017         // convert crops to pixel
1018         if(rAttr.IsCropped())
1019         {
1020             if( aMapGraph == MAP_PIXEL )
1021             {
1022                 // crops are in 1/100th mm -> to MAP_PIXEL
1023                 aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
1024                     Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
1025                     aMap100);
1026                 aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
1027                     Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
1028                     aMap100);
1029             }
1030             else
1031             {
1032                 // crops are in GraphicObject units -> to MAP_PIXEL
1033                 aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
1034                     Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
1035                     aMapGraph);
1036                 aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
1037                     Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
1038                     aMapGraph);
1039             }
1040 
1041             // convert from prefmapmode to pixel
1042             Size aSrcSizePixel(
1043                 Application::GetDefaultDevice()->LogicToPixel(
1044                     aSrcSize,
1045                     aMapGraph));
1046 
1047             if(rAttr.IsCropped()
1048                 && (aSrcSizePixel.Width() != aBitmapEx.GetSizePixel().Width() || aSrcSizePixel.Height() != aBitmapEx.GetSizePixel().Height())
1049                 && aSrcSizePixel.Width())
1050             {
1051                 // the size in pixels calculated from Graphic's internal MapMode (aTransGraphic.GetPrefMapMode())
1052                 // and it's internal size (aTransGraphic.GetPrefSize()) is different from it's real pixel size.
1053                 // This can be interpreted as this values to be set wrong, but needs to be corrected since e.g.
1054                 // existing cropping is calculated based on this logic values already.
1055                 // aBitmapEx.Scale(aSrcSizePixel);
1056 
1057                 // another possibility is to adapt the values created so far with a factor; this
1058                 // will keep the original Bitmap untouched and thus quality will not change
1059                 // caution: convert to double first, else pretty big errors may occurr
1060                 const double fFactorX((double)aBitmapEx.GetSizePixel().Width() / aSrcSizePixel.Width());
1061                 const double fFactorY((double)aBitmapEx.GetSizePixel().Height() / aSrcSizePixel.Height());
1062 
1063                 aCropLeftTop.Width() = basegfx::fround(aCropLeftTop.Width() * fFactorX);
1064                 aCropLeftTop.Height() = basegfx::fround(aCropLeftTop.Height() * fFactorY);
1065                 aCropRightBottom.Width() = basegfx::fround(aCropRightBottom.Width() * fFactorX);
1066                 aCropRightBottom.Height() = basegfx::fround(aCropRightBottom.Height() * fFactorY);
1067 
1068                 aSrcSizePixel = aBitmapEx.GetSizePixel();
1069             }
1070 
1071             // setup crop rectangle in pixel
1072             aCropRect = Rectangle( aCropLeftTop.Width(), aCropLeftTop.Height(),
1073                                  aSrcSizePixel.Width() - aCropRightBottom.Width(),
1074                                  aSrcSizePixel.Height() - aCropRightBottom.Height() );
1075         }
1076 
1077         // #105641# Also crop animations
1078         if( aTransGraphic.IsAnimated() )
1079         {
1080             sal_uInt16 nFrame;
1081             Animation aAnim( aTransGraphic.GetAnimation() );
1082 
1083             for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
1084             {
1085                 AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
1086 
1087                 if( !aCropRect.IsInside( Rectangle(aAnimBmp.aPosPix, aAnimBmp.aSizePix) ) )
1088                 {
1089                     // setup actual cropping (relative to frame position)
1090                     Rectangle aCropRectRel( aCropRect );
1091                     aCropRectRel.Move( -aAnimBmp.aPosPix.X(),
1092                                        -aAnimBmp.aPosPix.Y() );
1093 
1094                     // cropping affects this frame, apply it then
1095                     // do _not_ apply enlargement, this is done below
1096                     ImplTransformBitmap( aAnimBmp.aBmpEx, rAttr, Size(), Size(),
1097                                          aCropRectRel, rDestSize, sal_False );
1098 
1099                     aAnim.Replace( aAnimBmp, nFrame );
1100                 }
1101                 // else: bitmap completely within crop area,
1102                 // i.e. nothing is cropped away
1103             }
1104 
1105             // now, apply enlargement (if any) through global animation size
1106             if( aCropLeftTop.Width() < 0 ||
1107                 aCropLeftTop.Height() < 0 ||
1108                 aCropRightBottom.Width() < 0 ||
1109                 aCropRightBottom.Height() < 0 )
1110             {
1111                 Size aNewSize( aAnim.GetDisplaySizePixel() );
1112                 aNewSize.Width() += aCropRightBottom.Width() < 0 ? -aCropRightBottom.Width() : 0;
1113                 aNewSize.Width() += aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0;
1114                 aNewSize.Height() += aCropRightBottom.Height() < 0 ? -aCropRightBottom.Height() : 0;
1115                 aNewSize.Height() += aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0;
1116                 aAnim.SetDisplaySizePixel( aNewSize );
1117             }
1118 
1119             // if topleft has changed, we must move all frames to the
1120             // right and bottom, resp.
1121             if( aCropLeftTop.Width() < 0 ||
1122                 aCropLeftTop.Height() < 0 )
1123             {
1124                 Point aPosOffset( aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0,
1125                                   aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0 );
1126 
1127                 for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
1128                 {
1129                     AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
1130 
1131                     aAnimBmp.aPosPix += aPosOffset;
1132 
1133                     aAnim.Replace( aAnimBmp, nFrame );
1134                 }
1135             }
1136 
1137             aTransGraphic = aAnim;
1138         }
1139         else
1140         {
1141             ImplTransformBitmap( aBitmapEx, rAttr, aCropLeftTop, aCropRightBottom,
1142                                  aCropRect, rDestSize, sal_True );
1143 
1144             aTransGraphic = aBitmapEx;
1145         }
1146 
1147         aTransGraphic.SetPrefSize( rDestSize );
1148         aTransGraphic.SetPrefMapMode( rDestMap );
1149     }
1150 
1151     GraphicObject aGrfObj( aTransGraphic );
1152     aTransGraphic = aGrfObj.GetTransformedGraphic( &rAttr );
1153 
1154 	return aTransGraphic;
1155 }
1156 
1157 // -----------------------------------------------------------------------------
1158 
1159 Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const // TODO: Change to Impl
1160 {
1161 	GetGraphic();
1162 
1163 	Graphic     aGraphic;
1164     GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
1165 
1166 	if( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() )
1167 	{
1168 		if( aAttr.IsSpecialDrawMode() || aAttr.IsAdjusted() || aAttr.IsMirrored() || aAttr.IsRotated() || aAttr.IsTransparent() )
1169 		{
1170 			if( GetType() == GRAPHIC_BITMAP )
1171 			{
1172 				if( IsAnimated() )
1173 				{
1174 					Animation aAnimation( maGraphic.GetAnimation() );
1175 					GraphicManager::ImplAdjust( aAnimation, aAttr, ADJUSTMENT_ALL );
1176                     aAnimation.SetLoopCount( mnAnimationLoopCount );
1177 					aGraphic = aAnimation;
1178 				}
1179 				else
1180 				{
1181 					BitmapEx aBmpEx( maGraphic.GetBitmapEx() );
1182 					GraphicManager::ImplAdjust( aBmpEx, aAttr, ADJUSTMENT_ALL );
1183 					aGraphic = aBmpEx;
1184 				}
1185 			}
1186 			else
1187 			{
1188 				GDIMetaFile aMtf( maGraphic.GetGDIMetaFile() );
1189 				GraphicManager::ImplAdjust( aMtf, aAttr, ADJUSTMENT_ALL );
1190 				aGraphic = aMtf;
1191 			}
1192 		}
1193 		else
1194         {
1195 			if( ( GetType() == GRAPHIC_BITMAP ) && IsAnimated() )
1196 			{
1197 				Animation aAnimation( maGraphic.GetAnimation() );
1198                 aAnimation.SetLoopCount( mnAnimationLoopCount );
1199 				aGraphic = aAnimation;
1200 			}
1201             else
1202 			    aGraphic = maGraphic;
1203         }
1204 	}
1205 
1206 	return aGraphic;
1207 }
1208 
1209 // -----------------------------------------------------------------------------
1210 
1211 void GraphicObject::ResetAnimationLoopCount()
1212 {
1213 	if( IsAnimated() && !IsSwappedOut() )
1214 	{
1215 		maGraphic.ResetAnimationLoopCount();
1216 
1217 		if( mpSimpleCache )
1218 			mpSimpleCache->maGraphic.ResetAnimationLoopCount();
1219 	}
1220 }
1221 
1222 // -----------------------------------------------------------------------------
1223 
1224 sal_Bool GraphicObject::SwapOut()
1225 {
1226 	sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut() : sal_False );
1227 
1228 	if( bRet && mpMgr )
1229 		mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1230 
1231 	return bRet;
1232 }
1233 
1234 // -----------------------------------------------------------------------------
1235 
1236 sal_Bool GraphicObject::SwapOut( SvStream* pOStm )
1237 {
1238 	sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut( pOStm ) : sal_False );
1239 
1240 	if( bRet && mpMgr )
1241 		mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1242 
1243 	return bRet;
1244 }
1245 
1246 // -----------------------------------------------------------------------------
1247 
1248 sal_Bool GraphicObject::SwapIn()
1249 {
1250 	sal_Bool bRet;
1251 
1252 	if( mbAutoSwapped )
1253 	{
1254 		ImplAutoSwapIn();
1255 		bRet = sal_True;
1256 	}
1257 	else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
1258 		bRet = sal_True;
1259 	else
1260 	{
1261 		bRet = maGraphic.SwapIn();
1262 
1263 		if( bRet && mpMgr )
1264 			mpMgr->ImplGraphicObjectWasSwappedIn( *this );
1265 	}
1266 
1267 	if( bRet )
1268 		ImplAssignGraphicData();
1269 
1270 	return bRet;
1271 }
1272 
1273 // -----------------------------------------------------------------------------
1274 
1275 sal_Bool GraphicObject::SwapIn( SvStream* pIStm )
1276 {
1277 	sal_Bool bRet;
1278 
1279 	if( mbAutoSwapped )
1280 	{
1281 		ImplAutoSwapIn();
1282 		bRet = sal_True;
1283 	}
1284 	else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
1285 		bRet = sal_True;
1286 	else
1287 	{
1288 		bRet = maGraphic.SwapIn( pIStm );
1289 
1290 		if( bRet && mpMgr )
1291 			mpMgr->ImplGraphicObjectWasSwappedIn( *this );
1292 	}
1293 
1294 	if( bRet )
1295 		ImplAssignGraphicData();
1296 
1297 	return bRet;
1298 }
1299 
1300 // -----------------------------------------------------------------------------
1301 
1302 void GraphicObject::SetSwapState()
1303 {
1304 	if( !IsSwappedOut() )
1305 	{
1306 		mbAutoSwapped = sal_True;
1307 
1308 		if( mpMgr )
1309 			mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1310 	}
1311 }
1312 
1313 // -----------------------------------------------------------------------------
1314 
1315 IMPL_LINK( GraphicObject, ImplAutoSwapOutHdl, void*, EMPTYARG )
1316 {
1317 	if( !IsSwappedOut() )
1318 	{
1319 		mbIsInSwapOut = sal_True;
1320 
1321 		SvStream* pStream = GetSwapStream();
1322 
1323 		if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
1324 		{
1325 			if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
1326 				mbAutoSwapped = SwapOut( NULL );
1327 			else
1328 			{
1329 				if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
1330 					mbAutoSwapped = SwapOut();
1331 				else
1332 				{
1333 					mbAutoSwapped = SwapOut( pStream );
1334 					delete pStream;
1335 				}
1336 			}
1337 		}
1338 
1339 		mbIsInSwapOut = sal_False;
1340 	}
1341 
1342 	if( mpSwapOutTimer )
1343 		mpSwapOutTimer->Start();
1344 
1345 	return 0L;
1346 }
1347 
1348 // ------------------------------------------------------------------------
1349 
1350 SvStream& operator>>( SvStream& rIStm, GraphicObject& rGraphicObj )
1351 {
1352 	VersionCompat	aCompat( rIStm, STREAM_READ );
1353 	Graphic			aGraphic;
1354 	GraphicAttr		aAttr;
1355 	ByteString		aLink;
1356 	sal_Bool			bLink;
1357 
1358 	rIStm >> aGraphic >> aAttr >> bLink;
1359 
1360 	rGraphicObj.SetGraphic( aGraphic );
1361 	rGraphicObj.SetAttr( aAttr );
1362 
1363 	if( bLink )
1364 	{
1365 		rIStm >> aLink;
1366 		rGraphicObj.SetLink( UniString( aLink, RTL_TEXTENCODING_UTF8 ) );
1367 	}
1368 	else
1369 		rGraphicObj.SetLink();
1370 
1371 	rGraphicObj.SetSwapStreamHdl();
1372 
1373 	return rIStm;
1374 }
1375 
1376 // ------------------------------------------------------------------------
1377 
1378 SvStream& operator<<( SvStream& rOStm, const GraphicObject& rGraphicObj )
1379 {
1380 	VersionCompat	aCompat( rOStm, STREAM_WRITE, 1 );
1381 	const sal_Bool		bLink =  rGraphicObj.HasLink();
1382 
1383 	rOStm << rGraphicObj.GetGraphic() << rGraphicObj.GetAttr() << bLink;
1384 
1385 	if( bLink )
1386 		rOStm << ByteString( rGraphicObj.GetLink(), RTL_TEXTENCODING_UTF8 );
1387 
1388 	return rOStm;
1389 }
1390 
1391 #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:"
1392 
1393 GraphicObject GraphicObject::CreateGraphicObjectFromURL( const ::rtl::OUString &rURL )
1394 {
1395 	const String aURL( rURL ), aPrefix( RTL_CONSTASCII_STRINGPARAM(UNO_NAME_GRAPHOBJ_URLPREFIX) );
1396 	if( aURL.Search( aPrefix ) == 0 )
1397 	{
1398 		// graphic manager url
1399 		ByteString aUniqueID( String(rURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 )), RTL_TEXTENCODING_UTF8 );
1400 		return GraphicObject( aUniqueID );
1401 	}
1402 	else
1403 	{
1404 		Graphic		aGraphic;
1405 		if ( aURL.Len() )
1406 		{
1407 			SvStream*	pStream = utl::UcbStreamHelper::CreateStream( aURL, STREAM_READ );
1408 			if( pStream )
1409 				GraphicConverter::Import( *pStream, aGraphic );
1410 		}
1411 
1412 		return GraphicObject( aGraphic );
1413 	}
1414 }
1415 
1416 // calculate scalings between real image size and logic object size. This
1417 // is necessary since the crop values are relative to original bitmap size
1418 basegfx::B2DVector GraphicObject::calculateCropScaling(
1419     double fWidth,
1420     double fHeight,
1421     double fLeftCrop,
1422     double fTopCrop,
1423     double fRightCrop,
1424     double fBottomCrop) const
1425 {
1426     const MapMode aMapMode100thmm(MAP_100TH_MM);
1427     Size aBitmapSize(GetPrefSize());
1428     double fFactorX(1.0);
1429     double fFactorY(1.0);
1430 
1431     if(MAP_PIXEL == GetPrefMapMode().GetMapUnit())
1432     {
1433         aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm);
1434     }
1435     else
1436     {
1437         aBitmapSize = Application::GetDefaultDevice()->LogicToLogic(aBitmapSize, GetPrefMapMode(), aMapMode100thmm);
1438     }
1439 
1440     const double fDivX(aBitmapSize.Width() - fLeftCrop - fRightCrop);
1441     const double fDivY(aBitmapSize.Height() - fTopCrop - fBottomCrop);
1442 
1443     if(!basegfx::fTools::equalZero(fDivX))
1444     {
1445         fFactorX = fabs(fWidth) / fDivX;
1446     }
1447 
1448     if(!basegfx::fTools::equalZero(fDivY))
1449     {
1450         fFactorY = fabs(fHeight) / fDivY;
1451     }
1452 
1453     return basegfx::B2DVector(fFactorX,fFactorY);
1454 }
1455 
1456 // eof
1457