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