Update git submodules
[LibreOffice.git] / vcl / source / gdi / impgraph.cxx
blob347dd5dc651b29ad937574cfbf350fcabb3be28e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <comphelper/fileformat.h>
24 #include <o3tl/make_shared.hxx>
25 #include <tools/fract.hxx>
26 #include <tools/vcompat.hxx>
27 #include <tools/urlobj.hxx>
28 #include <tools/stream.hxx>
29 #include <unotools/ucbhelper.hxx>
30 #include <unotools/ucbstreamhelper.hxx>
31 #include <unotools/tempfile.hxx>
32 #include <utility>
33 #include <vcl/filter/SvmReader.hxx>
34 #include <vcl/filter/SvmWriter.hxx>
35 #include <vcl/outdev.hxx>
36 #include <vcl/graphicfilter.hxx>
37 #include <vcl/virdev.hxx>
38 #include <vcl/gfxlink.hxx>
39 #include <vcl/cvtgrf.hxx>
40 #include <vcl/graph.hxx>
41 #include <vcl/metaact.hxx>
42 #include <impgraph.hxx>
43 #include <com/sun/star/graphic/XPrimitive2D.hpp>
44 #include <drawinglayer/primitive2d/baseprimitive2d.hxx>
45 #include <vcl/dibtools.hxx>
46 #include <map>
47 #include <memory>
48 #include <vcl/gdimetafiletools.hxx>
49 #include <vcl/TypeSerializer.hxx>
50 #include <vcl/pdfread.hxx>
51 #include <graphic/VectorGraphicLoader.hxx>
53 #define GRAPHIC_MTFTOBMP_MAXEXT 2048
54 #define GRAPHIC_STREAMBUFSIZE 8192UL
56 #define SWAP_FORMAT_ID COMPAT_FORMAT( 'S', 'W', 'A', 'P' )
58 using namespace com::sun::star;
61 class ImpSwapFile
63 private:
64 utl::TempFileFast maTempFile;
65 OUString maOriginURL;
67 public:
68 ImpSwapFile(OUString aOriginURL)
69 : maOriginURL(std::move(aOriginURL))
73 SvStream* getStream() { return maTempFile.GetStream(StreamMode::READWRITE); }
74 OUString const & getOriginURL() const { return maOriginURL; }
77 SvStream* ImpGraphic::getSwapFileStream() const
79 if (mpSwapFile)
80 return mpSwapFile->getStream();
81 return nullptr;
84 ImpGraphic::ImpGraphic(bool bDefault)
85 : MemoryManaged(false)
86 , meType(bDefault ? GraphicType::Default : GraphicType::NONE)
90 ImpGraphic::ImpGraphic(const ImpGraphic& rImpGraphic)
91 : MemoryManaged(rImpGraphic)
92 , maMetaFile(rImpGraphic.maMetaFile)
93 , maBitmapEx(rImpGraphic.maBitmapEx)
94 , maSwapInfo(rImpGraphic.maSwapInfo)
95 , mpSwapFile(rImpGraphic.mpSwapFile)
96 , mpGfxLink(rImpGraphic.mpGfxLink)
97 , maVectorGraphicData(rImpGraphic.maVectorGraphicData)
98 , meType(rImpGraphic.meType)
99 , mnSizeBytes(rImpGraphic.mnSizeBytes)
100 , mbSwapOut(rImpGraphic.mbSwapOut)
101 , mbDummyContext(rImpGraphic.mbDummyContext)
102 , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
103 , mbPrepared(rImpGraphic.mbPrepared)
105 updateCurrentSizeInBytes(mnSizeBytes);
107 // Special case for animations
108 if (rImpGraphic.mpAnimation)
110 mpAnimation = std::make_unique<Animation>(*rImpGraphic.mpAnimation);
111 maBitmapEx = mpAnimation->GetBitmapEx();
115 ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic) noexcept
116 : MemoryManaged(rImpGraphic)
117 , maMetaFile(std::move(rImpGraphic.maMetaFile))
118 , maBitmapEx(std::move(rImpGraphic.maBitmapEx))
119 , maSwapInfo(std::move(rImpGraphic.maSwapInfo))
120 , mpAnimation(std::move(rImpGraphic.mpAnimation))
121 , mpSwapFile(std::move(rImpGraphic.mpSwapFile))
122 , mpGfxLink(std::move(rImpGraphic.mpGfxLink))
123 , maVectorGraphicData(std::move(rImpGraphic.maVectorGraphicData))
124 , meType(rImpGraphic.meType)
125 , mnSizeBytes(rImpGraphic.mnSizeBytes)
126 , mbSwapOut(rImpGraphic.mbSwapOut)
127 , mbDummyContext(rImpGraphic.mbDummyContext)
128 , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
129 , mbPrepared (rImpGraphic.mbPrepared)
131 updateCurrentSizeInBytes(mnSizeBytes);
133 rImpGraphic.clear();
134 rImpGraphic.mbDummyContext = false;
137 ImpGraphic::ImpGraphic(std::shared_ptr<GfxLink> xGfxLink, sal_Int32 nPageIndex)
138 : MemoryManaged(true)
139 , mpGfxLink(std::move(xGfxLink))
140 , meType(GraphicType::Bitmap)
141 , mbSwapOut(true)
143 maSwapInfo.mbIsTransparent = true;
144 maSwapInfo.mbIsAlpha = true;
145 maSwapInfo.mbIsEPS = false;
146 maSwapInfo.mbIsAnimated = false;
147 maSwapInfo.mnAnimationLoopCount = 0;
148 maSwapInfo.mnPageIndex = nPageIndex;
150 ensureCurrentSizeInBytes();
153 ImpGraphic::ImpGraphic(GraphicExternalLink aGraphicExternalLink)
154 : MemoryManaged(true)
155 , meType(GraphicType::Default)
156 , maGraphicExternalLink(std::move(aGraphicExternalLink))
158 ensureCurrentSizeInBytes();
161 ImpGraphic::ImpGraphic(const BitmapEx& rBitmapEx)
162 : MemoryManaged(!rBitmapEx.IsEmpty())
163 , maBitmapEx(rBitmapEx)
164 , meType(rBitmapEx.IsEmpty() ? GraphicType::NONE : GraphicType::Bitmap)
166 ensureCurrentSizeInBytes();
169 ImpGraphic::ImpGraphic(const std::shared_ptr<VectorGraphicData>& rVectorGraphicDataPtr)
170 : MemoryManaged(bool(rVectorGraphicDataPtr))
171 , maVectorGraphicData(rVectorGraphicDataPtr)
172 , meType(rVectorGraphicDataPtr ? GraphicType::Bitmap : GraphicType::NONE)
174 ensureCurrentSizeInBytes();
177 ImpGraphic::ImpGraphic(const Animation& rAnimation)
178 : MemoryManaged(true)
179 , maBitmapEx(rAnimation.GetBitmapEx())
180 , mpAnimation(std::make_unique<Animation>(rAnimation))
181 , meType(GraphicType::Bitmap)
183 ensureCurrentSizeInBytes();
186 ImpGraphic::ImpGraphic(const GDIMetaFile& rMetafile)
187 : MemoryManaged(true)
188 , maMetaFile(rMetafile)
189 , meType(GraphicType::GdiMetafile)
191 ensureCurrentSizeInBytes();
194 ImpGraphic::~ImpGraphic()
198 ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic )
200 if( &rImpGraphic != this )
202 maMetaFile = rImpGraphic.maMetaFile;
203 meType = rImpGraphic.meType;
204 mnSizeBytes = rImpGraphic.mnSizeBytes;
205 updateCurrentSizeInBytes(mnSizeBytes);
207 maSwapInfo = rImpGraphic.maSwapInfo;
208 mbDummyContext = rImpGraphic.mbDummyContext;
209 maGraphicExternalLink = rImpGraphic.maGraphicExternalLink;
211 mpAnimation.reset();
213 if ( rImpGraphic.mpAnimation )
215 mpAnimation = std::make_unique<Animation>( *rImpGraphic.mpAnimation );
216 maBitmapEx = mpAnimation->GetBitmapEx();
218 else
220 maBitmapEx = rImpGraphic.maBitmapEx;
223 mbSwapOut = rImpGraphic.mbSwapOut;
224 mpSwapFile = rImpGraphic.mpSwapFile;
225 mbPrepared = rImpGraphic.mbPrepared;
227 mpGfxLink = rImpGraphic.mpGfxLink;
229 maVectorGraphicData = rImpGraphic.maVectorGraphicData;
230 resetLastUsed();
232 changeExisting(mnSizeBytes);
235 return *this;
238 ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic)
240 maMetaFile = std::move(rImpGraphic.maMetaFile);
241 meType = rImpGraphic.meType;
242 mnSizeBytes = rImpGraphic.mnSizeBytes;
243 maSwapInfo = std::move(rImpGraphic.maSwapInfo);
244 mbDummyContext = rImpGraphic.mbDummyContext;
245 mpAnimation = std::move(rImpGraphic.mpAnimation);
246 maBitmapEx = std::move(rImpGraphic.maBitmapEx);
247 mbSwapOut = rImpGraphic.mbSwapOut;
248 mpSwapFile = std::move(rImpGraphic.mpSwapFile);
249 mpGfxLink = std::move(rImpGraphic.mpGfxLink);
250 maVectorGraphicData = std::move(rImpGraphic.maVectorGraphicData);
251 maGraphicExternalLink = rImpGraphic.maGraphicExternalLink;
252 mbPrepared = rImpGraphic.mbPrepared;
254 rImpGraphic.clear();
255 rImpGraphic.mbDummyContext = false;
256 resetLastUsed();
258 changeExisting(mnSizeBytes);
260 return *this;
263 bool ImpGraphic::operator==( const ImpGraphic& rOther ) const
265 if( this == &rOther )
266 return true;
268 if (mbPrepared && rOther.mbPrepared)
269 return (*mpGfxLink == *rOther.mpGfxLink);
271 if (!isAvailable() || !rOther.isAvailable())
272 return false;
274 if ( meType != rOther.meType )
275 return false;
277 bool bRet = false;
278 switch( meType )
280 case GraphicType::NONE:
281 case GraphicType::Default:
282 return true;
284 case GraphicType::GdiMetafile:
285 return ( rOther.maMetaFile == maMetaFile );
287 case GraphicType::Bitmap:
289 if(maVectorGraphicData)
291 if(maVectorGraphicData == rOther.maVectorGraphicData)
293 // equal instances
294 bRet = true;
296 else if(rOther.maVectorGraphicData)
298 // equal content
299 bRet = (*maVectorGraphicData) == (*rOther.maVectorGraphicData);
302 else if( mpAnimation )
304 if( rOther.mpAnimation && ( *rOther.mpAnimation == *mpAnimation ) )
305 bRet = true;
307 else if( !rOther.mpAnimation && ( rOther.maBitmapEx == maBitmapEx ) )
309 bRet = true;
312 break;
315 return bRet;
318 const std::shared_ptr<VectorGraphicData>& ImpGraphic::getVectorGraphicData() const
320 ensureAvailable();
322 return maVectorGraphicData;
325 void ImpGraphic::createSwapInfo()
327 if (isSwappedOut())
328 return;
330 if (!maBitmapEx.IsEmpty())
331 maSwapInfo.maSizePixel = maBitmapEx.GetSizePixel();
332 else
333 maSwapInfo.maSizePixel = Size();
335 maSwapInfo.maPrefMapMode = getPrefMapMode();
336 maSwapInfo.maPrefSize = getPrefSize();
337 maSwapInfo.mbIsAnimated = isAnimated();
338 maSwapInfo.mbIsEPS = isEPS();
339 maSwapInfo.mbIsTransparent = isTransparent();
340 maSwapInfo.mbIsAlpha = isAlpha();
341 maSwapInfo.mnAnimationLoopCount = getAnimationLoopCount();
342 maSwapInfo.mnPageIndex = getPageNumber();
345 void ImpGraphic::clearGraphics()
347 maBitmapEx.Clear();
348 maMetaFile.Clear();
349 mpAnimation.reset();
350 maVectorGraphicData.reset();
353 void ImpGraphic::setPrepared(bool bAnimated, const Size* pSizeHint)
355 mbPrepared = true;
356 mbSwapOut = true;
357 meType = GraphicType::Bitmap;
359 SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(mpGfxLink->GetData()), mpGfxLink->GetDataSize(), StreamMode::READ | StreamMode::WRITE);
361 if (pSizeHint)
363 maSwapInfo.maPrefSize = *pSizeHint;
364 maSwapInfo.maPrefMapMode = MapMode(MapUnit::Map100thMM);
367 GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
368 if (aDescriptor.Detect(true))
370 if (!pSizeHint)
372 // If we have logic size, work with that, as later pixel -> logic
373 // conversion will work with the output device DPI, not the graphic
374 // DPI.
375 Size aLogSize = aDescriptor.GetSize_100TH_MM();
376 if (aDescriptor.GetPreferredLogSize() && aDescriptor.GetPreferredMapMode())
378 maSwapInfo.maPrefSize = *aDescriptor.GetPreferredLogSize();
379 maSwapInfo.maPrefMapMode = *aDescriptor.GetPreferredMapMode();
381 else if (aLogSize.getWidth() && aLogSize.getHeight())
383 maSwapInfo.maPrefSize = aLogSize;
384 maSwapInfo.maPrefMapMode = MapMode(MapUnit::Map100thMM);
386 else
388 maSwapInfo.maPrefSize = aDescriptor.GetSizePixel();
389 maSwapInfo.maPrefMapMode = MapMode(MapUnit::MapPixel);
393 maSwapInfo.maSizePixel = aDescriptor.GetSizePixel();
394 maSwapInfo.mbIsTransparent = aDescriptor.IsTransparent();
395 maSwapInfo.mbIsAlpha = aDescriptor.IsAlpha();
396 } else {
397 maSwapInfo.mbIsTransparent = false;
398 maSwapInfo.mbIsAlpha = false;
401 maSwapInfo.mnAnimationLoopCount = 0;
402 maSwapInfo.mbIsEPS = false;
403 maSwapInfo.mbIsAnimated = bAnimated;
405 if (maVectorGraphicData)
406 maSwapInfo.mnPageIndex = maVectorGraphicData->getPageIndex();
409 void ImpGraphic::clear()
411 mpSwapFile.reset();
412 mbSwapOut = false;
413 mbPrepared = false;
415 // cleanup
416 clearGraphics();
417 meType = GraphicType::NONE;
418 mnSizeBytes = 0;
420 changeExisting(mnSizeBytes);
421 maGraphicExternalLink.msURL.clear();
424 bool ImpGraphic::isSupportedGraphic() const
426 return meType != GraphicType::NONE;
429 bool ImpGraphic::isTransparent() const
431 bool bRet(true);
433 if (mbSwapOut)
435 bRet = maSwapInfo.mbIsTransparent;
437 else if (meType == GraphicType::Bitmap && !maVectorGraphicData)
439 bRet = mpAnimation ? mpAnimation->IsTransparent() : maBitmapEx.IsAlpha();
442 return bRet;
445 bool ImpGraphic::isAlpha() const
447 bool bRet(false);
449 if (mbSwapOut)
451 bRet = maSwapInfo.mbIsAlpha;
453 else if (maVectorGraphicData)
455 bRet = true;
457 else if (meType == GraphicType::Bitmap)
459 bRet = (nullptr == mpAnimation && maBitmapEx.IsAlpha());
462 return bRet;
465 bool ImpGraphic::isAnimated() const
467 return mbSwapOut ? maSwapInfo.mbIsAnimated : mpAnimation != nullptr;
470 bool ImpGraphic::isEPS() const
472 if (mbSwapOut)
473 return maSwapInfo.mbIsEPS;
475 return( ( meType == GraphicType::GdiMetafile ) &&
476 ( maMetaFile.GetActionSize() > 0 ) &&
477 ( maMetaFile.GetAction( 0 )->GetType() == MetaActionType::EPS ) );
480 bool ImpGraphic::isAvailable() const
482 return !mbPrepared && !mbSwapOut;
485 bool ImpGraphic::makeAvailable()
487 return ensureAvailable();
490 void ImpGraphic::updateBitmapFromVectorGraphic(const Size& pixelSize) const
492 assert (maVectorGraphicData);
494 // use maBitmapEx as local buffer for rendered vector image
495 if (pixelSize.Width() && pixelSize.Height())
497 if (maBitmapEx.IsEmpty() || maBitmapEx.GetSizePixel() != pixelSize)
498 const_cast<ImpGraphic*>(this)->maBitmapEx = maVectorGraphicData->getBitmap(pixelSize);
500 else // maVectorGraphicData caches the replacement, so updating unconditionally is cheap
502 const_cast<ImpGraphic*>(this)->maBitmapEx = maVectorGraphicData->getReplacement();
505 if (maExPrefSize.getWidth() && maExPrefSize.getHeight())
506 const_cast<ImpGraphic*>(this)->maBitmapEx.SetPrefSize(maExPrefSize);
509 Bitmap ImpGraphic::getBitmap(const GraphicConversionParameters& rParameters) const
511 Bitmap aRetBmp;
513 ensureAvailable();
515 if( meType == GraphicType::Bitmap )
517 if (!mpAnimation && maVectorGraphicData)
518 updateBitmapFromVectorGraphic(rParameters.getSizePixel());
520 const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maBitmapEx );
522 aRetBmp = rRetBmpEx.GetBitmap( COL_WHITE );
524 if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
525 aRetBmp.Scale(rParameters.getSizePixel());
527 else if( ( meType != GraphicType::Default ) && isSupportedGraphic() )
529 if(maBitmapEx.IsEmpty())
531 // calculate size
532 ScopedVclPtrInstance< VirtualDevice > aVDev;
533 Size aDrawSize(aVDev->LogicToPixel(maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode()));
535 if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height())
537 // apply given size if exists
538 aDrawSize = rParameters.getSizePixel();
541 if(aDrawSize.Width() && aDrawSize.Height() && !rParameters.getUnlimitedSize()
542 && (aDrawSize.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aDrawSize.Height() > GRAPHIC_MTFTOBMP_MAXEXT))
544 // limit bitmap size to a maximum of GRAPHIC_MTFTOBMP_MAXEXT x GRAPHIC_MTFTOBMP_MAXEXT
545 double fWH(static_cast<double>(aDrawSize.Width()) / static_cast<double>(aDrawSize.Height()));
547 if(fWH <= 1.0)
549 aDrawSize.setWidth(basegfx::fround<tools::Long>(GRAPHIC_MTFTOBMP_MAXEXT * fWH));
550 aDrawSize.setHeight(GRAPHIC_MTFTOBMP_MAXEXT);
552 else
554 aDrawSize.setWidth(GRAPHIC_MTFTOBMP_MAXEXT);
555 aDrawSize.setHeight(basegfx::fround<tools::Long>(GRAPHIC_MTFTOBMP_MAXEXT / fWH));
559 // calculate pixel size. Normally, it's the same as aDrawSize, but may
560 // need to be extended when hairlines are on the right or bottom edge
561 Size aPixelSize(aDrawSize);
563 if(GraphicType::GdiMetafile == getType())
565 // tdf#126319 Removed correction based on hairline-at-the-extremes of
566 // the metafile. The task shows that this is no longer sufficient since
567 // less hairlines get used in general - what is good, but breaks that
568 // old fix. Anyways, hairlines are a left-over from non-AA times
569 // when it was not possible to paint lines taller than one pixel.
570 // This might need to be corrected further using primitives and
571 // the possibility to get better-quality ranges for correction. For
572 // now, always add that one pixel.
573 aPixelSize.setWidth(aPixelSize.getWidth() + 1);
574 aPixelSize.setHeight(aPixelSize.getHeight() + 1);
577 if(aVDev->SetOutputSizePixel(aPixelSize))
579 if(rParameters.getAntiAliase())
581 aVDev->SetAntialiasing(aVDev->GetAntialiasing() | AntialiasingFlags::Enable);
584 if(rParameters.getSnapHorVerLines())
586 aVDev->SetAntialiasing(aVDev->GetAntialiasing() | AntialiasingFlags::PixelSnapHairline);
589 draw(*aVDev, Point(), aDrawSize);
591 // use maBitmapEx as local buffer for rendered metafile
592 const_cast< ImpGraphic* >(this)->maBitmapEx = aVDev->GetBitmapEx( Point(), aVDev->GetOutputSizePixel() );
596 aRetBmp = maBitmapEx.GetBitmap();
599 if( !aRetBmp.IsEmpty() )
601 aRetBmp.SetPrefMapMode(getPrefMapMode());
602 aRetBmp.SetPrefSize(getPrefSize());
605 return aRetBmp;
608 BitmapEx ImpGraphic::getBitmapEx(const GraphicConversionParameters& rParameters) const
610 BitmapEx aRetBmpEx;
612 ensureAvailable();
614 if( meType == GraphicType::Bitmap )
616 if (!mpAnimation && maVectorGraphicData)
617 updateBitmapFromVectorGraphic(rParameters.getSizePixel());
619 aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maBitmapEx );
621 if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
623 aRetBmpEx.Scale(
624 rParameters.getSizePixel(),
625 BmpScaleFlag::Fast);
628 else if( ( meType != GraphicType::Default ) && isSupportedGraphic() )
630 if(maBitmapEx.IsEmpty())
632 const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) );
634 // use maBitmapEx as local buffer for rendered metafile
635 const_cast< ImpGraphic* >(this)->maBitmapEx = BitmapEx(getBitmap(rParameters), aMonoMask.getBitmap(rParameters));
638 aRetBmpEx = maBitmapEx;
641 return aRetBmpEx;
644 Animation ImpGraphic::getAnimation() const
646 Animation aAnimation;
648 ensureAvailable();
649 if( mpAnimation )
650 aAnimation = *mpAnimation;
652 return aAnimation;
655 const BitmapEx& ImpGraphic::getBitmapExRef() const
657 ensureAvailable();
658 return maBitmapEx;
661 const GDIMetaFile& ImpGraphic::getGDIMetaFile() const
663 ensureAvailable();
664 if (!maMetaFile.GetActionSize()
665 && maVectorGraphicData
666 && (VectorGraphicDataType::Emf == maVectorGraphicData->getType()
667 || VectorGraphicDataType::Wmf == maVectorGraphicData->getType()))
669 // If we have a Emf/Wmf VectorGraphic object, we
670 // need a way to get the Metafile data out of the primitive
671 // representation. Use a strict virtual hook (MetafileAccessor)
672 // to access the MetafilePrimitive2D directly. Also see comments in
673 // XEmfParser about this.
674 const std::deque< css::uno::Reference< css::graphic::XPrimitive2D > > aSequence(maVectorGraphicData->getPrimitive2DSequence());
676 if (1 == aSequence.size())
678 // try to cast to MetafileAccessor implementation
679 const css::uno::Reference< css::graphic::XPrimitive2D >& xReference(aSequence[0]);
680 auto pUnoPrimitive = static_cast< const drawinglayer::primitive2d::UnoPrimitive2D* >(xReference.get());
681 if (pUnoPrimitive)
683 const MetafileAccessor* pMetafileAccessor = dynamic_cast< const MetafileAccessor* >(pUnoPrimitive->getBasePrimitive2D().get());
685 if (pMetafileAccessor)
687 // it is a MetafileAccessor implementation, get Metafile
688 pMetafileAccessor->accessMetafile(const_cast< ImpGraphic* >(this)->maMetaFile);
694 if (GraphicType::Bitmap == meType && !maMetaFile.GetActionSize())
696 if (maVectorGraphicData)
697 updateBitmapFromVectorGraphic();
699 // #i119735#
700 // Use the local maMetaFile as container for a metafile-representation
701 // of the bitmap graphic. This will be done only once, thus be buffered.
702 // I checked all usages of maMetaFile, it is only used when type is not
703 // GraphicType::Bitmap. In operator= it will get copied, thus buffering will
704 // survive copying (change this if not wanted)
705 ImpGraphic* pThat = const_cast< ImpGraphic* >(this);
707 // #123983# directly create a metafile with the same PrefSize and PrefMapMode
708 // the bitmap has, this will be an always correct metafile
709 if(maBitmapEx.IsAlpha())
711 pThat->maMetaFile.AddAction(new MetaBmpExScaleAction(Point(), maBitmapEx.GetPrefSize(), maBitmapEx));
713 else
715 pThat->maMetaFile.AddAction(new MetaBmpScaleAction(Point(), maBitmapEx.GetPrefSize(), maBitmapEx.GetBitmap()));
718 pThat->maMetaFile.Stop();
719 pThat->maMetaFile.WindStart();
720 pThat->maMetaFile.SetPrefSize(maBitmapEx.GetPrefSize());
721 pThat->maMetaFile.SetPrefMapMode(maBitmapEx.GetPrefMapMode());
724 return maMetaFile;
727 Size ImpGraphic::getSizePixel() const
729 Size aSize;
731 if (isSwappedOut())
732 aSize = maSwapInfo.maSizePixel;
733 else
734 aSize = getBitmapEx(GraphicConversionParameters()).GetSizePixel();
736 return aSize;
739 Size ImpGraphic::getPrefSize() const
741 Size aSize;
743 if (isSwappedOut())
745 aSize = maSwapInfo.maPrefSize;
747 else
749 switch (meType)
751 case GraphicType::Bitmap:
753 if (maVectorGraphicData && maBitmapEx.IsEmpty())
755 if (!maExPrefSize.getWidth() || !maExPrefSize.getHeight())
757 // svg not yet buffered in maBitmapEx, return size derived from range
758 const basegfx::B2DRange& rRange = maVectorGraphicData->getRange();
760 #ifdef MACOSX
761 // tdf#157680 scale down estimated size of embedded PDF
762 // For some unknown reason, the embedded PDF sizes
763 // are 20x larger than expected. This only occurs on
764 // macOS so possibly there is some special conversion
765 // from MapUnit::MapPoint to MapUnit::MapTwip elsewhere
766 // in the code.
767 if (maVectorGraphicData->getType() == VectorGraphicDataType::Pdf)
768 aSize = Size(basegfx::fround(rRange.getWidth() / 20.0f), basegfx::fround(rRange.getHeight() / 20.0f));
769 else
770 #endif
771 aSize = Size(basegfx::fround<tools::Long>(rRange.getWidth()), basegfx::fround<tools::Long>(rRange.getHeight()));
773 else
775 aSize = maExPrefSize;
778 else
780 aSize = maBitmapEx.GetPrefSize();
782 if( !aSize.Width() || !aSize.Height() )
784 aSize = maBitmapEx.GetSizePixel();
788 break;
790 case GraphicType::GdiMetafile:
792 aSize = maMetaFile.GetPrefSize();
794 break;
796 case GraphicType::NONE:
797 case GraphicType::Default:
798 break;
802 return aSize;
805 void ImpGraphic::setValuesForPrefSize(const Size& rPrefSize)
807 switch (meType)
809 case GraphicType::Bitmap:
811 // used when importing a writer FlyFrame with SVG as graphic, added conversion
812 // to allow setting the PrefSize at the BitmapEx to hold it
813 if (maVectorGraphicData)
815 maExPrefSize = rPrefSize;
818 // #108077# Push through pref size to animation object,
819 // will be lost on copy otherwise
820 if (mpAnimation)
822 const_cast< BitmapEx& >(mpAnimation->GetBitmapEx()).SetPrefSize(rPrefSize);
825 maBitmapEx.SetPrefSize(rPrefSize);
827 break;
829 case GraphicType::GdiMetafile:
831 if (isSupportedGraphic())
832 maMetaFile.SetPrefSize(rPrefSize);
834 break;
836 case GraphicType::NONE:
837 case GraphicType::Default:
838 break;
842 void ImpGraphic::setPrefSize(const Size& rPrefSize)
844 ensureAvailable();
845 setValuesForPrefSize(rPrefSize);
848 MapMode ImpGraphic::getPrefMapMode() const
850 MapMode aMapMode;
852 if (isSwappedOut())
854 aMapMode = maSwapInfo.maPrefMapMode;
856 else
858 switch (meType)
860 case GraphicType::Bitmap:
862 if (maVectorGraphicData && maBitmapEx.IsEmpty())
864 // svg not yet buffered in maBitmapEx, return default PrefMapMode
865 aMapMode = MapMode(MapUnit::Map100thMM);
867 else
869 const Size aSize(maBitmapEx.GetPrefSize());
871 if (aSize.Width() && aSize.Height())
872 aMapMode = maBitmapEx.GetPrefMapMode();
875 break;
877 case GraphicType::GdiMetafile:
879 return maMetaFile.GetPrefMapMode();
881 break;
883 case GraphicType::NONE:
884 case GraphicType::Default:
885 break;
889 return aMapMode;
892 void ImpGraphic::setValuesForPrefMapMod(const MapMode& rPrefMapMode)
894 switch (meType)
896 case GraphicType::Bitmap:
898 if (maVectorGraphicData)
900 // ignore for Vector Graphic Data. If this is really used (except the grfcache)
901 // it can be extended by using maBitmapEx as buffer for updateBitmapFromVectorGraphic()
903 else
905 // #108077# Push through pref mapmode to animation object,
906 // will be lost on copy otherwise
907 if (mpAnimation)
909 const_cast<BitmapEx&>(mpAnimation->GetBitmapEx()).SetPrefMapMode(rPrefMapMode);
912 maBitmapEx.SetPrefMapMode(rPrefMapMode);
915 break;
917 case GraphicType::GdiMetafile:
919 maMetaFile.SetPrefMapMode(rPrefMapMode);
921 break;
923 case GraphicType::NONE:
924 case GraphicType::Default:
925 break;
929 void ImpGraphic::setPrefMapMode(const MapMode& rPrefMapMode)
931 ensureAvailable();
932 setValuesForPrefMapMod(rPrefMapMode);
935 void ImpGraphic::ensureCurrentSizeInBytes()
937 if (isAvailable())
938 changeExisting(getSizeBytes());
939 else
940 changeExisting(0);
943 sal_uLong ImpGraphic::getSizeBytes() const
945 if (mnSizeBytes > 0)
946 return mnSizeBytes;
948 if (mbPrepared)
949 ensureAvailable();
951 switch (meType)
953 case GraphicType::Bitmap:
955 if (maVectorGraphicData)
957 std::pair<VectorGraphicData::State, size_t> aPair(maVectorGraphicData->getSizeBytes());
958 if (VectorGraphicData::State::UNPARSED == aPair.first)
960 return aPair.second; // don't cache it until Vector Graphic Data is parsed
962 mnSizeBytes = aPair.second;
964 else
966 mnSizeBytes = mpAnimation ? mpAnimation->GetSizeBytes() : maBitmapEx.GetSizeBytes();
969 break;
971 case GraphicType::GdiMetafile:
973 mnSizeBytes = maMetaFile.GetSizeBytes();
975 break;
977 case GraphicType::NONE:
978 case GraphicType::Default:
979 break;
982 return mnSizeBytes;
985 void ImpGraphic::draw(OutputDevice& rOutDev, const Point& rDestPt) const
987 ensureAvailable();
989 if (isSwappedOut())
990 return;
992 switch (meType)
994 case GraphicType::Bitmap:
996 if (mpAnimation)
998 mpAnimation->Draw(rOutDev, rDestPt);
1000 else
1002 if (maVectorGraphicData)
1003 updateBitmapFromVectorGraphic();
1004 maBitmapEx.Draw(&rOutDev, rDestPt);
1007 break;
1009 case GraphicType::GdiMetafile:
1011 draw(rOutDev, rDestPt, maMetaFile.GetPrefSize());
1013 break;
1015 case GraphicType::Default:
1016 case GraphicType::NONE:
1017 break;
1021 void ImpGraphic::draw(OutputDevice& rOutDev,
1022 const Point& rDestPt, const Size& rDestSize) const
1024 ensureAvailable();
1026 if (isSwappedOut())
1027 return;
1029 switch (meType)
1031 case GraphicType::Bitmap:
1033 if (mpAnimation)
1035 mpAnimation->Draw(rOutDev, rDestPt, rDestSize);
1037 else
1039 if (maVectorGraphicData)
1040 updateBitmapFromVectorGraphic(rOutDev.LogicToPixel(rDestSize));
1041 maBitmapEx.Draw(&rOutDev, rDestPt, rDestSize);
1044 break;
1046 case GraphicType::GdiMetafile:
1048 const_cast<ImpGraphic*>(this)->maMetaFile.WindStart();
1049 const_cast<ImpGraphic*>(this)->maMetaFile.Play(rOutDev, rDestPt, rDestSize);
1050 const_cast<ImpGraphic*>(this)->maMetaFile.WindStart();
1052 break;
1054 case GraphicType::Default:
1055 case GraphicType::NONE:
1056 break;
1060 void ImpGraphic::startAnimation(OutputDevice& rOutDev, const Point& rDestPt,
1061 const Size& rDestSize, tools::Long nRendererId,
1062 OutputDevice* pFirstFrameOutDev )
1064 ensureAvailable();
1066 if( isSupportedGraphic() && !isSwappedOut() && mpAnimation )
1067 mpAnimation->Start(rOutDev, rDestPt, rDestSize, nRendererId, pFirstFrameOutDev);
1070 void ImpGraphic::stopAnimation( const OutputDevice* pOutDev, tools::Long nRendererId )
1072 ensureAvailable();
1074 if( isSupportedGraphic() && !isSwappedOut() && mpAnimation )
1075 mpAnimation->Stop( pOutDev, nRendererId );
1078 void ImpGraphic::setAnimationNotifyHdl( const Link<Animation*,void>& rLink )
1080 ensureAvailable();
1082 if( mpAnimation )
1083 mpAnimation->SetNotifyHdl( rLink );
1086 Link<Animation*,void> ImpGraphic::getAnimationNotifyHdl() const
1088 Link<Animation*,void> aLink;
1090 ensureAvailable();
1092 if( mpAnimation )
1093 aLink = mpAnimation->GetNotifyHdl();
1095 return aLink;
1098 sal_uInt32 ImpGraphic::getAnimationLoopCount() const
1100 if (mbSwapOut)
1101 return maSwapInfo.mnAnimationLoopCount;
1103 return mpAnimation ? mpAnimation->GetLoopCount() : 0;
1106 bool ImpGraphic::swapInContent(SvStream& rStream)
1108 bool bRet = false;
1110 sal_uInt32 nId;
1111 sal_Int32 nType;
1112 sal_Int32 nLength;
1114 rStream.ReadUInt32(nId);
1116 // check version
1117 if (SWAP_FORMAT_ID != nId)
1119 SAL_WARN("vcl", "Incompatible swap file!");
1120 return false;
1123 rStream.ReadInt32(nType);
1124 rStream.ReadInt32(nLength);
1126 meType = static_cast<GraphicType>(nType);
1128 if (meType == GraphicType::NONE || meType == GraphicType::Default)
1130 return true;
1132 else
1134 bRet = swapInGraphic(rStream);
1137 return bRet;
1140 bool ImpGraphic::swapOutGraphic(SvStream& rStream)
1142 if (rStream.GetError())
1143 return false;
1145 ensureAvailable();
1147 if (isSwappedOut())
1149 rStream.SetError(SVSTREAM_GENERALERROR);
1150 return false;
1153 switch (meType)
1155 case GraphicType::GdiMetafile:
1157 if(!rStream.GetError())
1159 SvmWriter aWriter(rStream);
1160 aWriter.Write(maMetaFile);
1163 break;
1165 case GraphicType::Bitmap:
1167 if (maVectorGraphicData)
1169 rStream.WriteInt32(sal_Int32(GraphicContentType::Vector));
1170 // stream out Vector Graphic defining data (length, byte array and evtl. path)
1171 // this is used e.g. in swapping out graphic data and in transporting it over UNO API
1172 // as sequence of bytes, but AFAIK not written anywhere to any kind of file, so it should be
1173 // no problem to extend it; only used at runtime
1174 switch (maVectorGraphicData->getType())
1176 case VectorGraphicDataType::Wmf:
1178 rStream.WriteUInt32(constWmfMagic);
1179 break;
1181 case VectorGraphicDataType::Emf:
1183 rStream.WriteUInt32(constEmfMagic);
1184 break;
1186 case VectorGraphicDataType::Svg:
1188 rStream.WriteUInt32(constSvgMagic);
1189 break;
1191 case VectorGraphicDataType::Pdf:
1193 rStream.WriteUInt32(constPdfMagic);
1194 break;
1198 rStream.WriteUInt32(maVectorGraphicData->getBinaryDataContainer().getSize());
1199 maVectorGraphicData->getBinaryDataContainer().writeToStream(rStream);
1201 else if (mpAnimation)
1203 rStream.WriteInt32(sal_Int32(GraphicContentType::Animation));
1204 WriteAnimation(rStream, *mpAnimation);
1206 else
1208 rStream.WriteInt32(sal_Int32(GraphicContentType::Bitmap));
1209 WriteDIBBitmapEx(maBitmapEx, rStream);
1212 break;
1214 case GraphicType::NONE:
1215 case GraphicType::Default:
1216 break;
1219 if (mpGfxLink)
1220 mpGfxLink->getDataContainer().swapOut();
1222 return true;
1225 bool ImpGraphic::swapOutContent(SvStream& rStream)
1227 ensureAvailable();
1229 bool bRet = false;
1231 if (meType == GraphicType::NONE || meType == GraphicType::Default || isSwappedOut())
1232 return false;
1234 sal_uLong nDataFieldPos;
1236 // Write the SWAP ID
1237 rStream.WriteUInt32(SWAP_FORMAT_ID);
1239 rStream.WriteInt32(static_cast<sal_Int32>(meType));
1241 // data size is updated later
1242 nDataFieldPos = rStream.Tell();
1243 rStream.WriteInt32(0);
1245 // write data block
1246 const sal_uInt64 nDataStart = rStream.Tell();
1248 swapOutGraphic(rStream);
1250 if (!rStream.GetError())
1252 // Write the written length th the header
1253 const sal_uInt64 nCurrentPosition = rStream.Tell();
1254 rStream.Seek(nDataFieldPos);
1255 rStream.WriteInt32(nCurrentPosition - nDataStart);
1256 rStream.Seek(nCurrentPosition);
1257 bRet = true;
1260 return bRet;
1263 bool ImpGraphic::swapOut()
1265 if (isSwappedOut())
1266 return false;
1268 bool bResult = false;
1270 // We have GfxLink so we have the source available
1271 if (mpGfxLink && mpGfxLink->IsNative())
1273 createSwapInfo();
1275 clearGraphics();
1277 // reset the swap file
1278 mpSwapFile.reset();
1280 mpGfxLink->getDataContainer().swapOut();
1282 // mark as swapped out
1283 mbSwapOut = true;
1285 bResult = true;
1287 else
1289 // Create a swap file
1290 auto pSwapFile = o3tl::make_shared<ImpSwapFile>(getOriginURL());
1292 // Open a stream to write the swap file to
1294 SvStream* pOutputStream = pSwapFile->getStream();
1296 if (!pOutputStream)
1297 return false;
1299 // Write to stream
1300 pOutputStream->SetVersion(SOFFICE_FILEFORMAT_50);
1301 pOutputStream->SetCompressMode(SvStreamCompressFlags::NATIVE);
1302 pOutputStream->SetBufferSize(GRAPHIC_STREAMBUFSIZE);
1304 if (!pOutputStream->GetError() && swapOutContent(*pOutputStream))
1306 pOutputStream->FlushBuffer();
1307 bResult = !pOutputStream->GetError();
1311 // Check if writing was successful
1312 if (bResult)
1314 // We have swapped out, so can clean memory and prepare swap info
1315 createSwapInfo();
1316 clearGraphics();
1318 mpSwapFile = std::move(pSwapFile);
1319 mbSwapOut = true;
1323 if (bResult)
1325 // Signal to manager that we have swapped out
1326 swappedOut(0);
1329 return bResult;
1332 bool ImpGraphic::ensureAvailable() const
1334 bool bResult = true;
1336 if (isSwappedOut())
1338 auto pThis = const_cast<ImpGraphic*>(this);
1339 pThis->registerIntoManager();
1341 bResult = pThis->swapIn();
1344 resetLastUsed();
1345 return bResult;
1348 void ImpGraphic::updateFromLoadedGraphic(const ImpGraphic* pGraphic)
1350 if (mbPrepared)
1352 GraphicExternalLink aLink = maGraphicExternalLink;
1353 Size aPrefSize = maSwapInfo.maPrefSize;
1354 MapMode aPrefMapMode = maSwapInfo.maPrefMapMode;
1355 *this = *pGraphic;
1356 if (aPrefSize.getWidth() && aPrefSize.getHeight() && aPrefMapMode == getPrefMapMode())
1358 // Use custom preferred size if it was set when the graphic was still unloaded.
1359 // Only set the size in case the unloaded and loaded unit matches.
1360 setPrefSize(aPrefSize);
1362 maGraphicExternalLink = std::move(aLink);
1364 else
1366 // Move over only graphic content
1367 mpAnimation.reset();
1368 if (pGraphic->mpAnimation)
1370 mpAnimation = std::make_unique<Animation>(*pGraphic->mpAnimation);
1371 maBitmapEx = mpAnimation->GetBitmapEx();
1373 else
1375 maBitmapEx = pGraphic->maBitmapEx;
1378 maMetaFile = pGraphic->maMetaFile;
1379 maVectorGraphicData = pGraphic->maVectorGraphicData;
1381 // Set to 0, to force recalculation
1382 mnSizeBytes = 0;
1383 mnChecksum = 0;
1385 restoreFromSwapInfo();
1387 mbSwapOut = false;
1391 void ImpGraphic::dumpState(rtl::OStringBuffer &rState)
1393 if (meType == GraphicType::NONE && mnSizeBytes == 0)
1394 return; // uninteresting.
1396 rState.append("\n\t");
1398 if (mbSwapOut)
1399 rState.append("swapped\t");
1400 else
1401 rState.append("loaded\t");
1403 rState.append(static_cast<sal_Int32>(meType));
1404 rState.append("\tsize:\t");
1405 rState.append(static_cast<sal_Int64>(mnSizeBytes));
1406 rState.append("\tgfxl:\t");
1407 rState.append(static_cast<sal_Int64>(mpGfxLink ? mpGfxLink->getSizeBytes() : -1));
1408 rState.append("\t");
1409 rState.append(static_cast<sal_Int32>(maSwapInfo.maSizePixel.Width()));
1410 rState.append("x");
1411 rState.append(static_cast<sal_Int32>(maSwapInfo.maSizePixel.Height()));
1412 rState.append("\t");
1413 rState.append(static_cast<sal_Int32>(maExPrefSize.Width()));
1414 rState.append("x");
1415 rState.append(static_cast<sal_Int32>(maExPrefSize.Height()));
1418 void ImpGraphic::restoreFromSwapInfo()
1420 setValuesForPrefMapMod(maSwapInfo.maPrefMapMode);
1421 setValuesForPrefSize(maSwapInfo.maPrefSize);
1423 if (maVectorGraphicData)
1425 maVectorGraphicData->setPageIndex(maSwapInfo.mnPageIndex);
1429 namespace
1432 std::optional<VectorGraphicDataType> lclConvertToVectorGraphicType(GfxLink const & rLink)
1434 switch(rLink.GetType())
1436 case GfxLinkType::NativePdf:
1437 return VectorGraphicDataType::Pdf;
1439 case GfxLinkType::NativeWmf:
1440 if (rLink.IsEMF())
1441 return VectorGraphicDataType::Emf;
1442 else
1443 return VectorGraphicDataType::Wmf;
1445 case GfxLinkType::NativeSvg:
1446 return VectorGraphicDataType::Svg;
1448 default:
1449 break;
1451 return std::optional<VectorGraphicDataType>();
1454 } // end namespace
1456 bool ImpGraphic::swapIn()
1458 if (!isSwappedOut())
1459 return false;
1461 bool bReturn = false;
1463 if (mbPrepared)
1465 Graphic aGraphic;
1466 if (!mpGfxLink->LoadNative(aGraphic))
1467 return false;
1469 updateFromLoadedGraphic(aGraphic.ImplGetImpGraphic());
1471 resetLastUsed();
1472 bReturn = true;
1474 else if (mpGfxLink && mpGfxLink->IsNative())
1476 std::optional<VectorGraphicDataType> oType = lclConvertToVectorGraphicType(*mpGfxLink);
1477 if (oType)
1479 maVectorGraphicData = vcl::loadVectorGraphic(mpGfxLink->getDataContainer(), *oType);
1481 // Set to 0, to force recalculation
1482 mnSizeBytes = 0;
1483 mnChecksum = 0;
1485 restoreFromSwapInfo();
1487 mbSwapOut = false;
1489 else
1491 Graphic aGraphic;
1492 if (!mpGfxLink->LoadNative(aGraphic))
1493 return false;
1495 ImpGraphic* pImpGraphic = aGraphic.ImplGetImpGraphic();
1496 if (meType != pImpGraphic->meType)
1497 return false;
1499 updateFromLoadedGraphic(pImpGraphic);
1502 resetLastUsed();
1503 bReturn = true;
1505 else
1507 SvStream* pStream = nullptr;
1509 if (mpSwapFile)
1510 pStream = mpSwapFile->getStream();
1512 if (pStream)
1514 pStream->SetVersion(SOFFICE_FILEFORMAT_50);
1515 pStream->SetCompressMode(SvStreamCompressFlags::NATIVE);
1516 pStream->SetBufferSize(GRAPHIC_STREAMBUFSIZE);
1517 pStream->Seek(STREAM_SEEK_TO_BEGIN);
1519 bReturn = swapInFromStream(*pStream);
1521 restoreFromSwapInfo();
1523 setOriginURL(mpSwapFile->getOriginURL());
1525 mpSwapFile.reset();
1529 if (bReturn)
1531 swappedIn(getSizeBytes());
1534 return bReturn;
1537 bool ImpGraphic::swapInFromStream(SvStream& rStream)
1539 bool bRet = false;
1541 if (rStream.GetError())
1542 return false;
1544 clearGraphics();
1545 mnSizeBytes = 0;
1546 mnChecksum = 0;
1548 bRet = swapInContent(rStream);
1550 if (!bRet)
1552 //throw away swapfile, etc.
1553 clear();
1556 mbSwapOut = false;
1558 return bRet;
1561 bool ImpGraphic::swapInGraphic(SvStream& rStream)
1563 bool bReturn = false;
1565 if (rStream.GetError())
1566 return bReturn;
1568 if (meType == GraphicType::Bitmap)
1570 sal_Int32 nContentType = -1;
1571 rStream.ReadInt32(nContentType);
1572 if (nContentType < 0)
1573 return false;
1575 auto eContentType = static_cast<GraphicContentType>(nContentType);
1577 switch (eContentType)
1579 case GraphicContentType::Bitmap:
1581 BitmapEx aBitmapEx;
1582 ReadDIBBitmapEx(aBitmapEx, rStream);
1583 if (!rStream.GetError())
1585 maBitmapEx = aBitmapEx;
1586 bReturn = true;
1589 break;
1591 case GraphicContentType::Animation:
1593 auto pAnimation = std::make_unique<Animation>();
1594 ReadAnimation(rStream, *pAnimation);
1595 if (!rStream.GetError())
1597 mpAnimation = std::move(pAnimation);
1598 maBitmapEx = mpAnimation->GetBitmapEx();
1599 bReturn = true;
1602 break;
1604 case GraphicContentType::Vector:
1606 // try to stream in Svg defining data (length, byte array and evtl. path)
1607 // See below (operator<<) for more information
1608 sal_uInt32 nMagic;
1609 rStream.ReadUInt32(nMagic);
1611 if (constSvgMagic == nMagic || constWmfMagic == nMagic || constEmfMagic == nMagic || constPdfMagic == nMagic)
1613 sal_uInt32 nVectorGraphicDataSize(0);
1614 rStream.ReadUInt32(nVectorGraphicDataSize);
1616 if (nVectorGraphicDataSize)
1618 BinaryDataContainer aDataContainer(rStream, nVectorGraphicDataSize);
1620 if (rStream.GetError())
1621 return false;
1623 VectorGraphicDataType aDataType;
1625 switch (nMagic)
1627 case constSvgMagic:
1628 aDataType = VectorGraphicDataType::Svg;
1629 break;
1630 case constWmfMagic:
1631 aDataType = VectorGraphicDataType::Wmf;
1632 break;
1633 case constEmfMagic:
1634 aDataType = VectorGraphicDataType::Emf;
1635 break;
1636 case constPdfMagic:
1637 aDataType = VectorGraphicDataType::Pdf;
1638 break;
1639 default:
1640 return false;
1643 auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aDataContainer, aDataType);
1645 if (!rStream.GetError())
1647 maVectorGraphicData = std::move(aVectorGraphicDataPtr);
1648 bReturn = true;
1653 break;
1656 else if (meType == GraphicType::GdiMetafile)
1658 GDIMetaFile aMetaFile;
1659 SvmReader aReader(rStream);
1660 aReader.Read(aMetaFile);
1661 if (!rStream.GetError())
1663 maMetaFile = aMetaFile;
1664 bReturn = true;
1667 return bReturn;
1670 void ImpGraphic::setGfxLink(const std::shared_ptr<GfxLink>& rGfxLink)
1672 ensureAvailable();
1674 mpGfxLink = rGfxLink;
1677 const std::shared_ptr<GfxLink> & ImpGraphic::getSharedGfxLink() const
1679 return mpGfxLink;
1682 GfxLink ImpGraphic::getGfxLink() const
1684 ensureAvailable();
1686 return( mpGfxLink ? *mpGfxLink : GfxLink() );
1689 bool ImpGraphic::isGfxLink() const
1691 return ( bool(mpGfxLink) );
1694 BitmapChecksum ImpGraphic::getChecksum() const
1696 if (mnChecksum != 0)
1697 return mnChecksum;
1699 ensureAvailable();
1701 switch (meType)
1703 case GraphicType::NONE:
1704 case GraphicType::Default:
1705 break;
1707 case GraphicType::Bitmap:
1709 if (maVectorGraphicData)
1710 mnChecksum = maVectorGraphicData->GetChecksum();
1711 else if (mpAnimation)
1712 mnChecksum = mpAnimation->GetChecksum();
1713 else
1714 mnChecksum = maBitmapEx.GetChecksum();
1716 break;
1718 case GraphicType::GdiMetafile:
1720 mnChecksum = SvmWriter::GetChecksum(maMetaFile);
1722 break;
1724 return mnChecksum;
1727 sal_Int32 ImpGraphic::getPageNumber() const
1729 if (isSwappedOut())
1730 return maSwapInfo.mnPageIndex;
1732 if (maVectorGraphicData)
1733 return maVectorGraphicData->getPageIndex();
1734 return -1;
1737 bool ImpGraphic::canReduceMemory() const
1739 return !isSwappedOut();
1742 bool ImpGraphic::reduceMemory()
1744 return swapOut();
1747 std::chrono::high_resolution_clock::time_point ImpGraphic::getLastUsed() const
1749 return maLastUsed;
1752 void ImpGraphic::resetLastUsed() const
1754 maLastUsed = std::chrono::high_resolution_clock::now();
1757 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */