xref: /aoo42x/main/svtools/source/graphic/grfmgr.cxx (revision 2376739d)
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             aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetLeftCrop(),
950                                                                                 rAttr.GetTopCrop() ),
951                                                                           aMap100 );
952             aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetRightCrop(),
953                                                                                     rAttr.GetBottomCrop() ),
954                                                                               aMap100 );
955         }
956         else
957         {
958             aCropLeftTop = OutputDevice::LogicToLogic( Size( rAttr.GetLeftCrop(),
959                                                              rAttr.GetTopCrop() ),
960                                                        aMap100,
961                                                        aMapGraph );
962             aCropRightBottom = OutputDevice::LogicToLogic( Size( rAttr.GetRightCrop(),
963                                                                  rAttr.GetBottomCrop() ),
964                                                            aMap100,
965                                                            aMapGraph );
966         }
967 
968         // #104115# If the metafile is cropped, give it a special
969         // treatment: clip against the remaining area, scale up such
970         // that this area later fills the desired size, and move the
971         // origin to the upper left edge of that area.
972         if( rAttr.IsCropped() )
973         {
974             const MapMode aMtfMapMode( aMtf.GetPrefMapMode() );
975 
976             Rectangle aClipRect( aMtfMapMode.GetOrigin().X() + aCropLeftTop.Width(),
977                                  aMtfMapMode.GetOrigin().Y() + aCropLeftTop.Height(),
978                                  aMtfMapMode.GetOrigin().X() + aSrcSize.Width() - aCropRightBottom.Width(),
979                                  aMtfMapMode.GetOrigin().Y() + aSrcSize.Height() - aCropRightBottom.Height() );
980 
981             // #104115# To correctly crop rotated metafiles, clip by view rectangle
982             aMtf.AddAction( new MetaISectRectClipRegionAction( aClipRect ), 0 );
983 
984             // #104115# To crop the metafile, scale larger than the output rectangle
985             aMtf.Scale( (double)rDestSize.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()),
986                         (double)rDestSize.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) );
987 
988             // #104115# Adapt the pref size by hand (scale changes it
989             // proportionally, but we want it to be smaller than the
990             // former size, to crop the excess out)
991             aMtf.SetPrefSize( Size( (long)((double)rDestSize.Width() *  (1.0 + (aCropLeftTop.Width() + aCropRightBottom.Width()) / aSrcSize.Width())  + .5),
992                                     (long)((double)rDestSize.Height() * (1.0 + (aCropLeftTop.Height() + aCropRightBottom.Height()) / aSrcSize.Height()) + .5) ) );
993 
994             // #104115# Adapt the origin of the new mapmode, such that it
995             // is shifted to the place where the cropped output starts
996             Point aNewOrigin( (long)((double)aMtfMapMode.GetOrigin().X() + rDestSize.Width() * aCropLeftTop.Width() / (aSrcSize.Width() - aCropLeftTop.Width() - aCropRightBottom.Width()) + .5),
997                               (long)((double)aMtfMapMode.GetOrigin().Y() + rDestSize.Height() * aCropLeftTop.Height() / (aSrcSize.Height() - aCropLeftTop.Height() - aCropRightBottom.Height()) + .5) );
998             MapMode aNewMap( rDestMap );
999             aNewMap.SetOrigin( OutputDevice::LogicToLogic(aNewOrigin, aMtfMapMode, rDestMap) );
1000             aMtf.SetPrefMapMode( aNewMap );
1001         }
1002         else
1003         {
1004             aMtf.Scale( Fraction( rDestSize.Width(), aSrcSize.Width() ), Fraction( rDestSize.Height(), aSrcSize.Height() ) );
1005             aMtf.SetPrefMapMode( rDestMap );
1006         }
1007 
1008         aTransGraphic = aMtf;
1009     }
1010     else if( GRAPHIC_BITMAP == eType )
1011     {
1012         BitmapEx aBitmapEx( aTransGraphic.GetBitmapEx() );
1013         Rectangle aCropRect;
1014 
1015         // convert crops to pixel (crops are always in GraphicObject units)
1016         if(rAttr.IsCropped())
1017         {
1018             aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel(
1019                 Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()),
1020                 aMapGraph);
1021             aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel(
1022                 Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()),
1023                 aMapGraph);
1024 
1025             // convert from prefmapmode to pixel
1026             Size aSrcSizePixel(
1027                 Application::GetDefaultDevice()->LogicToPixel(
1028                     aSrcSize,
1029                     aMapGraph));
1030 
1031             if(rAttr.IsCropped()
1032                 && (aSrcSizePixel.Width() != aBitmapEx.GetSizePixel().Width() || aSrcSizePixel.Height() != aBitmapEx.GetSizePixel().Height())
1033                 && aSrcSizePixel.Width())
1034             {
1035                 // the size in pixels calculated from Graphic's internal MapMode (aTransGraphic.GetPrefMapMode())
1036                 // and it's internal size (aTransGraphic.GetPrefSize()) is different from it's real pixel size.
1037                 // This can be interpreted as this values to be set wrong, but needs to be corrected since e.g.
1038                 // existing cropping is calculated based on this logic values already.
1039                 // aBitmapEx.Scale(aSrcSizePixel);
1040 
1041                 // another possibility is to adapt the values created so far with a factor; this
1042                 // will keep the original Bitmap untouched and thus quality will not change
1043                 const double fFactorX(aBitmapEx.GetSizePixel().Width() / aSrcSizePixel.Width());
1044                 const double fFactorY(aBitmapEx.GetSizePixel().Height() / aSrcSizePixel.Height());
1045 
1046                 aCropLeftTop.Width() = basegfx::fround(aCropLeftTop.Width() * fFactorX);
1047                 aCropLeftTop.Height() = basegfx::fround(aCropLeftTop.Height() * fFactorY);
1048                 aCropRightBottom.Width() = basegfx::fround(aCropRightBottom.Width() * fFactorX);
1049                 aCropRightBottom.Height() = basegfx::fround(aCropRightBottom.Height() * fFactorY);
1050 
1051                 aSrcSizePixel = aBitmapEx.GetSizePixel();
1052             }
1053 
1054             // setup crop rectangle in pixel
1055             aCropRect = Rectangle( aCropLeftTop.Width(), aCropLeftTop.Height(),
1056                                  aSrcSizePixel.Width() - aCropRightBottom.Width(),
1057                                  aSrcSizePixel.Height() - aCropRightBottom.Height() );
1058         }
1059 
1060         // #105641# Also crop animations
1061         if( aTransGraphic.IsAnimated() )
1062         {
1063             sal_uInt16 nFrame;
1064             Animation aAnim( aTransGraphic.GetAnimation() );
1065 
1066             for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
1067             {
1068                 AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
1069 
1070                 if( !aCropRect.IsInside( Rectangle(aAnimBmp.aPosPix, aAnimBmp.aSizePix) ) )
1071                 {
1072                     // setup actual cropping (relative to frame position)
1073                     Rectangle aCropRectRel( aCropRect );
1074                     aCropRectRel.Move( -aAnimBmp.aPosPix.X(),
1075                                        -aAnimBmp.aPosPix.Y() );
1076 
1077                     // cropping affects this frame, apply it then
1078                     // do _not_ apply enlargement, this is done below
1079                     ImplTransformBitmap( aAnimBmp.aBmpEx, rAttr, Size(), Size(),
1080                                          aCropRectRel, rDestSize, sal_False );
1081 
1082                     aAnim.Replace( aAnimBmp, nFrame );
1083                 }
1084                 // else: bitmap completely within crop area,
1085                 // i.e. nothing is cropped away
1086             }
1087 
1088             // now, apply enlargement (if any) through global animation size
1089             if( aCropLeftTop.Width() < 0 ||
1090                 aCropLeftTop.Height() < 0 ||
1091                 aCropRightBottom.Width() < 0 ||
1092                 aCropRightBottom.Height() < 0 )
1093             {
1094                 Size aNewSize( aAnim.GetDisplaySizePixel() );
1095                 aNewSize.Width() += aCropRightBottom.Width() < 0 ? -aCropRightBottom.Width() : 0;
1096                 aNewSize.Width() += aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0;
1097                 aNewSize.Height() += aCropRightBottom.Height() < 0 ? -aCropRightBottom.Height() : 0;
1098                 aNewSize.Height() += aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0;
1099                 aAnim.SetDisplaySizePixel( aNewSize );
1100             }
1101 
1102             // if topleft has changed, we must move all frames to the
1103             // right and bottom, resp.
1104             if( aCropLeftTop.Width() < 0 ||
1105                 aCropLeftTop.Height() < 0 )
1106             {
1107                 Point aPosOffset( aCropLeftTop.Width() < 0 ? -aCropLeftTop.Width() : 0,
1108                                   aCropLeftTop.Height() < 0 ? -aCropLeftTop.Height() : 0 );
1109 
1110                 for( nFrame=0; nFrame<aAnim.Count(); ++nFrame )
1111                 {
1112                     AnimationBitmap aAnimBmp( aAnim.Get( nFrame ) );
1113 
1114                     aAnimBmp.aPosPix += aPosOffset;
1115 
1116                     aAnim.Replace( aAnimBmp, nFrame );
1117                 }
1118             }
1119 
1120             aTransGraphic = aAnim;
1121         }
1122         else
1123         {
1124             ImplTransformBitmap( aBitmapEx, rAttr, aCropLeftTop, aCropRightBottom,
1125                                  aCropRect, rDestSize, sal_True );
1126 
1127             aTransGraphic = aBitmapEx;
1128         }
1129 
1130         aTransGraphic.SetPrefSize( rDestSize );
1131         aTransGraphic.SetPrefMapMode( rDestMap );
1132     }
1133 
1134     GraphicObject aGrfObj( aTransGraphic );
1135     aTransGraphic = aGrfObj.GetTransformedGraphic( &rAttr );
1136 
1137 	return aTransGraphic;
1138 }
1139 
1140 // -----------------------------------------------------------------------------
1141 
1142 Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const // TODO: Change to Impl
1143 {
1144 	GetGraphic();
1145 
1146 	Graphic     aGraphic;
1147     GraphicAttr aAttr( pAttr ? *pAttr : GetAttr() );
1148 
1149 	if( maGraphic.IsSupportedGraphic() && !maGraphic.IsSwapOut() )
1150 	{
1151 		if( aAttr.IsSpecialDrawMode() || aAttr.IsAdjusted() || aAttr.IsMirrored() || aAttr.IsRotated() || aAttr.IsTransparent() )
1152 		{
1153 			if( GetType() == GRAPHIC_BITMAP )
1154 			{
1155 				if( IsAnimated() )
1156 				{
1157 					Animation aAnimation( maGraphic.GetAnimation() );
1158 					GraphicManager::ImplAdjust( aAnimation, aAttr, ADJUSTMENT_ALL );
1159                     aAnimation.SetLoopCount( mnAnimationLoopCount );
1160 					aGraphic = aAnimation;
1161 				}
1162 				else
1163 				{
1164 					BitmapEx aBmpEx( maGraphic.GetBitmapEx() );
1165 					GraphicManager::ImplAdjust( aBmpEx, aAttr, ADJUSTMENT_ALL );
1166 					aGraphic = aBmpEx;
1167 				}
1168 			}
1169 			else
1170 			{
1171 				GDIMetaFile aMtf( maGraphic.GetGDIMetaFile() );
1172 				GraphicManager::ImplAdjust( aMtf, aAttr, ADJUSTMENT_ALL );
1173 				aGraphic = aMtf;
1174 			}
1175 		}
1176 		else
1177         {
1178 			if( ( GetType() == GRAPHIC_BITMAP ) && IsAnimated() )
1179 			{
1180 				Animation aAnimation( maGraphic.GetAnimation() );
1181                 aAnimation.SetLoopCount( mnAnimationLoopCount );
1182 				aGraphic = aAnimation;
1183 			}
1184             else
1185 			    aGraphic = maGraphic;
1186         }
1187 	}
1188 
1189 	return aGraphic;
1190 }
1191 
1192 // -----------------------------------------------------------------------------
1193 
1194 void GraphicObject::ResetAnimationLoopCount()
1195 {
1196 	if( IsAnimated() && !IsSwappedOut() )
1197 	{
1198 		maGraphic.ResetAnimationLoopCount();
1199 
1200 		if( mpSimpleCache )
1201 			mpSimpleCache->maGraphic.ResetAnimationLoopCount();
1202 	}
1203 }
1204 
1205 // -----------------------------------------------------------------------------
1206 
1207 sal_Bool GraphicObject::SwapOut()
1208 {
1209 	sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut() : sal_False );
1210 
1211 	if( bRet && mpMgr )
1212 		mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1213 
1214 	return bRet;
1215 }
1216 
1217 // -----------------------------------------------------------------------------
1218 
1219 sal_Bool GraphicObject::SwapOut( SvStream* pOStm )
1220 {
1221 	sal_Bool bRet = ( !mbAutoSwapped ? maGraphic.SwapOut( pOStm ) : sal_False );
1222 
1223 	if( bRet && mpMgr )
1224 		mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1225 
1226 	return bRet;
1227 }
1228 
1229 // -----------------------------------------------------------------------------
1230 
1231 sal_Bool GraphicObject::SwapIn()
1232 {
1233 	sal_Bool bRet;
1234 
1235 	if( mbAutoSwapped )
1236 	{
1237 		ImplAutoSwapIn();
1238 		bRet = sal_True;
1239 	}
1240 	else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
1241 		bRet = sal_True;
1242 	else
1243 	{
1244 		bRet = maGraphic.SwapIn();
1245 
1246 		if( bRet && mpMgr )
1247 			mpMgr->ImplGraphicObjectWasSwappedIn( *this );
1248 	}
1249 
1250 	if( bRet )
1251 		ImplAssignGraphicData();
1252 
1253 	return bRet;
1254 }
1255 
1256 // -----------------------------------------------------------------------------
1257 
1258 sal_Bool GraphicObject::SwapIn( SvStream* pIStm )
1259 {
1260 	sal_Bool bRet;
1261 
1262 	if( mbAutoSwapped )
1263 	{
1264 		ImplAutoSwapIn();
1265 		bRet = sal_True;
1266 	}
1267 	else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
1268 		bRet = sal_True;
1269 	else
1270 	{
1271 		bRet = maGraphic.SwapIn( pIStm );
1272 
1273 		if( bRet && mpMgr )
1274 			mpMgr->ImplGraphicObjectWasSwappedIn( *this );
1275 	}
1276 
1277 	if( bRet )
1278 		ImplAssignGraphicData();
1279 
1280 	return bRet;
1281 }
1282 
1283 // -----------------------------------------------------------------------------
1284 
1285 void GraphicObject::SetSwapState()
1286 {
1287 	if( !IsSwappedOut() )
1288 	{
1289 		mbAutoSwapped = sal_True;
1290 
1291 		if( mpMgr )
1292 			mpMgr->ImplGraphicObjectWasSwappedOut( *this );
1293 	}
1294 }
1295 
1296 // -----------------------------------------------------------------------------
1297 
1298 IMPL_LINK( GraphicObject, ImplAutoSwapOutHdl, void*, EMPTYARG )
1299 {
1300 	if( !IsSwappedOut() )
1301 	{
1302 		mbIsInSwapOut = sal_True;
1303 
1304 		SvStream* pStream = GetSwapStream();
1305 
1306 		if( GRFMGR_AUTOSWAPSTREAM_NONE != pStream )
1307 		{
1308 			if( GRFMGR_AUTOSWAPSTREAM_LINK == pStream )
1309 				mbAutoSwapped = SwapOut( NULL );
1310 			else
1311 			{
1312 				if( GRFMGR_AUTOSWAPSTREAM_TEMP == pStream )
1313 					mbAutoSwapped = SwapOut();
1314 				else
1315 				{
1316 					mbAutoSwapped = SwapOut( pStream );
1317 					delete pStream;
1318 				}
1319 			}
1320 		}
1321 
1322 		mbIsInSwapOut = sal_False;
1323 	}
1324 
1325 	if( mpSwapOutTimer )
1326 		mpSwapOutTimer->Start();
1327 
1328 	return 0L;
1329 }
1330 
1331 // ------------------------------------------------------------------------
1332 
1333 SvStream& operator>>( SvStream& rIStm, GraphicObject& rGraphicObj )
1334 {
1335 	VersionCompat	aCompat( rIStm, STREAM_READ );
1336 	Graphic			aGraphic;
1337 	GraphicAttr		aAttr;
1338 	ByteString		aLink;
1339 	sal_Bool			bLink;
1340 
1341 	rIStm >> aGraphic >> aAttr >> bLink;
1342 
1343 	rGraphicObj.SetGraphic( aGraphic );
1344 	rGraphicObj.SetAttr( aAttr );
1345 
1346 	if( bLink )
1347 	{
1348 		rIStm >> aLink;
1349 		rGraphicObj.SetLink( UniString( aLink, RTL_TEXTENCODING_UTF8 ) );
1350 	}
1351 	else
1352 		rGraphicObj.SetLink();
1353 
1354 	rGraphicObj.SetSwapStreamHdl();
1355 
1356 	return rIStm;
1357 }
1358 
1359 // ------------------------------------------------------------------------
1360 
1361 SvStream& operator<<( SvStream& rOStm, const GraphicObject& rGraphicObj )
1362 {
1363 	VersionCompat	aCompat( rOStm, STREAM_WRITE, 1 );
1364 	const sal_Bool		bLink =  rGraphicObj.HasLink();
1365 
1366 	rOStm << rGraphicObj.GetGraphic() << rGraphicObj.GetAttr() << bLink;
1367 
1368 	if( bLink )
1369 		rOStm << ByteString( rGraphicObj.GetLink(), RTL_TEXTENCODING_UTF8 );
1370 
1371 	return rOStm;
1372 }
1373 
1374 #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:"
1375 
1376 GraphicObject GraphicObject::CreateGraphicObjectFromURL( const ::rtl::OUString &rURL )
1377 {
1378 	const String aURL( rURL ), aPrefix( RTL_CONSTASCII_STRINGPARAM(UNO_NAME_GRAPHOBJ_URLPREFIX) );
1379 	if( aURL.Search( aPrefix ) == 0 )
1380 	{
1381 		// graphic manager url
1382 		ByteString aUniqueID( String(rURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 )), RTL_TEXTENCODING_UTF8 );
1383 		return GraphicObject( aUniqueID );
1384 	}
1385 	else
1386 	{
1387 		Graphic		aGraphic;
1388 		if ( aURL.Len() )
1389 		{
1390 			SvStream*	pStream = utl::UcbStreamHelper::CreateStream( aURL, STREAM_READ );
1391 			if( pStream )
1392 				GraphicConverter::Import( *pStream, aGraphic );
1393 		}
1394 
1395 		return GraphicObject( aGraphic );
1396 	}
1397 }
1398 
1399 // calculate scalings between real image size and logic object size. This
1400 // is necessary since the crop values are relative to original bitmap size
1401 basegfx::B2DVector GraphicObject::calculateCropScaling(
1402     double fWidth,
1403     double fHeight,
1404     double fLeftCrop,
1405     double fTopCrop,
1406     double fRightCrop,
1407     double fBottomCrop) const
1408 {
1409     const MapMode aMapMode100thmm(MAP_100TH_MM);
1410     Size aBitmapSize(GetPrefSize());
1411     double fFactorX(1.0);
1412     double fFactorY(1.0);
1413 
1414     if(MAP_PIXEL == GetPrefMapMode().GetMapUnit())
1415     {
1416         aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm);
1417     }
1418     else
1419     {
1420         aBitmapSize = Application::GetDefaultDevice()->LogicToLogic(aBitmapSize, GetPrefMapMode(), aMapMode100thmm);
1421     }
1422 
1423     const double fDivX(aBitmapSize.Width() - fLeftCrop - fRightCrop);
1424     const double fDivY(aBitmapSize.Height() - fTopCrop - fBottomCrop);
1425 
1426     if(!basegfx::fTools::equalZero(fDivX))
1427     {
1428         fFactorX = fabs(fWidth) / fDivX;
1429     }
1430 
1431     if(!basegfx::fTools::equalZero(fDivY))
1432     {
1433         fFactorY = fabs(fHeight) / fDivY;
1434     }
1435 
1436     return basegfx::B2DVector(fFactorX,fFactorY);
1437 }
1438 
1439 // eof
1440