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