LibreOffice Module drawinglayer (master) 1
emfpbrush.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
23#include <o3tl/safeint.hxx>
24#include <sal/log.hxx>
25#include "emfpbrush.hxx"
26#include "emfppath.hxx"
27
29{
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)
44 {
45 }
46
48 {
49 }
50
51 static OUString BrushTypeToString(sal_uInt32 type)
52 {
53 switch (type)
54 {
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";
60 }
61 return "";
62 }
63
65 {
66 sal_uInt32 header;
67
69
70 SAL_INFO("drawinglayer.emf", "EMF+\t\t\tHeader: 0x" << std::hex << header);
71 SAL_INFO("drawinglayer.emf", "EMF+\t\t\tType: " << BrushTypeToString(type) << "(0x" << type << ")" << std::dec);
72
73 switch (type)
74 {
76 {
77 sal_uInt32 color;
79
80 solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
81 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tSolid color: 0x" << std::hex << color << std::dec);
82 break;
83 }
85 {
86 sal_uInt32 style;
87 sal_uInt32 foregroundColor;
88 sal_uInt32 backgroundColor;
89 s.ReadUInt32(style);
90 s.ReadUInt32(foregroundColor);
91 s.ReadUInt32(backgroundColor);
92
93 hatchStyle = static_cast<EmfPlusHatchStyle>(style);
94 solidColor = ::Color(ColorAlpha, (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff);
95 secondColor = ::Color(ColorAlpha, (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff);
96 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tHatch style: 0x" << std::hex << style);
97 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tForeground color: 0x" << solidColor.AsRGBHexString());
98 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tBackground color: 0x" << secondColor.AsRGBHexString());
99 break;
100 }
102 {
103 SAL_WARN("drawinglayer.emf", "EMF+\tTODO: implement BrushTypeTextureFill brush");
104 break;
105 }
107 {
109 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tAdditional flags: 0x" << std::hex << additionalFlags << std::dec);
110 sal_uInt32 color;
111 s.ReadUInt32(color);
112 solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
113 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tCenter color: 0x" << std::hex << color << std::dec);
115 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tCenter point: " << firstPointX << "," << firstPointY);
117 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t number of surround colors: " << surroundColorsNumber);
118
119 surroundColors.reset( new ::Color[surroundColorsNumber] );
120
121 for (sal_uInt32 i = 0; i < surroundColorsNumber; i++)
122 {
123 s.ReadUInt32(color);
124 surroundColors[i] = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
125 if (i == 0)
127 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tSurround color[" << i << "]: 0x" << std::hex << color << std::dec);
128 }
129
130 if (additionalFlags & 0x01) // BrushDataPath
131 {
132 sal_Int32 pathLength;
133
134 s.ReadInt32(pathLength);
135 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPath length: " << pathLength);
136
137 sal_uInt64 const pos = s.Tell();
138
139 sal_uInt32 pathHeader;
140 sal_Int32 pathPoints, pathFlags;
141 s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags);
142
143 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPath (brush path gradient)");
144 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t\tHeader: 0x" << std::hex << pathHeader);
145 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t\tPoints: " << std::dec << pathPoints);
146 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t\tAdditional flags: 0x" << std::hex << pathFlags << std::dec);
147
148 path.reset( new EMFPPath(pathPoints) );
149 path->Read(s, pathFlags);
150
151 s.Seek(pos + pathLength);
152
153 const ::basegfx::B2DRectangle aBounds(::basegfx::utils::getRange(path->GetPolygon(rR, false)));
154 aWidth = aBounds.getWidth();
155 aHeight = aBounds.getHeight();
156 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " "
157 << aBounds.getWidth() << "x" << aBounds.getHeight());
158 }
159 else
160 {
161 sal_Int32 boundaryPointCount;
162 s.ReadInt32(boundaryPointCount);
163
164 sal_uInt64 const pos = s.Tell();
165 SAL_INFO("drawinglayer.emf", "EMF+\t use boundary, points: " << boundaryPointCount);
166 path.reset( new EMFPPath(boundaryPointCount) );
167 path->Read(s, 0x0);
168
169 s.Seek(pos + 8 * boundaryPointCount);
170
171 const ::basegfx::B2DRectangle aBounds(::basegfx::utils::getRange(path->GetPolygon(rR, false)));
172 aWidth = aBounds.getWidth();
173 aHeight = aBounds.getHeight();
174 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " "
175 << aBounds.getWidth() << "x" << aBounds.getHeight());
176 }
177
178 if (additionalFlags & 0x02) // BrushDataTransform
179 {
181 hasTransformation = true;
182 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
183 }
184
185 // BrushDataPresetColors and BrushDataBlendFactorsH
186 if ((additionalFlags & 0x04) && (additionalFlags & 0x08))
187 {
188 SAL_WARN("drawinglayer.emf", "EMF+\t Brush must not contain both BrushDataPresetColors and BrushDataBlendFactorsH");
189 return;
190 }
191 if (additionalFlags & 0x08) // BrushDataBlendFactorsH
192 {
194 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tuse blend, points: " << blendPoints);
195 blendPositions.reset( new float[2 * blendPoints] );
197
198 for (sal_uInt32 i = 0; i < blendPoints; i++)
199 {
201 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tposition[" << i << "]: " << blendPositions[i]);
202 }
203
204 for (sal_uInt32 i = 0; i < blendPoints; i++)
205 {
207 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tFactor[" << i << "]: " << blendFactors[i]);
208 }
209 }
210
211 if (additionalFlags & 0x04) // BrushDataPresetColors
212 {
214 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
215 colorblendPositions.reset( new float[colorblendPoints] );
216 colorblendColors.reset( new ::Color[colorblendPoints] );
217
218 for (sal_uInt32 i = 0; i < colorblendPoints; i++)
219 {
221 SAL_INFO("drawinglayer.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]);
222 }
223
224 for (sal_uInt32 i = 0; i < colorblendPoints; i++)
225 {
226 s.ReadUInt32(color);
227 colorblendColors[i] = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
228 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tColor[" << i << "]: 0x" << std::hex << color << std::dec);
229 }
230 }
231
232 break;
233 }
235 {
237 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tLinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec << ", wrapMode: " << wrapMode);
239 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tFirst gradient point: " << firstPointX << ":" << firstPointY
240 << ", size " << aWidth << "x" << aHeight);
241 sal_uInt32 color;
242 s.ReadUInt32(color);
243 solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
244 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tfirst color: 0x" << std::hex << color << std::dec);
245 s.ReadUInt32(color);
246 secondColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
247 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tsecond color: 0x" << std::hex << color << std::dec);
248
249 // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
250 s.ReadUInt32(color);
251 s.ReadUInt32(color);
252
253 if (additionalFlags & 0x02) //BrushDataTransform
254 {
256 hasTransformation = true;
257 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse brush transformation: " << brush_transformation);
258 }
259 // BrushDataPresetColors and BrushDataBlendFactorsH
260 if ((additionalFlags & 0x04) && (additionalFlags & 0x08))
261 {
262 SAL_WARN("drawinglayer.emf", "EMF+\t Brush must not contain both BrushDataPresetColors and BrushDataBlendFactorsH");
263 return;
264 }
265
266 if (additionalFlags & 0x08) // BrushDataBlendFactorsH
267 {
269 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse blend, points: " << blendPoints);
270 blendPositions.reset( new float[2 * blendPoints] );
272
273 for (sal_uInt32 i = 0; i < blendPoints; i++)
274 {
276 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPosition[" << i << "]: " << blendPositions[i]);
277 }
278
279 for (sal_uInt32 i = 0; i < blendPoints; i++)
280 {
282 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tFactor[" << i << "]: " << blendFactors[i]);
283 }
284 }
285
286 if (additionalFlags & 0x04)
287 {
289 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
290 colorblendPositions.reset( new float[colorblendPoints] );
291 colorblendColors.reset( new ::Color[colorblendPoints] );
292
293 for (sal_uInt32 i = 0; i < colorblendPoints; i++)
294 {
296 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPosition[" << i << "]: " << colorblendPositions[i]);
297 }
298
299 for (sal_uInt32 i = 0; i < colorblendPoints; i++)
300 {
301 s.ReadUInt32(color);
302 colorblendColors[i] = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
303 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tColor[" << i << "]: 0x" << std::hex << color << std::dec);
304 }
305 }
306
307 break;
308 }
309 default:
310 {
311 SAL_WARN("drawinglayer.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
312 }
313 }
314 }
315}
316
317/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr sal_Int8 header[]
OUString AsRGBHexString() const
sal_uInt64 Tell() const
SvStream & ReadFloat(float &rFloat)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
sal_uInt64 Seek(sal_uInt64 nPos)
SvStream & ReadInt32(sal_Int32 &rInt32)
ColorAlpha
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
@ BrushTypeLinearGradient
Definition: emfpbrush.hxx:90
@ BrushTypePathGradient
Definition: emfpbrush.hxx:89
@ BrushTypeTextureFill
Definition: emfpbrush.hxx:88
static OUString BrushTypeToString(sal_uInt32 type)
Definition: emfpbrush.cxx:51
@ HatchStyleHorizontal
Definition: emfpbrush.hxx:29
int i
std::unique_ptr<::Color[]> surroundColors
Definition: emfpbrush.hxx:114
sal_uInt32 surroundColorsNumber
Definition: emfpbrush.hxx:113
virtual ~EMFPBrush() override
Definition: emfpbrush.cxx:47
std::unique_ptr< float[]> blendPositions
Definition: emfpbrush.hxx:108
void Read(SvStream &s, EmfPlusHelperData const &rR)
Definition: emfpbrush.cxx:64
sal_uInt32 additionalFlags
Definition: emfpbrush.hxx:99
std::unique_ptr< float[]> colorblendPositions
Definition: emfpbrush.hxx:111
std::unique_ptr< EMFPPath > path
Definition: emfpbrush.hxx:115
basegfx::B2DHomMatrix brush_transformation
Definition: emfpbrush.hxx:105
std::unique_ptr<::Color[]> colorblendColors
Definition: emfpbrush.hxx:112
EmfPlusHatchStyle hatchStyle
Definition: emfpbrush.hxx:116
static bool readXForm(SvStream &rIn, basegfx::B2DHomMatrix &rTarget)
ResultType type
size_t pos