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