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<css::awt::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 rGfxLink = GfxLink(BinaryDataContainer(mrStream, 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(rGfxLink.GetPrefMapMode());
150 }
151
152 if (rGfxLink.GetDataSize())
153 {
154 if (rGfxLink.GetData())
155 mrStream.WriteBytes(rGfxLink.GetData(), rGfxLink.GetDataSize());
156 }
157}
158
159namespace
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_uInt64 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
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 {
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 SvmReader aReader(mrStream);
258 aReader.Read(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);
273
275 || constPdfMagic == nMagic)
276 {
277 sal_uInt32 nLength = 0;
279
280 if (nLength)
281 {
282 BinaryDataContainer aDataContainer(mrStream, nLength);
283
284 if (!mrStream.GetError())
285 {
287
288 switch (nMagic)
289 {
290 case constWmfMagic:
291 aDataType = VectorGraphicDataType::Wmf;
292 break;
293 case constEmfMagic:
294 aDataType = VectorGraphicDataType::Emf;
295 break;
296 case constPdfMagic:
297 aDataType = VectorGraphicDataType::Pdf;
298 break;
299 }
300
301 auto aVectorGraphicDataPtr
302 = std::make_shared<VectorGraphicData>(aDataContainer, aDataType);
303 rGraphic = Graphic(aVectorGraphicDataPtr);
304 }
305 }
306 }
307 else
308 {
309 mrStream.SetError(nOriginalError);
310 }
311
312 mrStream.Seek(nInitialStreamPosition);
313 }
314 }
315 mrStream.SetEndian(nOldFormat);
316 }
317}
318
320{
321 Graphic aGraphic(rGraphic);
322
323 if (!aGraphic.makeAvailable())
324 return;
325
326 auto pGfxLink = aGraphic.GetSharedGfxLink();
327
329 && (mrStream.GetCompressMode() & SvStreamCompressFlags::NATIVE) && pGfxLink
330 && pGfxLink->IsNative())
331 {
332 // native format
334
335 // write compat info, destructor writes stuff into the header
336 {
337 VersionCompatWrite aCompat(mrStream, 1);
338 }
339 pGfxLink->SetPrefMapMode(aGraphic.GetPrefMapMode());
340 pGfxLink->SetPrefSize(aGraphic.GetPrefSize());
341 writeGfxLink(*pGfxLink);
342 }
343 else
344 {
345 // own format
346 const SvStreamEndian nOldFormat = mrStream.GetEndian();
347 mrStream.SetEndian(SvStreamEndian::LITTLE);
348
349 switch (aGraphic.GetType())
350 {
353 break;
354
356 {
357 auto pVectorGraphicData = aGraphic.getVectorGraphicData();
358 if (pVectorGraphicData)
359 {
360 // stream out Vector Graphic defining data (length, byte array and evtl. path)
361 // this is used e.g. in swapping out graphic data and in transporting it over UNO API
362 // as sequence of bytes, but AFAIK not written anywhere to any kind of file, so it should be
363 // no problem to extend it; only used at runtime
364 switch (pVectorGraphicData->getType())
365 {
367 {
369 break;
370 }
372 {
374 break;
375 }
377 {
379 break;
380 }
382 {
384 break;
385 }
386 }
387
388 sal_uInt32 nSize = pVectorGraphicData->getBinaryDataContainer().getSize();
389 mrStream.WriteUInt32(nSize);
390 pVectorGraphicData->getBinaryDataContainer().writeToStream(mrStream);
391
392 // For backwards compatibility, used to serialize path
394 }
395 else if (aGraphic.IsAnimated())
396 {
398 }
399 else
400 {
402 }
403 }
404 break;
405
406 default:
407 {
408 if (aGraphic.IsSupportedGraphic())
409 {
410 if (!mrStream.GetError())
411 {
412 SvmWriter aWriter(mrStream);
413 aWriter.Write(rGraphic.GetGDIMetaFile());
414 }
415 }
416 }
417 break;
418 }
419 mrStream.SetEndian(nOldFormat);
420 }
421}
422
423bool TooLargeScaleForMapMode(const Fraction& rScale, int nDPI)
424{
425 // ImplLogicToPixel will multiply its values by this numerator * dpi and then double that
426 // result before dividing
427 if (rScale.GetNumerator() > std::numeric_limits<sal_Int32>::max() / nDPI / 2)
428 return true;
429 if (rScale.GetNumerator() < std::numeric_limits<sal_Int32>::min() / nDPI / 2)
430 return true;
431 return false;
432}
433
434static bool UselessScaleForMapMode(const Fraction& rScale)
435{
436 if (!rScale.IsValid())
437 return true;
438 if (static_cast<double>(rScale) < 0.0)
439 return true;
440 return false;
441}
442
444{
446 sal_uInt16 nTmp16(0);
447 Point aOrigin;
448 Fraction aScaleX;
449 Fraction aScaleY;
450 bool bSimple(true);
451
452 mrStream.ReadUInt16(nTmp16);
453 MapUnit eUnit = static_cast<MapUnit>(nTmp16);
454 readPoint(aOrigin);
455 readFraction(aScaleX);
456 readFraction(aScaleY);
457 mrStream.ReadCharAsBool(bSimple);
458
459 const bool bBogus = UselessScaleForMapMode(aScaleX) || UselessScaleForMapMode(aScaleY);
460 SAL_WARN_IF(bBogus, "vcl", "invalid scale");
461
462 if (bSimple || bBogus)
463 rMapMode = MapMode(eUnit);
464 else
465 rMapMode = MapMode(eUnit, aOrigin, aScaleX, aScaleY);
466}
467
469{
470 VersionCompatWrite aCompat(mrStream, 1);
471
472 mrStream.WriteUInt16(sal_uInt16(rMapMode.GetMapUnit()));
473 writePoint(rMapMode.GetOrigin());
474 writeFraction(rMapMode.GetScaleX());
475 writeFraction(rMapMode.GetScaleY());
476 mrStream.WriteBool(rMapMode.IsSimple());
477}
478
479/* 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
void SetStyle(css::awt::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)
css::awt::GradientStyle GetStyle() const
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:185
MapUnit GetMapUnit() const
Definition: mapmod.cxx:181
bool IsSimple() const
Definition: mapmod.cxx:189
const Point & GetOrigin() const
Definition: mapmod.cxx:183
const Fraction & GetScaleY() const
Definition: mapmod.cxx:187
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)
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:1742
bool ReadDIBBitmapEx(BitmapEx &rTarget, SvStream &rIStm, bool bFileHeader, bool bMSOFormat)
Definition: dibtools.cxx:1623
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
const sal_uInt16 nMagic
QPRO_FUNC_TYPE nType
SvStreamEndian
UNDERLYING_TYPE get() const
VectorGraphicDataType
sal_Int32 nLength