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;
37  Color aStartColor;
38  Color aEndColor;
39  sal_uInt16 nAngle;
40  sal_uInt16 nBorder;
41  sal_uInt16 nOffsetX;
42  sal_uInt16 nOffsetY;
43  sal_uInt16 nIntensityStart;
44  sal_uInt16 nIntensityEnd;
45  sal_uInt16 nStepCount;
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  rGradient.SetAngle(nAngle);
62  rGradient.SetBorder(nBorder);
63  rGradient.SetOfsX(nOffsetX);
64  rGradient.SetOfsY(nOffsetY);
65  rGradient.SetStartIntensity(nIntensityStart);
66  rGradient.SetEndIntensity(nIntensityEnd);
67  rGradient.SetSteps(nStepCount);
68 }
69 
71 {
72  VersionCompat aCompat(mrStream, StreamMode::WRITE, 1);
73 
74  mrStream.WriteUInt16(static_cast<sal_uInt16>(rGradient.GetStyle()));
75  writeColor(rGradient.GetStartColor());
76  writeColor(rGradient.GetEndColor());
77  mrStream.WriteUInt16(rGradient.GetAngle());
78  mrStream.WriteUInt16(rGradient.GetBorder());
79  mrStream.WriteUInt16(rGradient.GetOfsX());
80  mrStream.WriteUInt16(rGradient.GetOfsY());
83  mrStream.WriteUInt16(rGradient.GetSteps());
84 }
85 
87 {
88  sal_uInt16 nType = 0;
89  sal_uInt32 nDataSize = 0;
90  sal_uInt32 nUserId = 0;
91 
92  Size aSize;
93  MapMode aMapMode;
94  bool bMapAndSizeValid = false;
95 
96  {
97  VersionCompat aCompat(mrStream, StreamMode::READ);
98 
99  // Version 1
100  mrStream.ReadUInt16(nType);
101  mrStream.ReadUInt32(nDataSize);
102  mrStream.ReadUInt32(nUserId);
103 
104  if (aCompat.GetVersion() >= 2)
105  {
106  readSize(aSize);
107  ReadMapMode(mrStream, aMapMode);
108  bMapAndSizeValid = true;
109  }
110  }
111 
112  auto nRemainingData = mrStream.remainingSize();
113  if (nDataSize > nRemainingData)
114  {
115  SAL_WARN("vcl", "graphic link stream is smaller than requested size");
116  nDataSize = nRemainingData;
117  }
118 
119  std::unique_ptr<sal_uInt8[]> pBuffer(new sal_uInt8[nDataSize]);
120  mrStream.ReadBytes(pBuffer.get(), nDataSize);
121 
122  rGfxLink = GfxLink(std::move(pBuffer), nDataSize, static_cast<GfxLinkType>(nType));
123  rGfxLink.SetUserId(nUserId);
124 
125  if (bMapAndSizeValid)
126  {
127  rGfxLink.SetPrefSize(aSize);
128  rGfxLink.SetPrefMapMode(aMapMode);
129  }
130 }
131 
133 {
134  {
135  VersionCompat aCompat(mrStream, StreamMode::WRITE, 2);
136 
137  // Version 1
138  mrStream.WriteUInt16(sal_uInt16(rGfxLink.GetType()));
139  mrStream.WriteUInt32(rGfxLink.GetDataSize());
140  mrStream.WriteUInt32(rGfxLink.GetUserId());
141 
142  // Version 2
143  writeSize(rGfxLink.GetPrefSize());
144  WriteMapMode(mrStream, rGfxLink.GetPrefMapMode());
145  }
146 
147  if (rGfxLink.GetDataSize())
148  {
149  if (rGfxLink.GetData())
150  mrStream.WriteBytes(rGfxLink.GetData(), rGfxLink.GetDataSize());
151  }
152 }
153 
154 namespace
155 {
156 #define NATIVE_FORMAT_50 COMPAT_FORMAT('N', 'A', 'T', '5')
157 
158 constexpr sal_uInt32 constSvgMagic = createMagic('s', 'v', 'g', '0');
159 constexpr sal_uInt32 constWmfMagic = createMagic('w', 'm', 'f', '0');
160 constexpr sal_uInt32 constEmfMagic = createMagic('e', 'm', 'f', '0');
161 constexpr sal_uInt32 constPdfMagic = createMagic('p', 'd', 'f', '0');
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  // read Id
174  mrStream.ReadUInt32(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. CAUTION: Eof is only true AFTER reading another
179  // byte, a speciality of SvMemoryStream (!)
180  if (!mrStream.good())
181  return;
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  VersionCompat aCompat(mrStream, StreamMode::READ);
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  sal_uInt64 nBeginPoisition = mrStream.Tell();
224 
225  mrStream.ReadUInt32(nMagic1);
226  mrStream.ReadUInt32(nMagic2);
227  mrStream.Seek(nBeginPoisition);
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  VectorGraphicDataArray aData(nLength);
282 
283  mrStream.ReadBytes(aData.getArray(), nLength);
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>(aData, aPath, 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  VersionCompat aCompat(mrStream, StreamMode::WRITE, 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->getVectorGraphicDataType())
367  {
369  {
370  mrStream.WriteUInt32(constWmfMagic);
371  break;
372  }
374  {
375  mrStream.WriteUInt32(constEmfMagic);
376  break;
377  }
379  {
380  mrStream.WriteUInt32(constSvgMagic);
381  break;
382  }
384  {
385  mrStream.WriteUInt32(constPdfMagic);
386  break;
387  }
388  }
389 
390  sal_uInt32 nSize = pVectorGraphicData->getVectorGraphicDataArrayLength();
391  mrStream.WriteUInt32(nSize);
393  pVectorGraphicData->getVectorGraphicDataArray().getConstArray(), nSize);
394  mrStream.WriteUniOrByteString(pVectorGraphicData->getPath(),
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 
419 /* 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:380
void writeSize(const Size &rSize)
bool IsSupportedGraphic() const
Definition: graph.cxx:305
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:600
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:503
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)
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:320
Animation GetAnimation() const
Definition: graph.cxx:335
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
#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:554
GraphicType GetType() const
Definition: graph.cxx:294
sal_uInt16 GetAngle() const
sal_uInt16 GetOfsX() const
std::size_t WriteBytes(const void *pData, std::size_t nSize)
void writeGradient(const Gradient &rGradient)
long const nBorder
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
SvStreamEndian GetEndian() const
css::uno::Sequence< sal_Int8 > VectorGraphicDataArray
MapMode GetPrefMapMode() const
Definition: graph.cxx:375
unsigned char sal_uInt8
void SetAngle(sal_uInt16 nAngle)
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:249
void SetPrefSize(const Size &rPrefSize)
Definition: graph.cxx:369
#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:539
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)