1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <tools/diagnose_ex.h>
21 #include <tools/stream.hxx>
22 #include <sal/log.hxx>
23 #include <vcl/vectorgraphicdata.hxx>
24 #include <comphelper/processfactory.hxx>
25 #include <com/sun/star/graphic/SvgTools.hpp>
26 #include <com/sun/star/graphic/EmfTools.hpp>
27 #include <com/sun/star/graphic/Primitive2DTools.hpp>
28 #include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
29 #include <com/sun/star/util/XAccounting.hpp>
30 #include <vcl/canvastools.hxx>
31 #include <comphelper/seqstream.hxx>
32 #include <comphelper/sequence.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/outdev.hxx>
35 #include <vcl/wmfexternal.hxx>
37 using namespace ::com::sun::star
;
39 BitmapEx
convertPrimitive2DSequenceToBitmapEx(
40 const std::deque
< css::uno::Reference
< css::graphic::XPrimitive2D
> >& rSequence
,
41 const basegfx::B2DRange
& rTargetRange
,
42 const sal_uInt32 nMaximumQuadraticPixels
)
46 if(!rSequence
.empty())
48 // create replacement graphic from maSequence
49 // create XPrimitive2DRenderer
52 uno::Reference
< uno::XComponentContext
> xContext(::comphelper::getProcessComponentContext());
53 const uno::Reference
< graphic::XPrimitive2DRenderer
> xPrimitive2DRenderer
= graphic::Primitive2DTools::create(xContext
);
55 uno::Sequence
< beans::PropertyValue
> aViewParameters
;
56 geometry::RealRectangle2D aRealRect
;
58 aRealRect
.X1
= rTargetRange
.getMinX();
59 aRealRect
.Y1
= rTargetRange
.getMinY();
60 aRealRect
.X2
= rTargetRange
.getMaxX();
61 aRealRect
.Y2
= rTargetRange
.getMaxY();
64 const Size
aDPI(Application::GetDefaultDevice()->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch
)));
66 const uno::Reference
< rendering::XBitmap
> xBitmap(
67 xPrimitive2DRenderer
->rasterize(
68 comphelper::containerToSequence(rSequence
),
73 nMaximumQuadraticPixels
));
77 const uno::Reference
< rendering::XIntegerReadOnlyBitmap
> xIntBmp(xBitmap
, uno::UNO_QUERY_THROW
);
78 aRetval
= vcl::unotools::bitmapExFromXBitmap(xIntBmp
);
81 catch (const uno::Exception
&)
83 TOOLS_WARN_EXCEPTION("vcl", "Got no graphic::XPrimitive2DRenderer!");
85 catch (const std::exception
& e
)
87 SAL_WARN("vcl", "Got no graphic::XPrimitive2DRenderer! : " << e
.what());
94 static size_t estimateSize(
95 std::deque
<uno::Reference
<graphic::XPrimitive2D
>> const& rSequence
)
98 for (auto& it
: rSequence
)
100 uno::Reference
<util::XAccounting
> const xAcc(it
, uno::UNO_QUERY
);
101 assert(xAcc
.is()); // we expect only BasePrimitive2D from SVG parser
102 nRet
+= xAcc
->estimateUsage();
107 bool VectorGraphicData::operator==(const VectorGraphicData
& rCandidate
) const
109 if (getVectorGraphicDataType() == rCandidate
.getVectorGraphicDataType())
111 if (getVectorGraphicDataArrayLength() == rCandidate
.getVectorGraphicDataArrayLength())
114 getVectorGraphicDataArray().getConstArray(),
115 rCandidate
.getVectorGraphicDataArray().getConstArray(),
116 getVectorGraphicDataArrayLength()))
126 void VectorGraphicData::setWmfExternalHeader(const WmfExternal
& aExtHeader
)
128 if (!mpExternalHeader
)
130 mpExternalHeader
.reset( new WmfExternal
);
133 *mpExternalHeader
= aExtHeader
;
136 void VectorGraphicData::ensureReplacement()
138 ensureSequenceAndRange();
140 if(maReplacement
.IsEmpty() && !maSequence
.empty())
142 maReplacement
= convertPrimitive2DSequenceToBitmapEx(maSequence
, getRange());
146 void VectorGraphicData::ensureSequenceAndRange()
148 if (!mbSequenceCreated
&& maVectorGraphicDataArray
.hasElements())
150 // import SVG to maSequence, also set maRange
154 const uno::Reference
< io::XInputStream
> myInputStream(new comphelper::SequenceInputStream(maVectorGraphicDataArray
));
156 if(myInputStream
.is())
158 // create Vector Graphic Data interpreter
159 uno::Reference
<uno::XComponentContext
> xContext(::comphelper::getProcessComponentContext());
161 if (VectorGraphicDataType::Emf
== getVectorGraphicDataType()
162 || VectorGraphicDataType::Wmf
== getVectorGraphicDataType())
164 const uno::Reference
< graphic::XEmfParser
> xEmfParser
= graphic::EmfTools::create(xContext
);
165 uno::Sequence
< ::beans::PropertyValue
> aSequence
;
167 if (mpExternalHeader
)
169 aSequence
= mpExternalHeader
->getSequence();
172 maSequence
= comphelper::sequenceToContainer
<std::deque
<css::uno::Reference
< css::graphic::XPrimitive2D
>>>(xEmfParser
->getDecomposition(myInputStream
, maPath
, aSequence
));
176 const uno::Reference
< graphic::XSvgParser
> xSvgParser
= graphic::SvgTools::create(xContext
);
178 maSequence
= comphelper::sequenceToContainer
<std::deque
<css::uno::Reference
< css::graphic::XPrimitive2D
>>>(xSvgParser
->getDecomposition(myInputStream
, maPath
));
182 if(!maSequence
.empty())
184 const sal_Int32
nCount(maSequence
.size());
185 geometry::RealRectangle2D aRealRect
;
186 uno::Sequence
< beans::PropertyValue
> aViewParameters
;
188 for(sal_Int32
a(0); a
< nCount
; a
++)
191 const css::uno::Reference
< css::graphic::XPrimitive2D
> xReference(maSequence
[a
]);
195 aRealRect
= xReference
->getRange(aViewParameters
);
206 mNestedBitmapSize
= estimateSize(maSequence
);
207 mbSequenceCreated
= true;
211 auto VectorGraphicData::getSizeBytes() const -> std::pair
<State
, size_t>
213 if (maSequence
.empty() && maVectorGraphicDataArray
.hasElements())
215 return std::make_pair(State::UNPARSED
, maVectorGraphicDataArray
.getLength());
219 return std::make_pair(State::PARSED
, maVectorGraphicDataArray
.getLength() + mNestedBitmapSize
);
223 VectorGraphicData::VectorGraphicData(
224 const VectorGraphicDataArray
& rVectorGraphicDataArray
,
225 const OUString
& rPath
,
226 VectorGraphicDataType eVectorDataType
)
227 : maVectorGraphicDataArray(rVectorGraphicDataArray
),
229 mbSequenceCreated(false),
233 mNestedBitmapSize(0),
234 meVectorGraphicDataType(eVectorDataType
)
238 VectorGraphicData::VectorGraphicData(
239 const OUString
& rPath
,
240 VectorGraphicDataType eVectorDataType
)
241 : maVectorGraphicDataArray(),
243 mbSequenceCreated(false),
247 mNestedBitmapSize(0),
248 meVectorGraphicDataType(eVectorDataType
)
250 SvFileStream
rIStm(rPath
, StreamMode::STD_READ
);
253 const sal_uInt32
nStmLen(rIStm
.remainingSize());
256 maVectorGraphicDataArray
.realloc(nStmLen
);
257 rIStm
.ReadBytes(maVectorGraphicDataArray
.begin(), nStmLen
);
259 if (rIStm
.GetError())
261 maVectorGraphicDataArray
= VectorGraphicDataArray();
266 VectorGraphicData::~VectorGraphicData()
270 const basegfx::B2DRange
& VectorGraphicData::getRange() const
272 const_cast< VectorGraphicData
* >(this)->ensureSequenceAndRange();
277 const std::deque
< css::uno::Reference
< css::graphic::XPrimitive2D
> >& VectorGraphicData::getPrimitive2DSequence() const
279 const_cast< VectorGraphicData
* >(this)->ensureSequenceAndRange();
284 const BitmapEx
& VectorGraphicData::getReplacement() const
286 const_cast< VectorGraphicData
* >(this)->ensureReplacement();
288 return maReplacement
;
291 BitmapChecksum
VectorGraphicData::GetChecksum() const
293 return vcl_get_checksum(0, maVectorGraphicDataArray
.getConstArray(), maVectorGraphicDataArray
.getLength());
296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */