1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
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
68 , customStartCapLen(0)
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
)
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";
142 static OUString
LineJoinTypeToString(sal_uInt32 jointype
)
146 case LineJoinTypeMiter
: return "LineJoinTypeMiter";
147 case LineJoinTypeBevel
: return "LineJoinTypeBevel";
148 case LineJoinTypeRound
: return "LineJoinTypeRound";
149 case LineJoinTypeMiterClipped
: return "LineJoinTypeMiterClipped";
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";
165 static OUString
PenAlignmentToString(sal_uInt32 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";
178 /// Convert stroke caps between EMF+ and rendering API
179 sal_Int8
EMFPPen::lcl_convertStrokeCap(sal_uInt32 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.
206 void EMFPPen::Read(SvStream
& s
, EmfPlusHelperData
const & rR
)
208 sal_uInt32 graphicsVersion
, penType
;
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
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
<< ")");
240 if (penDataFlags
& PenDataEndCap
)
243 SAL_INFO("drawinglayer", "EMF+\t\tendCap: " << LineCapTypeToString(endCap
) << " (0x" << std::hex
<< startCap
<< ")");
250 if (penDataFlags
& PenDataJoin
)
252 s
.ReadInt32(lineJoin
);
253 SAL_WARN("drawinglayer", "EMF+\t\tTODO PenDataJoin: " << LineJoinTypeToString(lineJoin
) << " (0x" << std::hex
<< lineJoin
<< ")");
260 if (penDataFlags
& PenDataMiterLimit
)
262 s
.ReadFloat(miterLimit
);
263 SAL_WARN("drawinglayer", "EMF+\t\tTODO PenDataMiterLimit: " << std::dec
<< miterLimit
);
270 if (penDataFlags
& PenDataLineStyle
)
272 s
.ReadInt32(dashStyle
);
273 SAL_INFO("drawinglayer", "EMF+\t\tdashStyle: " << DashedLineCapTypeToString(dashStyle
) << " (0x" << std::hex
<< dashStyle
<< ")");
280 if (penDataFlags
& PenDataDashedLineCap
)
282 s
.ReadInt32(dashCap
);
283 SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataDashedLineCap: 0x" << std::hex
<< dashCap
);
290 if (penDataFlags
& PenDataDashedLineOffset
)
292 s
.ReadFloat(dashOffset
);
293 SAL_WARN("drawinglayer", "EMF+\t\t TODO PenDataDashedLineOffset: 0x" << std::hex
<< dashOffset
);
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
<< ")");
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
);
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
);
386 EMFPBrush::Read(s
, rR
);
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */