nss: upgrade to release 3.73
[LibreOffice.git] / drawinglayer / source / tools / emfppen.cxx
blob60500b6bf7ecf88daffc172b51dfb3eec8e1206c
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 <com/sun/star/rendering/PathCapType.hpp>
21 #include <com/sun/star/rendering/PathJoinType.hpp>
22 #include <o3tl/safeint.hxx>
23 #include <sal/log.hxx>
24 #include <rtl/ustrbuf.hxx>
26 #include "emfppen.hxx"
27 #include "emfpcustomlinecap.hxx"
29 using namespace ::com::sun::star;
30 using namespace ::basegfx;
32 namespace emfplushelper
34 namespace {
36 enum EmfPlusPenData
38 PenDataTransform = 0x00000001,
39 PenDataStartCap = 0x00000002,
40 PenDataEndCap = 0x00000004,
41 PenDataJoin = 0x00000008,
42 PenDataMiterLimit = 0x00000010,
43 PenDataLineStyle = 0x00000020,
44 PenDataDashedLineCap = 0x00000040,
45 PenDataDashedLineOffset = 0x00000080,
46 PenDataDashedLine = 0x00000100,
47 PenDataAlignment = 0x00000200,
48 PenDataCompoundLine = 0x00000400,
49 PenDataCustomStartCap = 0x00000800,
50 PenDataCustomEndCap = 0x00001000
55 EMFPPen::EMFPPen()
56 : EMFPBrush()
57 , penDataFlags(0)
58 , penUnit(0)
59 , penWidth(0.0)
60 , startCap(0)
61 , endCap(0)
62 , lineJoin(0)
63 , miterLimit(0.0)
64 , dashStyle(0)
65 , dashCap(0)
66 , dashOffset(0.0)
67 , alignment(0)
68 , customStartCapLen(0)
69 , customEndCapLen(0)
73 EMFPPen::~EMFPPen()
77 static OUString PenDataFlagsToString(sal_uInt32 flags)
79 rtl::OUStringBuffer sFlags;
81 if (flags & EmfPlusPenDataTransform)
82 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataTransform");
84 if (flags & EmfPlusPenDataStartCap)
85 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataStartCap");
87 if (flags & EmfPlusPenDataEndCap)
88 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataEndCap");
90 if (flags & EmfPlusPenDataJoin)
91 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataJoin");
93 if (flags & EmfPlusPenDataMiterLimit)
94 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataMiterLimit");
96 if (flags & EmfPlusPenDataLineStyle)
97 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataLineStyle");
99 if (flags & EmfPlusPenDataDashedLineCap)
100 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataDashedLineCap");
102 if (flags & EmfPlusPenDataDashedLineOffset)
103 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataDashedLineOffset");
105 if (flags & EmfPlusPenDataDashedLine)
106 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataDashedLine");
108 if (flags & EmfPlusPenDataAlignment)
109 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataAlignment");
111 if (flags & EmfPlusPenDataCompoundLine)
112 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataCompoundLine");
114 if (flags & EmfPlusPenDataCustomStartCap)
115 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataCustomStartCap");
117 if (flags & EmfPlusPenDataCustomEndCap)
118 sFlags.append("\nEMF+\t\t\tEmfPlusPenDataCustomEndCap");
120 return sFlags.makeStringAndClear();
123 static OUString LineCapTypeToString(sal_uInt32 linecap)
125 switch (linecap)
127 case LineCapTypeFlat: return "LineCapTypeFlat";
128 case LineCapTypeSquare: return "LineCapTypeSquare";
129 case LineCapTypeRound: return "LineCapTypeRound";
130 case LineCapTypeTriangle: return "LineCapTypeTriangle";
131 case LineCapTypeNoAnchor: return "LineCapTypeNoAnchor";
132 case LineCapTypeSquareAnchor: return "LineCapTypeSquareAnchor";
133 case LineCapTypeRoundAnchor: return "LineCapTypeRoundAchor";
134 case LineCapTypeDiamondAnchor: return "LineCapTypeDiamondAnchor";
135 case LineCapTypeArrowAnchor: return "LineCapTypeArrowAnchor";
136 case LineCapTypeAnchorMask: return "LineCapTypeAnchorMask";
137 case LineCapTypeCustom: return "LineCapTypeCustom";
139 return "";
142 static OUString LineJoinTypeToString(sal_uInt32 jointype)
144 switch (jointype)
146 case LineJoinTypeMiter: return "LineJoinTypeMiter";
147 case LineJoinTypeBevel: return "LineJoinTypeBevel";
148 case LineJoinTypeRound: return "LineJoinTypeRound";
149 case LineJoinTypeMiterClipped: return "LineJoinTypeMiterClipped";
151 return "";
154 static OUString DashedLineCapTypeToString(sal_uInt32 dashedlinecaptype)
156 switch (dashedlinecaptype)
158 case DashedLineCapTypeFlat: return "DashedLineCapTypeFlat";
159 case DashedLineCapTypeRound: return "DashedLineCapTypeRound";
160 case DashedLineCapTypeTriangle: return "DashedLineCapTypeTriangle";
162 return "";
165 static OUString PenAlignmentToString(sal_uInt32 alignment)
167 switch (alignment)
169 case PenAlignmentCenter: return "PenAlignmentCenter";
170 case PenAlignmentInset: return "PenAlignmentInset";
171 case PenAlignmentLeft: return "PenAlignmentLeft";
172 case PenAlignmentOutset: return "PenAlignmentOutset";
173 case PenAlignmentRight: return "PenAlignmentRight";
175 return "";
178 /// Convert stroke caps between EMF+ and rendering API
179 sal_Int8 EMFPPen::lcl_convertStrokeCap(sal_uInt32 nEmfStroke)
181 switch (nEmfStroke)
183 case EmfPlusLineCapTypeSquare: return rendering::PathCapType::SQUARE;
184 case EmfPlusLineCapTypeRound: return rendering::PathCapType::ROUND;
187 // we have no mapping for EmfPlusLineCapTypeTriangle = 0x00000003,
188 // so return BUTT always
189 return rendering::PathCapType::BUTT;
192 sal_Int8 EMFPPen::lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin)
194 switch (nEmfLineJoin)
196 case EmfPlusLineJoinTypeMiter: // fall-through
197 case EmfPlusLineJoinTypeMiterClipped: return rendering::PathJoinType::MITER;
198 case EmfPlusLineJoinTypeBevel: return rendering::PathJoinType::BEVEL;
199 case EmfPlusLineJoinTypeRound: return rendering::PathJoinType::ROUND;
202 assert(false); // Line Join type isn't in specification.
203 return 0;
206 void EMFPPen::Read(SvStream& s, EmfPlusHelperData const & rR)
208 sal_uInt32 graphicsVersion, penType;
209 int i;
210 s.ReadUInt32(graphicsVersion).ReadUInt32(penType).ReadUInt32(penDataFlags).ReadUInt32(penUnit).ReadFloat(penWidth);
211 SAL_INFO("drawinglayer", "EMF+\t\tGraphics version: 0x" << std::hex << graphicsVersion);
212 SAL_INFO("drawinglayer", "EMF+\t\tType: " << penType);
213 SAL_INFO("drawinglayer", "EMF+\t\tPen data flags: 0x" << penDataFlags << PenDataFlagsToString(penDataFlags));
214 SAL_INFO("drawinglayer", "EMF+\t\tUnit: " << UnitTypeToString(penUnit));
215 SAL_INFO("drawinglayer", "EMF+\t\tWidth: " << std::dec << penWidth);
217 // If a zero width is specified, a minimum value must be used, which is determined by the units
218 if (penWidth == 0.0)
219 { //TODO Check if these values is correct
220 penWidth = penUnit == 0 ? 0.18f
221 : 0.05f; // 0.05f is taken from old EMF+ implementation (case of Unit == Pixel etc.)
224 if (penDataFlags & PenDataTransform)
226 EmfPlusHelperData::readXForm(s, pen_transformation);
227 SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataTransform: " << pen_transformation);
230 if (penDataFlags & PenDataStartCap)
232 s.ReadInt32(startCap);
233 SAL_INFO("drawinglayer", "EMF+\t\tstartCap: " << LineCapTypeToString(startCap) << " (0x" << std::hex << startCap << ")");
235 else
237 startCap = 0;
240 if (penDataFlags & PenDataEndCap)
242 s.ReadInt32(endCap);
243 SAL_INFO("drawinglayer", "EMF+\t\tendCap: " << LineCapTypeToString(endCap) << " (0x" << std::hex << startCap << ")");
245 else
247 endCap = 0;
250 if (penDataFlags & PenDataJoin)
252 s.ReadInt32(lineJoin);
253 SAL_WARN("drawinglayer", "EMF+\t\tTODO PenDataJoin: " << LineJoinTypeToString(lineJoin) << " (0x" << std::hex << lineJoin << ")");
255 else
257 lineJoin = 0;
260 if (penDataFlags & PenDataMiterLimit)
262 s.ReadFloat(miterLimit);
263 SAL_WARN("drawinglayer", "EMF+\t\tTODO PenDataMiterLimit: " << std::dec << miterLimit);
265 else
267 miterLimit = 0;
270 if (penDataFlags & PenDataLineStyle)
272 s.ReadInt32(dashStyle);
273 SAL_INFO("drawinglayer", "EMF+\t\tdashStyle: " << DashedLineCapTypeToString(dashStyle) << " (0x" << std::hex << dashStyle << ")");
275 else
277 dashStyle = 0;
280 if (penDataFlags & PenDataDashedLineCap)
282 s.ReadInt32(dashCap);
283 SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataDashedLineCap: 0x" << std::hex << dashCap);
285 else
287 dashCap = 0;
290 if (penDataFlags & PenDataDashedLineOffset)
292 s.ReadFloat(dashOffset);
293 SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataDashedLineOffset: 0x" << std::hex << dashOffset);
295 else
297 dashOffset = 0;
300 if (penDataFlags & PenDataDashedLine)
302 dashStyle = EmfPlusLineStyleCustom;
303 sal_Int32 dashPatternLen;
305 s.ReadInt32(dashPatternLen);
306 SAL_INFO("drawinglayer", "EMF+\t\t\tdashPatternLen: " << dashPatternLen);
308 if (dashPatternLen<0 || o3tl::make_unsigned(dashPatternLen)>SAL_MAX_INT32 / sizeof(float))
310 dashPatternLen = SAL_MAX_INT32 / sizeof(float);
313 dashPattern.resize( dashPatternLen );
315 for (i = 0; i < dashPatternLen; i++)
317 s.ReadFloat(dashPattern[i]);
318 SAL_INFO("drawinglayer", "EMF+\t\t\t\tdashPattern[" << i << "]: " << dashPattern[i]);
322 if (penDataFlags & PenDataAlignment)
324 s.ReadInt32(alignment);
325 SAL_WARN("drawinglayer", "EMF+\t\t\tTODO PenDataAlignment: " << PenAlignmentToString(alignment) << " (0x" << std::hex << alignment << ")");
327 else
329 alignment = 0;
332 if (penDataFlags & PenDataCompoundLine)
334 SAL_WARN("drawinglayer", "EMF+\t\t\tTODO PenDataCompoundLine");
335 sal_Int32 compoundArrayLen;
336 s.ReadInt32(compoundArrayLen);
338 if (compoundArrayLen<0 || o3tl::make_unsigned(compoundArrayLen)>SAL_MAX_INT32 / sizeof(float))
340 compoundArrayLen = SAL_MAX_INT32 / sizeof(float);
343 compoundArray.resize(compoundArrayLen);
345 for (i = 0; i < compoundArrayLen; i++)
347 s.ReadFloat(compoundArray[i]);
348 SAL_INFO("drawinglayer", "EMF+\t\t\t\tcompoundArray[" << i << "]: " << compoundArray[i]);
352 if (penDataFlags & PenDataCustomStartCap)
354 s.ReadInt32(customStartCapLen);
355 SAL_INFO("drawinglayer", "EMF+\t\t\tcustomStartCapLen: " << customStartCapLen);
356 sal_uInt64 const pos = s.Tell();
358 customStartCap.reset( new EMFPCustomLineCap() );
359 customStartCap->Read(s, rR);
361 // maybe we don't read everything yet, play it safe ;-)
362 s.Seek(pos + customStartCapLen);
364 else
366 customStartCapLen = 0;
369 if (penDataFlags & PenDataCustomEndCap)
371 s.ReadInt32(customEndCapLen);
372 SAL_INFO("drawinglayer", "EMF+\t\t\tcustomEndCapLen: " << customEndCapLen);
373 sal_uInt64 const pos = s.Tell();
375 customEndCap.reset( new EMFPCustomLineCap() );
376 customEndCap->Read(s, rR);
378 // maybe we don't read everything yet, play it safe ;-)
379 s.Seek(pos + customEndCapLen);
381 else
383 customEndCapLen = 0;
386 EMFPBrush::Read(s, rR);
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */