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