nss: upgrade to release 3.73
[LibreOffice.git] / drawinglayer / source / tools / emfpbrush.cxx
blobca0c27b23ecfebb24914362e583f2e1c1a5ce57c
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 <basegfx/range/b2drange.hxx>
21 #include <basegfx/range/b2drectangle.hxx>
22 #include <basegfx/polygon/b2dpolypolygontools.hxx>
23 #include <o3tl/safeint.hxx>
24 #include <sal/log.hxx>
25 #include "emfpbrush.hxx"
26 #include "emfppath.hxx"
28 namespace emfplushelper
30 EMFPBrush::EMFPBrush()
31 : type(0)
32 , additionalFlags(0)
33 , wrapMode(0)
34 , firstPointX(0.0)
35 , firstPointY(0.0)
36 , aWidth(0.0)
37 , aHeight(0.0)
38 , hasTransformation(false)
39 , blendPoints(0)
40 , blendFactors(nullptr)
41 , colorblendPoints(0)
42 , surroundColorsNumber(0)
43 , hatchStyle(HatchStyleHorizontal)
47 EMFPBrush::~EMFPBrush()
51 static OUString BrushTypeToString(sal_uInt32 type)
53 switch (type)
55 case BrushTypeSolidColor: return "BrushTypeSolidColor";
56 case BrushTypeHatchFill: return "BrushTypeHatchFill";
57 case BrushTypeTextureFill: return "BrushTypeTextureFill";
58 case BrushTypePathGradient: return "BrushTypePathGradient";
59 case BrushTypeLinearGradient: return "BrushTypeLinearGradient";
61 return "";
64 void EMFPBrush::Read(SvStream& s, EmfPlusHelperData const & rR)
66 sal_uInt32 header;
68 s.ReadUInt32(header).ReadUInt32(type);
70 SAL_INFO("drawinglayer", "EMF+\t\t\tHeader: 0x" << std::hex << header);
71 SAL_INFO("drawinglayer", "EMF+\t\t\tType: " << BrushTypeToString(type) << "(0x" << type << ")" << std::dec);
73 switch (type)
75 case BrushTypeSolidColor:
77 sal_uInt32 color;
78 s.ReadUInt32(color);
80 solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
81 SAL_INFO("drawinglayer", "EMF+\t\t\t\tSolid color: 0x" << std::hex << color << std::dec);
82 break;
84 case BrushTypeHatchFill:
86 sal_uInt32 style;
87 sal_uInt32 foregroundColor;
88 sal_uInt32 backgroundColor;
89 s.ReadUInt32(style);
90 s.ReadUInt32(foregroundColor);
91 s.ReadUInt32(backgroundColor);
93 hatchStyle = static_cast<EmfPlusHatchStyle>(style);
94 solidColor = ::Color(0xff - (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff);
95 secondColor = ::Color(0xff - (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff);
96 SAL_INFO("drawinglayer", "EMF+\t\t\t\tHatch style: 0x" << std::hex << style);
97 SAL_INFO("drawinglayer", "EMF+\t\t\t\tForeground color: 0x" << solidColor.AsRGBHexString());
98 SAL_INFO("drawinglayer", "EMF+\t\t\t\tBackground color: 0x" << secondColor.AsRGBHexString());
99 break;
101 case BrushTypeTextureFill:
103 SAL_WARN("drawinglayer", "EMF+\tTODO: implement BrushTypeTextureFill brush");
104 break;
106 case BrushTypePathGradient:
108 s.ReadUInt32(additionalFlags).ReadInt32(wrapMode);
109 SAL_INFO("drawinglayer", "EMF+\t\t\t\tAdditional flags: 0x" << std::hex << additionalFlags << std::dec);
110 sal_uInt32 color;
111 s.ReadUInt32(color);
112 solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
113 SAL_INFO("drawinglayer", "EMF+\t\t\t\tCenter color: 0x" << std::hex << color << std::dec);
114 s.ReadFloat(firstPointX).ReadFloat(firstPointY);
115 SAL_INFO("drawinglayer", "EMF+\t\t\t\tCenter point: " << firstPointX << "," << firstPointY);
116 s.ReadInt32(surroundColorsNumber);
117 SAL_INFO("drawinglayer", "EMF+\t\t\t\t number of surround colors: " << surroundColorsNumber);
119 if (surroundColorsNumber<0 || o3tl::make_unsigned(surroundColorsNumber)>SAL_MAX_INT32 / sizeof(::Color))
121 surroundColorsNumber = SAL_MAX_INT32 / sizeof(::Color);
124 surroundColors.reset( new ::Color[surroundColorsNumber] );
126 for (int i = 0; i < surroundColorsNumber; i++)
128 s.ReadUInt32(color);
129 surroundColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
130 if (i == 0)
131 secondColor = surroundColors[0];
132 SAL_INFO("drawinglayer", "EMF+\t\t\t\tSurround color[" << i << "]: 0x" << std::hex << color << std::dec);
135 if (additionalFlags & 0x01)
137 sal_Int32 pathLength;
139 s.ReadInt32(pathLength);
140 SAL_INFO("drawinglayer", "EMF+\t\t\t\tPath length: " << pathLength);
142 sal_uInt64 const pos = s.Tell();
144 sal_uInt32 pathHeader;
145 sal_Int32 pathPoints, pathFlags;
146 s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags);
148 SAL_INFO("drawinglayer", "EMF+\t\t\t\tPath (brush path gradient)");
149 SAL_INFO("drawinglayer", "EMF+\t\t\t\t\tHeader: 0x" << std::hex << pathHeader);
150 SAL_INFO("drawinglayer", "EMF+\t\t\t\t\tPoints: " << std::dec << pathPoints);
151 SAL_INFO("drawinglayer", "EMF+\t\t\t\t\tAdditional flags: 0x" << std::hex << pathFlags << std::dec);
153 path.reset( new EMFPPath(pathPoints) );
154 path->Read(s, pathFlags);
156 s.Seek(pos + pathLength);
158 const ::basegfx::B2DRectangle aBounds(::basegfx::utils::getRange(path->GetPolygon(rR, false)));
159 aWidth = aBounds.getWidth();
160 aHeight = aBounds.getHeight();
161 SAL_INFO("drawinglayer", "EMF+\t\t\t\tPolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " "
162 << aBounds.getWidth() << "x" << aBounds.getHeight());
164 else
166 sal_Int32 boundaryPointCount;
167 s.ReadInt32(boundaryPointCount);
169 sal_uInt64 const pos = s.Tell();
170 SAL_INFO("drawinglayer", "EMF+\t use boundary, points: " << boundaryPointCount);
171 path.reset( new EMFPPath(boundaryPointCount) );
172 path->Read(s, 0x0);
174 s.Seek(pos + 8 * boundaryPointCount);
176 const ::basegfx::B2DRectangle aBounds(::basegfx::utils::getRange(path->GetPolygon(rR, false)));
177 aWidth = aBounds.getWidth();
178 aHeight = aBounds.getHeight();
179 SAL_INFO("drawinglayer", "EMF+\t\t\t\tPolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " "
180 << aBounds.getWidth() << "x" << aBounds.getHeight());
183 if (additionalFlags & 0x02)
185 EmfPlusHelperData::readXForm(s, brush_transformation);
186 hasTransformation = true;
187 SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
190 if (additionalFlags & 0x08)
192 s.ReadInt32(blendPoints);
193 SAL_INFO("drawinglayer", "EMF+\t\t\t\tuse blend, points: " << blendPoints);
194 if (blendPoints<0 || o3tl::make_unsigned(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float)))
195 blendPoints = SAL_MAX_INT32 / (2 * sizeof(float));
196 blendPositions.reset( new float[2 * blendPoints] );
197 blendFactors = blendPositions.get() + blendPoints;
199 for (int i = 0; i < blendPoints; i++)
201 s.ReadFloat(blendPositions[i]);
202 SAL_INFO("drawinglayer", "EMF+\t\t\t\tposition[" << i << "]: " << blendPositions[i]);
205 for (int i = 0; i < blendPoints; i++)
207 s.ReadFloat(blendFactors[i]);
208 SAL_INFO("drawinglayer", "EMF+\t\t\t\tFactor[" << i << "]: " << blendFactors[i]);
212 if (additionalFlags & 0x04)
214 s.ReadInt32(colorblendPoints);
215 SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
217 if (colorblendPoints<0 || o3tl::make_unsigned(colorblendPoints)>SAL_MAX_INT32 / sizeof(float))
219 colorblendPoints = SAL_MAX_INT32 / sizeof(float);
222 if (o3tl::make_unsigned(colorblendPoints) > SAL_MAX_INT32 / sizeof(::Color))
224 colorblendPoints = SAL_MAX_INT32 / sizeof(::Color);
227 colorblendPositions.reset( new float[colorblendPoints] );
228 colorblendColors.reset( new ::Color[colorblendPoints] );
230 for (int i = 0; i < colorblendPoints; i++)
232 s.ReadFloat(colorblendPositions[i]);
233 SAL_INFO("drawinglayer", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]);
236 for (int i = 0; i < colorblendPoints; i++)
238 s.ReadUInt32(color);
239 colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
240 SAL_INFO("drawinglayer", "EMF+\t\t\t\tColor[" << i << "]: 0x" << std::hex << color << std::dec);
244 break;
246 case BrushTypeLinearGradient:
248 s.ReadUInt32(additionalFlags).ReadInt32(wrapMode);
249 SAL_INFO("drawinglayer", "EMF+\t\t\t\tLinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec << ", wrapMode: " << wrapMode);
250 s.ReadFloat(firstPointX).ReadFloat(firstPointY).ReadFloat(aWidth).ReadFloat(aHeight);
251 SAL_INFO("drawinglayer", "EMF+\t\t\t\tFirst gradient point: " << firstPointX << ":" << firstPointY
252 << ", size " << aWidth << "x" << aHeight);
253 sal_uInt32 color;
254 s.ReadUInt32(color);
255 solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
256 SAL_INFO("drawinglayer", "EMF+\t\t\t\tfirst color: 0x" << std::hex << color << std::dec);
257 s.ReadUInt32(color);
258 secondColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
259 SAL_INFO("drawinglayer", "EMF+\t\t\t\tsecond color: 0x" << std::hex << color << std::dec);
261 // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
262 s.ReadUInt32(color);
263 s.ReadUInt32(color);
265 if (additionalFlags & 0x02)
267 EmfPlusHelperData::readXForm(s, brush_transformation);
268 hasTransformation = true;
269 SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
272 if (additionalFlags & 0x08)
274 s.ReadInt32(blendPoints);
275 SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse blend, points: " << blendPoints);
276 if (blendPoints<0 || o3tl::make_unsigned(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float)))
277 blendPoints = SAL_MAX_INT32 / (2 * sizeof(float));
278 blendPositions.reset( new float[2 * blendPoints] );
279 blendFactors = blendPositions.get() + blendPoints;
281 for (int i = 0; i < blendPoints; i++)
283 s.ReadFloat(blendPositions[i]);
284 SAL_INFO("drawinglayer", "EMF+\t\t\t\tPosition[" << i << "]: " << blendPositions[i]);
287 for (int i = 0; i < blendPoints; i++)
289 s.ReadFloat(blendFactors[i]);
290 SAL_INFO("drawinglayer", "EMF+\t\t\t\tFactor[" << i << "]: " << blendFactors[i]);
294 if (additionalFlags & 0x04)
296 s.ReadInt32(colorblendPoints);
297 SAL_INFO("drawinglayer", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
299 if (colorblendPoints<0 || o3tl::make_unsigned(colorblendPoints)>SAL_MAX_INT32 / sizeof(float))
301 colorblendPoints = SAL_MAX_INT32 / sizeof(float);
304 if (o3tl::make_unsigned(colorblendPoints) > SAL_MAX_INT32 / sizeof(::Color))
306 colorblendPoints = sal_uInt32(SAL_MAX_INT32) / sizeof(::Color);
309 colorblendPositions.reset( new float[colorblendPoints] );
310 colorblendColors.reset( new ::Color[colorblendPoints] );
312 for (int i = 0; i < colorblendPoints; i++)
314 s.ReadFloat(colorblendPositions[i]);
315 SAL_INFO("drawinglayer", "EMF+\t\t\t\tPosition[" << i << "]: " << colorblendPositions[i]);
318 for (int i = 0; i < colorblendPoints; i++)
320 s.ReadUInt32(color);
321 colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
322 SAL_INFO("drawinglayer", "EMF+\t\t\t\tColor[" << i << "]: 0x" << std::hex << color << std::dec);
326 break;
328 default:
330 SAL_WARN("drawinglayer", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
336 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */