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