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