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