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