LibreOffice Module vcl (master)  1
TypeSerializer.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 <vcl/TypeSerializer.hxx>
21 #include <tools/vcompat.hxx>
22 #include <tools/fract.hxx>
23 #include <sal/log.hxx>
24 #include <comphelper/fileformat.h>
25 #include <vcl/filter/SvmReader.hxx>
26 #include <vcl/filter/SvmWriter.hxx>
27 #include <vcl/gdimtf.hxx>
28 #include <vcl/dibtools.hxx>
29 
31  : GenericTypeSerializer(rStream)
32 {
33 }
34 
36 {
37  VersionCompatRead aCompat(mrStream);
38 
39  sal_uInt16 nStyle = 0;
40  Color aStartColor;
41  Color aEndColor;
42  sal_uInt16 nAngle = 0;
43  sal_uInt16 nBorder = 0;
44  sal_uInt16 nOffsetX = 0;
45  sal_uInt16 nOffsetY = 0;
46  sal_uInt16 nIntensityStart = 0;
47  sal_uInt16 nIntensityEnd = 0;
48  sal_uInt16 nStepCount = 0;
49 
50  mrStream.ReadUInt16(nStyle);
51  readColor(aStartColor);
52  readColor(aEndColor);
53  mrStream.ReadUInt16(nAngle);
54  mrStream.ReadUInt16(nBorder);
55  mrStream.ReadUInt16(nOffsetX);
56  mrStream.ReadUInt16(nOffsetY);
57  mrStream.ReadUInt16(nIntensityStart);
58  mrStream.ReadUInt16(nIntensityEnd);
59  mrStream.ReadUInt16(nStepCount);
60 
61  rGradient.SetStyle(static_cast<GradientStyle>(nStyle));
62  rGradient.SetStartColor(aStartColor);
63  rGradient.SetEndColor(aEndColor);
64  if (nAngle > 3600)
65  {
66  SAL_WARN("vcl", "angle out of range " << nAngle);
67  nAngle = 0;
68  }
69  rGradient.SetAngle(Degree10(nAngle));
70  rGradient.SetBorder(nBorder);
71  rGradient.SetOfsX(nOffsetX);
72  rGradient.SetOfsY(nOffsetY);
73  rGradient.SetStartIntensity(nIntensityStart);
74  rGradient.SetEndIntensity(nIntensityEnd);
75  rGradient.SetSteps(nStepCount);
76 }
77 
79 {
80  VersionCompatWrite aCompat(mrStream, 1);
81 
82  mrStream.WriteUInt16(static_cast<sal_uInt16>(rGradient.GetStyle()));
83  writeColor(rGradient.GetStartColor());
84  writeColor(rGradient.GetEndColor());
85  mrStream.WriteUInt16(rGradient.GetAngle().get());
86  mrStream.WriteUInt16(rGradient.GetBorder());
87  mrStream.WriteUInt16(rGradient.GetOfsX());
88  mrStream.WriteUInt16(rGradient.GetOfsY());
91  mrStream.WriteUInt16(rGradient.GetSteps());
92 }
93 
95 {
96  sal_uInt16 nType = 0;
97  sal_uInt32 nDataSize = 0;
98  sal_uInt32 nUserId = 0;
99 
100  Size aSize;
101  MapMode aMapMode;
102  bool bMapAndSizeValid = false;
103 
104  {
105  VersionCompatRead aCompat(mrStream);
106 
107  // Version 1
108  mrStream.ReadUInt16(nType);
109  mrStream.ReadUInt32(nDataSize);
110  mrStream.ReadUInt32(nUserId);
111 
112  if (aCompat.GetVersion() >= 2)
113  {
114  readSize(aSize);
115  readMapMode(aMapMode);
116  bMapAndSizeValid = true;
117  }
118  }
119 
120  auto nRemainingData = mrStream.remainingSize();
121  if (nDataSize > nRemainingData)
122  {
123  SAL_WARN("vcl", "graphic link stream is smaller than requested size");
124  nDataSize = nRemainingData;
125  }
126 
127  std::unique_ptr<sal_uInt8[]> pBuffer(new sal_uInt8[nDataSize]);
128  mrStream.ReadBytes(pBuffer.get(), nDataSize);
129 
130  rGfxLink = GfxLink(std::move(pBuffer), nDataSize, static_cast<GfxLinkType>(nType));
131  rGfxLink.SetUserId(nUserId);
132 
133  if (bMapAndSizeValid)
134  {
135  rGfxLink.SetPrefSize(aSize);
136  rGfxLink.SetPrefMapMode(aMapMode);
137  }
138 }
139 
141 {
142  {
143  VersionCompatWrite aCompat(mrStream, 2);
144 
145  // Version 1
146  mrStream.WriteUInt16(sal_uInt16(rGfxLink.GetType()));
147  mrStream.WriteUInt32(rGfxLink.GetDataSize());
148  mrStream.WriteUInt32(rGfxLink.GetUserId());
149 
150  // Version 2
151  writeSize(rGfxLink.GetPrefSize());
152  writeMapMode(rGfxLink.GetPrefMapMode());
153  }
154 
155  if (rGfxLink.GetDataSize())
156  {
157  if (rGfxLink.GetData())
158  mrStream.WriteBytes(rGfxLink.GetData(), rGfxLink.GetDataSize());
159  }
160 }
161 
162 namespace
163 {
164 #define NATIVE_FORMAT_50 COMPAT_FORMAT('N', 'A', 'T', '5')
165 
166 } // end anonymous namespace
167 
169 {
170  if (mrStream.GetError())
171  return;
172 
173  const sal_uLong nInitialStreamPosition = mrStream.Tell();
174  sal_uInt32 nType;
175 
176  // if there is no more data, avoid further expensive
177  // reading which will create VDevs and other stuff, just to
178  // read nothing.
179  if (mrStream.remainingSize() < 4)
180  return;
181 
182  // read Id
183  mrStream.ReadUInt32(nType);
184 
185  if (NATIVE_FORMAT_50 == nType)
186  {
187  Graphic aGraphic;
188  GfxLink aLink;
189 
190  // read compat info, destructor writes stuff into the header
191  {
192  VersionCompatRead aCompat(mrStream);
193  }
194 
195  readGfxLink(aLink);
196 
197  if (!mrStream.GetError() && aLink.LoadNative(aGraphic))
198  {
199  if (aLink.IsPrefMapModeValid())
200  aGraphic.SetPrefMapMode(aLink.GetPrefMapMode());
201 
202  if (aLink.IsPrefSizeValid())
203  aGraphic.SetPrefSize(aLink.GetPrefSize());
204  }
205  else
206  {
207  mrStream.Seek(nInitialStreamPosition);
209  }
210  rGraphic = aGraphic;
211  }
212  else
213  {
214  BitmapEx aBitmapEx;
215  const SvStreamEndian nOldFormat = mrStream.GetEndian();
216 
217  mrStream.SeekRel(-4);
218  mrStream.SetEndian(SvStreamEndian::LITTLE);
219  ReadDIBBitmapEx(aBitmapEx, mrStream);
220 
221  if (!mrStream.GetError())
222  {
223  sal_uInt32 nMagic1 = 0;
224  sal_uInt32 nMagic2 = 0;
225  if (mrStream.remainingSize() >= 8)
226  {
227  sal_uInt64 nBeginPosition = mrStream.Tell();
228  mrStream.ReadUInt32(nMagic1);
229  mrStream.ReadUInt32(nMagic2);
230  mrStream.Seek(nBeginPosition);
231  }
232  if (!mrStream.GetError())
233  {
234  if (nMagic1 == 0x5344414e && nMagic2 == 0x494d4931)
235  {
236  Animation aAnimation;
237  ReadAnimation(mrStream, aAnimation);
238 
239  // #108077# manually set loaded BmpEx to Animation
240  // (which skips loading its BmpEx if already done)
241  aAnimation.SetBitmapEx(aBitmapEx);
242  rGraphic = Graphic(aAnimation);
243  }
244  else
245  {
246  rGraphic = Graphic(aBitmapEx);
247  }
248  }
249  else
250  {
252  }
253  }
254  else
255  {
256  GDIMetaFile aMetaFile;
257 
258  mrStream.Seek(nInitialStreamPosition);
260  SvmReader aReader(mrStream);
261  aReader.Read(aMetaFile);
262 
263  if (!mrStream.GetError())
264  {
265  rGraphic = Graphic(aMetaFile);
266  }
267  else
268  {
269  ErrCode nOriginalError = mrStream.GetErrorCode();
270  // try to stream in Svg defining data (length, byte array and evtl. path)
271  // See below (operator<<) for more information
272  sal_uInt32 nMagic;
273  mrStream.Seek(nInitialStreamPosition);
275  mrStream.ReadUInt32(nMagic);
276 
277  if (constSvgMagic == nMagic || constWmfMagic == nMagic || constEmfMagic == nMagic
278  || constPdfMagic == nMagic)
279  {
280  sal_uInt32 nLength = 0;
281  mrStream.ReadUInt32(nLength);
282 
283  if (nLength)
284  {
285  auto rData = std::make_unique<std::vector<sal_uInt8>>(nLength);
286  mrStream.ReadBytes(rData->data(), rData->size());
287  BinaryDataContainer aDataContainer(std::move(rData));
288 
289  if (!mrStream.GetError())
290  {
292 
293  switch (nMagic)
294  {
295  case constWmfMagic:
296  aDataType = VectorGraphicDataType::Wmf;
297  break;
298  case constEmfMagic:
299  aDataType = VectorGraphicDataType::Emf;
300  break;
301  case constPdfMagic:
302  aDataType = VectorGraphicDataType::Pdf;
303  break;
304  }
305 
306  auto aVectorGraphicDataPtr
307  = std::make_shared<VectorGraphicData>(aDataContainer, aDataType);
308  rGraphic = Graphic(aVectorGraphicDataPtr);
309  }
310  }
311  }
312  else
313  {
314  mrStream.SetError(nOriginalError);
315  }
316 
317  mrStream.Seek(nInitialStreamPosition);
318  }
319  }
320  mrStream.SetEndian(nOldFormat);
321  }
322 }
323 
325 {
326  Graphic aGraphic(rGraphic);
327 
328  if (!aGraphic.makeAvailable())
329  return;
330 
331  auto pGfxLink = aGraphic.GetSharedGfxLink();
332 
334  && (mrStream.GetCompressMode() & SvStreamCompressFlags::NATIVE) && pGfxLink
335  && pGfxLink->IsNative())
336  {
337  // native format
339 
340  // write compat info, destructor writes stuff into the header
341  {
342  VersionCompatWrite aCompat(mrStream, 1);
343  }
344  pGfxLink->SetPrefMapMode(aGraphic.GetPrefMapMode());
345  pGfxLink->SetPrefSize(aGraphic.GetPrefSize());
346  writeGfxLink(*pGfxLink);
347  }
348  else
349  {
350  // own format
351  const SvStreamEndian nOldFormat = mrStream.GetEndian();
352  mrStream.SetEndian(SvStreamEndian::LITTLE);
353 
354  switch (aGraphic.GetType())
355  {
356  case GraphicType::NONE:
358  break;
359 
360  case GraphicType::Bitmap:
361  {
362  auto pVectorGraphicData = aGraphic.getVectorGraphicData();
363  if (pVectorGraphicData)
364  {
365  // stream out Vector Graphic defining data (length, byte array and evtl. path)
366  // this is used e.g. in swapping out graphic data and in transporting it over UNO API
367  // as sequence of bytes, but AFAIK not written anywhere to any kind of file, so it should be
368  // no problem to extend it; only used at runtime
369  switch (pVectorGraphicData->getType())
370  {
372  {
374  break;
375  }
377  {
379  break;
380  }
382  {
384  break;
385  }
387  {
389  break;
390  }
391  }
392 
393  sal_uInt32 nSize = pVectorGraphicData->getBinaryDataContainer().getSize();
394  mrStream.WriteUInt32(nSize);
395  mrStream.WriteBytes(pVectorGraphicData->getBinaryDataContainer().getData(),
396  nSize);
397  // For backwards compatibility, used to serialize path
399  }
400  else if (aGraphic.IsAnimated())
401  {
402  WriteAnimation(mrStream, aGraphic.GetAnimation());
403  }
404  else
405  {
407  }
408  }
409  break;
410 
411  default:
412  {
413  if (aGraphic.IsSupportedGraphic())
414  {
415  if (!mrStream.GetError())
416  {
417  SvmWriter aWriter(mrStream);
418  aWriter.Write(rGraphic.GetGDIMetaFile());
419  }
420  }
421  }
422  break;
423  }
424  mrStream.SetEndian(nOldFormat);
425  }
426 }
427 
429 {
430  VersionCompatRead aCompat(mrStream);
431  sal_uInt16 nTmp16(0);
432  Point aOrigin;
433  Fraction aScaleX;
434  Fraction aScaleY;
435  bool bSimple(true);
436 
437  mrStream.ReadUInt16(nTmp16);
438  MapUnit eUnit = static_cast<MapUnit>(nTmp16);
439  readPoint(aOrigin);
440  readFraction(aScaleX);
441  readFraction(aScaleY);
442  mrStream.ReadCharAsBool(bSimple);
443 
444  if (bSimple)
445  rMapMode = MapMode(eUnit);
446  else
447  rMapMode = MapMode(eUnit, aOrigin, aScaleX, aScaleY);
448 }
449 
451 {
452  VersionCompatWrite aCompat(mrStream, 1);
453 
454  mrStream.WriteUInt16(sal_uInt16(rMapMode.GetMapUnit()));
455  writePoint(rMapMode.GetOrigin());
456  writeFraction(rMapMode.GetScaleX());
457  writeFraction(rMapMode.GetScaleY());
458  mrStream.WriteBool(rMapMode.IsSimple());
459 }
460 
461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr sal_uInt32 constSvgMagic
void SetEndColor(const Color &rColor)
SvStream & WriteBool(bool b)
const Fraction & GetScaleX() const
Definition: mapmod.cxx:142
VectorGraphicDataType
GradientStyle GetStyle() const
void readGraphic(Graphic &rGraphic)
SvStream & WriteUInt16(sal_uInt16 nUInt16)
void readPoint(Point &rPoint)
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
void readMapMode(MapMode &rMapMode)
sal_Int32 GetVersion() const
sal_uInt16 GetOfsY() const
sal_uIntPtr sal_uLong
void SetPrefMapMode(const MapMode &rPrefMapMode)
Definition: graph.cxx:379
void writeSize(const Size &rSize)
bool IsSimple() const
Definition: mapmod.cxx:146
SvStream & ReadCharAsBool(bool &rBool)
bool IsSupportedGraphic() const
Definition: graph.cxx:304
sal_uInt16 GetBorder() const
void readFraction(Fraction &rFraction)
const ContentProperties & rData
void SetBitmapEx(const BitmapEx &rBmpEx)
Definition: Animation.hxx:59
sal_uInt64 Seek(sal_uInt64 nPos)
#define ERRCODE_IO_WRONGFORMAT
Definition: errcode.hxx:217
void SetBorder(sal_uInt16 nBorder)
SvStreamCompressFlags GetCompressMode() const
void writeGfxLink(const GfxLink &rGfxLink)
SvStream & ReadAnimation(SvStream &rIStm, Animation &rAnimation)
Definition: Animation.cxx:599
void SetEndIntensity(sal_uInt16 nIntens)
sal_uInt64 SeekRel(sal_Int64 nPos)
SvStream & Read(GDIMetaFile &rMetaFile, ImplMetaReadData *pData=nullptr)
Definition: SvmReader.cxx:63
const std::shared_ptr< GfxLink > & GetSharedGfxLink() const
Definition: graph.cxx:504
void SetSteps(sal_uInt16 nSteps)
SvStream & Write(const GDIMetaFile &rMetaFile)
Definition: SvmWriter.cxx:38
ErrCode GetError() const
bool ReadDIBBitmapEx(BitmapEx &rTarget, SvStream &rIStm, bool bFileHeader, bool bMSOFormat)
Definition: dibtools.cxx:1704
void SetOfsY(sal_uInt16 nOfsY)
constexpr sal_uInt32 constEmfMagic
Container for the binary data, whose responsibility is to manage the make it as simple as possible to...
const Fraction & GetScaleY() const
Definition: mapmod.cxx:144
const sal_uInt16 nMagic
void SetStartColor(const Color &rColor)
const GDIMetaFile & GetGDIMetaFile() const
Definition: graph.cxx:339
SvStream & WriteUInt32(sal_uInt32 nUInt32)
void writePoint(const Point &rPoint)
sal_uInt64 remainingSize()
void readSize(Size &rSize)
bool IsAnimated() const
Definition: graph.cxx:319
Animation GetAnimation() const
Definition: graph.cxx:334
void writeFraction(Fraction const &rFraction)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
UNDERLYING_TYPE get() const
#define SOFFICE_FILEFORMAT_50
bool WriteDIBBitmapEx(const BitmapEx &rSource, SvStream &rOStm)
Definition: dibtools.cxx:1835
SvStream & WriteAnimation(SvStream &rOStm, const Animation &rAnimation)
Definition: Animation.cxx:553
GraphicType GetType() const
Definition: graph.cxx:293
sal_uInt16 GetOfsX() const
std::size_t WriteBytes(const void *pData, std::size_t nSize)
float u
void writeGradient(const Gradient &rGradient)
void SetError(ErrCode nErrorCode)
sal_uInt16 GetEndIntensity() const
MapUnit GetMapUnit() const
Definition: mapmod.cxx:138
ErrCode const & GetErrorCode() const
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:329
void SetOfsX(sal_uInt16 nOfsX)
sal_uInt16 GetSteps() const
const Color & GetStartColor() const
std::size_t ReadBytes(void *pData, std::size_t nSize)
Size GetPrefSize() const
Definition: graph.cxx:363
tools::Long const nBorder
void SetAngle(Degree10 nAngle)
SvStreamEndian GetEndian() const
Degree10 GetAngle() const
MapMode GetPrefMapMode() const
Definition: graph.cxx:374
unsigned char sal_uInt8
sal_uInt16 GetVersion() const
void SetEndian(SvStreamEndian SvStreamEndian)
SvStream & WriteUniOrByteString(std::u16string_view rStr, rtl_TextEncoding eDestCharSet)
const Color & GetEndColor() const
rtl_TextEncoding GetStreamCharSet() const
sal_uInt64 Tell() const
QPRO_FUNC_TYPE nType
bool makeAvailable()
Definition: graph.cxx:248
void SetPrefSize(const Size &rPrefSize)
Definition: graph.cxx:368
const Point & GetOrigin() const
Definition: mapmod.cxx:140
#define NATIVE_FORMAT_50
MapUnit
#define SAL_WARN(area, stream)
void readGfxLink(GfxLink &rGfxLink)
SvStreamEndian
virtual void ResetError()
TypeSerializer(SvStream &rStream)
sal_Int32 nLength
void writeColor(const Color &rColor)
const std::shared_ptr< VectorGraphicData > & getVectorGraphicData() const
Definition: graph.cxx:524
void SetStyle(GradientStyle eStyle)
void readGradient(Gradient &rGradient)
constexpr sal_uInt32 constWmfMagic
void writeGraphic(const Graphic &rGraphic)
sal_uInt16 GetStartIntensity() const
constexpr sal_uInt32 constPdfMagic
void writeMapMode(MapMode const &rMapMode)
void SetStartIntensity(sal_uInt16 nIntens)
void readColor(Color &rColor)