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
21#include <tools/vcompat.hxx>
22#include <tools/fract.hxx>
23#include <sal/log.hxx>
27#include <vcl/gdimtf.hxx>
28#include <vcl/dibtools.hxx>
29
31 : GenericTypeSerializer(rStream)
32{
33}
34
36{
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);
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 {
106
107 // Version 1
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
162namespace
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_uInt64 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
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 {
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);
276
278 || constPdfMagic == nMagic)
279 {
280 sal_uInt32 nLength = 0;
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 {
358 break;
359
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 {
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
428bool TooLargeScaleForMapMode(const Fraction& rScale, int nDPI)
429{
430 // ImplLogicToPixel will multiply its values by this numerator * dpi and then double that
431 // result before dividing
432 if (rScale.GetNumerator() > std::numeric_limits<sal_Int32>::max() / nDPI / 2)
433 return true;
434 if (rScale.GetNumerator() < std::numeric_limits<sal_Int32>::min() / nDPI / 2)
435 return true;
436 return false;
437}
438
439static bool UselessScaleForMapMode(const Fraction& rScale)
440{
441 if (!rScale.IsValid())
442 return true;
443 if (TooLargeScaleForMapMode(rScale, 96))
444 return true;
445 if (static_cast<double>(rScale) < 0.0)
446 return true;
447 return false;
448}
449
451{
453 sal_uInt16 nTmp16(0);
454 Point aOrigin;
455 Fraction aScaleX;
456 Fraction aScaleY;
457 bool bSimple(true);
458
459 mrStream.ReadUInt16(nTmp16);
460 MapUnit eUnit = static_cast<MapUnit>(nTmp16);
461 readPoint(aOrigin);
462 readFraction(aScaleX);
463 readFraction(aScaleY);
464 mrStream.ReadCharAsBool(bSimple);
465
466 const bool bBogus = UselessScaleForMapMode(aScaleX) || UselessScaleForMapMode(aScaleY);
467 SAL_WARN_IF(bBogus, "vcl", "invalid scale");
468
469 if (bSimple || bBogus)
470 rMapMode = MapMode(eUnit);
471 else
472 rMapMode = MapMode(eUnit, aOrigin, aScaleX, aScaleY);
473}
474
476{
477 VersionCompatWrite aCompat(mrStream, 1);
478
479 mrStream.WriteUInt16(sal_uInt16(rMapMode.GetMapUnit()));
480 writePoint(rMapMode.GetOrigin());
481 writeFraction(rMapMode.GetScaleX());
482 writeFraction(rMapMode.GetScaleY());
483 mrStream.WriteBool(rMapMode.IsSimple());
484}
485
486/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvStream & ReadAnimation(SvStream &rIStm, Animation &rAnimation)
Definition: Animation.cxx:634
SvStream & WriteAnimation(SvStream &rOStm, const Animation &rAnimation)
Definition: Animation.cxx:588
#define NATIVE_FORMAT_50
static bool UselessScaleForMapMode(const Fraction &rScale)
bool TooLargeScaleForMapMode(const Fraction &rScale, int nDPI)
constexpr sal_uInt32 constPdfMagic
constexpr sal_uInt32 constSvgMagic
constexpr sal_uInt32 constEmfMagic
constexpr sal_uInt32 constWmfMagic
void SetBitmapEx(const BitmapEx &rBmpEx)
Definition: Animation.hxx:61
Container for the binary data, whose responsibility is to manage the make it as simple as possible to...
sal_Int32 GetNumerator() const
bool IsValid() const
sal_uInt16 GetStartIntensity() const
GradientStyle GetStyle() const
void SetStyle(GradientStyle eStyle)
void SetOfsX(sal_uInt16 nOfsX)
Degree10 GetAngle() const
sal_uInt16 GetEndIntensity() const
void SetStartIntensity(sal_uInt16 nIntens)
sal_uInt16 GetOfsX() const
sal_uInt16 GetBorder() const
const Color & GetEndColor() const
sal_uInt16 GetOfsY() const
void SetBorder(sal_uInt16 nBorder)
const Color & GetStartColor() const
void SetStartColor(const Color &rColor)
void SetSteps(sal_uInt16 nSteps)
sal_uInt16 GetSteps() const
void SetOfsY(sal_uInt16 nOfsY)
void SetAngle(Degree10 nAngle)
void SetEndColor(const Color &rColor)
void SetEndIntensity(sal_uInt16 nIntens)
Size GetPrefSize() const
Definition: graph.cxx:364
bool makeAvailable()
Definition: graph.cxx:249
Animation GetAnimation() const
Definition: graph.cxx:335
void SetPrefMapMode(const MapMode &rPrefMapMode)
Definition: graph.cxx:380
bool IsSupportedGraphic() const
Definition: graph.cxx:305
const std::shared_ptr< GfxLink > & GetSharedGfxLink() const
Definition: graph.cxx:505
const GDIMetaFile & GetGDIMetaFile() const
Definition: graph.cxx:340
GraphicType GetType() const
Definition: graph.cxx:294
bool IsAnimated() const
Definition: graph.cxx:320
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:330
MapMode GetPrefMapMode() const
Definition: graph.cxx:375
void SetPrefSize(const Size &rPrefSize)
Definition: graph.cxx:369
const std::shared_ptr< VectorGraphicData > & getVectorGraphicData() const
Definition: graph.cxx:525
const Fraction & GetScaleX() const
Definition: mapmod.cxx:150
MapUnit GetMapUnit() const
Definition: mapmod.cxx:146
bool IsSimple() const
Definition: mapmod.cxx:154
const Point & GetOrigin() const
Definition: mapmod.cxx:148
const Fraction & GetScaleY() const
Definition: mapmod.cxx:152
virtual void ResetError()
SvStream & ReadCharAsBool(bool &rBool)
sal_uInt64 Tell() const
void SetEndian(SvStreamEndian SvStreamEndian)
SvStream & WriteUniOrByteString(std::u16string_view rStr, rtl_TextEncoding eDestCharSet)
SvStreamCompressFlags GetCompressMode() const
std::size_t WriteBytes(const void *pData, std::size_t nSize)
SvStream & WriteBool(bool b)
SvStream & WriteUInt16(sal_uInt16 nUInt16)
sal_Int32 GetVersion() const
SvStream & WriteUInt32(sal_uInt32 nUInt32)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
SvStreamEndian GetEndian() const
void SetError(ErrCode nErrorCode)
sal_uInt64 Seek(sal_uInt64 nPos)
std::size_t ReadBytes(void *pData, std::size_t nSize)
rtl_TextEncoding GetStreamCharSet() const
sal_uInt64 SeekRel(sal_Int64 nPos)
ErrCode GetError() const
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
ErrCode const & GetErrorCode() const
sal_uInt64 remainingSize()
SvStream & Read(GDIMetaFile &rMetaFile, ImplMetaReadData *pData=nullptr)
Definition: SvmReader.cxx:65
SvStream & Write(const GDIMetaFile &rMetaFile)
Definition: SvmWriter.cxx:38
void writeGradient(const Gradient &rGradient)
TypeSerializer(SvStream &rStream)
void readGraphic(Graphic &rGraphic)
void writeMapMode(MapMode const &rMapMode)
void writeGfxLink(const GfxLink &rGfxLink)
void readMapMode(MapMode &rMapMode)
void writeGraphic(const Graphic &rGraphic)
void readGradient(Gradient &rGradient)
void readGfxLink(GfxLink &rGfxLink)
sal_uInt16 GetVersion() const
void writeFraction(Fraction const &rFraction)
void readPoint(Point &rPoint)
void writeColor(const Color &rColor)
void writePoint(const Point &rPoint)
void readSize(Size &rSize)
void readFraction(Fraction &rFraction)
void readColor(Color &rColor)
void writeSize(const Size &rSize)
bool WriteDIBBitmapEx(const BitmapEx &rSource, SvStream &rOStm)
Definition: dibtools.cxx:1807
bool ReadDIBBitmapEx(BitmapEx &rTarget, SvStream &rIStm, bool bFileHeader, bool bMSOFormat)
Definition: dibtools.cxx:1676
float u
#define ERRCODE_IO_WRONGFORMAT
#define SOFFICE_FILEFORMAT_50
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
MapUnit
tools::Long const nBorder
GradientStyle
const sal_uInt16 nMagic
QPRO_FUNC_TYPE nType
SvStreamEndian
UNDERLYING_TYPE get() const
unsigned char sal_uInt8
VectorGraphicDataType
sal_Int32 nLength