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