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