LibreOffice Module vcl (master)  1
vectorgraphicdata.cxx
Go to the documentation of this file.
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 <tools/diagnose_ex.h>
21 #include <tools/stream.hxx>
22 #include <sal/log.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>
36 
37 using namespace ::com::sun::star;
38 
40  const std::deque< css::uno::Reference< css::graphic::XPrimitive2D > >& rSequence,
41  const basegfx::B2DRange& rTargetRange,
42  const sal_uInt32 nMaximumQuadraticPixels)
43 {
44  BitmapEx aRetval;
45 
46  if(!rSequence.empty())
47  {
48  // create replacement graphic from maSequence
49  // create XPrimitive2DRenderer
50  try
51  {
52  uno::Reference< uno::XComponentContext > xContext(::comphelper::getProcessComponentContext());
53  const uno::Reference< graphic::XPrimitive2DRenderer > xPrimitive2DRenderer = graphic::Primitive2DTools::create(xContext);
54 
55  uno::Sequence< beans::PropertyValue > aViewParameters;
56  geometry::RealRectangle2D aRealRect;
57 
58  aRealRect.X1 = rTargetRange.getMinX();
59  aRealRect.Y1 = rTargetRange.getMinY();
60  aRealRect.X2 = rTargetRange.getMaxX();
61  aRealRect.Y2 = rTargetRange.getMaxY();
62 
63  // get system DPI
64  const Size aDPI(Application::GetDefaultDevice()->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch)));
65 
66  const uno::Reference< rendering::XBitmap > xBitmap(
67  xPrimitive2DRenderer->rasterize(
69  aViewParameters,
70  aDPI.getWidth(),
71  aDPI.getHeight(),
72  aRealRect,
73  nMaximumQuadraticPixels));
74 
75  if(xBitmap.is())
76  {
77  const uno::Reference< rendering::XIntegerReadOnlyBitmap> xIntBmp(xBitmap, uno::UNO_QUERY_THROW);
78  aRetval = vcl::unotools::bitmapExFromXBitmap(xIntBmp);
79  }
80  }
81  catch (const uno::Exception&)
82  {
83  TOOLS_WARN_EXCEPTION("vcl", "Got no graphic::XPrimitive2DRenderer!");
84  }
85  catch (const std::exception& e)
86  {
87  SAL_WARN("vcl", "Got no graphic::XPrimitive2DRenderer! : " << e.what());
88  }
89  }
90 
91  return aRetval;
92 }
93 
94 static size_t estimateSize(
95  std::deque<uno::Reference<graphic::XPrimitive2D>> const& rSequence)
96 {
97  size_t nRet(0);
98  for (auto& it : rSequence)
99  {
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();
103  }
104  return nRet;
105 }
106 
108 {
110  {
112  {
113  if (0 == memcmp(
114  getVectorGraphicDataArray().getConstArray(),
115  rCandidate.getVectorGraphicDataArray().getConstArray(),
117  {
118  return true;
119  }
120  }
121  }
122 
123  return false;
124 }
125 
127 {
128  if (!mpExternalHeader)
129  {
130  mpExternalHeader.reset( new WmfExternal );
131  }
132 
133  *mpExternalHeader = aExtHeader;
134 }
135 
137 {
139 
140  if(maReplacement.IsEmpty() && !maSequence.empty())
141  {
143  }
144 }
145 
147 {
148  if (!mbSequenceCreated && maVectorGraphicDataArray.hasElements())
149  {
150  // import SVG to maSequence, also set maRange
151  maRange.reset();
152 
153  // create stream
154  const uno::Reference< io::XInputStream > myInputStream(new comphelper::SequenceInputStream(maVectorGraphicDataArray));
155 
156  if(myInputStream.is())
157  {
158  // create Vector Graphic Data interpreter
159  uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
160 
163  {
164  const uno::Reference< graphic::XEmfParser > xEmfParser = graphic::EmfTools::create(xContext);
165  uno::Sequence< ::beans::PropertyValue > aSequence;
166 
167  if (mpExternalHeader)
168  {
169  aSequence = mpExternalHeader->getSequence();
170  }
171 
172  maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xEmfParser->getDecomposition(myInputStream, maPath, aSequence));
173  }
174  else
175  {
176  const uno::Reference< graphic::XSvgParser > xSvgParser = graphic::SvgTools::create(xContext);
177 
178  maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xSvgParser->getDecomposition(myInputStream, maPath));
179  }
180  }
181 
182  if(!maSequence.empty())
183  {
184  const sal_Int32 nCount(maSequence.size());
185  geometry::RealRectangle2D aRealRect;
186  uno::Sequence< beans::PropertyValue > aViewParameters;
187 
188  for(sal_Int32 a(0); a < nCount; a++)
189  {
190  // get reference
191  const css::uno::Reference< css::graphic::XPrimitive2D > xReference(maSequence[a]);
192 
193  if(xReference.is())
194  {
195  aRealRect = xReference->getRange(aViewParameters);
196 
197  maRange.expand(
199  aRealRect.X1,
200  aRealRect.Y1,
201  aRealRect.X2,
202  aRealRect.Y2));
203  }
204  }
205  }
207  mbSequenceCreated = true;
208  }
209 }
210 
211 auto VectorGraphicData::getSizeBytes() const -> std::pair<State, size_t>
212 {
213  if (maSequence.empty() && maVectorGraphicDataArray.hasElements())
214  {
215  return std::make_pair(State::UNPARSED, maVectorGraphicDataArray.getLength());
216  }
217  else
218  {
219  return std::make_pair(State::PARSED, maVectorGraphicDataArray.getLength() + mNestedBitmapSize);
220  }
221 }
222 
224  const VectorGraphicDataArray& rVectorGraphicDataArray,
225  const OUString& rPath,
226  VectorGraphicDataType eVectorDataType)
227 : maVectorGraphicDataArray(rVectorGraphicDataArray),
228  maPath(rPath),
229  mbSequenceCreated(false),
230  maRange(),
231  maSequence(),
232  maReplacement(),
233  mNestedBitmapSize(0),
234  meVectorGraphicDataType(eVectorDataType)
235 {
236 }
237 
239  const OUString& rPath,
240  VectorGraphicDataType eVectorDataType)
241 : maVectorGraphicDataArray(),
242  maPath(rPath),
243  mbSequenceCreated(false),
244  maRange(),
245  maSequence(),
246  maReplacement(),
247  mNestedBitmapSize(0),
248  meVectorGraphicDataType(eVectorDataType)
249 {
250  SvFileStream rIStm(rPath, StreamMode::STD_READ);
251  if(rIStm.GetError())
252  return;
253  const sal_uInt32 nStmLen(rIStm.remainingSize());
254  if (nStmLen)
255  {
256  maVectorGraphicDataArray.realloc(nStmLen);
257  rIStm.ReadBytes(maVectorGraphicDataArray.begin(), nStmLen);
258 
259  if (rIStm.GetError())
260  {
262  }
263  }
264 }
265 
267 {
268 }
269 
271 {
272  const_cast< VectorGraphicData* >(this)->ensureSequenceAndRange();
273 
274  return maRange;
275 }
276 
277 const std::deque< css::uno::Reference< css::graphic::XPrimitive2D > >& VectorGraphicData::getPrimitive2DSequence() const
278 {
279  const_cast< VectorGraphicData* >(this)->ensureSequenceAndRange();
280 
281  return maSequence;
282 }
283 
285 {
286  const_cast< VectorGraphicData* >(this)->ensureReplacement();
287 
288  return maReplacement;
289 }
290 
292 {
293  return vcl_get_checksum(0, maVectorGraphicDataArray.getConstArray(), maVectorGraphicDataArray.getLength());
294 }
295 
296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const BitmapEx & getReplacement() const
VectorGraphicDataType
sal_uInt64 BitmapChecksum
Definition: checksum.hxx:30
void expand(const B2DTuple &rTuple)
std::pair< State, size_t > getSizeBytes() const
const VectorGraphicDataArray & getVectorGraphicDataArray() const
data read
const std::deque< css::uno::Reference< css::graphic::XPrimitive2D > > & getPrimitive2DSequence() const
OUString const maPath
BitmapChecksum vcl_get_checksum(BitmapChecksum Checksum, const void *Data, sal_uInt32 DatLen)
Definition: checksum.hxx:72
const basegfx::B2DRange & getRange() const
data read and evtl. on demand creation
void setWmfExternalHeader(const WmfExternal &aExtHeader)
special: needed for emf/wmf, maybe replaced by scaling the result later (?)
::BitmapEx bitmapExFromXBitmap(const uno::Reference< rendering::XIntegerReadOnlyBitmap > &xInputBitmap)
double getMaxX() const
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
Definition: svapp.cxx:1054
const VectorGraphicDataType & getVectorGraphicDataType() const
ErrCode GetError() const
BitmapChecksum GetChecksum() const
VectorGraphicDataArray maVectorGraphicDataArray
sal_uInt64 remainingSize()
double getMaxY() const
basegfx::B2DRange maRange
bool IsEmpty() const
Definition: bitmapex.cxx:203
#define TOOLS_WARN_EXCEPTION(area, stream)
bool operator==(const VectorGraphicData &rCandidate) const
compare op
std::size_t ReadBytes(void *pData, std::size_t nSize)
css::uno::Sequence< sal_Int8 > VectorGraphicDataArray
std::unique_ptr< WmfExternal > mpExternalHeader
double getMinY() const
static size_t estimateSize(std::deque< uno::Reference< graphic::XPrimitive2D >> const &rSequence)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
VectorGraphicData(const VectorGraphicData &)=delete
Reference< XComponentContext > getProcessComponentContext()
sal_uInt32 getVectorGraphicDataArrayLength() const
BitmapEx convertPrimitive2DSequenceToBitmapEx(const std::deque< css::uno::Reference< css::graphic::XPrimitive2D > > &rSequence, const basegfx::B2DRange &rTargetRange, const sal_uInt32 nMaximumQuadraticPixels)
#define SAL_WARN(area, stream)
double getMinX() const
std::deque< css::uno::Reference< css::graphic::XPrimitive2D > > maSequence
long getHeight() const
long getWidth() const
B2DRange maRange