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