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 <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  VersionCompat aCompat(mrStream, StreamMode::READ);
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  VersionCompat aCompat(mrStream, StreamMode::WRITE, 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  VersionCompat aCompat(mrStream, StreamMode::READ);
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  VersionCompat aCompat(mrStream, StreamMode::WRITE, 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 constexpr sal_uInt32 constSvgMagic = createMagic('s', 'v', 'g', '0');
164 constexpr sal_uInt32 constWmfMagic = createMagic('w', 'm', 'f', '0');
165 constexpr sal_uInt32 constEmfMagic = createMagic('e', 'm', 'f', '0');
166 constexpr sal_uInt32 constPdfMagic = createMagic('p', 'd', 'f', '0');
167 
168 } // end anonymous namespace
169 
171 {
172  if (mrStream.GetError())
173  return;
174 
175  const sal_uLong nInitialStreamPosition = mrStream.Tell();
176  sal_uInt32 nType;
177 
178  // read Id
179  mrStream.ReadUInt32(nType);
180 
181  // if there is no more data, avoid further expensive
182  // reading which will create VDevs and other stuff, just to
183  // read nothing. CAUTION: Eof is only true AFTER reading another
184  // byte, a speciality of SvMemoryStream (!)
185  if (!mrStream.good())
186  return;
187 
188  if (NATIVE_FORMAT_50 == nType)
189  {
190  Graphic aGraphic;
191  GfxLink aLink;
192 
193  // read compat info, destructor writes stuff into the header
194  {
195  VersionCompat aCompat(mrStream, StreamMode::READ);
196  }
197 
198  readGfxLink(aLink);
199 
200  if (!mrStream.GetError() && aLink.LoadNative(aGraphic))
201  {
202  if (aLink.IsPrefMapModeValid())
203  aGraphic.SetPrefMapMode(aLink.GetPrefMapMode());
204 
205  if (aLink.IsPrefSizeValid())
206  aGraphic.SetPrefSize(aLink.GetPrefSize());
207  }
208  else
209  {
210  mrStream.Seek(nInitialStreamPosition);
212  }
213  rGraphic = aGraphic;
214  }
215  else
216  {
217  BitmapEx aBitmapEx;
218  const SvStreamEndian nOldFormat = mrStream.GetEndian();
219 
220  mrStream.SeekRel(-4);
221  mrStream.SetEndian(SvStreamEndian::LITTLE);
222  ReadDIBBitmapEx(aBitmapEx, mrStream);
223 
224  if (!mrStream.GetError())
225  {
226  sal_uInt32 nMagic1 = 0;
227  sal_uInt32 nMagic2 = 0;
228  sal_uInt64 nBeginPosition = mrStream.Tell();
229 
230  mrStream.ReadUInt32(nMagic1);
231  mrStream.ReadUInt32(nMagic2);
232  mrStream.Seek(nBeginPosition);
233 
234  if (!mrStream.GetError())
235  {
236  if (nMagic1 == 0x5344414e && nMagic2 == 0x494d4931)
237  {
238  Animation aAnimation;
239  ReadAnimation(mrStream, aAnimation);
240 
241  // #108077# manually set loaded BmpEx to Animation
242  // (which skips loading its BmpEx if already done)
243  aAnimation.SetBitmapEx(aBitmapEx);
244  rGraphic = Graphic(aAnimation);
245  }
246  else
247  {
248  rGraphic = Graphic(aBitmapEx);
249  }
250  }
251  else
252  {
254  }
255  }
256  else
257  {
258  GDIMetaFile aMetaFile;
259 
260  mrStream.Seek(nInitialStreamPosition);
262  ReadGDIMetaFile(mrStream, aMetaFile);
263 
264  if (!mrStream.GetError())
265  {
266  rGraphic = Graphic(aMetaFile);
267  }
268  else
269  {
270  ErrCode nOriginalError = mrStream.GetErrorCode();
271  // try to stream in Svg defining data (length, byte array and evtl. path)
272  // See below (operator<<) for more information
273  sal_uInt32 nMagic;
274  mrStream.Seek(nInitialStreamPosition);
276  mrStream.ReadUInt32(nMagic);
277 
278  if (constSvgMagic == nMagic || constWmfMagic == nMagic || constEmfMagic == nMagic
279  || constPdfMagic == nMagic)
280  {
281  sal_uInt32 nLength = 0;
282  mrStream.ReadUInt32(nLength);
283 
284  if (nLength)
285  {
286  VectorGraphicDataArray aData(nLength);
287 
288  mrStream.ReadBytes(aData.getArray(), nLength);
290 
291  if (!mrStream.GetError())
292  {
294 
295  switch (nMagic)
296  {
297  case constWmfMagic:
298  aDataType = VectorGraphicDataType::Wmf;
299  break;
300  case constEmfMagic:
301  aDataType = VectorGraphicDataType::Emf;
302  break;
303  case constPdfMagic:
304  aDataType = VectorGraphicDataType::Pdf;
305  break;
306  }
307 
308  auto aVectorGraphicDataPtr
309  = std::make_shared<VectorGraphicData>(aData, aPath, aDataType);
310  rGraphic = Graphic(aVectorGraphicDataPtr);
311  }
312  }
313  }
314  else
315  {
316  mrStream.SetError(nOriginalError);
317  }
318 
319  mrStream.Seek(nInitialStreamPosition);
320  }
321  }
322  mrStream.SetEndian(nOldFormat);
323  }
324 }
325 
327 {
328  Graphic aGraphic(rGraphic);
329 
330  if (!aGraphic.makeAvailable())
331  return;
332 
333  auto pGfxLink = aGraphic.GetSharedGfxLink();
334 
336  && (mrStream.GetCompressMode() & SvStreamCompressFlags::NATIVE) && pGfxLink
337  && pGfxLink->IsNative())
338  {
339  // native format
341 
342  // write compat info, destructor writes stuff into the header
343  {
344  VersionCompat aCompat(mrStream, StreamMode::WRITE, 1);
345  }
346  pGfxLink->SetPrefMapMode(aGraphic.GetPrefMapMode());
347  pGfxLink->SetPrefSize(aGraphic.GetPrefSize());
348  writeGfxLink(*pGfxLink);
349  }
350  else
351  {
352  // own format
353  const SvStreamEndian nOldFormat = mrStream.GetEndian();
354  mrStream.SetEndian(SvStreamEndian::LITTLE);
355 
356  switch (aGraphic.GetType())
357  {
358  case GraphicType::NONE:
360  break;
361 
362  case GraphicType::Bitmap:
363  {
364  auto pVectorGraphicData = aGraphic.getVectorGraphicData();
365  if (pVectorGraphicData)
366  {
367  // stream out Vector Graphic defining data (length, byte array and evtl. path)
368  // this is used e.g. in swapping out graphic data and in transporting it over UNO API
369  // as sequence of bytes, but AFAIK not written anywhere to any kind of file, so it should be
370  // no problem to extend it; only used at runtime
371  switch (pVectorGraphicData->getVectorGraphicDataType())
372  {
374  {
375  mrStream.WriteUInt32(constWmfMagic);
376  break;
377  }
379  {
380  mrStream.WriteUInt32(constEmfMagic);
381  break;
382  }
384  {
385  mrStream.WriteUInt32(constSvgMagic);
386  break;
387  }
389  {
390  mrStream.WriteUInt32(constPdfMagic);
391  break;
392  }
393  }
394 
395  sal_uInt32 nSize = pVectorGraphicData->getVectorGraphicDataArrayLength();
396  mrStream.WriteUInt32(nSize);
398  pVectorGraphicData->getVectorGraphicDataArray().getConstArray(), nSize);
399  mrStream.WriteUniOrByteString(pVectorGraphicData->getPath(),
401  }
402  else if (aGraphic.IsAnimated())
403  {
404  WriteAnimation(mrStream, aGraphic.GetAnimation());
405  }
406  else
407  {
409  }
410  }
411  break;
412 
413  default:
414  {
415  if (aGraphic.IsSupportedGraphic())
417  }
418  break;
419  }
420  mrStream.SetEndian(nOldFormat);
421  }
422 }
423 
424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetEndColor(const Color &rColor)
VectorGraphicDataType
GradientStyle GetStyle() const
void readGraphic(Graphic &rGraphic)
SvStream & WriteUInt16(sal_uInt16 nUInt16)
const char aData[]
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:375
void writeSize(const Size &rSize)
bool IsSupportedGraphic() const
Definition: graph.cxx:300
sal_uInt16 GetBorder() const
void SetBitmapEx(const BitmapEx &rBmpEx)
Definition: Animation.hxx:59
sal_uInt64 Seek(sal_uInt64 nPos)
#define ERRCODE_IO_WRONGFORMAT
Definition: errcode.hxx:219
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)
void SetSteps(sal_uInt16 nSteps)
ErrCode GetError() const
bool ReadDIBBitmapEx(BitmapEx &rTarget, SvStream &rIStm, bool bFileHeader, bool bMSOFormat)
Definition: dibtools.cxx:1743
void SetOfsY(sal_uInt16 nOfsY)
SvStream & WriteGDIMetaFile(SvStream &rOStm, const GDIMetaFile &rGDIMetaFile)
Definition: gdimtf.cxx:2729
const sal_uInt16 nMagic
std::shared_ptr< GfxLink > GetSharedGfxLink() const
Definition: graph.cxx:498
SvStream & WriteUniOrByteString(const OUString &rStr, rtl_TextEncoding eDestCharSet)
void SetStartColor(const Color &rColor)
const GDIMetaFile & GetGDIMetaFile() const
Definition: graph.cxx:335
SvStream & WriteUInt32(sal_uInt32 nUInt32)
constexpr sal_uInt32 createMagic(char char1, char char2, char char3, char char4)
sal_uInt64 remainingSize()
void readSize(Size &rSize)
bool IsAnimated() const
Definition: graph.cxx:315
Animation GetAnimation() const
Definition: graph.cxx:330
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
UNDERLYING_TYPE get() const
#define SOFFICE_FILEFORMAT_50
bool WriteDIBBitmapEx(const BitmapEx &rSource, SvStream &rOStm)
Definition: dibtools.cxx:1874
SvStream & WriteAnimation(SvStream &rOStm, const Animation &rAnimation)
Definition: Animation.cxx:551
GraphicType GetType() const
Definition: graph.cxx:289
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:325
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:359
tools::Long const nBorder
void SetAngle(Degree10 nAngle)
SvStreamEndian GetEndian() const
css::uno::Sequence< sal_Int8 > VectorGraphicDataArray
Degree10 GetAngle() const
MapMode GetPrefMapMode() const
Definition: graph.cxx:370
unsigned char sal_uInt8
SvStream & ReadGDIMetaFile(SvStream &rIStm, GDIMetaFile &rGDIMetaFile, ImplMetaReadData *pData)
Definition: gdimtf.cxx:2645
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:244
void SetPrefSize(const Size &rPrefSize)
Definition: graph.cxx:364
#define NATIVE_FORMAT_50
bool good() const
#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:534
void SetStyle(GradientStyle eStyle)
void readGradient(Gradient &rGradient)
void writeGraphic(const Graphic &rGraphic)
sal_uInt16 GetStartIntensity() const
void SetStartIntensity(sal_uInt16 nIntens)
OUString ReadUniOrByteString(rtl_TextEncoding eSrcCharSet)
void readColor(Color &rColor)