bump product version to 7.2.5.1
[LibreOffice.git] / vcl / source / gdi / TypeSerializer.cxx
blob4fc05ec5c5d73c8e7beff9daebdfd3e4f05a4679
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/TypeSerializer.hxx>
21 #include <tools/vcompat.hxx>
22 #include <tools/fract.hxx>
23 #include <sal/log.hxx>
24 #include <comphelper/fileformat.h>
25 #include <vcl/gdimtf.hxx>
26 #include <vcl/dibtools.hxx>
28 TypeSerializer::TypeSerializer(SvStream& rStream)
29 : GenericTypeSerializer(rStream)
33 void TypeSerializer::readGradient(Gradient& rGradient)
35 VersionCompatRead aCompat(mrStream);
37 sal_uInt16 nStyle = 0;
38 Color aStartColor;
39 Color aEndColor;
40 sal_uInt16 nAngle = 0;
41 sal_uInt16 nBorder = 0;
42 sal_uInt16 nOffsetX = 0;
43 sal_uInt16 nOffsetY = 0;
44 sal_uInt16 nIntensityStart = 0;
45 sal_uInt16 nIntensityEnd = 0;
46 sal_uInt16 nStepCount = 0;
48 mrStream.ReadUInt16(nStyle);
49 readColor(aStartColor);
50 readColor(aEndColor);
51 mrStream.ReadUInt16(nAngle);
52 mrStream.ReadUInt16(nBorder);
53 mrStream.ReadUInt16(nOffsetX);
54 mrStream.ReadUInt16(nOffsetY);
55 mrStream.ReadUInt16(nIntensityStart);
56 mrStream.ReadUInt16(nIntensityEnd);
57 mrStream.ReadUInt16(nStepCount);
59 rGradient.SetStyle(static_cast<GradientStyle>(nStyle));
60 rGradient.SetStartColor(aStartColor);
61 rGradient.SetEndColor(aEndColor);
62 if (nAngle > 3600)
64 SAL_WARN("vcl", "angle out of range " << nAngle);
65 nAngle = 0;
67 rGradient.SetAngle(Degree10(nAngle));
68 rGradient.SetBorder(nBorder);
69 rGradient.SetOfsX(nOffsetX);
70 rGradient.SetOfsY(nOffsetY);
71 rGradient.SetStartIntensity(nIntensityStart);
72 rGradient.SetEndIntensity(nIntensityEnd);
73 rGradient.SetSteps(nStepCount);
76 void TypeSerializer::writeGradient(const Gradient& rGradient)
78 VersionCompatWrite aCompat(mrStream, 1);
80 mrStream.WriteUInt16(static_cast<sal_uInt16>(rGradient.GetStyle()));
81 writeColor(rGradient.GetStartColor());
82 writeColor(rGradient.GetEndColor());
83 mrStream.WriteUInt16(rGradient.GetAngle().get());
84 mrStream.WriteUInt16(rGradient.GetBorder());
85 mrStream.WriteUInt16(rGradient.GetOfsX());
86 mrStream.WriteUInt16(rGradient.GetOfsY());
87 mrStream.WriteUInt16(rGradient.GetStartIntensity());
88 mrStream.WriteUInt16(rGradient.GetEndIntensity());
89 mrStream.WriteUInt16(rGradient.GetSteps());
92 void TypeSerializer::readGfxLink(GfxLink& rGfxLink)
94 sal_uInt16 nType = 0;
95 sal_uInt32 nDataSize = 0;
96 sal_uInt32 nUserId = 0;
98 Size aSize;
99 MapMode aMapMode;
100 bool bMapAndSizeValid = false;
103 VersionCompatRead aCompat(mrStream);
105 // Version 1
106 mrStream.ReadUInt16(nType);
107 mrStream.ReadUInt32(nDataSize);
108 mrStream.ReadUInt32(nUserId);
110 if (aCompat.GetVersion() >= 2)
112 readSize(aSize);
113 readMapMode(aMapMode);
114 bMapAndSizeValid = true;
118 auto nRemainingData = mrStream.remainingSize();
119 if (nDataSize > nRemainingData)
121 SAL_WARN("vcl", "graphic link stream is smaller than requested size");
122 nDataSize = nRemainingData;
125 std::unique_ptr<sal_uInt8[]> pBuffer(new sal_uInt8[nDataSize]);
126 mrStream.ReadBytes(pBuffer.get(), nDataSize);
128 rGfxLink = GfxLink(std::move(pBuffer), nDataSize, static_cast<GfxLinkType>(nType));
129 rGfxLink.SetUserId(nUserId);
131 if (bMapAndSizeValid)
133 rGfxLink.SetPrefSize(aSize);
134 rGfxLink.SetPrefMapMode(aMapMode);
138 void TypeSerializer::writeGfxLink(const GfxLink& rGfxLink)
141 VersionCompatWrite aCompat(mrStream, 2);
143 // Version 1
144 mrStream.WriteUInt16(sal_uInt16(rGfxLink.GetType()));
145 mrStream.WriteUInt32(rGfxLink.GetDataSize());
146 mrStream.WriteUInt32(rGfxLink.GetUserId());
148 // Version 2
149 writeSize(rGfxLink.GetPrefSize());
150 writeMapMode(rGfxLink.GetPrefMapMode());
153 if (rGfxLink.GetDataSize())
155 if (rGfxLink.GetData())
156 mrStream.WriteBytes(rGfxLink.GetData(), rGfxLink.GetDataSize());
160 namespace
162 #define NATIVE_FORMAT_50 COMPAT_FORMAT('N', 'A', 'T', '5')
164 } // end anonymous namespace
166 void TypeSerializer::readGraphic(Graphic& rGraphic)
168 if (mrStream.GetError())
169 return;
171 const sal_uLong nInitialStreamPosition = mrStream.Tell();
172 sal_uInt32 nType;
174 // if there is no more data, avoid further expensive
175 // reading which will create VDevs and other stuff, just to
176 // read nothing.
177 if (mrStream.remainingSize() < 4)
178 return;
180 // read Id
181 mrStream.ReadUInt32(nType);
183 if (NATIVE_FORMAT_50 == nType)
185 Graphic aGraphic;
186 GfxLink aLink;
188 // read compat info, destructor writes stuff into the header
190 VersionCompatRead aCompat(mrStream);
193 readGfxLink(aLink);
195 if (!mrStream.GetError() && aLink.LoadNative(aGraphic))
197 if (aLink.IsPrefMapModeValid())
198 aGraphic.SetPrefMapMode(aLink.GetPrefMapMode());
200 if (aLink.IsPrefSizeValid())
201 aGraphic.SetPrefSize(aLink.GetPrefSize());
203 else
205 mrStream.Seek(nInitialStreamPosition);
206 mrStream.SetError(ERRCODE_IO_WRONGFORMAT);
208 rGraphic = aGraphic;
210 else
212 BitmapEx aBitmapEx;
213 const SvStreamEndian nOldFormat = mrStream.GetEndian();
215 mrStream.SeekRel(-4);
216 mrStream.SetEndian(SvStreamEndian::LITTLE);
217 ReadDIBBitmapEx(aBitmapEx, mrStream);
219 if (!mrStream.GetError())
221 sal_uInt32 nMagic1 = 0;
222 sal_uInt32 nMagic2 = 0;
223 if (mrStream.remainingSize() >= 8)
225 sal_uInt64 nBeginPosition = mrStream.Tell();
226 mrStream.ReadUInt32(nMagic1);
227 mrStream.ReadUInt32(nMagic2);
228 mrStream.Seek(nBeginPosition);
230 if (!mrStream.GetError())
232 if (nMagic1 == 0x5344414e && nMagic2 == 0x494d4931)
234 Animation aAnimation;
235 ReadAnimation(mrStream, aAnimation);
237 // #108077# manually set loaded BmpEx to Animation
238 // (which skips loading its BmpEx if already done)
239 aAnimation.SetBitmapEx(aBitmapEx);
240 rGraphic = Graphic(aAnimation);
242 else
244 rGraphic = Graphic(aBitmapEx);
247 else
249 mrStream.ResetError();
252 else
254 GDIMetaFile aMetaFile;
256 mrStream.Seek(nInitialStreamPosition);
257 mrStream.ResetError();
258 ReadGDIMetaFile(mrStream, aMetaFile);
260 if (!mrStream.GetError())
262 rGraphic = Graphic(aMetaFile);
264 else
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);
271 mrStream.ResetError();
272 mrStream.ReadUInt32(nMagic);
274 if (constSvgMagic == nMagic || constWmfMagic == nMagic || constEmfMagic == nMagic
275 || constPdfMagic == nMagic)
277 sal_uInt32 nLength = 0;
278 mrStream.ReadUInt32(nLength);
280 if (nLength)
282 auto rData = std::make_unique<std::vector<sal_uInt8>>(nLength);
283 mrStream.ReadBytes(rData->data(), rData->size());
284 BinaryDataContainer aDataContainer(std::move(rData));
286 if (!mrStream.GetError())
288 VectorGraphicDataType aDataType(VectorGraphicDataType::Svg);
290 switch (nMagic)
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;
303 auto aVectorGraphicDataPtr
304 = std::make_shared<VectorGraphicData>(aDataContainer, aDataType);
305 rGraphic = Graphic(aVectorGraphicDataPtr);
309 else
311 mrStream.SetError(nOriginalError);
314 mrStream.Seek(nInitialStreamPosition);
317 mrStream.SetEndian(nOldFormat);
321 void TypeSerializer::writeGraphic(const Graphic& rGraphic)
323 Graphic aGraphic(rGraphic);
325 if (!aGraphic.makeAvailable())
326 return;
328 auto pGfxLink = aGraphic.GetSharedGfxLink();
330 if (mrStream.GetVersion() >= SOFFICE_FILEFORMAT_50
331 && (mrStream.GetCompressMode() & SvStreamCompressFlags::NATIVE) && pGfxLink
332 && pGfxLink->IsNative())
334 // native format
335 mrStream.WriteUInt32(NATIVE_FORMAT_50);
337 // write compat info, destructor writes stuff into the header
339 VersionCompatWrite aCompat(mrStream, 1);
341 pGfxLink->SetPrefMapMode(aGraphic.GetPrefMapMode());
342 pGfxLink->SetPrefSize(aGraphic.GetPrefSize());
343 writeGfxLink(*pGfxLink);
345 else
347 // own format
348 const SvStreamEndian nOldFormat = mrStream.GetEndian();
349 mrStream.SetEndian(SvStreamEndian::LITTLE);
351 switch (aGraphic.GetType())
353 case GraphicType::NONE:
354 case GraphicType::Default:
355 break;
357 case GraphicType::Bitmap:
359 auto pVectorGraphicData = aGraphic.getVectorGraphicData();
360 if (pVectorGraphicData)
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->getType())
368 case VectorGraphicDataType::Wmf:
370 mrStream.WriteUInt32(constWmfMagic);
371 break;
373 case VectorGraphicDataType::Emf:
375 mrStream.WriteUInt32(constEmfMagic);
376 break;
378 case VectorGraphicDataType::Svg:
380 mrStream.WriteUInt32(constSvgMagic);
381 break;
383 case VectorGraphicDataType::Pdf:
385 mrStream.WriteUInt32(constPdfMagic);
386 break;
390 sal_uInt32 nSize = pVectorGraphicData->getBinaryDataContainer().getSize();
391 mrStream.WriteUInt32(nSize);
392 mrStream.WriteBytes(pVectorGraphicData->getBinaryDataContainer().getData(),
393 nSize);
394 // For backwards compatibility, used to serialize path
395 mrStream.WriteUniOrByteString(u"", mrStream.GetStreamCharSet());
397 else if (aGraphic.IsAnimated())
399 WriteAnimation(mrStream, aGraphic.GetAnimation());
401 else
403 WriteDIBBitmapEx(aGraphic.GetBitmapEx(), mrStream);
406 break;
408 default:
410 if (aGraphic.IsSupportedGraphic())
411 WriteGDIMetaFile(mrStream, rGraphic.GetGDIMetaFile());
413 break;
415 mrStream.SetEndian(nOldFormat);
419 void TypeSerializer::readMapMode(MapMode& rMapMode)
421 VersionCompatRead aCompat(mrStream);
422 sal_uInt16 nTmp16(0);
423 Point aOrigin;
424 Fraction aScaleX;
425 Fraction aScaleY;
426 bool bSimple(true);
428 mrStream.ReadUInt16(nTmp16);
429 MapUnit eUnit = static_cast<MapUnit>(nTmp16);
430 readPoint(aOrigin);
431 readFraction(aScaleX);
432 readFraction(aScaleY);
433 mrStream.ReadCharAsBool(bSimple);
435 if (bSimple)
436 rMapMode = MapMode(eUnit);
437 else
438 rMapMode = MapMode(eUnit, aOrigin, aScaleX, aScaleY);
441 void TypeSerializer::writeMapMode(MapMode const& rMapMode)
443 VersionCompatWrite aCompat(mrStream, 1);
445 mrStream.WriteUInt16(sal_uInt16(rMapMode.GetMapUnit()));
446 writePoint(rMapMode.GetOrigin());
447 writeFraction(rMapMode.GetScaleX());
448 writeFraction(rMapMode.GetScaleY());
449 mrStream.WriteBool(rMapMode.IsSimple());
452 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */