xref: /trunk/main/vcl/source/gdi/impgraph.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
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_vcl.hxx"
26 
27 #include <tools/vcompat.hxx>
28 #include <tools/urlobj.hxx>
29 #include <tools/debug.hxx>
30 #include <tools/stream.hxx>
31 
32 #include <ucbhelper/content.hxx>
33 
34 #include <unotools/ucbstreamhelper.hxx>
35 #include <unotools/tempfile.hxx>
36 
37 #include <vcl/outdev.hxx>
38 #include <vcl/virdev.hxx>
39 #include <vcl/gfxlink.hxx>
40 #include <vcl/cvtgrf.hxx>
41 #include <vcl/salbtype.hxx>
42 #include <vcl/graph.hxx>
43 #include <vcl/metaact.hxx>
44 
45 #include <impgraph.hxx>
46 
47 #include <com/sun/star/ucb/CommandAbortedException.hpp>
48 
49 // -----------
50 // - Defines -
51 // -----------
52 
53 #define GRAPHIC_MAXPARTLEN          256000L
54 #define GRAPHIC_MTFTOBMP_MAXEXT     2048
55 #define GRAPHIC_STREAMBUFSIZE       8192UL
56 
57 #define SYS_WINMETAFILE             0x00000003L
58 #define SYS_WNTMETAFILE             0x00000004L
59 #define SYS_OS2METAFILE             0x00000005L
60 #define SYS_MACMETAFILE             0x00000006L
61 
62 #define GRAPHIC_FORMAT_50           static_cast<sal_uInt32>(COMPAT_FORMAT( 'G', 'R', 'F', '5' ))
63 #define NATIVE_FORMAT_50            static_cast<sal_uInt32>(COMPAT_FORMAT( 'N', 'A', 'T', '5' ))
64 
65 // ---------------
66 // - ImpSwapFile -
67 // ---------------
68 
69 struct ImpSwapFile
70 {
71     INetURLObject   aSwapURL;
72     sal_uLong           nRefCount;
73 };
74 
75 // -----------------
76 // - Graphicreader -
77 // -----------------
78 
79 class ReaderData
80 {
81 public:
82     Size    maPreviewSize;
83 };
84 
85 GraphicReader::~GraphicReader()
86 {
87     delete mpReaderData;
88 }
89 
90 // ------------------------------------------------------------------------
91 
92 sal_Bool GraphicReader::IsPreviewModeEnabled() const
93 {
94     if( !mpReaderData )
95         return sal_False;
96     if( mpReaderData->maPreviewSize.Width() )
97         return sal_True;
98     if( mpReaderData->maPreviewSize.Height() )
99         return sal_True;
100     return sal_False;
101 }
102 
103 // ------------------------------------------------------------------------
104 
105 void GraphicReader::DisablePreviewMode()
106 {
107     if( mpReaderData )
108         mpReaderData->maPreviewSize = Size( 0, 0 );
109 }
110 
111 // ------------------------------------------------------------------------
112 
113 void GraphicReader::SetPreviewSize( const Size& rSize )
114 {
115     if( !mpReaderData )
116         mpReaderData = new ReaderData;
117     mpReaderData->maPreviewSize = rSize;
118 }
119 
120 // ------------------------------------------------------------------------
121 
122 Size GraphicReader::GetPreviewSize() const
123 {
124     Size aSize( 0, 0 );
125     if( mpReaderData )
126         aSize = mpReaderData->maPreviewSize;
127     return aSize;
128 }
129 
130 // --------------
131 // - ImpGraphic -
132 // --------------
133 
134 ImpGraphic::ImpGraphic() :
135         mpAnimation     ( NULL ),
136         mpContext       ( NULL ),
137         mpSwapFile      ( NULL ),
138         mpGfxLink       ( NULL ),
139         meType          ( GRAPHIC_NONE ),
140         mnDocFilePos    ( 0UL ),
141         mnSizeBytes     ( 0UL ),
142         mnRefCount      ( 1UL ),
143         mbSwapOut       ( sal_False ),
144         mbSwapUnderway  ( sal_False )
145 {
146 }
147 
148 // ------------------------------------------------------------------------
149 
150 ImpGraphic::ImpGraphic( const ImpGraphic& rImpGraphic ) :
151         maMetaFile      ( rImpGraphic.maMetaFile ),
152         maEx            ( rImpGraphic.maEx ),
153         mpContext       ( NULL ),
154         mpSwapFile      ( rImpGraphic.mpSwapFile ),
155         meType          ( rImpGraphic.meType ),
156         maDocFileURLStr ( rImpGraphic.maDocFileURLStr ),
157         mnDocFilePos    ( rImpGraphic.mnDocFilePos ),
158         mnSizeBytes     ( rImpGraphic.mnSizeBytes ),
159         mnRefCount      ( 1UL ),
160         mbSwapOut       ( rImpGraphic.mbSwapOut ),
161         mbSwapUnderway  ( sal_False )
162 {
163     if( mpSwapFile )
164         mpSwapFile->nRefCount++;
165 
166     if( rImpGraphic.mpGfxLink )
167         mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
168     else
169         mpGfxLink = NULL;
170 
171     if( rImpGraphic.mpAnimation )
172     {
173         mpAnimation = new Animation( *rImpGraphic.mpAnimation );
174         maEx = mpAnimation->GetBitmapEx();
175     }
176     else
177         mpAnimation = NULL;
178 }
179 
180 // ------------------------------------------------------------------------
181 
182 ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
183         maEx            ( rBitmap ),
184         mpAnimation     ( NULL ),
185         mpContext       ( NULL ),
186         mpSwapFile      ( NULL ),
187         mpGfxLink       ( NULL ),
188         meType          ( !rBitmap ? GRAPHIC_NONE : GRAPHIC_BITMAP ),
189         mnDocFilePos    ( 0UL ),
190         mnSizeBytes     ( 0UL ),
191         mnRefCount      ( 1UL ),
192         mbSwapOut       ( sal_False ),
193         mbSwapUnderway  ( sal_False )
194 {
195 }
196 
197 // ------------------------------------------------------------------------
198 
199 ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) :
200         maEx            ( rBitmapEx ),
201         mpAnimation     ( NULL ),
202         mpContext       ( NULL ),
203         mpSwapFile      ( NULL ),
204         mpGfxLink       ( NULL ),
205         meType          ( !rBitmapEx ? GRAPHIC_NONE : GRAPHIC_BITMAP ),
206         mnDocFilePos    ( 0UL ),
207         mnSizeBytes     ( 0UL ),
208         mnRefCount      ( 1UL ),
209         mbSwapOut       ( sal_False ),
210         mbSwapUnderway  ( sal_False )
211 {
212 }
213 
214 // ------------------------------------------------------------------------
215 
216 ImpGraphic::ImpGraphic( const Animation& rAnimation ) :
217         maEx            ( rAnimation.GetBitmapEx() ),
218         mpAnimation     ( new Animation( rAnimation ) ),
219         mpContext       ( NULL ),
220         mpSwapFile      ( NULL ),
221         mpGfxLink       ( NULL ),
222         meType          ( GRAPHIC_BITMAP ),
223         mnDocFilePos    ( 0UL ),
224         mnSizeBytes     ( 0UL ),
225         mnRefCount      ( 1UL ),
226         mbSwapOut       ( sal_False ),
227         mbSwapUnderway  ( sal_False )
228 {
229 }
230 
231 // ------------------------------------------------------------------------
232 
233 ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) :
234         maMetaFile      ( rMtf ),
235         mpAnimation     ( NULL ),
236         mpContext       ( NULL ),
237         mpSwapFile      ( NULL ),
238         mpGfxLink       ( NULL ),
239         meType          ( GRAPHIC_GDIMETAFILE ),
240         mnDocFilePos    ( 0UL ),
241         mnSizeBytes     ( 0UL ),
242         mnRefCount      ( 1UL ),
243         mbSwapOut       ( sal_False ),
244         mbSwapUnderway  ( sal_False )
245 {
246 }
247 
248 // ------------------------------------------------------------------------
249 
250 ImpGraphic::~ImpGraphic()
251 {
252     ImplClear();
253 
254     if( (sal_uLong) mpContext > 1UL )
255         delete mpContext;
256 }
257 
258 // ------------------------------------------------------------------------
259 
260 ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic )
261 {
262     if( &rImpGraphic != this )
263     {
264         if( !mbSwapUnderway )
265             ImplClear();
266 
267         maMetaFile = rImpGraphic.maMetaFile;
268         meType = rImpGraphic.meType;
269         mnSizeBytes = rImpGraphic.mnSizeBytes;
270 
271         delete mpAnimation;
272 
273         if ( rImpGraphic.mpAnimation )
274         {
275             mpAnimation = new Animation( *rImpGraphic.mpAnimation );
276             maEx = mpAnimation->GetBitmapEx();
277         }
278         else
279         {
280             mpAnimation = NULL;
281             maEx = rImpGraphic.maEx;
282         }
283 
284         if( !mbSwapUnderway )
285         {
286             maDocFileURLStr = rImpGraphic.maDocFileURLStr;
287             mnDocFilePos = rImpGraphic.mnDocFilePos;
288             mbSwapOut = rImpGraphic.mbSwapOut;
289             mpSwapFile = rImpGraphic.mpSwapFile;
290 
291             if( mpSwapFile )
292                 mpSwapFile->nRefCount++;
293         }
294 
295         delete mpGfxLink;
296 
297         if( rImpGraphic.mpGfxLink )
298             mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
299         else
300             mpGfxLink = NULL;
301     }
302 
303     return *this;
304 }
305 
306 // ------------------------------------------------------------------------
307 
308 sal_Bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const
309 {
310     sal_Bool bRet = sal_False;
311 
312     if( this == &rImpGraphic )
313         bRet = sal_True;
314     else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) )
315     {
316         switch( meType )
317         {
318             case( GRAPHIC_NONE ):
319                 bRet = sal_True;
320             break;
321 
322             case( GRAPHIC_GDIMETAFILE ):
323             {
324                 if( rImpGraphic.maMetaFile == maMetaFile )
325                     bRet = sal_True;
326             }
327             break;
328 
329             case( GRAPHIC_BITMAP ):
330             {
331                 if( mpAnimation )
332                 {
333                     if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) )
334                         bRet = sal_True;
335                 }
336                 else if( !rImpGraphic.mpAnimation && ( rImpGraphic.maEx == maEx ) )
337                     bRet = sal_True;
338             }
339             break;
340 
341             default:
342             break;
343         }
344     }
345 
346     return bRet;
347 }
348 
349 // ------------------------------------------------------------------------
350 
351 void ImpGraphic::ImplClearGraphics( sal_Bool bCreateSwapInfo )
352 {
353     if( bCreateSwapInfo && !ImplIsSwapOut() )
354     {
355         maSwapInfo.maPrefMapMode = ImplGetPrefMapMode();
356         maSwapInfo.maPrefSize = ImplGetPrefSize();
357     }
358 
359     maEx.Clear();
360     maMetaFile.Clear();
361 
362     if( mpAnimation )
363     {
364         mpAnimation->Clear();
365         delete mpAnimation;
366         mpAnimation = NULL;
367     }
368 
369     if( mpGfxLink )
370     {
371         delete mpGfxLink;
372         mpGfxLink = NULL;
373     }
374 }
375 
376 // ------------------------------------------------------------------------
377 
378 void ImpGraphic::ImplClear()
379 {
380     if( mpSwapFile )
381     {
382         if( mpSwapFile->nRefCount > 1 )
383             mpSwapFile->nRefCount--;
384         else
385         {
386             try
387             {
388                 ::ucbhelper::Content aCnt( mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE ),
389                                      ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
390 
391                 aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
392                                      ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
393             }
394             catch( const ::com::sun::star::ucb::ContentCreationException& )
395             {
396             }
397             catch( const ::com::sun::star::uno::RuntimeException& )
398             {
399             }
400             catch( const ::com::sun::star::ucb::CommandAbortedException& )
401             {
402             }
403             catch( const ::com::sun::star::uno::Exception& )
404             {
405             }
406 
407             delete mpSwapFile;
408         }
409 
410         mpSwapFile = NULL;
411     }
412 
413     mbSwapOut = sal_False;
414     mnDocFilePos = 0UL;
415     maDocFileURLStr.Erase();
416 
417     // cleanup
418     ImplClearGraphics( sal_False );
419     meType = GRAPHIC_NONE;
420     mnSizeBytes = 0;
421 }
422 
423 // ------------------------------------------------------------------------
424 
425 GraphicType ImpGraphic::ImplGetType() const
426 {
427     return meType;
428 }
429 
430 // ------------------------------------------------------------------------
431 
432 void ImpGraphic::ImplSetDefaultType()
433 {
434     ImplClear();
435     meType = GRAPHIC_DEFAULT;
436 }
437 
438 // ------------------------------------------------------------------------
439 
440 sal_Bool ImpGraphic::ImplIsSupportedGraphic() const
441 {
442     return( meType != GRAPHIC_NONE );
443 }
444 
445 // ------------------------------------------------------------------------
446 
447 sal_Bool ImpGraphic::ImplIsTransparent() const
448 {
449     sal_Bool bRet;
450 
451     if( meType == GRAPHIC_BITMAP )
452         bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() );
453     else
454         bRet = sal_True;
455 
456     return bRet;
457 }
458 
459 // ------------------------------------------------------------------------
460 
461 sal_Bool ImpGraphic::ImplIsAlpha() const
462 {
463     sal_Bool bRet;
464 
465     if( meType == GRAPHIC_BITMAP )
466         bRet = ( NULL == mpAnimation ) && maEx.IsAlpha();
467     else
468         bRet = sal_False;
469 
470     return bRet;
471 }
472 
473 // ------------------------------------------------------------------------
474 
475 sal_Bool ImpGraphic::ImplIsAnimated() const
476 {
477     return( mpAnimation != NULL );
478 }
479 
480 // ------------------------------------------------------------------------
481 
482 sal_Bool ImpGraphic::ImplIsEPS() const
483 {
484     return( ( meType == GRAPHIC_GDIMETAFILE ) &&
485             ( maMetaFile.GetActionCount() > 0 ) &&
486             ( maMetaFile.GetAction( 0 )->GetType() == META_EPS_ACTION ) );
487 }
488 
489 // ------------------------------------------------------------------------
490 
491 sal_Bool ImpGraphic::ImplIsRenderGraphic() const
492 {
493     return( ( GRAPHIC_GDIMETAFILE == meType ) &&
494             ( 1 == maMetaFile.GetActionCount() ) &&
495             ( META_RENDERGRAPHIC_ACTION == maMetaFile.GetAction( 0 )->GetType() ) );
496 }
497 
498 // ------------------------------------------------------------------------
499 
500 sal_Bool ImpGraphic::ImplHasRenderGraphic() const
501 {
502     sal_Bool bRet = sal_False;
503 
504     if( GRAPHIC_GDIMETAFILE == meType )
505     {
506         GDIMetaFile& rMtf = const_cast< ImpGraphic* >( this )->maMetaFile;
507 
508         for( MetaAction* pAct = rMtf.FirstAction(); pAct && !bRet; pAct = rMtf.NextAction() )
509         {
510             if( META_RENDERGRAPHIC_ACTION == pAct->GetType() )
511             {
512                 bRet = sal_True;
513             }
514         }
515 
516         rMtf.WindStart();
517     }
518 
519     return( bRet );
520 }
521 
522 // ------------------------------------------------------------------------
523 
524 Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const
525 {
526     Bitmap aRetBmp;
527 
528     if( meType == GRAPHIC_BITMAP )
529     {
530         const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
531         const Color     aReplaceColor( COL_WHITE );
532 
533         aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor );
534 
535         if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
536             aRetBmp.Scale(rParameters.getSizePixel());
537     }
538     else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
539     {
540         // use corner points of graphic to determine the pixel
541         // extent of the graphic (rounding errors are possible else)
542         VirtualDevice   aVDev;
543         const Point     aNullPt;
544         const Point     aTLPix( aVDev.LogicToPixel( aNullPt, maMetaFile.GetPrefMapMode() ) );
545         const Point     aBRPix( aVDev.LogicToPixel( Point( maMetaFile.GetPrefSize().Width() - 1, maMetaFile.GetPrefSize().Height() - 1 ), maMetaFile.GetPrefMapMode() ) );
546         Size            aDrawSize( aVDev.LogicToPixel( maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode() ) );
547         Size            aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
548 
549         if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height())
550         {
551             aDrawSize.Width() = FRound((double)rParameters.getSizePixel().Width() *
552                 (double)aDrawSize.Width() / (double)aSizePix.Width());
553             aDrawSize.Height() = FRound((double)rParameters.getSizePixel().Height() *
554                 (double)aDrawSize.Height() / (double)aSizePix.Height());
555 
556             aSizePix = rParameters.getSizePixel();
557         }
558 
559         if( aSizePix.Width() && aSizePix.Height() && !rParameters.getUnlimitedSize()
560             && (aSizePix.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aSizePix.Height() > GRAPHIC_MTFTOBMP_MAXEXT))
561         {
562             const Size  aOldSizePix( aSizePix );
563             double      fWH = (double) aSizePix.Width() / aSizePix.Height();
564 
565             if( fWH <= 1.0 )
566                 aSizePix.Width() = FRound( GRAPHIC_MTFTOBMP_MAXEXT * fWH ), aSizePix.Height() = GRAPHIC_MTFTOBMP_MAXEXT;
567             else
568                 aSizePix.Width() = GRAPHIC_MTFTOBMP_MAXEXT, aSizePix.Height() = FRound(  GRAPHIC_MTFTOBMP_MAXEXT / fWH );
569 
570             aDrawSize.Width() = FRound( ( (double) aDrawSize.Width() * aSizePix.Width() ) / aOldSizePix.Width() );
571             aDrawSize.Height() = FRound( ( (double) aDrawSize.Height() * aSizePix.Height() ) / aOldSizePix.Height() );
572         }
573 
574         if( aVDev.SetOutputSizePixel( aSizePix ) )
575         {
576             if(rParameters.getAntiAliase())
577             {
578                 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
579             }
580 
581             if(rParameters.getSnapHorVerLines())
582             {
583                 aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_PIXELSNAPHAIRLINE);
584             }
585 
586             ImplDraw( &aVDev, aNullPt, aDrawSize );
587             aRetBmp =  aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() );
588         }
589     }
590 
591     if( !!aRetBmp )
592     {
593         aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() );
594         aRetBmp.SetPrefSize( ImplGetPrefSize() );
595     }
596 
597     return aRetBmp;
598 }
599 
600 // ------------------------------------------------------------------------
601 
602 BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const
603 {
604     BitmapEx aRetBmpEx;
605 
606     if( meType == GRAPHIC_BITMAP )
607     {
608         aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
609 
610         if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
611             aRetBmpEx.Scale(rParameters.getSizePixel());
612     }
613     else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
614     {
615         const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) );
616         aRetBmpEx = BitmapEx(ImplGetBitmap(rParameters), aMonoMask.ImplGetBitmap(rParameters));
617     }
618 
619     return aRetBmpEx;
620 }
621 
622 // ------------------------------------------------------------------------
623 
624 Animation ImpGraphic::ImplGetAnimation() const
625 {
626     Animation aAnimation;
627 
628     if( mpAnimation )
629         aAnimation = *mpAnimation;
630 
631     return aAnimation;
632 }
633 
634 // ------------------------------------------------------------------------
635 
636 ::vcl::RenderGraphic ImpGraphic::ImplGetRenderGraphic() const
637 {
638     ::vcl::RenderGraphic aRet;
639 
640     if( ImplIsRenderGraphic() )
641         aRet = static_cast< MetaRenderGraphicAction* >( maMetaFile.GetAction( 0 ) )->GetRenderGraphic();
642 
643     return( aRet );
644 }
645 
646 // ------------------------------------------------------------------------
647 
648 const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const
649 {
650     return maMetaFile;
651 }
652 
653 // ------------------------------------------------------------------------
654 
655 Size ImpGraphic::ImplGetPrefSize() const
656 {
657     Size aSize;
658 
659     if( ImplIsSwapOut() )
660         aSize = maSwapInfo.maPrefSize;
661     else
662     {
663         switch( meType )
664         {
665             case( GRAPHIC_NONE ):
666             case( GRAPHIC_DEFAULT ):
667             break;
668 
669             case( GRAPHIC_BITMAP ):
670             {
671                 aSize = maEx.GetPrefSize();
672 
673                 if( !aSize.Width() || !aSize.Height() )
674                     aSize = maEx.GetSizePixel();
675             }
676             break;
677 
678             default:
679             {
680                 if( ImplIsSupportedGraphic() )
681                   aSize = maMetaFile.GetPrefSize();
682             }
683             break;
684         }
685     }
686 
687     return aSize;
688 }
689 
690 // ------------------------------------------------------------------------
691 
692 void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize )
693 {
694     switch( meType )
695     {
696         case( GRAPHIC_NONE ):
697         case( GRAPHIC_DEFAULT ):
698         break;
699 
700         case( GRAPHIC_BITMAP ):
701             // #108077# Push through pref size to animation object,
702             // will be lost on copy otherwise
703             if( ImplIsAnimated() )
704                 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize( rPrefSize );
705 
706             maEx.SetPrefSize( rPrefSize );
707         break;
708 
709         default:
710         {
711             if( ImplIsSupportedGraphic() )
712                 maMetaFile.SetPrefSize( rPrefSize );
713         }
714         break;
715     }
716 }
717 
718 // ------------------------------------------------------------------------
719 
720 MapMode ImpGraphic::ImplGetPrefMapMode() const
721 {
722     MapMode aMapMode;
723 
724     if( ImplIsSwapOut() )
725         aMapMode = maSwapInfo.maPrefMapMode;
726     else
727     {
728         switch( meType )
729         {
730             case( GRAPHIC_NONE ):
731             case( GRAPHIC_DEFAULT ):
732             break;
733 
734             case( GRAPHIC_BITMAP ):
735             {
736                 const Size aSize( maEx.GetPrefSize() );
737 
738                 if ( aSize.Width() && aSize.Height() )
739                     aMapMode = maEx.GetPrefMapMode();
740             }
741             break;
742 
743             default:
744             {
745                 if( ImplIsSupportedGraphic() )
746                     return maMetaFile.GetPrefMapMode();
747             }
748             break;
749         }
750     }
751 
752     return aMapMode;
753 }
754 
755 // ------------------------------------------------------------------------
756 
757 void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode )
758 {
759     switch( meType )
760     {
761         case( GRAPHIC_NONE ):
762         case( GRAPHIC_DEFAULT ):
763         break;
764 
765         case( GRAPHIC_BITMAP ):
766             // #108077# Push through pref mapmode to animation object,
767             // will be lost on copy otherwise
768             if( ImplIsAnimated() )
769                 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefMapMode( rPrefMapMode );
770 
771             maEx.SetPrefMapMode( rPrefMapMode );
772         break;
773 
774         default:
775         {
776             if( ImplIsSupportedGraphic() )
777                 maMetaFile.SetPrefMapMode( rPrefMapMode );
778         }
779         break;
780     }
781 }
782 
783 // ------------------------------------------------------------------------
784 
785 sal_uLong ImpGraphic::ImplGetSizeBytes() const
786 {
787     if( 0 == mnSizeBytes )
788     {
789         if( meType == GRAPHIC_BITMAP )
790         {
791             mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maEx.GetSizeBytes();
792         }
793         else if( meType == GRAPHIC_GDIMETAFILE )
794         {
795             mnSizeBytes = maMetaFile.GetSizeBytes();
796         }
797     }
798 
799     return( mnSizeBytes );
800 }
801 
802 // ------------------------------------------------------------------------
803 
804 void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const
805 {
806     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
807     {
808         switch( meType )
809         {
810             case( GRAPHIC_DEFAULT ):
811             break;
812 
813             case( GRAPHIC_BITMAP ):
814             {
815                 if ( mpAnimation )
816                     mpAnimation->Draw( pOutDev, rDestPt );
817                 else
818                     maEx.Draw( pOutDev, rDestPt );
819             }
820             break;
821 
822             default:
823                 ImplDraw( pOutDev, rDestPt, maMetaFile.GetPrefSize() );
824             break;
825         }
826     }
827 }
828 
829 // ------------------------------------------------------------------------
830 
831 void ImpGraphic::ImplDraw( OutputDevice* pOutDev,
832                            const Point& rDestPt, const Size& rDestSize ) const
833 {
834     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
835     {
836         switch( meType )
837         {
838             case( GRAPHIC_DEFAULT ):
839             break;
840 
841             case( GRAPHIC_BITMAP ):
842             {
843                 if( mpAnimation )
844                     mpAnimation->Draw( pOutDev, rDestPt, rDestSize );
845                 else
846                     maEx.Draw( pOutDev, rDestPt, rDestSize );
847             }
848             break;
849 
850             default:
851             {
852                 ( (ImpGraphic*) this )->maMetaFile.WindStart();
853                 ( (ImpGraphic*) this )->maMetaFile.Play( pOutDev, rDestPt, rDestSize );
854                 ( (ImpGraphic*) this )->maMetaFile.WindStart();
855             }
856             break;
857         }
858     }
859 }
860 
861 // ------------------------------------------------------------------------
862 
863 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev,
864                                      const Point& rDestPt,
865                                      long nExtraData,
866                                      OutputDevice* pFirstFrameOutDev )
867 {
868     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
869         mpAnimation->Start( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev );
870 }
871 
872 // ------------------------------------------------------------------------
873 
874 void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt,
875                                      const Size& rDestSize, long nExtraData,
876                                      OutputDevice* pFirstFrameOutDev )
877 {
878     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
879         mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev );
880 }
881 
882 // ------------------------------------------------------------------------
883 
884 void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData )
885 {
886     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
887         mpAnimation->Stop( pOutDev, nExtraData );
888 }
889 
890 // ------------------------------------------------------------------------
891 
892 void ImpGraphic::ImplSetAnimationNotifyHdl( const Link& rLink )
893 {
894     if( mpAnimation )
895         mpAnimation->SetNotifyHdl( rLink );
896 }
897 
898 // ------------------------------------------------------------------------
899 
900 Link ImpGraphic::ImplGetAnimationNotifyHdl() const
901 {
902     Link aLink;
903 
904     if( mpAnimation )
905         aLink = mpAnimation->GetNotifyHdl();
906 
907     return aLink;
908 }
909 
910 // ------------------------------------------------------------------------
911 
912 sal_uLong ImpGraphic::ImplGetAnimationLoopCount() const
913 {
914     return( mpAnimation ? mpAnimation->GetLoopCount() : 0UL );
915 }
916 
917 // ------------------------------------------------------------------------
918 
919 void ImpGraphic::ImplResetAnimationLoopCount()
920 {
921     if( mpAnimation )
922         mpAnimation->ResetLoopCount();
923 }
924 
925 // ------------------------------------------------------------------------
926 
927 List* ImpGraphic::ImplGetAnimationInfoList() const
928 {
929     return( mpAnimation ? mpAnimation->GetAInfoList() : NULL );
930 }
931 
932 // ------------------------------------------------------------------------
933 
934 GraphicReader* ImpGraphic::ImplGetContext()
935 {
936     return mpContext;
937 }
938 
939 // ------------------------------------------------------------------------
940 
941 void ImpGraphic::ImplSetContext( GraphicReader* pReader )
942 {
943     mpContext = pReader;
944 }
945 
946 // ------------------------------------------------------------------------
947 
948 void ImpGraphic::ImplSetDocFileName( const String& rName, sal_uLong nFilePos )
949 {
950     const INetURLObject aURL( rName );
951 
952     DBG_ASSERT( !rName.Len() || ( aURL.GetProtocol() != INET_PROT_NOT_VALID ), "Graphic::SetDocFileName(...): invalid URL" );
953 
954     maDocFileURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE );
955     mnDocFilePos = nFilePos;
956 }
957 
958 // ------------------------------------------------------------------------
959 
960 const String& ImpGraphic::ImplGetDocFileName() const
961 {
962     return maDocFileURLStr;
963 }
964 
965 // ------------------------------------------------------------------------
966 
967 sal_uLong ImpGraphic::ImplGetDocFilePos() const
968 {
969     return mnDocFilePos;
970 }
971 
972 // ------------------------------------------------------------------------
973 
974 sal_Bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm, sal_Bool bSwap )
975 {
976     MapMode         aMapMode;
977     Size            aSize;
978     const sal_uLong     nStartPos = rIStm.Tell();
979     sal_uInt32      nId;
980     sal_uLong           nHeaderLen;
981     long            nType;
982     long            nLen;
983     const sal_uInt16    nOldFormat = rIStm.GetNumberFormatInt();
984     sal_Bool            bRet = sal_False;
985 
986     if( !mbSwapUnderway )
987     {
988         const String        aTempURLStr( maDocFileURLStr );
989         const sal_uLong         nTempPos = mnDocFilePos;
990 
991         ImplClear();
992 
993         maDocFileURLStr = aTempURLStr;
994         mnDocFilePos = nTempPos;
995     }
996 
997     rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
998     rIStm >> nId;
999 
1000     // check version
1001     if( GRAPHIC_FORMAT_50 == nId )
1002     {
1003         // read new style header
1004         VersionCompat* pCompat = new VersionCompat( rIStm, STREAM_READ );
1005 
1006         rIStm >> nType;
1007         rIStm >> nLen;
1008         rIStm >> aSize;
1009         rIStm >> aMapMode;
1010 
1011         delete pCompat;
1012     }
1013     else
1014     {
1015         // read old style header
1016         long nWidth, nHeight;
1017         long nMapMode, nScaleNumX, nScaleDenomX;
1018         long nScaleNumY, nScaleDenomY, nOffsX, nOffsY;
1019 
1020         rIStm.SeekRel( -4L );
1021 
1022         rIStm >> nType >> nLen >> nWidth >> nHeight;
1023         rIStm >> nMapMode >> nScaleNumX >> nScaleDenomX >> nScaleNumY;
1024         rIStm >> nScaleDenomY >> nOffsX >> nOffsY;
1025 
1026         // swapped
1027         if( nType > 100L )
1028         {
1029             nType = SWAPLONG( nType );
1030             nLen = SWAPLONG( nLen );
1031             nWidth = SWAPLONG( nWidth );
1032             nHeight = SWAPLONG( nHeight );
1033             nMapMode = SWAPLONG( nMapMode );
1034             nScaleNumX = SWAPLONG( nScaleNumX );
1035             nScaleDenomX = SWAPLONG( nScaleDenomX );
1036             nScaleNumY = SWAPLONG( nScaleNumY );
1037             nScaleDenomY = SWAPLONG( nScaleDenomY );
1038             nOffsX = SWAPLONG( nOffsX );
1039             nOffsY = SWAPLONG( nOffsY );
1040         }
1041 
1042         aSize = Size( nWidth, nHeight );
1043         aMapMode = MapMode( (MapUnit) nMapMode, Point( nOffsX, nOffsY ),
1044                             Fraction( nScaleNumX, nScaleDenomX ),
1045                             Fraction( nScaleNumY, nScaleDenomY ) );
1046     }
1047 
1048     nHeaderLen = rIStm.Tell() - nStartPos;
1049     meType = (GraphicType) nType;
1050 
1051     if( meType )
1052     {
1053         if( meType == GRAPHIC_BITMAP )
1054         {
1055             maEx.aBitmapSize = aSize;
1056 
1057             if( aMapMode != MapMode() )
1058             {
1059                 maEx.SetPrefMapMode( aMapMode );
1060                 maEx.SetPrefSize( aSize );
1061             }
1062         }
1063         else
1064         {
1065             maMetaFile.SetPrefMapMode( aMapMode );
1066             maMetaFile.SetPrefSize( aSize );
1067         }
1068 
1069         if( bSwap )
1070         {
1071             if( maDocFileURLStr.Len() )
1072             {
1073                 rIStm.Seek( nStartPos + nHeaderLen + nLen );
1074                 bRet = mbSwapOut = sal_True;
1075             }
1076             else
1077             {
1078                 ::utl::TempFile     aTempFile;
1079                 const INetURLObject aTmpURL( aTempFile.GetURL() );
1080 
1081                 if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() )
1082                 {
1083                     SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
1084 
1085                     if( pOStm )
1086                     {
1087                         sal_uLong   nFullLen = nHeaderLen + nLen;
1088                         sal_uLong   nPartLen = Min( nFullLen, (sal_uLong) GRAPHIC_MAXPARTLEN );
1089                         sal_uInt8*  pBuffer = (sal_uInt8*) rtl_allocateMemory( nPartLen );
1090 
1091                         pOStm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1092 
1093                         if( pBuffer )
1094                         {
1095                             rIStm.Seek( nStartPos );
1096 
1097                             while( nFullLen )
1098                             {
1099                                 rIStm.Read( (char*) pBuffer, nPartLen );
1100                                 pOStm->Write( (char*) pBuffer, nPartLen );
1101 
1102                                 nFullLen -= nPartLen;
1103 
1104                                 if( nFullLen < GRAPHIC_MAXPARTLEN )
1105                                     nPartLen = nFullLen;
1106                             }
1107 
1108                             rtl_freeMemory( pBuffer );
1109                             sal_uLong nReadErr = rIStm.GetError(), nWriteErr = pOStm->GetError();
1110                             delete pOStm, pOStm = NULL;
1111 
1112                             if( !nReadErr && !nWriteErr )
1113                             {
1114                                 bRet = mbSwapOut = sal_True;
1115                                 mpSwapFile = new ImpSwapFile;
1116                                 mpSwapFile->nRefCount = 1;
1117                                 mpSwapFile->aSwapURL = aTmpURL;
1118                             }
1119                             else
1120                             {
1121                                 try
1122                                 {
1123                                     ::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ),
1124                                                          ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
1125 
1126                                     aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1127                                                          ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
1128                                 }
1129                                 catch( const ::com::sun::star::ucb::ContentCreationException& )
1130                                 {
1131                                 }
1132                                 catch( const ::com::sun::star::uno::RuntimeException& )
1133                                 {
1134                                 }
1135                                 catch( const ::com::sun::star::ucb::CommandAbortedException& )
1136                                 {
1137                                 }
1138                                 catch( const ::com::sun::star::uno::Exception& )
1139                                 {
1140                                 }
1141                             }
1142                         }
1143 
1144                         delete pOStm;
1145                     }
1146                 }
1147             }
1148         }
1149         else if( meType == GRAPHIC_BITMAP || meType == GRAPHIC_GDIMETAFILE )
1150         {
1151             rIStm >> *this;
1152             bRet = ( rIStm.GetError() == 0UL );
1153         }
1154         else if( meType >= SYS_WINMETAFILE && meType <= SYS_MACMETAFILE )
1155         {
1156             Graphic aSysGraphic;
1157             sal_uLong   nCvtType;
1158 
1159             switch( sal::static_int_cast<sal_uLong>(meType) )
1160             {
1161                 case( SYS_WINMETAFILE ):
1162                 case( SYS_WNTMETAFILE ): nCvtType = CVT_WMF; break;
1163                 case( SYS_OS2METAFILE ): nCvtType = CVT_MET; break;
1164                 case( SYS_MACMETAFILE ): nCvtType = CVT_PCT; break;
1165 
1166                 default:
1167                     nCvtType = CVT_UNKNOWN;
1168                 break;
1169             }
1170 
1171             if( nType && GraphicConverter::Import( rIStm, aSysGraphic, nCvtType ) == ERRCODE_NONE )
1172             {
1173                 *this = ImpGraphic( aSysGraphic.GetGDIMetaFile() );
1174                 bRet = ( rIStm.GetError() == 0UL );
1175             }
1176             else
1177                 meType = GRAPHIC_DEFAULT;
1178         }
1179 
1180         if( bRet )
1181         {
1182             ImplSetPrefMapMode( aMapMode );
1183             ImplSetPrefSize( aSize );
1184         }
1185     }
1186     else
1187         bRet = sal_True;
1188 
1189     rIStm.SetNumberFormatInt( nOldFormat );
1190 
1191     return bRet;
1192 }
1193 
1194 // ------------------------------------------------------------------------
1195 
1196 sal_Bool ImpGraphic::ImplWriteEmbedded( SvStream& rOStm )
1197 {
1198     sal_Bool bRet = sal_False;
1199 
1200     if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() )
1201     {
1202         const MapMode   aMapMode( ImplGetPrefMapMode() );
1203         const Size      aSize( ImplGetPrefSize() );
1204         const sal_uInt16    nOldFormat = rOStm.GetNumberFormatInt();
1205         sal_uLong           nDataFieldPos;
1206 
1207         rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1208 
1209         // write correct version ( old style/new style header )
1210         if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
1211         {
1212             // write ID for new format (5.0)
1213             rOStm << GRAPHIC_FORMAT_50;
1214 
1215             // write new style header
1216             VersionCompat* pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
1217 
1218             rOStm << (long) meType;
1219 
1220             // data size is updated later
1221             nDataFieldPos = rOStm.Tell();
1222             rOStm << (long) 0;
1223 
1224             rOStm << aSize;
1225             rOStm << aMapMode;
1226 
1227             delete pCompat;
1228         }
1229         else
1230         {
1231             // write old style (<=4.0) header
1232             rOStm << (long) meType;
1233 
1234             // data size is updated later
1235             nDataFieldPos = rOStm.Tell();
1236             rOStm << (long) 0;
1237 
1238             rOStm << (long) aSize.Width();
1239             rOStm << (long) aSize.Height();
1240             rOStm << (long) aMapMode.GetMapUnit();
1241             rOStm << (long) aMapMode.GetScaleX().GetNumerator();
1242             rOStm << (long) aMapMode.GetScaleX().GetDenominator();
1243             rOStm << (long) aMapMode.GetScaleY().GetNumerator();
1244             rOStm << (long) aMapMode.GetScaleY().GetDenominator();
1245             rOStm << (long) aMapMode.GetOrigin().X();
1246             rOStm << (long) aMapMode.GetOrigin().Y();
1247         }
1248 
1249         // write data block
1250         if( !rOStm.GetError() )
1251         {
1252             const sal_uLong nDataStart = rOStm.Tell();
1253 
1254             if( ImplIsSupportedGraphic() )
1255                 rOStm << *this;
1256 
1257             if( !rOStm.GetError() )
1258             {
1259                 const sal_uLong nStmPos2 = rOStm.Tell();
1260                 rOStm.Seek( nDataFieldPos );
1261                 rOStm << (long) ( nStmPos2 - nDataStart );
1262                 rOStm.Seek( nStmPos2 );
1263                 bRet = sal_True;
1264             }
1265         }
1266 
1267         rOStm.SetNumberFormatInt( nOldFormat );
1268     }
1269 
1270     return bRet;
1271 }
1272 
1273 // ------------------------------------------------------------------------
1274 
1275 sal_Bool ImpGraphic::ImplSwapOut()
1276 {
1277     sal_Bool bRet = sal_False;
1278 
1279     if( !ImplIsSwapOut() )
1280     {
1281         if( !maDocFileURLStr.Len() )
1282         {
1283             ::utl::TempFile     aTempFile;
1284             const INetURLObject aTmpURL( aTempFile.GetURL() );
1285 
1286             if( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() )
1287             {
1288                 SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
1289 
1290                 if( pOStm )
1291                 {
1292                     pOStm->SetVersion( SOFFICE_FILEFORMAT_50 );
1293                     pOStm->SetCompressMode( COMPRESSMODE_NATIVE );
1294 
1295                     if( ( bRet = ImplSwapOut( pOStm ) ) == sal_True )
1296                     {
1297                         mpSwapFile = new ImpSwapFile;
1298                         mpSwapFile->nRefCount = 1;
1299                         mpSwapFile->aSwapURL = aTmpURL;
1300                     }
1301                     else
1302                     {
1303                         delete pOStm, pOStm = NULL;
1304 
1305                         try
1306                         {
1307                             ::ucbhelper::Content aCnt( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ),
1308                                                  ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
1309 
1310                             aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1311                                                  ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
1312                         }
1313                         catch( const ::com::sun::star::ucb::ContentCreationException& )
1314                         {
1315                         }
1316                         catch( const ::com::sun::star::uno::RuntimeException& )
1317                         {
1318                         }
1319                         catch( const ::com::sun::star::ucb::CommandAbortedException& )
1320                         {
1321                         }
1322                         catch( const ::com::sun::star::uno::Exception& )
1323                         {
1324                         }
1325                     }
1326 
1327                     delete pOStm;
1328                 }
1329             }
1330         }
1331         else
1332         {
1333             ImplClearGraphics( sal_True );
1334             bRet = mbSwapOut = sal_True;
1335         }
1336     }
1337 
1338     return bRet;
1339 }
1340 
1341 // ------------------------------------------------------------------------
1342 
1343 sal_Bool ImpGraphic::ImplSwapOut( SvStream* pOStm )
1344 {
1345     sal_Bool bRet = sal_False;
1346 
1347     if( pOStm )
1348     {
1349         pOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
1350 
1351         if( !pOStm->GetError() && ImplWriteEmbedded( *pOStm ) )
1352         {
1353             pOStm->Flush();
1354 
1355             if( !pOStm->GetError() )
1356             {
1357                 ImplClearGraphics( sal_True );
1358                 bRet = mbSwapOut = sal_True;
1359             }
1360         }
1361     }
1362     else
1363     {
1364         ImplClearGraphics( sal_True );
1365         bRet = mbSwapOut = sal_True;
1366     }
1367 
1368     return bRet;
1369 }
1370 
1371 // ------------------------------------------------------------------------
1372 
1373 sal_Bool ImpGraphic::ImplSwapIn()
1374 {
1375     sal_Bool bRet = sal_False;
1376 
1377     if( ImplIsSwapOut() )
1378     {
1379         String aSwapURL;
1380 
1381         if( mpSwapFile )
1382             aSwapURL = mpSwapFile->aSwapURL.GetMainURL( INetURLObject::NO_DECODE );
1383         else
1384             aSwapURL = maDocFileURLStr;
1385 
1386         if( aSwapURL.Len() )
1387         {
1388             SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aSwapURL, STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
1389 
1390             if( pIStm )
1391             {
1392                 pIStm->SetVersion( SOFFICE_FILEFORMAT_50 );
1393                 pIStm->SetCompressMode( COMPRESSMODE_NATIVE );
1394 
1395                 if( !mpSwapFile )
1396                     pIStm->Seek( mnDocFilePos );
1397 
1398                 bRet = ImplSwapIn( pIStm );
1399                 delete pIStm;
1400 
1401                 if( mpSwapFile )
1402                 {
1403                     if( mpSwapFile->nRefCount > 1 )
1404                         mpSwapFile->nRefCount--;
1405                     else
1406                     {
1407                         try
1408                         {
1409                             ::ucbhelper::Content aCnt( aSwapURL,
1410                                                  ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
1411 
1412                             aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
1413                                                  ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
1414                         }
1415                         catch( const ::com::sun::star::ucb::ContentCreationException& )
1416                         {
1417                         }
1418                         catch( const ::com::sun::star::uno::RuntimeException& )
1419                         {
1420                         }
1421                         catch( const ::com::sun::star::ucb::CommandAbortedException& )
1422                         {
1423                         }
1424                         catch( const ::com::sun::star::uno::Exception& )
1425                         {
1426                         }
1427 
1428                         delete mpSwapFile;
1429                     }
1430 
1431                     mpSwapFile = NULL;
1432                 }
1433             }
1434         }
1435     }
1436 
1437     return bRet;
1438 }
1439 
1440 // ------------------------------------------------------------------------
1441 
1442 sal_Bool ImpGraphic::ImplSwapIn( SvStream* pIStm )
1443 {
1444     sal_Bool bRet = sal_False;
1445 
1446     if( pIStm )
1447     {
1448         pIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
1449 
1450         if( !pIStm->GetError() )
1451         {
1452             mbSwapUnderway = sal_True;
1453             bRet = ImplReadEmbedded( *pIStm );
1454             mbSwapUnderway = sal_False;
1455 
1456             if( !bRet )
1457                 ImplClear();
1458             else
1459                 mbSwapOut = sal_False;
1460         }
1461     }
1462 
1463     return bRet;
1464 }
1465 
1466 // ------------------------------------------------------------------------
1467 
1468 sal_Bool ImpGraphic::ImplIsSwapOut() const
1469 {
1470     return mbSwapOut;
1471 }
1472 
1473 // ------------------------------------------------------------------------
1474 
1475 void ImpGraphic::ImplSetLink( const GfxLink& rGfxLink )
1476 {
1477     delete mpGfxLink;
1478     mpGfxLink = new GfxLink( rGfxLink );
1479 
1480     if( mpGfxLink->IsNative() )
1481         mpGfxLink->SwapOut();
1482 }
1483 
1484 // ------------------------------------------------------------------------
1485 
1486 GfxLink ImpGraphic::ImplGetLink()
1487 {
1488     return( mpGfxLink ? *mpGfxLink : GfxLink() );
1489 }
1490 
1491 // ------------------------------------------------------------------------
1492 
1493 sal_Bool ImpGraphic::ImplIsLink() const
1494 {
1495     return ( mpGfxLink != NULL ) ? sal_True : sal_False;
1496 }
1497 
1498 // ------------------------------------------------------------------------
1499 
1500 sal_uLong ImpGraphic::ImplGetChecksum() const
1501 {
1502     sal_uLong nRet = 0;
1503 
1504     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
1505     {
1506         switch( meType )
1507         {
1508             case( GRAPHIC_DEFAULT ):
1509             break;
1510 
1511             case( GRAPHIC_BITMAP ):
1512             {
1513                 if( mpAnimation )
1514                     nRet = mpAnimation->GetChecksum();
1515                 else
1516                     nRet = maEx.GetChecksum();
1517             }
1518             break;
1519 
1520             default:
1521                 nRet = maMetaFile.GetChecksum();
1522             break;
1523         }
1524     }
1525 
1526     return nRet;
1527 }
1528 
1529 // ------------------------------------------------------------------------
1530 
1531 sal_Bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const
1532 {
1533     sal_Bool bResult = sal_False;
1534 
1535     if( !rOStm.GetError() )
1536     {
1537         if( !ImplIsSwapOut() )
1538         {
1539             if( mpGfxLink && mpGfxLink->IsNative() )
1540                 bResult = mpGfxLink->ExportNative( rOStm );
1541             else
1542             {
1543                 rOStm << *this;
1544                 bResult = ( rOStm.GetError() == ERRCODE_NONE );
1545             }
1546         }
1547         else
1548              rOStm.SetError( SVSTREAM_GENERALERROR );
1549     }
1550 
1551     return bResult;
1552 }
1553 
1554 // ------------------------------------------------------------------------
1555 
1556 SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic )
1557 {
1558     if( !rIStm.GetError() )
1559     {
1560         const sal_uLong nStmPos1 = rIStm.Tell();
1561         sal_uInt32 nTmp;
1562 
1563         if ( !rImpGraphic.mbSwapUnderway )
1564             rImpGraphic.ImplClear();
1565 
1566         // read Id
1567         rIStm >> nTmp;
1568 
1569         // if there is no more data, avoid further expensive
1570         // reading which will create VDevs and other stuff, just to
1571         // read nothing. CAUTION: Eof is only true AFTER reading another
1572         // byte, a speciality of SvMemoryStream (!)
1573         if(!rIStm.GetError() && !rIStm.IsEof())
1574         {
1575             if( NATIVE_FORMAT_50 == nTmp )
1576             {
1577                 Graphic         aGraphic;
1578                 GfxLink         aLink;
1579                 VersionCompat*  pCompat;
1580 
1581                 // read compat info
1582                 pCompat = new VersionCompat( rIStm, STREAM_READ );
1583                 delete pCompat;
1584 
1585                 rIStm >> aLink;
1586 
1587                 // set dummy link to avoid creation of additional link after filtering;
1588                 // we set a default link to avoid unnecessary swapping of native data
1589                 aGraphic.SetLink( GfxLink() );
1590 
1591                 if( !rIStm.GetError() && aLink.LoadNative( aGraphic ) )
1592                 {
1593                     // set link only, if no other link was set
1594                     const sal_Bool bSetLink = ( rImpGraphic.mpGfxLink == NULL );
1595 
1596                     // assign graphic
1597                     rImpGraphic = *aGraphic.ImplGetImpGraphic();
1598 
1599                     if( aLink.IsPrefMapModeValid() )
1600                         rImpGraphic.ImplSetPrefMapMode( aLink.GetPrefMapMode() );
1601 
1602                     if( aLink.IsPrefSizeValid() )
1603                         rImpGraphic.ImplSetPrefSize( aLink.GetPrefSize() );
1604 
1605                     if( bSetLink )
1606                         rImpGraphic.ImplSetLink( aLink );
1607                 }
1608                 else
1609                 {
1610                     rIStm.Seek( nStmPos1 );
1611                     rIStm.SetError( ERRCODE_IO_WRONGFORMAT );
1612                 }
1613             }
1614             else
1615             {
1616                 BitmapEx        aBmpEx;
1617                 const sal_uInt16    nOldFormat = rIStm.GetNumberFormatInt();
1618 
1619                 rIStm.SeekRel( -4 );
1620                 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1621                 rIStm >> aBmpEx;
1622 
1623                 if( !rIStm.GetError() )
1624                 {
1625                     sal_uInt32  nMagic1(0), nMagic2(0);
1626                     sal_uLong   nActPos = rIStm.Tell();
1627 
1628                     rIStm >> nMagic1 >> nMagic2;
1629                     rIStm.Seek( nActPos );
1630 
1631                     rImpGraphic = ImpGraphic( aBmpEx );
1632 
1633                     if( !rIStm.GetError() && ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) )
1634                     {
1635                         delete rImpGraphic.mpAnimation;
1636                         rImpGraphic.mpAnimation = new Animation;
1637                         rIStm >> *rImpGraphic.mpAnimation;
1638 
1639                         // #108077# manually set loaded BmpEx to Animation
1640                         // (which skips loading its BmpEx if already done)
1641                         rImpGraphic.mpAnimation->SetBitmapEx(aBmpEx);
1642                     }
1643                     else
1644                         rIStm.ResetError();
1645                 }
1646                 else
1647                 {
1648                     GDIMetaFile aMtf;
1649 
1650                     rIStm.Seek( nStmPos1 );
1651                     rIStm.ResetError();
1652                     rIStm >> aMtf;
1653 
1654                     if( !rIStm.GetError() )
1655                         rImpGraphic = aMtf;
1656                     else
1657                         rIStm.Seek( nStmPos1 );
1658                 }
1659 
1660                 rIStm.SetNumberFormatInt( nOldFormat );
1661             }
1662         }
1663     }
1664 
1665     return rIStm;
1666 }
1667 
1668 // ------------------------------------------------------------------------
1669 
1670 SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic )
1671 {
1672     if( !rOStm.GetError() )
1673     {
1674         if( !rImpGraphic.ImplIsSwapOut() )
1675         {
1676             if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) &&
1677                 ( rOStm.GetCompressMode() & COMPRESSMODE_NATIVE ) &&
1678                 rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() )
1679             {
1680                 VersionCompat* pCompat;
1681 
1682                 // native format
1683                 rOStm << NATIVE_FORMAT_50;
1684 
1685                 // write compat info
1686                 pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
1687                 delete pCompat;
1688 
1689                 rImpGraphic.mpGfxLink->SetPrefMapMode( rImpGraphic.ImplGetPrefMapMode() );
1690                 rImpGraphic.mpGfxLink->SetPrefSize( rImpGraphic.ImplGetPrefSize() );
1691                 rOStm << *rImpGraphic.mpGfxLink;
1692             }
1693             else
1694             {
1695                 // own format
1696                 const sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt();
1697                 rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1698 
1699                 switch( rImpGraphic.ImplGetType() )
1700                 {
1701                     case( GRAPHIC_NONE ):
1702                     case( GRAPHIC_DEFAULT ):
1703                     break;
1704 
1705                     case GRAPHIC_BITMAP:
1706                     {
1707                         if ( rImpGraphic.ImplIsAnimated() )
1708                             rOStm << *rImpGraphic.mpAnimation;
1709                         else
1710                             rOStm << rImpGraphic.maEx;
1711                     }
1712                     break;
1713 
1714                     default:
1715                     {
1716                         if( rImpGraphic.ImplIsSupportedGraphic() )
1717                             rOStm << rImpGraphic.maMetaFile;
1718                     }
1719                     break;
1720                 }
1721 
1722                 rOStm.SetNumberFormatInt( nOldFormat );
1723             }
1724         }
1725         else
1726              rOStm.SetError( SVSTREAM_GENERALERROR );
1727     }
1728 
1729     return rOStm;
1730 }
1731