/src/libreoffice/emfio/inc/mtftools.hxx
Line | Count | Source |
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 | | #pragma once |
20 | | |
21 | | #include <basegfx/utils/b2dclipstate.hxx> |
22 | | #include <basegfx/vector/b2enums.hxx> |
23 | | #include <tools/poly.hxx> |
24 | | #include <vcl/font.hxx> |
25 | | #include <vcl/bitmap.hxx> |
26 | | #include <vcl/lineinfo.hxx> |
27 | | #include <vcl/rendercontext/State.hxx> |
28 | | #include <vcl/hatch.hxx> |
29 | | #include <vcl/metaact.hxx> |
30 | | #include <rtl/ref.hxx> |
31 | | |
32 | | #include <com/sun/star/drawing/LineCap.hpp> |
33 | | |
34 | | #include "emfiodllapi.h" |
35 | | |
36 | | namespace emfio |
37 | | { |
38 | | /* [MS-EMF] - v20210625 - pages 43, 107 */ |
39 | | enum class RegionMode : sal_uInt32 |
40 | | { |
41 | | RGN_AND = 0x01, |
42 | | RGN_OR = 0x02, |
43 | | RGN_XOR = 0x03, |
44 | | RGN_DIFF = 0x04, |
45 | | RGN_COPY = 0x05 |
46 | | }; |
47 | | |
48 | | /* [MS-EMF] - v20210625 - pages 40, 198 */ |
49 | | enum class BackgroundMode : sal_uInt32 |
50 | | { |
51 | | NONE = 0, |
52 | | Transparent = 1, |
53 | | OPAQUE = 2, |
54 | | }; |
55 | | |
56 | | /* [MS-EMF] - v20210625 - pages 40, 210 */ |
57 | | /* xform stuff */ |
58 | | enum class ModifyWorldTransformMode : sal_uInt32 |
59 | | { |
60 | | MWT_IDENTITY = 0x01, |
61 | | MWT_LEFTMULTIPLY = 0x02, |
62 | | MWT_RIGHTMULTIPLY = 0x03, |
63 | | MWT_SET = 0x04 |
64 | | }; |
65 | | |
66 | | constexpr sal_uInt32 ENHMETA_STOCK_OBJECT = 0x80000000; |
67 | | |
68 | | /* [MS-EMF] - v20210625 - pages 44, 45, 182 */ |
69 | | /* Stock Logical Objects */ |
70 | | enum class StockObject : sal_uInt32 |
71 | | { |
72 | | WHITE_BRUSH = 0, |
73 | | LTGRAY_BRUSH = 1, |
74 | | GRAY_BRUSH = 2, |
75 | | DKGRAY_BRUSH = 3, |
76 | | BLACK_BRUSH = 4, |
77 | | NULL_BRUSH = 5, |
78 | | WHITE_PEN = 6, |
79 | | BLACK_PEN = 7, |
80 | | NULL_PEN = 8, |
81 | | ANSI_FIXED_FONT = 11, |
82 | | ANSI_VAR_FONT = 12, |
83 | | SYSTEM_FIXED_FONT = 16 |
84 | | }; |
85 | | |
86 | | /* Note: This enum is incomplete compared to the specification */ |
87 | | /* [MS-WMF] - v20210625 - pages 25-26 */ |
88 | | enum class WMFRasterOp : sal_uInt16 |
89 | | { |
90 | | NONE = 0, |
91 | | Black = 1, |
92 | | Not = 6, |
93 | | XorPen = 7, |
94 | | Nop = 11, |
95 | | CopyPen = 13 |
96 | | }; |
97 | | |
98 | | /* Note: We have MapMode elsewhere, so we use MappingMode instead */ |
99 | | /* [MS-EMF] - v20210625 - pages 38-50, 202 */ |
100 | | /* Mapping modes */ |
101 | | enum MappingMode : sal_uInt32 |
102 | | { |
103 | | MM_TEXT = 0x01, |
104 | | MM_LOMETRIC = 0x02, |
105 | | MM_HIMETRIC = 0x03, |
106 | | MM_LOENGLISH = 0x04, |
107 | | MM_HIENGLISH = 0x05, |
108 | | MM_TWIPS = 0x06, |
109 | | MM_ISOTROPIC = 0x07, |
110 | | MM_ANISOTROPIC = 0x08 |
111 | | }; |
112 | | |
113 | | /* Note: No type is specified, but 32-bit unsigned is used to provide |
114 | | * to match the number of bits in the binary literal, and also the |
115 | | * previous definition of SetGfxMode() and GetGfxMode() functions */ |
116 | | /* [MS-EMF] - v20210625 - pages 35 */ |
117 | | /* Graphics modes */ |
118 | | enum class GraphicsMode : sal_uInt32 |
119 | | { |
120 | | GM_COMPATIBLE = 0x00000001, |
121 | | GM_ADVANCED = 0x00000002 |
122 | | } ; |
123 | | |
124 | | /* [MS-WMF] - v20210625 - pages 46 */ |
125 | | /* StretchBlt() modes */ |
126 | | enum class StretchMode : sal_uInt16 |
127 | | { |
128 | | BLACKONWHITE = 0x0001, |
129 | | WHITEONBLACK = 0x0002, |
130 | | COLORONCOLOR = 0x0003, |
131 | | HALFTONE = 0x0004, |
132 | | STRETCH_ANDSCANS = BLACKONWHITE, |
133 | | STRETCH_ORSCANS = WHITEONBLACK, |
134 | | STRETCH_DELETESCANS = COLORONCOLOR |
135 | | }; |
136 | | |
137 | | constexpr sal_Int32 LF_FACESIZE = 32; |
138 | | |
139 | | struct LOGFONTW |
140 | | { |
141 | | sal_Int32 lfHeight; |
142 | | sal_Int32 lfWidth; |
143 | | sal_Int32 lfEscapement; |
144 | | sal_Int32 lfOrientation; |
145 | | sal_Int32 lfWeight; |
146 | | sal_uInt8 lfItalic; |
147 | | sal_uInt8 lfUnderline; |
148 | | sal_uInt8 lfStrikeOut; |
149 | | sal_uInt8 lfCharSet; |
150 | | sal_uInt8 lfOutPrecision; |
151 | | sal_uInt8 lfClipPrecision; |
152 | | sal_uInt8 lfQuality; |
153 | | sal_uInt8 lfPitchAndFamily; |
154 | | OUString alfFaceName; |
155 | | LOGFONTW() |
156 | 21.4k | : lfHeight(0) |
157 | 21.4k | , lfWidth(0) |
158 | 21.4k | , lfEscapement(0) |
159 | 21.4k | , lfOrientation(0) |
160 | 21.4k | , lfWeight(0) |
161 | 21.4k | , lfItalic(0) |
162 | 21.4k | , lfUnderline(0) |
163 | 21.4k | , lfStrikeOut(0) |
164 | 21.4k | , lfCharSet(0) |
165 | 21.4k | , lfOutPrecision(0) |
166 | 21.4k | , lfClipPrecision(0) |
167 | 21.4k | , lfQuality(0) |
168 | 21.4k | , lfPitchAndFamily(0) |
169 | 21.4k | { |
170 | 21.4k | } |
171 | | }; |
172 | | |
173 | | /* [MS-WMF] - v20210625 - pages 153 */ |
174 | | enum TextAlignmentMode : sal_uInt16 |
175 | | { |
176 | | TA_NOUPDATECP = 0x0000, |
177 | | TA_UPDATECP = 0x0001, |
178 | | TA_LEFT = 0x0000, |
179 | | TA_RIGHT = 0x0002, |
180 | | TA_CENTER = 0x0006, |
181 | | TA_RIGHT_CENTER = (TA_RIGHT | TA_CENTER), |
182 | | TA_TOP = 0x0000, |
183 | | TA_BOTTOM = 0x0008, |
184 | | // In [MS-WMF] 2.1.2.3, TA_BASELINE value is wrong. |
185 | | // It is 0x0018 and it should be 0x0010. |
186 | | TA_BASELINE = 0x0010, |
187 | | TA_RTLREADING = 0x0100 |
188 | | }; |
189 | | |
190 | | /* Note: This enum is incomplete compared to the specification */ |
191 | | /* [MS-EMF] - v20210625 - pages 47-50, 126 */ |
192 | | /* Ternary raster operations */ |
193 | | enum TernaryRasterOperation : sal_uInt32 |
194 | | { |
195 | | SRCCOPY = 0x00CC0020L, |
196 | | SRCPAINT = 0x00EE0086L, |
197 | | SRCAND = 0x008800C6L, |
198 | | SRCINVERT = 0x00660046L, |
199 | | SRCERASE = 0x00440328L, |
200 | | PATCOPY = 0x00F00021L, |
201 | | PATINVERT = 0x005A0049L, |
202 | | BLACKNESS = 0x00000042L, |
203 | | WHITENESS = 0x00FF0062L |
204 | | }; |
205 | | |
206 | | /* [MS-EMF] - v20210625 - pages 40, 41, 65 */ |
207 | | enum PenStyle : sal_uInt32 |
208 | | { |
209 | | PS_COSMETIC = 0x00000000, |
210 | | PS_GEOMETRIC = 0x00010000, |
211 | | |
212 | | PS_SOLID = 0x00000000, |
213 | | PS_DASH = 0x00000001, |
214 | | PS_DOT = 0x00000002, |
215 | | PS_DASHDOT = 0x00000003, |
216 | | PS_DASHDOTDOT = 0x00000004, |
217 | | PS_NULL = 0x00000005, |
218 | | PS_INSIDEFRAME = 0x00000006, |
219 | | PS_USERSTYLE = 0x00000007, |
220 | | PS_ALTERNATE = 0x00000008, |
221 | | PS_STYLE_MASK = 0x0000000F, |
222 | | |
223 | | PS_ENDCAP_ROUND = 0x00000000, |
224 | | PS_ENDCAP_SQUARE = 0x00000100, |
225 | | PS_ENDCAP_FLAT = 0x00000200, |
226 | | PS_ENDCAP_STYLE_MASK = 0x00000F00, |
227 | | |
228 | | PS_JOIN_ROUND = 0x00000000, |
229 | | PS_JOIN_BEVEL = 0x00001000, |
230 | | PS_JOIN_MITER = 0x00002000, |
231 | | PS_JOIN_STYLE_MASK = 0x0000F000 |
232 | | }; |
233 | | |
234 | | /* [MS-WMF] - v20210625 - pages 30, 82 */ |
235 | | /* Character Sets */ |
236 | | enum CharacterSet : sal_uInt8 |
237 | | { |
238 | | ANSI_CHARSET = 0x00000000, |
239 | | DEFAULT_CHARSET = 0x00000001, |
240 | | SYMBOL_CHARSET = 0x00000002, |
241 | | SHIFTJIS_CHARSET = 0x00000080, |
242 | | HANGUL_CHARSET = 0x00000081, |
243 | | GB2312_CHARSET = 0x00000086, |
244 | | CHINESEBIG5_CHARSET = 0x00000088, |
245 | | OEM_CHARSET = 0x000000FF, |
246 | | /* WINVER >= 0x0400 */ |
247 | | MAC_CHARSET = 0x0000004D, |
248 | | JOHAB_CHARSET = 0x00000082, |
249 | | GREEK_CHARSET = 0x000000A1, |
250 | | TURKISH_CHARSET = 0x000000A2, |
251 | | VIETNAMESE_CHARSET = 0x000000A3, |
252 | | HEBREW_CHARSET = 0x000000B1, |
253 | | ARABIC_CHARSET = 0x000000B2, |
254 | | BALTIC_CHARSET = 0x000000BA, |
255 | | RUSSIAN_CHARSET = 0x000000CC, |
256 | | THAI_CHARSET = 0x000000DE, |
257 | | EASTEUROPE_CHARSET = 0x000000EE |
258 | | }; |
259 | | |
260 | | /* Note: This enum is incomplete compared to the specification */ |
261 | | /* [MS-EMF] - v20210625 - pages 32, 283 */ |
262 | | enum ExtTextOutOptions : sal_uInt32 |
263 | | { |
264 | | ETO_OPAQUE = 0x0002, |
265 | | ETO_CLIPPED = 0x0004, |
266 | | /* WINVER >= 0x0400 */ |
267 | | ETO_GLYPH_INDEX = 0x0010, |
268 | | ETO_RTLREADING = 0x0080, |
269 | | /* _WIN32_WINNT >= 0x0500 */ |
270 | | ETO_NO_RECT = 0x0100, |
271 | | ETO_SMALL_CHARS = 0x0200, |
272 | | ETO_PDY = 0x2000 |
273 | | }; |
274 | | |
275 | | /* [MS-WMF] - v20210625 - pages 44, 96 */ |
276 | | /* This is packed into a byte as 2 bits */ |
277 | | enum PitchFont : sal_uInt8 |
278 | | { |
279 | | DEFAULT_PITCH = 0, |
280 | | FIXED_PITCH = 1, |
281 | | VARIABLE_PITCH = 2 |
282 | | }; |
283 | | |
284 | | /* [MS-WMF] - v20210625 - pages 33, */ |
285 | | enum FamilyFont : sal_uInt8 |
286 | | { |
287 | | FF_DONTCARE = 0x00, |
288 | | FF_ROMAN = 0x01, |
289 | | FF_SWISS = 0x02, |
290 | | FF_MODERN = 0x03, |
291 | | FF_SCRIPT = 0x04, |
292 | | FF_DECORATIVE = 0x05 |
293 | | }; |
294 | | |
295 | | enum WeightFont |
296 | | { |
297 | | FW_THIN = 100, |
298 | | FW_EXTRALIGHT = 200, |
299 | | FW_LIGHT = 300, |
300 | | FW_NORMAL = 400, |
301 | | FW_MEDIUM = 500, |
302 | | FW_SEMIBOLD = 600, |
303 | | FW_BOLD = 700, |
304 | | FW_EXTRABOLD = 800, |
305 | | FW_ULTRALIGHT = 200, |
306 | | FW_ULTRABOLD = 800, |
307 | | FW_BLACK = 900 |
308 | | }; |
309 | | |
310 | | /* [MS-WMF] - v20210625 - pages 29, 30, 182 */ |
311 | | enum class BrushStyle : sal_uInt16 |
312 | | { |
313 | | BS_SOLID = 0, |
314 | | BS_NULL = 1, |
315 | | BS_HOLLOW = 1, |
316 | | BS_HATCHED = 2, |
317 | | BS_PATTERN = 3, |
318 | | BS_INDEXED = 4, |
319 | | BS_DIBPATTERN = 5, |
320 | | BS_DIBPATTERNPT = 6, |
321 | | BS_PATTERN8X8 = 7, |
322 | | BS_DIBPATTERN8X8 = 8, |
323 | | BS_MONOPATTERN = 9 |
324 | | }; |
325 | | |
326 | | constexpr sal_Int32 RDH_RECTANGLES = 1; |
327 | | constexpr sal_Int32 W_MFCOMMENT = 15; |
328 | | constexpr sal_Int32 PRIVATE_ESCAPE_UNICODE = 2; |
329 | | |
330 | | //Scalar constants |
331 | | constexpr sal_Int32 UNDOCUMENTED_WIN_RCL_RELATION = 32; |
332 | | constexpr sal_Int32 MS_FIXPOINT_BITCOUNT_28_4 = 4; |
333 | | |
334 | | /** Map a Windows hatch index (HS_*) to a VCL Hatch. |
335 | | * [MS-WMF] 2.1.1.12 HatchStyle Enumeration */ |
336 | | Hatch mapWindowsHatch(sal_uInt32 nHatchIndex, const Color& rColor); |
337 | | } |
338 | | |
339 | | //============================ WmfReader ================================== |
340 | | |
341 | | namespace emfio |
342 | | { |
343 | | class WinMtfClipPath |
344 | | { |
345 | | basegfx::utils::B2DClipState maClip; |
346 | | |
347 | | public: |
348 | 103k | WinMtfClipPath() : maClip() {}; |
349 | | |
350 | | void setClipPath(const basegfx::B2DPolyPolygon&, RegionMode nClippingMode); |
351 | | void intersectClip(const basegfx::B2DPolyPolygon& rPolyPolygon); |
352 | | void excludeClip(const basegfx::B2DPolyPolygon& rPolyPolygon); |
353 | | void moveClipRegion(const Size& rSize); |
354 | | void setDefaultClipPath(); |
355 | | |
356 | 12.1k | bool isEmpty() const { return maClip.isCleared(); } |
357 | | |
358 | 0 | basegfx::utils::B2DClipState const & getClip() const { return maClip; } |
359 | | basegfx::B2DPolyPolygon const & getClipPath() const; |
360 | | |
361 | | bool operator==(const WinMtfClipPath& rPath) const |
362 | 67.9k | { |
363 | 67.9k | return maClip == rPath.maClip; |
364 | 67.9k | }; |
365 | | }; |
366 | | |
367 | | class WinMtfPathObj : public tools::PolyPolygon |
368 | | { |
369 | | bool bClosed; |
370 | | |
371 | | public: |
372 | | |
373 | | WinMtfPathObj() : |
374 | 103k | bClosed(true) |
375 | 103k | {} |
376 | | |
377 | | void Init() |
378 | 8.69k | { |
379 | 8.69k | Clear(); |
380 | 8.69k | bClosed = true; |
381 | 8.69k | } |
382 | | |
383 | | void ClosePath(); |
384 | | void AddPoint(const Point& rPoint); |
385 | | void AddPolygon(const tools::Polygon& rPoly); |
386 | | void AddPolyLine(const tools::Polygon& rPoly); |
387 | | void AddPolyPolygon(const tools::PolyPolygon& rPolyPolygon); |
388 | | }; |
389 | | |
390 | | struct EMFIO_DLLPUBLIC GDIObj |
391 | | { |
392 | 587k | GDIObj() = default; |
393 | 2.96k | GDIObj(GDIObj const &) = default; |
394 | 590k | virtual ~GDIObj() = default; // Polymorphic base class |
395 | 538k | GDIObj & operator =(GDIObj const &) = default; |
396 | | }; |
397 | | |
398 | | struct EMFIO_DLLPUBLIC WinMtfFontStyle final : GDIObj |
399 | | { |
400 | | vcl::Font aFont; |
401 | | |
402 | | explicit WinMtfFontStyle(LOGFONTW const & rLogFont); |
403 | | |
404 | | ~WinMtfFontStyle() override; |
405 | | }; |
406 | | |
407 | | enum class WinMtfFillStyleType |
408 | | { |
409 | | Solid, Pattern, Hatch |
410 | | }; |
411 | | |
412 | | struct WinMtfFillStyle final : GDIObj |
413 | | { |
414 | | Color aFillColor; |
415 | | bool bTransparent; |
416 | | WinMtfFillStyleType aType; |
417 | | Bitmap aBmp; |
418 | | Hatch aHatch; |
419 | | |
420 | | WinMtfFillStyle() |
421 | 145k | : aFillColor(COL_BLACK) |
422 | 145k | , bTransparent(false) |
423 | 145k | , aType(WinMtfFillStyleType::Solid) |
424 | 145k | {} |
425 | | |
426 | | WinMtfFillStyle(const Color& rColor, bool bTrans = false) |
427 | 157k | : aFillColor(rColor) |
428 | 157k | , bTransparent(bTrans) |
429 | 157k | , aType(WinMtfFillStyleType::Solid) |
430 | 157k | {} |
431 | | |
432 | | explicit WinMtfFillStyle(Bitmap const & rBmp) |
433 | 17.9k | : bTransparent(false) |
434 | 17.9k | , aType(WinMtfFillStyleType::Pattern) |
435 | 17.9k | , aBmp(rBmp) |
436 | 17.9k | {} |
437 | | |
438 | | WinMtfFillStyle(const Color& rColor, const Hatch& rHatch) |
439 | 32 | : aFillColor(rColor) |
440 | 32 | , bTransparent(false) |
441 | 32 | , aType(WinMtfFillStyleType::Hatch) |
442 | 32 | , aHatch(rHatch) |
443 | 32 | {} |
444 | | |
445 | | bool operator==(const WinMtfFillStyle& rStyle) const |
446 | 125k | { |
447 | 125k | return aFillColor == rStyle.aFillColor |
448 | 116k | && bTransparent == rStyle.bTransparent |
449 | 116k | && aType == rStyle.aType |
450 | 114k | && aHatch == rStyle.aHatch |
451 | 114k | && aBmp == rStyle.aBmp; |
452 | 125k | } |
453 | | }; |
454 | | |
455 | | |
456 | | struct WinMtfPalette final : GDIObj |
457 | | { |
458 | | std::vector< Color > aPaletteColors; |
459 | | |
460 | | WinMtfPalette() |
461 | 20.8k | : aPaletteColors(std::vector< Color >{}) |
462 | 20.8k | {} |
463 | | |
464 | | WinMtfPalette(std::vector<Color> paletteColors) |
465 | 3.23k | : aPaletteColors(std::move(paletteColors)) |
466 | 3.23k | {} |
467 | | |
468 | | }; |
469 | | |
470 | | |
471 | | struct WinMtfLineStyle final : GDIObj |
472 | | { |
473 | | Color aLineColor; |
474 | | LineInfo aLineInfo; |
475 | | bool bTransparent; |
476 | | bool bHasHatch; |
477 | | Hatch aHatch; |
478 | | |
479 | | WinMtfLineStyle() |
480 | 145k | : aLineColor(COL_BLACK) |
481 | 145k | , bTransparent(false) |
482 | 145k | , bHasHatch(false) |
483 | 145k | {} |
484 | | |
485 | | WinMtfLineStyle(const Color& rColor, bool bTrans = false) |
486 | 61.9k | : aLineColor(rColor) |
487 | 61.9k | , bTransparent(bTrans) |
488 | 61.9k | , bHasHatch(false) |
489 | 61.9k | {} |
490 | | |
491 | | WinMtfLineStyle(const Color& rColor, const sal_uInt32 nStyle, const sal_uInt32 nPenWidth) |
492 | 10.7k | : aLineColor(rColor) |
493 | 10.7k | , bHasHatch(false) |
494 | 10.7k | { |
495 | | // According to documentation: nStyle = PS_COSMETIC = 0x0 - line with a width of one logical unit and a style that is a solid color |
496 | | // tdf#140271 Based on observed behaviour the line width is not constant with PS_COSMETIC |
497 | | |
498 | | // Width 0 means default width for LineInfo (HairLine) with 1 pixel wide |
499 | 10.7k | aLineInfo.SetWidth(nPenWidth); |
500 | 10.7k | switch (nStyle & PS_STYLE_MASK) |
501 | 10.7k | { |
502 | 816 | case PS_DASHDOTDOT: |
503 | 816 | aLineInfo.SetStyle(LineStyle::Dash); |
504 | 816 | aLineInfo.SetDashCount(1); |
505 | 816 | aLineInfo.SetDotCount(2); |
506 | 816 | break; |
507 | 623 | case PS_DASHDOT: |
508 | 623 | aLineInfo.SetStyle(LineStyle::Dash); |
509 | 623 | aLineInfo.SetDashCount(1); |
510 | 623 | aLineInfo.SetDotCount(1); |
511 | 623 | break; |
512 | 352 | case PS_DOT: |
513 | 352 | aLineInfo.SetStyle(LineStyle::Dash); |
514 | 352 | aLineInfo.SetDashCount(0); |
515 | 352 | aLineInfo.SetDotCount(1); |
516 | 352 | break; |
517 | 1.03k | case PS_DASH: |
518 | 1.03k | aLineInfo.SetStyle(LineStyle::Dash); |
519 | 1.03k | aLineInfo.SetDashCount(1); |
520 | 1.03k | aLineInfo.SetDotCount(0); |
521 | 1.03k | break; |
522 | 291 | case PS_NULL: |
523 | 291 | aLineInfo.SetStyle(LineStyle::NONE); |
524 | 291 | break; |
525 | 314 | case PS_INSIDEFRAME: // TODO Implement PS_INSIDEFRAME |
526 | 7.35k | case PS_SOLID: |
527 | 7.64k | default: |
528 | 7.64k | aLineInfo.SetStyle(LineStyle::Solid); |
529 | 10.7k | } |
530 | 10.7k | if (nPenWidth) |
531 | 7.71k | switch (nStyle & PS_ENDCAP_STYLE_MASK) |
532 | 7.71k | { |
533 | 5.84k | case PS_ENDCAP_ROUND: |
534 | 5.84k | aLineInfo.SetLineCap(css::drawing::LineCap_ROUND); |
535 | 5.84k | break; |
536 | 486 | case PS_ENDCAP_SQUARE: |
537 | 486 | aLineInfo.SetLineCap(css::drawing::LineCap_SQUARE); |
538 | 486 | break; |
539 | 109 | case PS_ENDCAP_FLAT: |
540 | 1.38k | default: |
541 | 1.38k | aLineInfo.SetLineCap(css::drawing::LineCap_BUTT); |
542 | 7.71k | } |
543 | 3.05k | else |
544 | 3.05k | aLineInfo.SetLineCap(css::drawing::LineCap_BUTT); |
545 | 10.7k | switch (nStyle & PS_JOIN_STYLE_MASK) |
546 | 10.7k | { |
547 | 8.25k | case PS_JOIN_ROUND: |
548 | 8.25k | aLineInfo.SetLineJoin(basegfx::B2DLineJoin::Round); |
549 | 8.25k | break; |
550 | 493 | case PS_JOIN_BEVEL: |
551 | 493 | aLineInfo.SetLineJoin(basegfx::B2DLineJoin::Bevel); |
552 | 493 | break; |
553 | | // Undocumented but based on experiments with MS Paint and MS Word, |
554 | | // the default Join Style is PS_JOIN_MITER |
555 | 638 | case PS_JOIN_MITER: |
556 | 2.01k | default: |
557 | 2.01k | aLineInfo.SetLineJoin(basegfx::B2DLineJoin::Miter); |
558 | 10.7k | } |
559 | 10.7k | bTransparent = aLineInfo.GetStyle() == LineStyle::NONE; |
560 | 10.7k | } |
561 | | |
562 | | bool operator==(const WinMtfLineStyle& rStyle) const |
563 | 115k | { |
564 | 115k | return aLineColor == rStyle.aLineColor |
565 | 83.5k | && bTransparent == rStyle.bTransparent |
566 | 83.1k | && aLineInfo == rStyle.aLineInfo |
567 | 82.0k | && bHasHatch == rStyle.bHasHatch |
568 | 82.0k | && aHatch == rStyle.aHatch; |
569 | 115k | } |
570 | | }; |
571 | | |
572 | | struct XForm |
573 | | { |
574 | | float eM11; |
575 | | float eM12; |
576 | | float eM21; |
577 | | float eM22; |
578 | | float eDx; |
579 | | float eDy; |
580 | | |
581 | | XForm() |
582 | 170k | : eM11(1.0f) |
583 | 170k | , eM12(0.0f) |
584 | 170k | , eM21(0.0f) |
585 | 170k | , eM22(1.0f) |
586 | 170k | , eDx(0.0f) |
587 | 170k | , eDy(0.0f) |
588 | 170k | {} |
589 | | }; |
590 | | |
591 | | SvStream& operator >> (SvStream& rInStream, XForm& rXForm); |
592 | | |
593 | | struct SaveStruct |
594 | | { |
595 | | BackgroundMode nBkMode; |
596 | | MappingMode eMapMode; |
597 | | GraphicsMode eGfxMode; |
598 | | vcl::text::ComplexTextLayoutFlags nTextLayoutMode; |
599 | | sal_Int32 nWinOrgX, nWinOrgY, nWinExtX, nWinExtY; |
600 | | sal_Int32 nDevOrgX, nDevOrgY, nDevWidth, nDevHeight; |
601 | | |
602 | | WinMtfLineStyle aLineStyle; |
603 | | WinMtfFillStyle aFillStyle; |
604 | | |
605 | | vcl::Font aFont; |
606 | | Color aBkColor; |
607 | | Color aTextColor; |
608 | | sal_uInt32 nTextAlign; |
609 | | RasterOp eRasterOp; |
610 | | |
611 | | Point aActPos; |
612 | | WinMtfPathObj maPathObj; |
613 | | WinMtfClipPath maClipPath; |
614 | | XForm aXForm; |
615 | | |
616 | | bool bClockWiseArcDirection; |
617 | | bool bFillStyleSelected; |
618 | | sal_uInt32 nPolyFillMode; |
619 | | }; |
620 | | |
621 | | struct BSaveStruct |
622 | | { |
623 | | Bitmap aBmp; |
624 | | tools::Rectangle aOutRect; |
625 | | sal_uInt32 nWinRop; |
626 | | bool m_bForceAlpha = false; |
627 | | |
628 | | BSaveStruct(const Bitmap& rBmp, const tools::Rectangle& rOutRect, sal_uInt32 nRop, |
629 | | bool bForceAlpha = false) |
630 | 64.5k | : aBmp(rBmp) |
631 | 64.5k | , aOutRect(rOutRect) |
632 | 64.5k | , nWinRop(nRop) |
633 | 64.5k | , m_bForceAlpha(bForceAlpha) |
634 | 64.5k | {} |
635 | | }; |
636 | | |
637 | | // tdf#127471 implement detection and correction of wrongly scaled |
638 | | // fonts in own-written, old (before this fix) EMF/WMF files |
639 | | class ScaledFontDetectCorrectHelper |
640 | | { |
641 | | private: |
642 | | rtl::Reference<MetaFontAction> maCurrentMetaFontAction; |
643 | | std::vector<double> maAlternativeFontScales; |
644 | | std::vector<std::pair<rtl::Reference<MetaFontAction>, double>> maPositiveIdentifiedCases; |
645 | | std::vector<std::pair<rtl::Reference<MetaFontAction>, double>> maNegativeIdentifiedCases; |
646 | | |
647 | | public: |
648 | | ScaledFontDetectCorrectHelper(); |
649 | | void endCurrentMetaFontAction(); |
650 | | void newCurrentMetaFontAction(const rtl::Reference<MetaFontAction>& rNewMetaFontAction); |
651 | | void evaluateAlternativeFontScale(OUString const & rText, tools::Long nImportedTextLength); |
652 | | void applyAlternativeFontScale(); |
653 | | }; |
654 | | |
655 | | class MtfTools |
656 | | { |
657 | | MtfTools(MtfTools const &) = delete; |
658 | | MtfTools& operator =(MtfTools const &) = delete; |
659 | | |
660 | | protected: |
661 | | WinMtfPathObj maPathObj; |
662 | | WinMtfClipPath maClipPath; |
663 | | |
664 | | WinMtfLineStyle maLatestLineStyle; |
665 | | WinMtfLineStyle maLineStyle; |
666 | | WinMtfLineStyle maNopLineStyle; |
667 | | WinMtfFillStyle maLatestFillStyle; |
668 | | WinMtfFillStyle maFillStyle; |
669 | | WinMtfFillStyle maNopFillStyle; |
670 | | WinMtfPalette maPalette; |
671 | | |
672 | | vcl::Font maLatestFont; |
673 | | vcl::Font maFont; |
674 | | sal_uInt32 mnLatestTextAlign; |
675 | | sal_uInt32 mnTextAlign; |
676 | | Color maLatestTextColor; |
677 | | Color maTextColor; |
678 | | Color maLatestBkColor; |
679 | | Color maBkColor; |
680 | | vcl::text::ComplexTextLayoutFlags mnLatestTextLayoutMode; |
681 | | vcl::text::ComplexTextLayoutFlags mnTextLayoutMode; |
682 | | BackgroundMode mnLatestBkMode; |
683 | | BackgroundMode mnBkMode; |
684 | | RasterOp meLatestRasterOp; |
685 | | RasterOp meRasterOp; |
686 | | |
687 | | std::vector< std::unique_ptr<GDIObj> > mvGDIObj; |
688 | | Point maActPos; |
689 | | WMFRasterOp mnRop; |
690 | | std::vector< std::shared_ptr<SaveStruct> > mvSaveStack; |
691 | | |
692 | | GraphicsMode meGfxMode; |
693 | | MappingMode meMapMode; |
694 | | |
695 | | XForm maXForm; |
696 | | sal_Int32 mnDevOrgX; |
697 | | sal_Int32 mnDevOrgY; |
698 | | sal_Int32 mnDevWidth; |
699 | | sal_Int32 mnDevHeight; |
700 | | sal_Int32 mnWinOrgX; |
701 | | sal_Int32 mnWinOrgY; |
702 | | sal_Int32 mnWinExtX; |
703 | | sal_Int32 mnWinExtY; |
704 | | |
705 | | sal_Int32 mnPixX; // Reference Device in pixel |
706 | | sal_Int32 mnPixY; // Reference Device in pixel |
707 | | sal_Int32 mnMillX; // Reference Device in Mill |
708 | | sal_Int32 mnMillY; // Reference Device in Mill |
709 | | tools::Rectangle mrclFrame; |
710 | | tools::Rectangle mrclBounds; |
711 | | |
712 | | GDIMetaFile* mpGDIMetaFile; |
713 | | |
714 | | SvStream* mpInputStream; // the WMF/EMF file to be read |
715 | | sal_uInt32 mnStartPos; |
716 | | sal_uInt32 mnEndPos; |
717 | | std::vector<BSaveStruct> maBmpSaveList; |
718 | | |
719 | | // tdf#127471 always try to detect - only used with ScaledText |
720 | | ScaledFontDetectCorrectHelper maScaledFontHelper; |
721 | | |
722 | | bool mbNopMode : 1; |
723 | | bool mbClockWiseArcDirection : 1; |
724 | | bool mbFillStyleSelected : 1; |
725 | | sal_uInt32 mnPolyFillMode; // ALTERNATE(1) or WINDING(2) |
726 | | bool mbClipNeedsUpdate : 1; |
727 | | bool mbComplexClip : 1; |
728 | | bool mbIsMapWinSet : 1; |
729 | | bool mbIsMapDevSet : 1; |
730 | | |
731 | | void ResetInternalState(); |
732 | | void UpdateLineStyle(); |
733 | | void UpdateFillStyle(); |
734 | | |
735 | | Point ImplMap(const Point& rPt); |
736 | | Point ImplScale(const Point& rPt); |
737 | | Size ImplMap(const Size& rSize, bool bDoWorldTransform = true); |
738 | | tools::Rectangle ImplMap(const tools::Rectangle& rRectangle); |
739 | | void ImplMap(vcl::Font& rFont); |
740 | | tools::Polygon& ImplMap(tools::Polygon& rPolygon); |
741 | | tools::PolyPolygon& ImplMap(tools::PolyPolygon& rPolyPolygon); |
742 | | void ImplScale(tools::Polygon& rPolygon); |
743 | | tools::PolyPolygon& ImplScale(tools::PolyPolygon& rPolyPolygon); |
744 | | void ImplResizeObjectArry(sal_uInt32 nNewEntry); |
745 | | void ImplSetNonPersistentLineColorTransparenz(); |
746 | | void ImplDrawClippedPolyPolygon(const tools::PolyPolygon& rPolyPoly); |
747 | | void ImplDrawBitmap(const Point& rPos, const Size& rSize, const Bitmap& rBitmap); |
748 | | bool ImplEmitLineHatch(const tools::Polygon& rPoly); |
749 | | void ImplEmitPatternFill(const tools::PolyPolygon& rPolyPoly); |
750 | | |
751 | | public: |
752 | | |
753 | | void SetDevByWin(); //Hack to set varying defaults for incompletely defined files. |
754 | | void SetDevOrg(const Point& rPoint); |
755 | | void SetDevOrgOffset(sal_Int32 nXAdd, sal_Int32 nYAdd); |
756 | | void SetDevExt(const Size& rSize, bool regular = true); |
757 | | void ScaleDevExt(double fX, double fY); |
758 | | |
759 | | void SetWinOrg(const Point& rPoint, bool bIsEMF = false); |
760 | 2.06k | Point GetWinOrg() { return Point(mnWinOrgX, mnWinOrgY); } |
761 | | void SetWinOrgOffset(sal_Int32 nX, sal_Int32 nY); |
762 | | void SetWinExt(const Size& rSize, bool bIsEMF = false); |
763 | | void ScaleWinExt(double fX, double fY); |
764 | | |
765 | | void SetrclBounds(const tools::Rectangle& rRect); |
766 | | void SetrclFrame(const tools::Rectangle& rRect); |
767 | | void SetRefPix(const Size& rSize); |
768 | | void SetRefMill(const Size& rSize); |
769 | | |
770 | | void SetMapMode(MappingMode mnMapMode); |
771 | | void SetWorldTransform(const XForm& rXForm); |
772 | | void ModifyWorldTransform(const XForm& rXForm, ModifyWorldTransformMode nMode); |
773 | | |
774 | | void Push(); |
775 | | void Pop( const sal_Int32 nSavedDC = -1 ); |
776 | | |
777 | | WMFRasterOp SetRasterOp(WMFRasterOp nRasterOp); |
778 | | void StrokeAndFillPath(bool bStroke, bool bFill); |
779 | | |
780 | | void SetArcDirection(bool bCounterClockWise); |
781 | 8.17k | bool IsArcDirectionClockWise() { return mbClockWiseArcDirection; }; |
782 | 73.9k | void SetGfxMode(GraphicsMode nGfxMode) { meGfxMode = nGfxMode; }; |
783 | 24.7k | GraphicsMode GetGfxMode() const { return meGfxMode; }; |
784 | | void SetBkMode(BackgroundMode nMode); |
785 | | void SetPolyFillMode(sal_uInt32 nPolyFillMode); |
786 | | void SetBkColor(const Color& rColor); |
787 | | void SetTextColor(const Color& rColor); |
788 | | void SetTextAlign(sal_uInt32 nAlign); |
789 | | |
790 | | void CreateObject(std::unique_ptr<GDIObj> pObject); |
791 | | void CreateObjectIndexed(sal_uInt32 nIndex, std::unique_ptr<GDIObj> pObject); |
792 | | void CreateObject(); |
793 | | |
794 | | void DeleteObject(sal_uInt32 nIndex); |
795 | | void SelectObject(sal_uInt32 nIndex); |
796 | 27.3k | rtl_TextEncoding GetCharSet() const { return maFont.GetCharSet(); }; |
797 | 0 | const vcl::Font& GetFont() const { return maFont; } |
798 | | void SetTextLayoutMode(vcl::text::ComplexTextLayoutFlags nLayoutMode); |
799 | | |
800 | 8.69k | void ClearPath() { maPathObj.Init(); }; |
801 | 28.1k | void ClosePath() { maPathObj.ClosePath(); }; |
802 | 104 | const tools::PolyPolygon& GetPathObj() const { return maPathObj; }; |
803 | | |
804 | | void MoveTo(const Point& rPoint, bool bRecordPath = false); |
805 | | void LineTo(const Point& rPoint, bool bRecordPath = false); |
806 | | void DrawPixel(const Point& rSource, const Color& rColor); |
807 | | void DrawRect(const tools::Rectangle& rRect, bool bEdge = true); |
808 | | void DrawRectWithBGColor(const tools::Rectangle& rRect); |
809 | | void DrawRoundRect(const tools::Rectangle& rRect, const Size& rSize); |
810 | | void DrawEllipse(const tools::Rectangle& rRect); |
811 | | void DrawArc( |
812 | | const tools::Rectangle& rRect, |
813 | | const Point& rStartAngle, |
814 | | const Point& rEndAngle, |
815 | | bool bDrawTo = false |
816 | | ); |
817 | | void DrawPie( |
818 | | const tools::Rectangle& rRect, |
819 | | const Point& rStartAngle, |
820 | | const Point& rEndAngle |
821 | | ); |
822 | | void DrawChord( |
823 | | const tools::Rectangle& rRect, |
824 | | const Point& rStartAngle, |
825 | | const Point& rEndAngle |
826 | | ); |
827 | | void DrawPolygon(tools::Polygon rPolygon, bool bRecordPath); |
828 | | void DrawPolyPolygon(tools::PolyPolygon& rPolyPolygon, bool bRecordPath = false); |
829 | | void DrawPolyLine(tools::Polygon rPolygon, |
830 | | bool bDrawTo = false, |
831 | | bool bRecordPath = false |
832 | | ); |
833 | | void DrawPolyBezier(tools::Polygon rPolygon, |
834 | | bool bDrawTo, |
835 | | bool bRecordPath |
836 | | ); |
837 | | void DrawText(Point& rPosition, |
838 | | OUString const & rString, |
839 | | KernArray* pDXArry = nullptr, |
840 | | tools::Long* pDYArry = nullptr, |
841 | | const float fXScale = 1.0, |
842 | | const float fYScale = 1.0, |
843 | | bool bRecordPath = false, |
844 | | GraphicsMode nGraphicsMode = GraphicsMode::GM_COMPATIBLE); |
845 | | |
846 | | /// Render pre-shaped glyph indices as polypolygon outlines. |
847 | | /// Returns false if the required font is not available (caller |
848 | | /// should fall back to DrawText). |
849 | | bool DrawGlyphs(Point& rPosition, |
850 | | const std::vector<sal_uInt16>& rGlyphIds, |
851 | | KernArray* pDXArry = nullptr, |
852 | | tools::Long* pDYArry = nullptr, |
853 | | const float fXScale = 1.0, |
854 | | const float fYScale = 1.0, |
855 | | bool bRecordPath = false, |
856 | | GraphicsMode nGraphicsMode = GraphicsMode::GM_COMPATIBLE); |
857 | | |
858 | | void ResolveBitmapActions(std::vector<BSaveStruct>& rSaveList); |
859 | | |
860 | | void IntersectClipRect(const tools::Rectangle& rRect); |
861 | | void ExcludeClipRect(const tools::Rectangle& rRect); |
862 | | void MoveClipRegion(const Size& rSize); |
863 | | void SetClipPath( |
864 | | const tools::PolyPolygon& rPolyPoly, |
865 | | RegionMode nClippingMode, |
866 | | bool bIsMapped |
867 | | ); |
868 | | void SetDefaultClipPath(); |
869 | | void UpdateClipRegion(); |
870 | | void AddFromGDIMetaFile(GDIMetaFile& rGDIMetaFile); |
871 | | |
872 | | void PassEMFPlus(void const * pBuffer, sal_uInt32 nLength); |
873 | | void PassEMFPlusHeaderInfo(); |
874 | | |
875 | | Color ReadColor(); |
876 | | |
877 | | explicit MtfTools(GDIMetaFile& rGDIMetaFile, SvStream& rStreamWMF); |
878 | | ~MtfTools(); |
879 | | }; |
880 | | } |
881 | | |
882 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |