LibreOffice Module emfio (master) 1
emfreader.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 */
21#include <emfreader.hxx>
22#include <sal/log.hxx>
23#include <osl/diagnose.h>
24#include <vcl/dibtools.hxx>
25#include <o3tl/safeint.hxx>
26#include <o3tl/sprintf.hxx>
27#include <tools/stream.hxx>
28#include <memory>
30#include <vcl/graph.hxx>
31#include <vcl/pdfread.hxx>
32#include <rtl/bootstrap.hxx>
33
34#ifdef DBG_UTIL
36#endif
37
38// GDI-Array
39
40#define EMR_HEADER 1
41#define EMR_POLYBEZIER 2
42#define EMR_POLYGON 3
43#define EMR_POLYLINE 4
44#define EMR_POLYBEZIERTO 5
45#define EMR_POLYLINETO 6
46#define EMR_POLYPOLYLINE 7
47#define EMR_POLYPOLYGON 8
48#define EMR_SETWINDOWEXTEX 9
49#define EMR_SETWINDOWORGEX 10
50#define EMR_SETVIEWPORTEXTEX 11
51#define EMR_SETVIEWPORTORGEX 12
52#define EMR_SETBRUSHORGEX 13
53#define EMR_EOF 14
54#define EMR_SETPIXELV 15
55#define EMR_SETMAPPERFLAGS 16
56#define EMR_SETMAPMODE 17
57#define EMR_SETBKMODE 18
58#define EMR_SETPOLYFILLMODE 19
59#define EMR_SETROP2 20
60#define EMR_SETSTRETCHBLTMODE 21
61#define EMR_SETTEXTALIGN 22
62#define EMR_SETCOLORADJUSTMENT 23
63#define EMR_SETTEXTCOLOR 24
64#define EMR_SETBKCOLOR 25
65#define EMR_OFFSETCLIPRGN 26
66#define EMR_MOVETOEX 27
67#define EMR_SETMETARGN 28
68#define EMR_EXCLUDECLIPRECT 29
69#define EMR_INTERSECTCLIPRECT 30
70#define EMR_SCALEVIEWPORTEXTEX 31
71#define EMR_SCALEWINDOWEXTEX 32
72#define EMR_SAVEDC 33
73#define EMR_RESTOREDC 34
74#define EMR_SETWORLDTRANSFORM 35
75#define EMR_MODIFYWORLDTRANSFORM 36
76#define EMR_SELECTOBJECT 37
77#define EMR_CREATEPEN 38
78#define EMR_CREATEBRUSHINDIRECT 39
79#define EMR_DELETEOBJECT 40
80#define EMR_ANGLEARC 41
81#define EMR_ELLIPSE 42
82#define EMR_RECTANGLE 43
83#define EMR_ROUNDRECT 44
84#define EMR_ARC 45
85#define EMR_CHORD 46
86#define EMR_PIE 47
87#define EMR_SELECTPALETTE 48
88#define EMR_CREATEPALETTE 49
89#define EMR_SETPALETTEENTRIES 50
90#define EMR_RESIZEPALETTE 51
91#define EMR_REALIZEPALETTE 52
92#define EMR_EXTFLOODFILL 53
93#define EMR_LINETO 54
94#define EMR_ARCTO 55
95#define EMR_POLYDRAW 56
96#define EMR_SETARCDIRECTION 57
97#define EMR_SETMITERLIMIT 58
98#define EMR_BEGINPATH 59
99#define EMR_ENDPATH 60
100#define EMR_CLOSEFIGURE 61
101#define EMR_FILLPATH 62
102#define EMR_STROKEANDFILLPATH 63
103#define EMR_STROKEPATH 64
104#define EMR_FLATTENPATH 65
105#define EMR_WIDENPATH 66
106#define EMR_SELECTCLIPPATH 67
107#define EMR_ABORTPATH 68
108
109#define EMR_COMMENT 70 // Contains arbitrary private data.
110// Comment Identifiers:
111#define EMR_COMMENT_EMFPLUS 0x2B464D45 // Contains embedded EMF+ records.
112#define EMR_COMMENT_EMFSPOOL 0x00000000 // Contains embedded EMFSPOOL records.
113#define EMR_COMMENT_PUBLIC 0x43494447 // Specify extensions to EMF processing.
114
115#define EMR_FILLRGN 71
116#define EMR_FRAMERGN 72
117#define EMR_INVERTRGN 73
118#define EMR_PAINTRGN 74
119#define EMR_EXTSELECTCLIPRGN 75
120#define EMR_BITBLT 76
121#define EMR_STRETCHBLT 77
122#define EMR_MASKBLT 78
123#define EMR_PLGBLT 79
124#define EMR_SETDIBITSTODEVICE 80
125#define EMR_STRETCHDIBITS 81
126#define EMR_EXTCREATEFONTINDIRECTW 82
127#define EMR_EXTTEXTOUTA 83
128#define EMR_EXTTEXTOUTW 84
129#define EMR_POLYBEZIER16 85
130#define EMR_POLYGON16 86
131#define EMR_POLYLINE16 87
132#define EMR_POLYBEZIERTO16 88
133#define EMR_POLYLINETO16 89
134#define EMR_POLYPOLYLINE16 90
135#define EMR_POLYPOLYGON16 91
136#define EMR_POLYDRAW16 92
137#define EMR_CREATEMONOBRUSH 93
138#define EMR_CREATEDIBPATTERNBRUSHPT 94
139#define EMR_EXTCREATEPEN 95
140#define EMR_POLYTEXTOUTA 96
141#define EMR_POLYTEXTOUTW 97
142
143// WINDOWS VERSION >= 0x400
144#define EMR_SETICMMODE 98
145#define EMR_CREATECOLORSPACE 99
146#define EMR_SETCOLORSPACE 100
147#define EMR_DELETECOLORSPACE 101
148#define EMR_GLSRECORD 102
149#define EMR_GLSBOUNDEDRECORD 103
150#define EMR_PIXELFORMAT 104
151
152// WINDOWS VERSION >= 0x500
153#define EMR_DRAWESCAPE 105
154#define EMR_EXTESCAPE 106
155#define EMR_STARTDOC 107
156#define EMR_SMALLTEXTOUT 108
157#define EMR_FORCEUFIMAPPING 109
158#define EMR_NAMEDESCAPE 110
159#define EMR_COLORCORRECTPALETTE 111
160#define EMR_SETICMPROFILEA 112
161#define EMR_SETICMPROFILEW 113
162#define EMR_ALPHABLEND 114
163#define EMR_ALPHADIBBLEND 115
164#define EMR_TRANSPARENTBLT 116
165#define EMR_TRANSPARENTDIB 117
166#define EMR_GRADIENTFILL 118
167#define EMR_SETLINKEDUFIS 119
168#define EMR_SETTEXTJUSTIFICATION 120
169
170#define PDF_SIGNATURE 0x50444620 // "PDF "
171
172/* [MS-EMF] - v20210625 - page 28 */
173constexpr sal_Int32 ARCDIRECTION_CLOCKWISE = 0x00000002;
174
175namespace
176{
177
178/* [MS-EMF] - v20210625 - page 41 */
179/* 2.1.26 Point Enumeration */
180enum EMFPointTypes
181{
182 PT_CLOSEFIGURE = 0x01,
183 PT_LINETO = 0x02,
184 PT_BEZIERTO = 0x04,
185 PT_MOVETO = 0x06
186};
187
188const char *
189record_type_name(sal_uInt32 nRecType)
190{
191#ifndef SAL_LOG_INFO
192 (void) nRecType;
193 return "";
194#else
195 switch( nRecType )
196 {
197 case EMR_HEADER: return "HEADER";
198 case EMR_POLYBEZIER: return "POLYBEZIER";
199 case EMR_POLYGON: return "POLYGON";
200 case EMR_POLYLINE: return "POLYLINE";
201 case EMR_POLYBEZIERTO: return "POLYBEZIERTO";
202 case EMR_POLYLINETO: return "POLYLINETO";
203 case EMR_POLYPOLYLINE: return "POLYPOLYLINE";
204 case EMR_POLYPOLYGON: return "POLYPOLYGON";
205 case EMR_SETWINDOWEXTEX: return "SETWINDOWEXTEX";
206 case EMR_SETWINDOWORGEX: return "SETWINDOWORGEX";
207 case EMR_SETVIEWPORTEXTEX: return "SETVIEWPORTEXTEX";
208 case EMR_SETVIEWPORTORGEX: return "SETVIEWPORTORGEX";
209 case EMR_SETBRUSHORGEX: return "SETBRUSHORGEX";
210 case EMR_EOF: return "EOF";
211 case EMR_SETPIXELV: return "SETPIXELV";
212 case EMR_SETMAPPERFLAGS: return "SETMAPPERFLAGS";
213 case EMR_SETMAPMODE: return "SETMAPMODE";
214 case EMR_SETBKMODE: return "SETBKMODE";
215 case EMR_SETPOLYFILLMODE: return "SETPOLYFILLMODE";
216 case EMR_SETROP2: return "SETROP2";
217 case EMR_SETSTRETCHBLTMODE: return "SETSTRETCHBLTMODE";
218 case EMR_SETTEXTALIGN: return "SETTEXTALIGN";
219 case EMR_SETCOLORADJUSTMENT: return "SETCOLORADJUSTMENT";
220 case EMR_SETTEXTCOLOR: return "SETTEXTCOLOR";
221 case EMR_SETBKCOLOR: return "SETBKCOLOR";
222 case EMR_OFFSETCLIPRGN: return "OFFSETCLIPRGN";
223 case EMR_MOVETOEX: return "MOVETOEX";
224 case EMR_SETMETARGN: return "SETMETARGN";
225 case EMR_EXCLUDECLIPRECT: return "EXCLUDECLIPRECT";
226 case EMR_INTERSECTCLIPRECT: return "INTERSECTCLIPRECT";
227 case EMR_SCALEVIEWPORTEXTEX: return "SCALEVIEWPORTEXTEX";
228 case EMR_SCALEWINDOWEXTEX: return "SCALEWINDOWEXTEX";
229 case EMR_SAVEDC: return "SAVEDC";
230 case EMR_RESTOREDC: return "RESTOREDC";
231 case EMR_SETWORLDTRANSFORM: return "SETWORLDTRANSFORM";
232 case EMR_MODIFYWORLDTRANSFORM: return "MODIFYWORLDTRANSFORM";
233 case EMR_SELECTOBJECT: return "SELECTOBJECT";
234 case EMR_CREATEPEN: return "CREATEPEN";
235 case EMR_CREATEBRUSHINDIRECT: return "CREATEBRUSHINDIRECT";
236 case EMR_DELETEOBJECT: return "DELETEOBJECT";
237 case EMR_ANGLEARC: return "ANGLEARC";
238 case EMR_ELLIPSE: return "ELLIPSE";
239 case EMR_RECTANGLE: return "RECTANGLE";
240 case EMR_ROUNDRECT: return "ROUNDRECT";
241 case EMR_ARC: return "ARC";
242 case EMR_CHORD: return "CHORD";
243 case EMR_PIE: return "PIE";
244 case EMR_SELECTPALETTE: return "SELECTPALETTE";
245 case EMR_CREATEPALETTE: return "CREATEPALETTE";
246 case EMR_SETPALETTEENTRIES: return "SETPALETTEENTRIES";
247 case EMR_RESIZEPALETTE: return "RESIZEPALETTE";
248 case EMR_REALIZEPALETTE: return "REALIZEPALETTE";
249 case EMR_EXTFLOODFILL: return "EXTFLOODFILL";
250 case EMR_LINETO: return "LINETO";
251 case EMR_ARCTO: return "ARCTO";
252 case EMR_POLYDRAW: return "POLYDRAW";
253 case EMR_SETARCDIRECTION: return "SETARCDIRECTION";
254 case EMR_SETMITERLIMIT: return "SETMITERLIMIT";
255 case EMR_BEGINPATH: return "BEGINPATH";
256 case EMR_ENDPATH: return "ENDPATH";
257 case EMR_CLOSEFIGURE: return "CLOSEFIGURE";
258 case EMR_FILLPATH: return "FILLPATH";
259 case EMR_STROKEANDFILLPATH: return "STROKEANDFILLPATH";
260 case EMR_STROKEPATH: return "STROKEPATH";
261 case EMR_FLATTENPATH: return "FLATTENPATH";
262 case EMR_WIDENPATH: return "WIDENPATH";
263 case EMR_SELECTCLIPPATH: return "SELECTCLIPPATH";
264 case EMR_ABORTPATH: return "ABORTPATH";
265 case EMR_COMMENT: return "COMMENT";
266 case EMR_FILLRGN: return "FILLRGN";
267 case EMR_FRAMERGN: return "FRAMERGN";
268 case EMR_INVERTRGN: return "INVERTRGN";
269 case EMR_PAINTRGN: return "PAINTRGN";
270 case EMR_EXTSELECTCLIPRGN: return "EXTSELECTCLIPRGN";
271 case EMR_BITBLT: return "BITBLT";
272 case EMR_STRETCHBLT: return "STRETCHBLT";
273 case EMR_MASKBLT: return "MASKBLT";
274 case EMR_PLGBLT: return "PLGBLT";
275 case EMR_SETDIBITSTODEVICE: return "SETDIBITSTODEVICE";
276 case EMR_STRETCHDIBITS: return "STRETCHDIBITS";
277 case EMR_EXTCREATEFONTINDIRECTW: return "EXTCREATEFONTINDIRECTW";
278 case EMR_EXTTEXTOUTA: return "EXTTEXTOUTA";
279 case EMR_EXTTEXTOUTW: return "EXTTEXTOUTW";
280 case EMR_POLYBEZIER16: return "POLYBEZIER16";
281 case EMR_POLYGON16: return "POLYGON16";
282 case EMR_POLYLINE16: return "POLYLINE16";
283 case EMR_POLYBEZIERTO16: return "POLYBEZIERTO16";
284 case EMR_POLYLINETO16: return "POLYLINETO16";
285 case EMR_POLYPOLYLINE16: return "POLYPOLYLINE16";
286 case EMR_POLYPOLYGON16: return "POLYPOLYGON16";
287 case EMR_POLYDRAW16: return "POLYDRAW16";
288 case EMR_CREATEMONOBRUSH: return "CREATEMONOBRUSH";
289 case EMR_CREATEDIBPATTERNBRUSHPT: return "CREATEDIBPATTERNBRUSHPT";
290 case EMR_EXTCREATEPEN: return "EXTCREATEPEN";
291 case EMR_POLYTEXTOUTA: return "POLYTEXTOUTA";
292 case EMR_POLYTEXTOUTW: return "POLYTEXTOUTW";
293 case EMR_SETICMMODE: return "SETICMMODE";
294 case EMR_CREATECOLORSPACE: return "CREATECOLORSPACE";
295 case EMR_SETCOLORSPACE: return "SETCOLORSPACE";
296 case EMR_DELETECOLORSPACE: return "DELETECOLORSPACE";
297 case EMR_GLSRECORD: return "GLSRECORD";
298 case EMR_GLSBOUNDEDRECORD: return "GLSBOUNDEDRECORD";
299 case EMR_PIXELFORMAT: return "PIXELFORMAT";
300 case EMR_DRAWESCAPE: return "DRAWESCAPE";
301 case EMR_EXTESCAPE: return "EXTESCAPE";
302 case EMR_STARTDOC: return "STARTDOC";
303 case EMR_SMALLTEXTOUT: return "SMALLTEXTOUT";
304 case EMR_FORCEUFIMAPPING: return "FORCEUFIMAPPING";
305 case EMR_NAMEDESCAPE: return "NAMEDESCAPE";
306 case EMR_COLORCORRECTPALETTE: return "COLORCORRECTPALETTE";
307 case EMR_SETICMPROFILEA: return "SETICMPROFILEA";
308 case EMR_SETICMPROFILEW: return "SETICMPROFILEW";
309 case EMR_ALPHABLEND: return "ALPHABLEND";
310 case EMR_ALPHADIBBLEND: return "ALPHADIBBLEND";
311 case EMR_TRANSPARENTBLT: return "TRANSPARENTBLT";
312 case EMR_TRANSPARENTDIB: return "TRANSPARENTDIB";
313 case EMR_GRADIENTFILL: return "GRADIENTFILL";
314 case EMR_SETLINKEDUFIS: return "SETLINKEDUFIS";
315 case EMR_SETTEXTJUSTIFICATION: return "SETTEXTJUSTIFICATION";
316 default:
317 // Yes, return a pointer to a static buffer. This is a very
318 // local debugging output function, so no big deal.
319 static char buffer[11];
320 o3tl::sprintf(buffer, "0x%08" SAL_PRIxUINT32, nRecType);
321 return buffer;
322 }
323#endif
324}
325
326struct BLENDFUNCTION
327{
328 unsigned char aBlendOperation;
329 unsigned char aBlendFlags;
330 unsigned char aSrcConstantAlpha;
331 unsigned char aAlphaFormat;
332
333 friend SvStream& operator>>(SvStream& rInStream, BLENDFUNCTION& rBlendFun);
334};
335
336SvStream& operator>>(SvStream& rInStream, BLENDFUNCTION& rBlendFun)
337{
338 rInStream.ReadUChar(rBlendFun.aBlendOperation);
339 rInStream.ReadUChar(rBlendFun.aBlendFlags);
340 rInStream.ReadUChar(rBlendFun.aSrcConstantAlpha);
341 rInStream.ReadUChar(rBlendFun.aAlphaFormat);
342 return rInStream;
343}
344
345bool ImplReadRegion( basegfx::B2DPolyPolygon& rPolyPoly, SvStream& rStream, sal_uInt32 nLen, Point aWinOrg )
346{
347 if (nLen < 32) // 32 bytes - Size of RegionDataHeader
348 return false;
349
350 sal_uInt32 nHdSize, nType, nCountRects, nRgnSize;
351 rStream.ReadUInt32(nHdSize);
352 rStream.ReadUInt32(nType);
353 rStream.ReadUInt32(nCountRects);
354 rStream.ReadUInt32(nRgnSize);
355
356 sal_Int32 nLeft, nTop, nRight, nBottom;
357 //bounds of the region
358 rStream.ReadInt32(nLeft);
359 rStream.ReadInt32(nTop);
360 rStream.ReadInt32(nRight);
361 rStream.ReadInt32(nBottom);
362
363 if (!rStream.good() || nCountRects == 0 || nType != emfio::RDH_RECTANGLES)
364 return false;
365
366 SAL_INFO("emfio", "\t\tBounds Left: " << nLeft << ", top: " << nTop << ", right: " << nRight << ", bottom: " << nBottom);
367
368 nLen -= 32;
369
370 sal_uInt32 nSize;
371 if (o3tl::checked_multiply<sal_uInt32>(nCountRects, 16, nSize))
372 return false;
373 if (nLen < nSize)
374 return false;
375
376 for (sal_uInt32 i = 0; i < nCountRects; ++i)
377 {
378 rStream.ReadInt32(nLeft);
379 rStream.ReadInt32(nTop);
380 rStream.ReadInt32(nRight);
381 rStream.ReadInt32(nBottom);
382 nLeft += aWinOrg.X();
383 nRight += aWinOrg.X();
384 nTop += aWinOrg.Y();
385 nBottom += aWinOrg.Y();
386 rPolyPoly.append( basegfx::utils::createPolygonFromRect( ::basegfx::B2DRectangle( nLeft, nTop, nRight, nBottom ) ) );
387 SAL_INFO("emfio", "\t\t" << i << " Left: " << nLeft << ", top: " << nTop << ", right: " << nRight << ", bottom: " << nBottom);
388 }
390 {
391 rPolyPoly = basegfx::utils::solveCrossovers(rPolyPoly);
392 rPolyPoly = basegfx::utils::stripNeutralPolygons(rPolyPoly);
393 rPolyPoly = basegfx::utils::stripDispensablePolygons(rPolyPoly);
394 }
395 return true;
396}
397
398} // anonymous namespace
399
400namespace emfio
401{
403 : MtfTools(rGDIMetaFile, rStream)
404 , mnRecordCount(0)
405 , mbRecordPath(false)
406 , mbEMFPlus(false)
407 , mbEMFPlusDualMode(false)
408 {
409 }
410
412 {
413 }
414
415 const sal_uInt32 EMR_COMMENT_BEGINGROUP = 0x00000002;
416 const sal_uInt32 EMR_COMMENT_ENDGROUP = 0x00000003;
417 const sal_uInt32 EMR_COMMENT_MULTIFORMATS = 0x40000004;
418 const sal_uInt32 EMR_COMMENT_WINDOWS_METAFILE = 0x80000001;
419
420 void EmfReader::ReadGDIComment(sal_uInt32 nCommentId)
421 {
422 sal_uInt32 nPublicCommentIdentifier(0);
423 mpInputStream->ReadUInt32(nPublicCommentIdentifier);
424
425 SAL_INFO("emfio", "\t\tEMR_COMMENT_PUBLIC, id: 0x" << std::hex << nCommentId << std::dec);
426 switch (nPublicCommentIdentifier)
427 {
429 {
430 SAL_INFO("emfio", "\t\t\tEMR_COMMENT_BEGINGROUP");
431 sal_uInt32 left, top, right, bottom;
433
434 SAL_INFO("emfio", "\t\t\t\tBounding rect");
435 SAL_INFO("emfio", "\t\t\t\t\tLeft: " << left);
436 SAL_INFO("emfio", "\t\t\t\t\tTop: " << top);
437 SAL_INFO("emfio", "\t\t\t\t\tRight: " << right);
438 SAL_INFO("emfio", "\t\t\t\t\tBottom: " << bottom);
439
440 sal_uInt32 nDescChars(0);
441 mpInputStream->ReadUInt32(nDescChars);
442
443 OUString aDesc;
444 for (sal_uInt32 i=0; i < nDescChars; i++)
445 {
446 sal_uInt16 cChar(0);
448 if (cChar == '\0')
449 break;
450
451 sal_Unicode cUniChar = static_cast<sal_Unicode>(cChar);
452 aDesc = aDesc + OUStringChar(cUniChar);
453 }
454
455 SAL_INFO("emfio", "\t\tDescription: " << aDesc);
456 }
457 break;
458
460 SAL_INFO("emfio", "\t\t\tEMR_COMMENT_ENDGROUP");
461 break;
462
465 break;
466
468 SAL_WARN("emfio", "\t\tEMR_COMMENT_WINDOWS_METAFILE not implemented");
469 break;
470
471 default:
472 SAL_WARN("emfio", "\t\tEMR_COMMENT_PUBLIC not implemented, id: 0x" << std::hex << nCommentId << std::dec);
473 break;
474 }
475 }
476
478 {
480
481 sal_uInt32 nCountFormats(0);
482 mpInputStream->ReadUInt32(nCountFormats);
483 if (nCountFormats < 1)
484 {
485 return;
486 }
487
488 // Read the first EmrFormat.
489 sal_uInt32 nSignature(0);
490 mpInputStream->ReadUInt32(nSignature);
491 if (nSignature != PDF_SIGNATURE)
492 {
493 return;
494 }
495
496 sal_uInt32 nVersion(0);
498 if (nVersion != 1)
499 {
500 return;
501 }
502
503 sal_uInt32 nSizeData(0);
504 mpInputStream->ReadUInt32(nSizeData);
505 if (!nSizeData || nSizeData > mpInputStream->remainingSize())
506 {
507 return;
508 }
509
510 sal_uInt32 nOffData(0);
511 mpInputStream->ReadUInt32(nOffData);
512 if (!nOffData)
513 {
514 return;
515 }
516
517 std::vector<char> aPdfData(nSizeData);
518 mpInputStream->ReadBytes(aPdfData.data(), aPdfData.size());
519 if (!mpInputStream->good())
520 {
521 return;
522 }
523
524 SvMemoryStream aPdfStream;
525 aPdfStream.WriteBytes(aPdfData.data(), aPdfData.size());
526 aPdfStream.Seek(0);
527 Graphic aGraphic;
528 if (!vcl::ImportPDF(aPdfStream, aGraphic))
529 {
530 return;
531 }
532
533 // aGraphic will be the only output of the EMF parser, so its size hint can be the same as
534 // ours.
535 aGraphic.getVectorGraphicData()->setSizeHint(maSizeHint);
536
537 maBmpSaveList.emplace_back(
538 aGraphic.GetBitmapEx(), aOutputRect, SRCCOPY, /*bForceAlpha=*/true);
539 const std::shared_ptr<VectorGraphicData> pVectorGraphicData
540 = aGraphic.getVectorGraphicData();
541 if (!pVectorGraphicData)
542 {
543 return;
544 }
545
546 if (pVectorGraphicData->getType() != VectorGraphicDataType::Pdf)
547 {
548 return;
549 }
550
552 }
553
554 void EmfReader::ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC)
555 {
556 if (!mbEMFPlus)
557 {
559
560 #if OSL_DEBUG_LEVEL > 1
561 // debug code - write the stream to debug file /tmp/emf-stream.emf
562 sal_uInt64 const pos = mpInputStream->Tell();
564 SvFileStream file( OUString( "/tmp/emf-stream.emf" ), StreamMode::WRITE | StreamMode::TRUNC );
565
567 file.Flush();
568 file.Close();
569
571 #endif
572
573 }
574
575 mbEMFPlus = true;
576 sal_uInt64 const pos = mpInputStream->Tell();
577 auto buffer = std::make_unique<char[]>( length );
578 PassEMFPlus( buffer.get(), mpInputStream->ReadBytes(buffer.get(), length) );
579 buffer.reset();
581
582 bHaveDC = false;
583
584 // skip in SeekRel if impossibly unavailable
585 sal_uInt32 nRemainder = length;
586
587 const size_t nRequiredHeaderSize = 12;
588 while (nRemainder >= nRequiredHeaderSize)
589 {
590 sal_uInt16 type(0), flags(0);
591 sal_uInt32 size(0), dataSize(0);
592
594 nRemainder -= nRequiredHeaderSize;
595
596 SAL_INFO("emfio", "\t\tEMF+ record type: 0x" << std::hex << type << std::dec);
597
598 // Get Device Context
599 // TODO We should use EmfPlusRecordType::GetDC instead
600 if( type == 0x4004 )
601 {
602 bHaveDC = true;
603 SAL_INFO("emfio", "\t\tEMF+ lock DC (device context)");
604 }
605
606 // look for the "dual mode" in header
607 // it indicates that either EMF or EMF+ records should be processed
608 // 0x4001 = EMF+ header
609 // flags & 1 = dual mode active
610 if ( type == 0x4001 && flags & 1 )
611 {
612 mbEMFPlusDualMode = true;
613 SAL_INFO ("emfio", "\t\tEMF+ dual mode detected");
614 }
615
616 // Get the length of the remaining data of this record based
617 // on the alleged size
618 sal_uInt32 nRemainingRecordData = size >= nRequiredHeaderSize ?
619 size-nRequiredHeaderSize : 0;
620 // clip to available size
621 nRemainingRecordData = std::min(nRemainingRecordData, nRemainder);
622 mpInputStream->SeekRel(nRemainingRecordData);
623 nRemainder -= nRemainingRecordData;
624 }
625 mpInputStream->SeekRel(nRemainder);
626 }
627
628 // these are referenced from inside the templates
629 static SvStream& operator >> (SvStream& rStream, sal_Int16 &n)
630 {
631 return rStream.ReadInt16(n);
632 }
633
634 static SvStream& operator >> (SvStream& rStream, sal_Int32 &n)
635 {
636 return rStream.ReadInt32(n);
637 }
638
644 template <class T>
645 tools::Polygon EmfReader::ReadPolygonWithSkip(const bool skipFirst, sal_uInt32 nNextPos)
646 {
647 sal_uInt32 nPoints(0), nStartIndex(0);
648 mpInputStream->SeekRel( 16 );
649 mpInputStream->ReadUInt32( nPoints );
650 if (skipFirst)
651 {
652 nPoints ++;
653 nStartIndex ++;
654 }
655
656 return ReadPolygon<T>(nStartIndex, nPoints, nNextPos);
657 }
658
666 template <class T>
667 tools::Polygon EmfReader::ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints, sal_uInt32 nNextPos)
668 {
669 SAL_INFO ("emfio", "\t\tPolygon:");
670
671 bool bRecordOk = nPoints <= SAL_MAX_UINT16;
672 SAL_WARN_IF(!bRecordOk, "emfio", "polygon record has more polygons than we can handle");
673 if (!bRecordOk || !nPoints)
674 return tools::Polygon();
675
676 auto nRemainingSize = std::min(nNextPos - mpInputStream->Tell(), mpInputStream->remainingSize());
677 auto nMaxPossiblePoints = nRemainingSize / (sizeof(T) * 2);
678 auto nPointCount = nPoints - nStartIndex;
679 if (nPointCount > nMaxPossiblePoints)
680 {
681 SAL_WARN("emfio", "polygon claims more points than record can provide, truncating");
682 nPoints = nMaxPossiblePoints + nStartIndex;
683 }
684
685 tools::Polygon aPolygon(nPoints);
686 for (sal_uInt32 i = nStartIndex ; i < nPoints && mpInputStream->good(); i++ )
687 {
688 T nX, nY;
689 *mpInputStream >> nX >> nY;
690
691 SAL_INFO("emfio", "\t\t\tPoint " << i << " of " << nPoints - 1 << ": " << nX << ", " << nY);
692
693 if (!mpInputStream->good())
694 {
695 SAL_WARN("emfio", "short read on polygon, truncating");
696 aPolygon.SetSize(i);
697 break;
698 }
699 aPolygon[ i ] = Point( nX, nY );
700 }
701
702 return aPolygon;
703 }
704
709 template <class T>
710 void EmfReader::ReadAndDrawPolyLine(sal_uInt32 nNextPos)
711 {
712 SAL_INFO("emfio", "\t\tPolyline: ");
713
714 mpInputStream->SeekRel( 0x10 ); // TODO Skipping Bounds. A 128-bit WMF RectL object (specifies the bounding rectangle in device units.)
715
716 sal_uInt32 nNumberOfPolylines = 0;
717 mpInputStream->ReadUInt32( nNumberOfPolylines );
718 SAL_INFO("emfio", "\t\t\tPolylines: " << nNumberOfPolylines);
719
720 sal_uInt32 nCount = 0;
721 mpInputStream->ReadUInt32( nCount ); // total number of points in all polylines
722 SAL_INFO("emfio", "\t\t\tPoints: " << nCount);
723
724 const auto nEndPos = std::min(nNextPos, mnEndPos);
725 if (mpInputStream->Tell() >= nEndPos)
726 return;
727
728 // taking the amount of points of each polygon, retrieving the total number of points
729 if ( !(mpInputStream->good() &&
730 ( nNumberOfPolylines < SAL_MAX_UINT32 / sizeof( sal_uInt16 ) ) &&
731 ( nNumberOfPolylines * sizeof( sal_uInt16 ) ) <= ( nEndPos - mpInputStream->Tell() ))
732 )
733 return;
734
735 std::unique_ptr< sal_uInt32[] > pnPolylinePointCount( new sal_uInt32[ nNumberOfPolylines ] );
736 for ( sal_uInt32 i = 0; i < nNumberOfPolylines && mpInputStream->good(); i++ )
737 {
738 sal_uInt32 nPoints;
739 mpInputStream->ReadUInt32( nPoints );
740 SAL_INFO("emfio", "\t\t\tPoint " << i << " of " << nNumberOfPolylines << ": " << nPoints);
741 pnPolylinePointCount[ i ] = nPoints;
742 }
743
744 // Get polyline points:
745 for ( sal_uInt32 i = 0; ( i < nNumberOfPolylines ) && mpInputStream->good(); i++ )
746 {
747 tools::Polygon aPolygon = ReadPolygon<T>(0, pnPolylinePointCount[i], nNextPos);
748 DrawPolyLine(std::move(aPolygon), false, mbRecordPath);
749 }
750 }
751
756 template <class T>
757 void EmfReader::ReadAndDrawPolyPolygon(sal_uInt32 nNextPos)
758 {
759 SAL_INFO("emfio", "\t\tPolygon: ");
760 mpInputStream->SeekRel( 0x10 ); // RectL bounds
761
762 sal_uInt32 nPoly(0), nGesPoints(0), nReadPoints(0);
763 // Number of polygons
764 mpInputStream->ReadUInt32( nPoly ).ReadUInt32( nGesPoints );
765 SAL_INFO("emfio", "\t\t\tPolygons: " << nPoly);
766 SAL_INFO("emfio", "\t\t\tPoints: " << nGesPoints);
767
768 const auto nEndPos = std::min(nNextPos, mnEndPos);
769 if (mpInputStream->Tell() >= nEndPos)
770 return;
771 if (!mpInputStream->good())
772 return;
773 //check against numeric overflowing
774 if (nGesPoints >= SAL_MAX_UINT32 / sizeof(Point))
775 return;
776 if (nPoly >= SAL_MAX_UINT32 / sizeof(sal_uInt16))
777 return;
778 if (nPoly * sizeof(sal_uInt16) > nEndPos - mpInputStream->Tell())
779 return;
780
781 // Get number of points in each polygon
782 std::vector<sal_uInt16> aPoints(nPoly);
783 for (sal_uInt32 i = 0; i < nPoly && mpInputStream->good(); ++i)
784 {
785 sal_uInt32 nPoints(0);
786 mpInputStream->ReadUInt32( nPoints );
787
788 SAL_INFO("emfio", "\t\t\t\tPolygon " << i << " points: " << nPoints);
789
790 aPoints[i] = static_cast<sal_uInt16>(nPoints);
791 }
792
793 if ( mpInputStream->good() && ( nGesPoints * (sizeof(T)+sizeof(T)) ) <= ( nEndPos - mpInputStream->Tell() ) )
794 {
795 // Get polygon points
796 tools::PolyPolygon aPolyPoly(nPoly);
797 for (sal_uInt32 i = 0; i < nPoly && mpInputStream->good(); ++i)
798 {
799 const sal_uInt16 nPointCount(aPoints[i]);
800 std::vector<Point> aPtAry(nPointCount);
801 for (sal_uInt16 j = 0; j < nPointCount && mpInputStream->good(); ++j)
802 {
803 T nX(0), nY(0);
804 *mpInputStream >> nX >> nY;
805 aPtAry[j] = Point( nX, nY );
806 ++nReadPoints;
807 }
808
809 aPolyPoly.Insert(tools::Polygon(aPtAry.size(), aPtAry.data()));
810 }
811
812 DrawPolyPolygon(aPolyPoly, mbRecordPath);
813 }
814
815 OSL_ENSURE(nReadPoints == nGesPoints, "The number Points processed from EMR_POLYPOLYGON is unequal imported number (!)");
816 }
817
819 {
820 sal_uInt32 nStretchBltMode = 0;
821 sal_uInt32 nNextPos(0),
822 nW(0), nH(0), nColor(0), nIndex(0),
823 nDat32(0), nNom1(0), nDen1(0), nNom2(0), nDen2(0);
824 sal_Int32 nX32(0), nY32(0), nx32(0), ny32(0);
825
826 bool bStatus = ReadHeader();
827 bool bHaveDC = false;
828
829 OUString aEMFPlusDisable;
830 rtl::Bootstrap::get("EMF_PLUS_DISABLE", aEMFPlusDisable);
831 bool bEnableEMFPlus = aEMFPlusDisable.isEmpty();
832 if (!mbEnableEMFPlus)
833 {
834 // EMF+ is enabled if neither the bootstrap variable, not the member variable disables
835 // it.
836 bEnableEMFPlus = mbEnableEMFPlus;
837 }
838
839 SAL_INFO("emfio", "EMF+ reading is " << (bEnableEMFPlus ? "enabled" : "disabled"));
840
841 while (bStatus && mnRecordCount-- && mpInputStream->good() && !mbReadOtherGraphicFormat)
842 {
843 sal_uInt32 nRecType(0), nRecSize(0);
844 mpInputStream->ReadUInt32(nRecType).ReadUInt32(nRecSize);
845
846 if ( !mpInputStream->good() || ( nRecSize < 8 ) || ( nRecSize & 3 ) ) // Parameters are always divisible by 4
847 {
848 bStatus = false;
849 break;
850 }
851
852 auto nCurPos = mpInputStream->Tell();
853
854 if (mnEndPos < nCurPos - 8)
855 {
856 bStatus = false;
857 break;
858 }
859
860 const sal_uInt32 nMaxPossibleRecSize = mnEndPos - (nCurPos - 8);
861 if (nRecSize > nMaxPossibleRecSize)
862 {
863 bStatus = false;
864 break;
865 }
866
867 nNextPos = nCurPos + (nRecSize - 8);
868
869 if( !maBmpSaveList.empty()
870 && ( nRecType != EMR_STRETCHBLT )
871 && ( nRecType != EMR_STRETCHDIBITS )
872 ) {
874 }
875
876 bool bFlag = false;
877
878 SAL_INFO("emfio", "0x" << std::hex << (nNextPos - nRecSize) << "-0x" << nNextPos << " " << record_type_name(nRecType) << " size: "
879 << std::dec << nRecSize);
880
881 if( bEnableEMFPlus && nRecType == EMR_COMMENT )
882 {
883 sal_uInt32 length;
884
886
887 SAL_INFO("emfio", "\tGDI comment, length: " << length);
888
889 if( mpInputStream->good() && length >= 4 && length <= mpInputStream->remainingSize() ) {
890 sal_uInt32 nCommentId;
891
892 mpInputStream->ReadUInt32( nCommentId );
893
894 SAL_INFO("emfio", "\t\tbegin " << static_cast<char>(nCommentId & 0xff) << static_cast<char>((nCommentId & 0xff00) >> 8) << static_cast<char>((nCommentId & 0xff0000) >> 16) << static_cast<char>((nCommentId & 0xff000000) >> 24) << " id: 0x" << std::hex << nCommentId << std::dec);
895
896 if( nCommentId == EMR_COMMENT_EMFPLUS && nRecSize >= 12 )
897 {
898 // [MS-EMF] 2.3.3: DataSize includes both CommentIdentifier and CommentRecordParm fields.
899 // We have already read 4-byte CommentIdentifier, so reduce length appropriately
900 ReadEMFPlusComment( length-4, bHaveDC );
901 }
902 else if( nCommentId == EMR_COMMENT_PUBLIC && nRecSize >= 12 )
903 {
904 ReadGDIComment(nCommentId);
905 }
906 else if( nCommentId == EMR_COMMENT_EMFSPOOL && nRecSize >= 12 )
907 {
908 SAL_WARN("emfio", "\t\tEMFSPOOL not implemented, id: 0x" << std::hex << nCommentId << std::dec);
909 // TODO Implement reading EMFSPOOL comment
910
911 }
912 else
913 {
914 SAL_WARN("emfio", "\t\tunknown id: 0x" << std::hex << nCommentId << std::dec);
915 }
916 }
917 }
918 else if ( !bHaveDC && mbEMFPlusDualMode && nRecType != EMR_HEADER && nRecType != EMR_EOF )
919 {
920 // skip content (EMF record) in dual mode
921 // we process only EMR_COMMENT (see above) to access EMF+ data
922 // with 2 exceptions, according to EMF+ specification:
923 // EMR_HEADER and EMR_EOF
924 // if a device context is given (bHaveDC) process the following EMF record, too.
925 }
926 else if( !mbEMFPlus || bHaveDC || nRecType == EMR_EOF )
927 {
928 switch( nRecType )
929 {
930 case EMR_POLYBEZIERTO :
931 DrawPolyBezier(ReadPolygonWithSkip<sal_Int32>(true, nNextPos), true, mbRecordPath);
932 break;
933 case EMR_POLYBEZIER :
934 DrawPolyBezier(ReadPolygonWithSkip<sal_Int32>(false, nNextPos), false, mbRecordPath);
935 break;
936
937 case EMR_POLYGON :
938 DrawPolygon(ReadPolygonWithSkip<sal_Int32>(false, nNextPos), mbRecordPath);
939 break;
940
941 case EMR_POLYLINETO :
942 DrawPolyLine(ReadPolygonWithSkip<sal_Int32>(true, nNextPos), true, mbRecordPath);
943 break;
944
945 case EMR_POLYDRAW:
946 {
947 sal_uInt32 nPointsCount(0), nBezierCount(0);
948 std::vector<Point> aPoints;
949 bool wrongFile = false;
950 std::vector<unsigned char> aPointTypes;
952 .ReadInt32(nY32)
953 .ReadInt32(nx32)
954 .ReadInt32(ny32)
955 .ReadUInt32(nPointsCount);
956
957 aPoints.reserve(std::min<size_t>(nPointsCount, mpInputStream->remainingSize() / (sizeof(sal_Int32) * 2)));
958 for (sal_uInt32 i = 0; i < nPointsCount && mpInputStream->good(); i++)
959 {
960 sal_Int32 nX, nY;
961 *mpInputStream >> nX >> nY;
962 aPoints.push_back(Point(nX, nY));
963 }
964 aPointTypes.reserve(std::min<size_t>(nPointsCount, mpInputStream->remainingSize()));
965 for (sal_uInt32 i = 0; i < nPointsCount && mpInputStream->good(); i++)
966 {
967 unsigned char nPointType(0);
968 mpInputStream->ReadUChar(nPointType);
969 aPointTypes.push_back(nPointType);
970 }
971 nPointsCount = std::min(aPoints.size(), aPointTypes.size());
972 for (sal_uInt32 i = 0; i < nPointsCount; i++)
973 {
974 SAL_INFO_IF(aPointTypes[i] == PT_MOVETO, "emfio",
975 "\t\t" << i << "/" << nPointsCount - 1 << " PT_MOVETO, "
976 << aPoints[i].getX() << ", " << aPoints[i].getY());
977 SAL_INFO_IF((aPointTypes[i] != PT_MOVETO) && (aPointTypes[i] & PT_LINETO), "emfio",
978 "\t\t" << i << "/" << nPointsCount - 1 << " PT_LINETO, "
979 << aPoints[i].getX() << ", " << aPoints[i].getY());
980 SAL_INFO_IF((aPointTypes[i] != PT_MOVETO) && (aPointTypes[i] & PT_CLOSEFIGURE), "emfio",
981 "\t\t" << i << "/" << nPointsCount - 1 << " PT_CLOSEFIGURE, "
982 << aPoints[i].getX() << ", " << aPoints[i].getY());
983 SAL_INFO_IF((aPointTypes[i] != PT_MOVETO) && (aPointTypes[i] & PT_BEZIERTO), "emfio",
984 "\t\t" << i << "/" << nPointsCount - 1 << " PT_BEZIERTO, "
985 << aPoints[i].getX() << ", " << aPoints[i].getY());
986
987 if ((aPointTypes[i] != PT_MOVETO) && (aPointTypes[i] & PT_BEZIERTO))
988 nBezierCount++;
989 else if (nBezierCount % 3 == 0)
990 nBezierCount = 0;
991 else
992 {
993 SAL_WARN(
994 "emfio",
995 "EMF file error: Number of Bezier points is not set of three.");
996 wrongFile = true;
997 }
998 }
999 if (wrongFile) break;
1000 for (sal_uInt32 i = 0; i < nPointsCount; i++)
1001 {
1002 if (aPointTypes[i] == PT_MOVETO)
1003 MoveTo(aPoints[i], true);
1004 else if (aPointTypes[i] & PT_LINETO)
1005 {
1006 LineTo(aPoints[i], true);
1007 if (aPointTypes[i] & PT_CLOSEFIGURE)
1008 ClosePath();
1009 }
1010 else if (aPointTypes[i] & PT_BEZIERTO)
1011 {
1012 if (nPointsCount - i < 3)
1013 {
1014 SAL_WARN("emfio", "EMF file error: Not enough Bezier points.");
1015 break;
1016 }
1017 tools::Polygon aPolygon(4);
1018 aPolygon[0] = maActPos;
1019 aPolygon[1] = aPoints[i++];
1020 aPolygon[2] = aPoints[i++];
1021 aPolygon[3] = aPoints[i];
1022 DrawPolyBezier(std::move(aPolygon), true, true);
1023 if (aPointTypes[i] & PT_CLOSEFIGURE)
1024 ClosePath();
1025 }
1026 }
1027 StrokeAndFillPath(true, false);
1028 }
1029 break;
1030
1031 case EMR_POLYLINE :
1032 DrawPolyLine(ReadPolygonWithSkip<sal_Int32>(false, nNextPos), false, mbRecordPath);
1033 break;
1034
1035 case EMR_POLYPOLYLINE :
1036 ReadAndDrawPolyLine<sal_Int32>(nNextPos);
1037 break;
1038
1039 case EMR_POLYPOLYGON :
1040 ReadAndDrawPolyPolygon<sal_Int32>(nNextPos);
1041 break;
1042
1043 case EMR_SETWINDOWEXTEX :
1044 {
1045 sal_Int32 w = 0, h = 0;
1047 SAL_INFO("emfio", "\t\tWidth: " << w);
1048 SAL_INFO("emfio", "\t\tHeight: " << h);
1049 SetWinExt( Size( w, h ), true);
1050 }
1051 break;
1052
1053 case EMR_SETWINDOWORGEX :
1054 {
1055 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
1056 SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
1057 SetWinOrg( Point( nX32, nY32 ), true);
1058 }
1059 break;
1060
1062 {
1063 mpInputStream->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
1064 SAL_INFO("emfio", "\t\tHorizontal scale: " << nNom1 << " / " << nDen1);
1065 SAL_INFO("emfio", "\t\tVertical scale: " << nNom2 << " / " << nDen2);
1066
1067 if (nDen1 != 0 && nDen2 != 0)
1068 ScaleWinExt( static_cast<double>(nNom1) / nDen1, static_cast<double>(nNom2) / nDen2 );
1069 else
1070 SAL_WARN("vcl.emf", "ignoring bogus divide by zero");
1071 }
1072 break;
1073
1075 {
1076 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
1077 SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
1078 SetDevOrg( Point( nX32, nY32 ) );
1079 }
1080 break;
1081
1083 {
1084 mpInputStream->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
1085 SAL_INFO("emfio", "\t\tHorizontal scale: " << nNom1 << " / " << nDen1);
1086 SAL_INFO("emfio", "\t\tVertical scale: " << nNom2 << " / " << nDen2);
1087
1088 if (nDen1 != 0 && nDen2 != 0)
1089 ScaleDevExt( static_cast<double>(nNom1) / nDen1, static_cast<double>(nNom2) / nDen2 );
1090 else
1091 SAL_WARN("vcl.emf", "ignoring bogus divide by zero");
1092 }
1093 break;
1094
1096 {
1097 sal_Int32 w = 0, h = 0;
1099 SAL_INFO("emfio", "\t\tWidth: " << w);
1100 SAL_INFO("emfio", "\t\tHeight: " << h);
1101
1102 SetDevExt( Size( w, h ) );
1103 }
1104 break;
1105
1106 case EMR_EOF :
1107 mnRecordCount = 0;
1108 break;
1109
1110 case EMR_SETPIXELV :
1111 {
1112 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
1113 SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
1114 DrawPixel( Point( nX32, nY32 ), ReadColor() );
1115 }
1116 break;
1117
1118 case EMR_SETMAPMODE :
1119 {
1120 sal_uInt32 nMapMode(0);
1121 mpInputStream->ReadUInt32( nMapMode );
1122 SAL_INFO("emfio", "\t\tMapMode: 0x" << std::hex << nMapMode << std::dec);
1123 SetMapMode( static_cast<MappingMode>(nMapMode) );
1124 }
1125 break;
1126
1127 case EMR_SETBKMODE :
1128 {
1129 mpInputStream->ReadUInt32( nDat32 );
1130 SAL_INFO("emfio", "\t\tBkMode: 0x" << std::hex << nDat32 << std::dec);
1131 SetBkMode( static_cast<BackgroundMode>(nDat32) );
1132 }
1133 break;
1134
1135 case EMR_SETPOLYFILLMODE :
1136 break;
1137
1138 case EMR_SETROP2 :
1139 {
1140 mpInputStream->ReadUInt32( nDat32 );
1141 SAL_INFO("emfio", "\t\tROP2: 0x" << std::hex << nDat32 << std::dec);
1142 SetRasterOp( static_cast<WMFRasterOp>(nDat32) );
1143 }
1144 break;
1145
1147 {
1148 mpInputStream->ReadUInt32( nStretchBltMode );
1149 SAL_INFO("emfio", "\t\tStretchBltMode: 0x" << std::hex << nDat32 << std::dec);
1150 }
1151 break;
1152
1153 case EMR_SETTEXTALIGN :
1154 {
1155 mpInputStream->ReadUInt32( nDat32 );
1156 SAL_INFO("emfio", "\t\tTextAlign: 0x" << std::hex << nDat32 << std::dec);
1157 SetTextAlign( nDat32 );
1158 }
1159 break;
1160
1161 case EMR_SETTEXTCOLOR :
1162 {
1164 }
1165 break;
1166
1168 {
1171 }
1172 break;
1173
1174 case EMR_SETBKCOLOR :
1175 {
1176 SetBkColor( ReadColor() );
1177 }
1178 break;
1179
1180 case EMR_OFFSETCLIPRGN :
1181 {
1182 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
1183 SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
1184 MoveClipRegion( Size( nX32, nY32 ) );
1185 }
1186 break;
1187
1188 case EMR_MOVETOEX :
1189 {
1190 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
1191 SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
1192 MoveTo( Point( nX32, nY32 ), mbRecordPath);
1193 }
1194 break;
1195
1197 {
1198 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
1199 IntersectClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
1200 SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
1201 SAL_INFO("emfio", "\t\tPoint: (" << nx32 << ", " << ny32 << ")");
1202 }
1203 break;
1204
1205 case EMR_SAVEDC :
1206 {
1207 Push();
1208 }
1209 break;
1210
1211 case EMR_RESTOREDC :
1212 {
1213 sal_Int32 nSavedDC(0);
1214 mpInputStream->ReadInt32( nSavedDC );
1215 SAL_INFO( "emfio", "\t\t SavedDC Index: " << nSavedDC );
1216 if ( nSavedDC < 0 )
1217 Pop( nSavedDC );
1218 else
1219 Pop( -1 ); // For RestoreDC values above -1, treat as get last element
1220 }
1221 break;
1222
1224 {
1225 XForm aTempXForm;
1226 *mpInputStream >> aTempXForm;
1227 SetWorldTransform( aTempXForm );
1228 }
1229 break;
1230
1232 {
1233 sal_uInt32 nMode(0);
1234 XForm aTempXForm;
1235 *mpInputStream >> aTempXForm;
1236 mpInputStream->ReadUInt32( nMode );
1237 ModifyWorldTransform( aTempXForm, static_cast<ModifyWorldTransformMode>(nMode) );
1238 }
1239 break;
1240
1241 case EMR_SELECTOBJECT :
1242 {
1245 }
1246 break;
1247
1248 case EMR_CREATEPEN:
1249 {
1251 if ((nIndex & ENHMETA_STOCK_OBJECT) == 0)
1252 {
1253 sal_uInt32 nPenStyle(0);
1254 sal_Int32 nPenWidth(0), nIgnored;
1255 mpInputStream->ReadUInt32(nPenStyle).ReadInt32(nPenWidth).ReadInt32(nIgnored);
1256 SAL_INFO("emfio", "\t\tIndex: " << nIndex << " Style: 0x" << std::hex
1257 << nPenStyle << std::dec
1258 << " PenWidth: " << nPenWidth);
1259 if ((nPenStyle & PS_STYLE_MASK) > PS_INSIDEFRAME)
1260 nPenStyle = PS_COSMETIC;
1261 if ((nPenStyle & PS_GEOMETRIC) == 0)
1262 nPenWidth = 0;
1263 CreateObjectIndexed(nIndex, std::make_unique<WinMtfLineStyle>(ReadColor(), nPenStyle, nPenWidth));
1264 }
1265 }
1266 break;
1267
1268 case EMR_EXTCREATEPEN:
1269 {
1271 if ((nIndex & ENHMETA_STOCK_OBJECT) == 0)
1272 {
1273 sal_uInt32 offBmi, cbBmi, offBits, cbBits, nPenStyle, nWidth, nBrushStyle, elpNumEntries;
1274 sal_Int32 elpHatch;
1275 mpInputStream->ReadUInt32(offBmi).ReadUInt32(cbBmi).ReadUInt32(offBits).ReadUInt32(cbBits);
1276 mpInputStream->ReadUInt32(nPenStyle).ReadUInt32(nWidth).ReadUInt32(nBrushStyle);
1277 Color aColorRef = ReadColor();
1278 mpInputStream->ReadInt32(elpHatch).ReadUInt32(elpNumEntries);
1279
1280 if (!mpInputStream->good())
1281 bStatus = false;
1282 else
1283 {
1284 SAL_INFO("emfio", "\t\tStyle: 0x" << std::hex << nPenStyle << std::dec);
1285 if ((nPenStyle & PS_STYLE_MASK) > PS_INSIDEFRAME)
1286 nPenStyle = PS_COSMETIC;
1287 if ((nPenStyle & PS_GEOMETRIC) == 0)
1288 nWidth = 0;
1289 SAL_INFO("emfio", "\t\tWidth: " << nWidth);
1290 CreateObjectIndexed(nIndex, std::make_unique<WinMtfLineStyle>(aColorRef, nPenStyle, nWidth));
1291 }
1292 }
1293 }
1294 break;
1295
1297 {
1299 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1300 {
1301 sal_uInt32 nStyle;
1302 mpInputStream->ReadUInt32( nStyle );
1303 BrushStyle eStyle = static_cast<BrushStyle>(nStyle);
1304 CreateObjectIndexed(nIndex, std::make_unique<WinMtfFillStyle>( ReadColor(), ( eStyle == BrushStyle::BS_HOLLOW ) ));
1305 }
1306 }
1307 break;
1308
1309 case EMR_DELETEOBJECT :
1310 {
1312 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1314 }
1315 break;
1316
1317 case EMR_ELLIPSE :
1318 {
1319 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
1320 SAL_INFO("emfio", "\t\t Rectangle, left: " << nX32 << ", top: " << nY32 << ", right: " << nx32 << ", bottom: " << ny32);
1321
1322 sal_Int32 w(0), h(0);
1323 if (o3tl::checked_sub(nx32, nX32, w) || o3tl::checked_sub(ny32, nY32, h))
1324 SAL_WARN("emfio", "broken ellipse");
1325 else
1326 {
1327 tools::Long dw = w / 2;
1328 tools::Long dh = h / 2;
1329 Point aCenter( nX32 + dw, nY32 + dh );
1330 tools::Polygon aPoly( aCenter, dw, dh );
1331 DrawPolygon( std::move(aPoly), mbRecordPath );
1332 }
1333 }
1334 break;
1335
1336 case EMR_RECTANGLE :
1337 {
1338 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
1339 SAL_INFO("emfio", "\t\t Rectangle, left: " << nX32 << ", top: " << nY32 << ", right: " << nx32 << ", bottom: " << ny32);
1340 Point aPoints[] { Point(nX32, nY32),
1341 Point(nx32, nY32),
1342 Point(nx32, ny32),
1343 Point(nX32, ny32) };
1344 tools::Polygon aPoly(4, aPoints);
1345 aPoly.Optimize( PolyOptimizeFlags::CLOSE );
1346 DrawPolygon( std::move(aPoly), mbRecordPath );
1347 }
1348 break;
1349
1350 case EMR_ROUNDRECT :
1351 {
1352 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nW ).ReadUInt32( nH );
1353 tools::Polygon aRoundRectPoly( ReadRectangle( nX32, nY32, nx32, ny32 ), nW, nH );
1354 DrawPolygon( std::move(aRoundRectPoly), mbRecordPath );
1355 }
1356 break;
1357
1358 case EMR_ARC :
1359 case EMR_ARCTO :
1360 case EMR_CHORD :
1361 {
1362 sal_Int32 nStartX, nStartY, nEndX, nEndY;
1363 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadInt32( nStartX ).ReadInt32( nStartY ).ReadInt32( nEndX ).ReadInt32( nEndY );
1364 if (!mpInputStream->good())
1365 bStatus = false;
1366 else
1367 {
1368 SAL_INFO( "emfio", "\t\t Bounds: " << nX32 << ":" << nY32 << ", " << nx32 << ":" << ny32 << ", Start: " << nStartX << ":" << nStartY << ", End: " << nEndX << ":" << nEndY );
1369 tools::Polygon aPoly(ReadRectangle(nX32, nY32, nx32, ny32), Point(nStartX, nStartY), Point(nEndX, nEndY), PolyStyle::Arc, IsArcDirectionClockWise());
1370
1371 if ( nRecType == EMR_CHORD )
1372 DrawPolygon( std::move(aPoly), mbRecordPath );
1373 else
1374 DrawPolyLine( std::move(aPoly), nRecType == EMR_ARCTO, mbRecordPath );
1375 }
1376 }
1377 break;
1378
1379 case EMR_PIE :
1380 {
1381 sal_Int32 nStartX, nStartY, nEndX, nEndY;
1382 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadInt32( nStartX ).ReadInt32( nStartY ).ReadInt32( nEndX ).ReadInt32( nEndY );
1383 if (!mpInputStream->good())
1384 bStatus = false;
1385 else
1386 {
1387 tools::Polygon aPoly(ReadRectangle(nX32, nY32, nx32, ny32), Point(nStartX, nStartY), Point(nEndX, nEndY), PolyStyle::Pie, IsArcDirectionClockWise());
1388 DrawPolygon( std::move(aPoly), mbRecordPath );
1389 }
1390 }
1391 break;
1392
1393 case EMR_LINETO :
1394 {
1395 mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
1396 LineTo( Point( nX32, nY32 ), mbRecordPath);
1397 }
1398 break;
1399
1400 case EMR_BEGINPATH :
1401 {
1402 ClearPath();
1403 mbRecordPath = true;
1404 }
1405 break;
1406
1407 case EMR_ABORTPATH :
1408 ClearPath();
1409 [[fallthrough]];
1410 case EMR_ENDPATH :
1411 mbRecordPath = false;
1412 break;
1413
1414 case EMR_CLOSEFIGURE :
1415 ClosePath();
1416 break;
1417
1418 case EMR_FILLPATH :
1419 StrokeAndFillPath( false, true );
1420 break;
1421
1423 StrokeAndFillPath( true, true );
1424 break;
1425
1426 case EMR_STROKEPATH :
1427 StrokeAndFillPath( true, false );
1428 break;
1429
1430 case EMR_SELECTCLIPPATH :
1431 {
1432 sal_Int32 nClippingMode(0);
1433 mpInputStream->ReadInt32(nClippingMode);
1434 SetClipPath(GetPathObj(), static_cast<RegionMode>(nClippingMode), true);
1435 }
1436 break;
1437
1439 {
1440 sal_uInt32 nRemainingRecSize = nRecSize - 8;
1441 if (nRemainingRecSize < 8)
1442 bStatus = false;
1443 else
1444 {
1445 sal_Int32 nClippingMode(0), cbRgnData(0);
1446 mpInputStream->ReadInt32(cbRgnData);
1447 mpInputStream->ReadInt32(nClippingMode);
1448 nRemainingRecSize -= 8;
1449
1450 // This record's region data should be ignored if mode
1451 // is RGN_COPY - see EMF spec section 2.3.2.2
1452 if (static_cast<RegionMode>(nClippingMode) == RegionMode::RGN_COPY)
1453 {
1455 }
1456 else
1457 {
1458 basegfx::B2DPolyPolygon aPolyPoly;
1459 if (cbRgnData)
1460 ImplReadRegion(aPolyPoly, *mpInputStream, nRemainingRecSize, GetWinOrg());
1461 const tools::PolyPolygon aPolyPolygon(aPolyPoly);
1462 SetClipPath(aPolyPolygon, static_cast<RegionMode>(nClippingMode), false);
1463 }
1464 }
1465 }
1466 break;
1467
1468 case EMR_ALPHABLEND:
1469 {
1470 sal_Int32 xDest(0), yDest(0), cxDest(0), cyDest(0);
1471
1472 BLENDFUNCTION aFunc;
1473 sal_Int32 xSrc(0), ySrc(0), cxSrc(0), cySrc(0);
1474 XForm xformSrc;
1475 sal_uInt32 BkColorSrc(0), iUsageSrc(0), offBmiSrc(0);
1476 sal_uInt32 cbBmiSrc(0), offBitsSrc(0), cbBitsSrc(0);
1477
1478 sal_uInt32 nStart = mpInputStream->Tell() - 8;
1479 mpInputStream->SeekRel( 0x10 );
1480
1481 mpInputStream->ReadInt32( xDest ).ReadInt32( yDest ).ReadInt32( cxDest ).ReadInt32( cyDest );
1482 *mpInputStream >> aFunc;
1483 mpInputStream->ReadInt32( xSrc ).ReadInt32( ySrc );
1484 *mpInputStream >> xformSrc;
1485 mpInputStream->ReadUInt32( BkColorSrc ).ReadUInt32( iUsageSrc ).ReadUInt32( offBmiSrc ).ReadUInt32( cbBmiSrc )
1486 .ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc ).ReadInt32( cxSrc ).ReadInt32( cySrc ) ;
1487
1488 if ( !mpInputStream->good() ||
1489 (cbBitsSrc > (SAL_MAX_UINT32 - 14)) ||
1490 ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) ||
1491 cxDest == SAL_MAX_INT32 || cyDest == SAL_MAX_INT32 )
1492 {
1493 bStatus = false;
1494 }
1495 else
1496 {
1497 tools::Rectangle aRect(Point(xDest, yDest), Size(cxDest + 1, cyDest + 1));
1498
1499 const sal_uInt32 nSourceSize = cbBmiSrc + cbBitsSrc + 14;
1500 bool bSafeRead = nSourceSize <= (mnEndPos - mnStartPos);
1501 sal_uInt32 nDeltaToDIB5HeaderSize(0);
1502 const bool bReadAlpha(0x01 == aFunc.aAlphaFormat);
1503 if (bSafeRead && bReadAlpha)
1504 {
1505 // we need to read alpha channel data if AlphaFormat of BLENDFUNCTION is
1506 // AC_SRC_ALPHA (==0x01). To read it, create a temp DIB-File which is ready
1507 // for DIB-5 format
1508 const sal_uInt32 nHeaderSize = getDIBV5HeaderSize();
1509 if (cbBmiSrc > nHeaderSize)
1510 bSafeRead = false;
1511 else
1512 nDeltaToDIB5HeaderSize = nHeaderSize - cbBmiSrc;
1513 }
1514 if (bSafeRead)
1515 {
1516 const sal_uInt32 nTargetSize(cbBmiSrc + nDeltaToDIB5HeaderSize + cbBitsSrc + 14);
1517 char* pBuf = new char[ nTargetSize ];
1518 SvMemoryStream aTmp( pBuf, nTargetSize, StreamMode::READ | StreamMode::WRITE );
1519
1520 aTmp.ObjectOwnsMemory( true );
1521
1522 // write BM-Header (14 bytes)
1523 aTmp.WriteUChar( 'B' )
1524 .WriteUChar( 'M' )
1525 .WriteUInt32( cbBitsSrc )
1526 .WriteUInt16( 0 )
1527 .WriteUInt16( 0 )
1528 .WriteUInt32( cbBmiSrc + nDeltaToDIB5HeaderSize + 14 );
1529
1530 // copy DIBInfoHeader from source (cbBmiSrc bytes)
1531 mpInputStream->Seek( nStart + offBmiSrc );
1532 char* pWritePos = pBuf + 14;
1533 auto nRead = mpInputStream->ReadBytes(pWritePos, cbBmiSrc);
1534 if (nRead != cbBmiSrc)
1535 {
1536 // zero remainder if short read
1537 memset(pWritePos + nRead, 0, cbBmiSrc - nRead);
1538 }
1539
1540 if (bReadAlpha)
1541 {
1542 // need to add values for all stuff that DIBV5Header is bigger
1543 // than DIBInfoHeader, all values are correctly initialized to zero,
1544 // so we can use memset here
1545 memset(pBuf + cbBmiSrc + 14, 0, nDeltaToDIB5HeaderSize);
1546 }
1547
1548 // copy bitmap data from source (offBitsSrc bytes)
1549 mpInputStream->Seek( nStart + offBitsSrc );
1550 pWritePos = pBuf + 14 + nDeltaToDIB5HeaderSize + cbBmiSrc;
1551 nRead = mpInputStream->ReadBytes(pWritePos, cbBitsSrc);
1552 if (nRead != cbBitsSrc)
1553 {
1554 // zero remainder if short read
1555 memset(pWritePos + nRead, 0, cbBitsSrc - nRead);
1556 }
1557
1558 aTmp.Seek( 0 );
1559
1560 // prepare to read and fill BitmapEx
1561 BitmapEx aBitmapEx;
1562
1563 if(bReadAlpha)
1564 {
1565 Bitmap aBitmap;
1566 AlphaMask aAlpha;
1567
1568 if(ReadDIBV5(aBitmap, aAlpha, aTmp))
1569 {
1570 aBitmapEx = BitmapEx(aBitmap, aAlpha);
1571 }
1572 }
1573 else
1574 {
1575 Bitmap aBitmap;
1576
1577 if(ReadDIB(aBitmap, aTmp, true))
1578 {
1579 if(0xff != aFunc.aSrcConstantAlpha)
1580 {
1581 // add const alpha channel
1582 aBitmapEx = BitmapEx(
1583 aBitmap,
1584 AlphaMask(aBitmap.GetSizePixel(), &aFunc.aSrcConstantAlpha));
1585 }
1586 else
1587 {
1588 // just use Bitmap
1589 aBitmapEx = BitmapEx(aBitmap);
1590 }
1591 }
1592 }
1593
1594 if(!aBitmapEx.IsEmpty())
1595 {
1596 // test if it is sensible to crop
1597 if (cxSrc > 0 && cySrc > 0 && xSrc >= 0 && ySrc >= 0)
1598 {
1599 sal_Int32 xEndSrc;
1600 sal_Int32 yEndSrc;
1601 if (!o3tl::checked_add(xSrc, cxSrc, xEndSrc) && xEndSrc < aBitmapEx.GetSizePixel().Width() &&
1602 !o3tl::checked_add(ySrc, cySrc, yEndSrc) && yEndSrc < aBitmapEx.GetSizePixel().Height())
1603 {
1604 const tools::Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
1605 aBitmapEx.Crop( aCropRect );
1606 }
1607 }
1608
1609#ifdef DBG_UTIL
1610 static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore
1611
1612 if(bDoSaveForVisualControl)
1613 {
1614 // VCL_DUMP_BMP_PATH should be like C:/path/ or ~/path/
1615 static const OUString sDumpPath(OUString::createFromAscii(std::getenv("VCL_DUMP_BMP_PATH")));
1616 if(!sDumpPath.isEmpty())
1617 {
1618 SvFileStream aNew(sDumpPath + "metafile_content.png",
1619 StreamMode::WRITE | StreamMode::TRUNC);
1620 vcl::PngImageWriter aPNGWriter(aNew);
1621 aPNGWriter.write(aBitmapEx);
1622 }
1623 }
1624#endif
1625 maBmpSaveList.emplace_back(aBitmapEx, aRect, SRCAND|SRCINVERT);
1626 }
1627 }
1628 }
1629 }
1630 break;
1631
1632 case EMR_BITBLT : // PASSTHROUGH INTENDED
1633 case EMR_STRETCHBLT :
1634 {
1635 sal_Int32 xDest, yDest, cxDest, cyDest, xSrc, ySrc, cxSrc, cySrc;
1636 sal_uInt32 dwRop, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc;
1637 XForm xformSrc;
1638
1639 sal_uInt32 nStart = mpInputStream->Tell() - 8;
1640
1641 mpInputStream->SeekRel( 0x10 );
1642 mpInputStream->ReadInt32( xDest ).ReadInt32( yDest ).ReadInt32( cxDest ).ReadInt32( cyDest ).ReadUInt32( dwRop ).ReadInt32( xSrc ).ReadInt32( ySrc )
1643 >> xformSrc;
1644 mpInputStream->ReadUInt32( nColor ).ReadUInt32( iUsageSrc ).ReadUInt32( offBmiSrc ).ReadUInt32( cbBmiSrc )
1645 .ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc );
1646
1647 if ( nRecType == EMR_STRETCHBLT )
1648 mpInputStream->ReadInt32( cxSrc ).ReadInt32( cySrc );
1649 else
1650 cxSrc = cySrc = 0;
1651
1652 if (!mpInputStream->good() || (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc))
1653 bStatus = false;
1654 else
1655 {
1656 Bitmap aBitmap;
1657 tools::Rectangle aRect(Point(xDest, yDest), Size(cxDest, cyDest));
1658
1659 sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
1660 if ( nSize <= ( mnEndPos - mnStartPos ) )
1661 {
1662 char* pBuf = new char[ nSize ];
1663 SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
1664 aTmp.ObjectOwnsMemory( true );
1665 aTmp.WriteUChar( 'B' )
1666 .WriteUChar( 'M' )
1667 .WriteUInt32( cbBitsSrc )
1668 .WriteUInt16( 0 )
1669 .WriteUInt16( 0 )
1670 .WriteUInt32( cbBmiSrc + 14 );
1671
1672 mpInputStream->Seek( nStart + offBmiSrc );
1673 char* pWritePos = pBuf + 14;
1674 auto nRead = mpInputStream->ReadBytes(pWritePos, cbBmiSrc);
1675 if (nRead != cbBmiSrc)
1676 {
1677 // zero remainder if short read
1678 memset(pWritePos + nRead, 0, cbBmiSrc - nRead);
1679 }
1680
1681 mpInputStream->Seek( nStart + offBitsSrc );
1682 pWritePos = pBuf + 14 + cbBmiSrc;
1683 nRead = mpInputStream->ReadBytes(pWritePos, cbBitsSrc);
1684 if (nRead != cbBitsSrc)
1685 {
1686 // zero remainder if short read
1687 memset(pWritePos + nRead, 0, cbBitsSrc - nRead);
1688 }
1689
1690 aTmp.Seek( 0 );
1691 ReadDIB(aBitmap, aTmp, true);
1692
1693 // test if it is sensible to crop
1694 if ( (cxSrc > 0) && (cySrc > 0) &&
1695 (xSrc >= 0) && (ySrc >= 0) &&
1696 (aBitmap.GetSizePixel().Width() >= cxSrc) &&
1697 (xSrc <= aBitmap.GetSizePixel().Width() - cxSrc) &&
1698 (aBitmap.GetSizePixel().Height() >= cySrc) &&
1699 (ySrc <= aBitmap.GetSizePixel().Height() - cySrc) )
1700 {
1701 tools::Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
1702 aBitmap.Crop( aCropRect );
1703 }
1704
1705 maBmpSaveList.emplace_back(aBitmap, aRect, dwRop);
1706 }
1707 }
1708 }
1709 break;
1710
1711 case EMR_STRETCHDIBITS :
1712 {
1713 sal_Int32 xDest, yDest, xSrc, ySrc, cxSrc, cySrc, cxDest, cyDest;
1714 sal_uInt32 offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, iUsageSrc, dwRop;
1715 sal_uInt32 nStart = mpInputStream->Tell() - 8;
1716
1717 mpInputStream->SeekRel( 0x10 );
1718 mpInputStream->ReadInt32( xDest )
1719 .ReadInt32( yDest )
1720 .ReadInt32( xSrc )
1721 .ReadInt32( ySrc )
1722 .ReadInt32( cxSrc )
1723 .ReadInt32( cySrc )
1724 .ReadUInt32( offBmiSrc )
1725 .ReadUInt32( cbBmiSrc )
1726 .ReadUInt32( offBitsSrc )
1727 .ReadUInt32( cbBitsSrc )
1728 .ReadUInt32( iUsageSrc )
1729 .ReadUInt32( dwRop )
1730 .ReadInt32( cxDest )
1731 .ReadInt32( cyDest );
1732
1733 if (!mpInputStream->good() ||
1734 ((SAL_MAX_UINT32 - 14) < cbBitsSrc) ||
1735 ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc))
1736 {
1737 bStatus = false;
1738 }
1739 else
1740 {
1741 Bitmap aBitmap;
1742 tools::Rectangle aRect(xDest, yDest);
1743 aRect.SaturatingSetSize(Size(cxDest, cyDest));
1744
1745 sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
1746 if ( nSize <= ( mnEndPos - mnStartPos ) )
1747 {
1748 char* pBuf = new char[ nSize ];
1749 SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
1750 aTmp.ObjectOwnsMemory( true );
1751 aTmp.WriteUChar( 'B' )
1752 .WriteUChar( 'M' )
1753 .WriteUInt32( cbBitsSrc )
1754 .WriteUInt16( 0 )
1755 .WriteUInt16( 0 )
1756 .WriteUInt32( cbBmiSrc + 14 );
1757
1758 mpInputStream->Seek( nStart + offBmiSrc );
1759 char* pWritePos = pBuf + 14;
1760 auto nRead = mpInputStream->ReadBytes(pWritePos, cbBmiSrc);
1761 if (nRead != cbBmiSrc)
1762 {
1763 // zero remainder if short read
1764 memset(pWritePos + nRead, 0, cbBmiSrc - nRead);
1765 }
1766
1767 mpInputStream->Seek( nStart + offBitsSrc );
1768 pWritePos = pBuf + 14 + cbBmiSrc;
1769 nRead = mpInputStream->ReadBytes(pWritePos, cbBitsSrc);
1770 if (nRead != cbBitsSrc)
1771 {
1772 // zero remainder if short read
1773 memset(pWritePos + nRead, 0, cbBitsSrc - nRead);
1774 }
1775
1776 aTmp.Seek( 0 );
1777 ReadDIB(aBitmap, aTmp, true);
1778
1779 const tools::Long nWidthDiff = aBitmap.GetSizePixel().Width() - cxSrc;
1780 const tools::Long nHeightDiff = aBitmap.GetSizePixel().Height() - cySrc;
1781
1782 // test if it is sensible to crop
1783 if ( (cxSrc > 0) && (cySrc > 0) &&
1784 (xSrc >= 0) && (ySrc >= 0) &&
1785 (xSrc <= nWidthDiff) && (ySrc <= nHeightDiff) )
1786 {
1787 tools::Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
1788 aBitmap.Crop( aCropRect );
1789 }
1790 maBmpSaveList.emplace_back(aBitmap, aRect, dwRop);
1791 }
1792 }
1793 }
1794 break;
1795
1797 {
1799 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1800 {
1801 LOGFONTW aLogFont;
1802 mpInputStream->ReadInt32( aLogFont.lfHeight )
1803 .ReadInt32( aLogFont.lfWidth )
1804 .ReadInt32( aLogFont.lfEscapement )
1805 .ReadInt32( aLogFont.lfOrientation )
1806 .ReadInt32( aLogFont.lfWeight )
1807 .ReadUChar( aLogFont.lfItalic )
1808 .ReadUChar( aLogFont.lfUnderline )
1809 .ReadUChar( aLogFont.lfStrikeOut )
1810 .ReadUChar( aLogFont.lfCharSet )
1811 .ReadUChar( aLogFont.lfOutPrecision )
1812 .ReadUChar( aLogFont.lfClipPrecision )
1813 .ReadUChar( aLogFont.lfQuality )
1814 .ReadUChar( aLogFont.lfPitchAndFamily );
1815
1816 sal_Unicode lfFaceName[LF_FACESIZE+1];
1817 lfFaceName[LF_FACESIZE] = 0;
1818 for (int i = 0; i < LF_FACESIZE; ++i)
1819 {
1820 sal_uInt16 nChar(0);
1821 mpInputStream->ReadUInt16(nChar);
1822 lfFaceName[i] = nChar;
1823 }
1824 aLogFont.alfFaceName = OUString( lfFaceName );
1825
1826 // #i123216# Not used in the test case of #121382# (always identity in XForm), also
1827 // no hints in ms docu if FontSize should be scaled with WT. Using with the example
1828 // from #i123216# creates errors, so removing.
1829
1830 // // #i121382# Need to apply WorldTransform to FontHeight/Width; this should be completely
1831 // // changed to basegfx::B2DHomMatrix instead of 'struct XForm', but not now due to time
1832 // // constraints and dangers
1833 // const XForm& rXF = GetWorldTransform();
1834 // const basegfx::B2DHomMatrix aWT(rXF.eM11, rXF.eM21, rXF.eDx, rXF.eM12, rXF.eM22, rXF.eDy);
1835 // const basegfx::B2DVector aTransVec(aWT * basegfx::B2DVector(aLogFont.lfWidth, aLogFont.lfHeight));
1836 // aLogFont.lfWidth = aTransVec.getX();
1837 // aLogFont.lfHeight = aTransVec.getY();
1838 if (mpInputStream->good() && aLogFont.lfHeight != SAL_MIN_INT32 && aLogFont.lfWidth != SAL_MIN_INT32)
1839 {
1840 CreateObjectIndexed(nIndex, std::make_unique<WinMtfFontStyle>( aLogFont ));
1841 }
1842 }
1843 }
1844 break;
1845
1846 case EMR_POLYTEXTOUTA :
1847 case EMR_EXTTEXTOUTA :
1848 bFlag = true;
1849 [[fallthrough]];
1850 case EMR_POLYTEXTOUTW :
1851 case EMR_EXTTEXTOUTW :
1852 {
1853 sal_Int32 nLeft, nTop, nRight, nBottom;
1854 sal_uInt32 nGfxMode;
1855 float nXScale, nYScale;
1856 sal_uInt32 ncStrings( 1 );
1857 sal_Int32 ptlReferenceX, ptlReferenceY;
1858 sal_uInt32 nLen, nOffString, nOptions, offDx;
1859 sal_Int32 nLeftRect, nTopRect, nRightRect, nBottomRect;
1860
1861 nCurPos = mpInputStream->Tell() - 8;
1862
1863 mpInputStream->ReadInt32( nLeft ).ReadInt32( nTop ).ReadInt32( nRight ).ReadInt32( nBottom )
1864 .ReadUInt32( nGfxMode ).ReadFloat( nXScale ).ReadFloat( nYScale );
1865 SAL_INFO("emfio", "\t\tBounds: " << nLeft << ", " << nTop << ", " << nRight << ", " << nBottom);
1866 SAL_INFO("emfio", "\t\tiGraphicsMode: 0x" << std::hex << nGfxMode << std::dec);
1867 SAL_INFO("emfio", "\t\t Scale: " << nXScale << " x " << nYScale);
1868 if ( ( nRecType == EMR_POLYTEXTOUTA ) || ( nRecType == EMR_POLYTEXTOUTW ) )
1869 {
1870 mpInputStream->ReadUInt32( ncStrings );
1871 SAL_INFO("emfio", "\t\t Number of Text objects: " << ncStrings);
1872 if ( ncStrings == 0 )
1873 break;
1874 }
1875 mpInputStream->ReadInt32( ptlReferenceX ).ReadInt32( ptlReferenceY ).ReadUInt32( nLen ).ReadUInt32( nOffString ).ReadUInt32( nOptions );
1876 SAL_INFO("emfio", "\t\tReference: (" << ptlReferenceX << ", " << ptlReferenceY << ")");
1877
1878 mpInputStream->ReadInt32( nLeftRect ).ReadInt32( nTopRect ).ReadInt32( nRightRect ).ReadInt32( nBottomRect );
1879 mpInputStream->ReadUInt32( offDx );
1880
1881 if (!mpInputStream->good())
1882 bStatus = false;
1883 else
1884 {
1885 const tools::Rectangle aRect( nLeftRect, nTopRect, nRightRect, nBottomRect );
1886 const BackgroundMode mnBkModeBackup = mnBkMode;
1887 if ( nOptions & ETO_NO_RECT ) // Don't draw the background rectangle and text background
1889 else if ( nOptions & ETO_OPAQUE )
1890 DrawRectWithBGColor( aRect );
1891
1892 // ETO_RTLREADING indicates that the characters are laid from right to left
1894 if ( nOptions & ETO_RTLREADING )
1896 SetTextLayoutMode( nTextLayoutMode );
1897 SAL_WARN_IF( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) != 0, "emfio", "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
1898
1899 Point aPos( ptlReferenceX, ptlReferenceY );
1900 bool bOffStringSane = nOffString <= mnEndPos - nCurPos;
1901 if ( bOffStringSane )
1902 {
1903 mpInputStream->Seek( nCurPos + nOffString );
1904 OUString aText;
1905 if ( bFlag )
1906 {
1907 if ( nLen <= ( mnEndPos - mpInputStream->Tell() ) )
1908 {
1909 std::vector<char> pBuf( nLen );
1910 mpInputStream->ReadBytes(pBuf.data(), nLen);
1911 aText = OUString(pBuf.data(), nLen, GetCharSet());
1912 }
1913 }
1914 else
1915 {
1916 if ( ( nLen * sizeof(sal_Unicode) ) <= ( mnEndPos - mpInputStream->Tell() ) )
1917 {
1918 aText = read_uInt16s_ToOUString(*mpInputStream, nLen);
1919 }
1920 }
1921
1922 SAL_INFO("emfio", "\t\tText: " << aText);
1923 SAL_INFO("emfio", "\t\tDxBuffer:");
1924
1925 KernArray aDXAry;
1926 std::unique_ptr<tools::Long[]> pDYAry;
1927
1928 sal_Int32 nDxSize;
1929 sal_Int32 nBytesEach;
1930
1931 // Reading OutputDx
1932 // ETO_PDY flag indicates that we should read twice values
1933 // compared to the number of characters in the output string.
1934 // Values are stored in an array of 32-bit unsigned integers
1935 // named OutputDx, so there will be either 8 bytes or 4 bytes
1936 // each depending on ETO_PDY is set or not.
1937 if (nOptions & ETO_PDY)
1938 nBytesEach = 8;
1939 else
1940 nBytesEach = 4;
1941
1942 bool bOverflow = o3tl::checked_multiply<sal_Int32>(nLen, nBytesEach, nDxSize);
1943 if (!bOverflow && offDx && ((nCurPos + offDx + nDxSize) <= nNextPos ) && nNextPos <= mnEndPos)
1944 {
1945 mpInputStream->Seek( nCurPos + offDx );
1946 aDXAry.resize(aText.getLength());
1947 if (nOptions & ETO_PDY)
1948 {
1949 pDYAry.reset( new tools::Long[aText.getLength()] );
1950 }
1951
1952 for (sal_Int32 i = 0; i < aText.getLength(); ++i)
1953 {
1954 sal_Int32 nDxCount = 1;
1955 if ( static_cast<sal_uInt32>( aText.getLength() ) != nLen )
1956 {
1957 sal_Unicode cUniChar = aText[i];
1958 OString aTmp(&cUniChar, 1, GetCharSet());
1959 if (aTmp.getLength() > 1)
1960 {
1961 nDxCount = aTmp.getLength();
1962 }
1963 }
1964
1965 aDXAry.set(i, 0);
1966 if (nOptions & ETO_PDY)
1967 {
1968 pDYAry[i] = 0;
1969 }
1970
1971 while (nDxCount--)
1972 {
1973 sal_Int32 nDxTmp = 0;
1974 mpInputStream->ReadInt32(nDxTmp);
1975 aDXAry.set(i, o3tl::saturating_add(aDXAry[i], nDxTmp));
1976 if (nOptions & ETO_PDY)
1977 {
1978 sal_Int32 nDyTmp = 0;
1979 mpInputStream->ReadInt32(nDyTmp);
1980 pDYAry[i] += nDyTmp;
1981 }
1982 }
1983
1984 SAL_INFO("emfio", "\t\t\tSpacing " << i << ": " << aDXAry[i]);
1985 }
1986 }
1987 if ( nOptions & ETO_CLIPPED )
1988 {
1989 Push(); // Save the current clip. It will be restored after text drawing
1990 IntersectClipRect( aRect );
1991 }
1992 DrawText(aPos, aText, aDXAry.empty() ? nullptr : &aDXAry, pDYAry.get(), mbRecordPath, static_cast<GraphicsMode>(nGfxMode));
1993 if ( nOptions & ETO_CLIPPED )
1994 Pop();
1995 }
1996 mnBkMode = mnBkModeBackup;
1997 }
1998 }
1999 break;
2000
2001 case EMR_POLYBEZIERTO16 :
2002 DrawPolyBezier(ReadPolygonWithSkip<sal_Int16>(true, nNextPos), true, mbRecordPath);
2003 break;
2004
2005 case EMR_POLYBEZIER16 :
2006 DrawPolyBezier(ReadPolygonWithSkip<sal_Int16>(false, nNextPos), false, mbRecordPath);
2007 break;
2008
2009 case EMR_POLYGON16 :
2010 DrawPolygon(ReadPolygonWithSkip<sal_Int16>(false, nNextPos), mbRecordPath);
2011 break;
2012
2013 case EMR_POLYLINETO16 :
2014 DrawPolyLine(ReadPolygonWithSkip<sal_Int16>(true, nNextPos), true, mbRecordPath);
2015 break;
2016
2017 case EMR_POLYLINE16 :
2018 DrawPolyLine(ReadPolygonWithSkip<sal_Int16>(false, nNextPos), false, mbRecordPath);
2019 break;
2020
2021 case EMR_POLYPOLYLINE16 :
2022 ReadAndDrawPolyLine<sal_Int16>(nNextPos);
2023 break;
2024
2025 case EMR_POLYPOLYGON16 :
2026 ReadAndDrawPolyPolygon<sal_Int16>(nNextPos);
2027 break;
2028
2029 case EMR_FILLRGN :
2030 {
2031 sal_uInt32 nRemainingRecSize = nRecSize - 8;
2032 if (nRemainingRecSize < 24)
2033 bStatus = false;
2034 else
2035 {
2036 sal_uInt32 nRgnDataSize;
2037 basegfx::B2DPolyPolygon aPolyPoly;
2038 mpInputStream->SeekRel(16); // RectL bounds
2039 mpInputStream->ReadUInt32( nRgnDataSize ).ReadUInt32( nIndex );
2040 nRemainingRecSize -= 24;
2041
2042 if (ImplReadRegion(aPolyPoly, *mpInputStream, nRemainingRecSize, GetWinOrg()))
2043 {
2044 Push();
2046 tools::PolyPolygon aPolyPolygon(aPolyPoly);
2047 DrawPolyPolygon( aPolyPolygon );
2048 Pop();
2049 }
2050 }
2051 }
2052 break;
2053
2054 case EMR_PAINTRGN :
2055 {
2056 sal_uInt32 nRemainingRecSize = nRecSize - 8;
2057 if (nRemainingRecSize < 20)
2058 bStatus = false;
2059 else
2060 {
2061 sal_uInt32 nRgnDataSize;
2062 basegfx::B2DPolyPolygon aPolyPoly;
2063 mpInputStream->SeekRel(16); // Skipping RectL bounds
2064 mpInputStream->ReadUInt32( nRgnDataSize );
2065 nRemainingRecSize -= 20;
2066
2067 if (ImplReadRegion(aPolyPoly, *mpInputStream, nRemainingRecSize, GetWinOrg()))
2068 {
2069 tools::PolyPolygon aPolyPolygon(aPolyPoly);
2070 DrawPolyPolygon( aPolyPolygon );
2071 }
2072 }
2073 }
2074 break;
2075
2077 {
2078 sal_uInt32 nStart = mpInputStream->Tell() - 8;
2079 Bitmap aBitmap;
2080
2082
2083 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
2084 {
2085 sal_uInt32 usage, offBmi, cbBmi, offBits, cbBits;
2086
2087 mpInputStream->ReadUInt32( usage );
2088 mpInputStream->ReadUInt32( offBmi );
2089 mpInputStream->ReadUInt32( cbBmi );
2090 mpInputStream->ReadUInt32( offBits );
2091 mpInputStream->ReadUInt32( cbBits );
2092
2093 if ( !mpInputStream->good() || (cbBits > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBits < cbBmi) )
2094 bStatus = false;
2095 else if ( offBmi )
2096 {
2097 sal_uInt32 nSize = cbBmi + cbBits + 14;
2098 if ( nSize <= ( mnEndPos - mnStartPos ) )
2099 {
2100 char* pBuf = new char[ nSize ];
2101
2102 SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
2103 aTmp.ObjectOwnsMemory( true );
2104 aTmp.WriteUChar( 'B' )
2105 .WriteUChar( 'M' )
2106 .WriteUInt32( cbBits )
2107 .WriteUInt16( 0 )
2108 .WriteUInt16( 0 )
2109 .WriteUInt32( cbBmi + 14 );
2110
2111 mpInputStream->Seek( nStart + offBmi );
2112 char* pWritePos = pBuf + 14;
2113 auto nRead = mpInputStream->ReadBytes(pWritePos, cbBmi);
2114 if (nRead != cbBmi)
2115 {
2116 // zero remainder if short read
2117 memset(pWritePos + nRead, 0, cbBmi - nRead);
2118 }
2119
2120 mpInputStream->Seek( nStart + offBits );
2121 pWritePos = pBuf + 14 + cbBmi;
2122 nRead = mpInputStream->ReadBytes(pWritePos, cbBits);
2123 if (nRead != cbBits)
2124 {
2125 // zero remainder if short read
2126 memset(pWritePos + nRead, 0, cbBits - nRead);
2127 }
2128
2129 aTmp.Seek( 0 );
2130 ReadDIB(aBitmap, aTmp, true);
2131 }
2132 }
2133 }
2134
2135 CreateObjectIndexed(nIndex, std::make_unique<WinMtfFillStyle>( aBitmap ));
2136 }
2137 break;
2138
2139 case EMR_MASKBLT :
2140 case EMR_PLGBLT :
2142 case EMR_FRAMERGN :
2143 case EMR_INVERTRGN :
2144 case EMR_FLATTENPATH :
2145 case EMR_WIDENPATH :
2147 case EMR_RESIZEPALETTE :
2148 case EMR_EXTFLOODFILL :
2149 case EMR_ANGLEARC :
2151 case EMR_POLYDRAW16 :
2153 case EMR_SETCOLORSPACE :
2155 case EMR_GLSRECORD :
2157 case EMR_PIXELFORMAT :
2158 case EMR_DRAWESCAPE :
2159 case EMR_EXTESCAPE :
2160 case EMR_STARTDOC :
2161 case EMR_SMALLTEXTOUT :
2162 case EMR_FORCEUFIMAPPING :
2163 case EMR_NAMEDESCAPE :
2165 case EMR_SETICMPROFILEA :
2166 case EMR_SETICMPROFILEW :
2167 case EMR_TRANSPARENTBLT :
2168 case EMR_TRANSPARENTDIB :
2169 case EMR_GRADIENTFILL :
2170 case EMR_SETLINKEDUFIS :
2171 case EMR_SETMAPPERFLAGS :
2172 case EMR_SETICMMODE :
2173 case EMR_CREATEMONOBRUSH :
2174 case EMR_SETBRUSHORGEX :
2175 case EMR_SETMETARGN :
2176 case EMR_SETMITERLIMIT :
2177 case EMR_EXCLUDECLIPRECT :
2178 case EMR_REALIZEPALETTE :
2179 case EMR_SELECTPALETTE :
2180 case EMR_CREATEPALETTE :
2181 case EMR_ALPHADIBBLEND :
2183 {
2184 SAL_WARN("emfio", "TODO: EMF record not implemented: " << record_type_name(nRecType));
2185 }
2186 break;
2187
2188 case EMR_COMMENT :
2189 case EMR_HEADER : // has already been read at ReadHeader()
2190 break;
2191
2192 default : SAL_INFO("emfio", "Unknown Meta Action"); break;
2193 }
2194 }
2195 mpInputStream->Seek( nNextPos );
2196 }
2197
2198 // tdf#127471
2200
2201 if( !maBmpSaveList.empty() )
2203
2204 if ( bStatus )
2206
2207 return bStatus;
2208 };
2209
2211 {
2212 // Spare me the METAFILEHEADER here
2213 // Reading the METAHEADER - EMR_HEADER ([MS-EMF] section 2.3.4.2 EMR_HEADER Record Types)
2214 sal_uInt32 nType(0), nHeaderSize(0);
2216 SAL_INFO ("emfio", "0x0-0x" << std::hex << nHeaderSize << " " << record_type_name(nType) << " size: " << std::dec << nHeaderSize);
2217 if (nType != 0x00000001)
2218 {
2219 // per [MS-EMF] 2.3.4.2 EMF Header Record Types, type MUST be 0x00000001
2220 SAL_WARN("emfio", "EMF header type is not set to 0x00000001 - possibly corrupted file?");
2221 return false;
2222 }
2223
2224 // Start reading the EMR_HEADER Header object
2225
2226 // bound size (RectL object, see [MS-WMF] section 2.2.2.19)
2227 SAL_INFO("emfio", "\tBounding rectangle");
2228 tools::Rectangle rclBounds = ReadRectangle(); // rectangle in logical units
2229
2230 // picture frame size (RectL object)
2231 SAL_INFO("emfio", "\tPicture frame");
2232 tools::Rectangle rclFrame = ReadRectangle(); // rectangle in device units 1/100th mm
2233
2234 sal_uInt32 nSignature(0);
2235 mpInputStream->ReadUInt32(nSignature);
2236 SAL_INFO("emfio", "\tSignature: 0x" << std::hex << nSignature << std::dec);
2237
2238 // nSignature MUST be the ASCII characters "FME", see [WS-EMF] 2.2.9 Header Object
2239 // and 2.1.14 FormatSignature Enumeration
2240 if (nSignature != 0x464d4520)
2241 {
2242 SAL_WARN("emfio", "EMF\t\tSignature is not 0x464d4520 (\"FME\") - possibly corrupted file?");
2243 return false;
2244 }
2245
2246 sal_uInt32 nVersion(0);
2247 mpInputStream->ReadUInt32(nVersion); // according to [WS-EMF] 2.2.9, this SHOULD be 0x0001000, however
2248 // Microsoft note that not even Windows checks this...
2249 SAL_INFO("emfio", "\tVersion: 0x" << std::hex << nVersion << std::dec);
2250 if (nVersion != 0x00010000)
2251 {
2252 SAL_WARN("emfio", "EMF\t\tThis really should be 0x00010000, though not absolutely essential...");
2253 }
2254
2255 mpInputStream->ReadUInt32(mnEndPos); // size of metafile
2256 SAL_INFO("emfio", "\tMetafile size: " << mnEndPos);
2258
2259 sal_uInt32 nStrmPos = mpInputStream->Tell(); // checking if mnEndPos is valid
2260 sal_uInt32 nActualFileSize = nStrmPos + mpInputStream->remainingSize();
2261
2262 if ( nActualFileSize < mnEndPos )
2263 {
2264 SAL_WARN("emfio", "EMF\t\tEMF Header object records number of bytes as " << mnEndPos
2265 << ", however the file size is actually " << nActualFileSize
2266 << " bytes. Possible file corruption?");
2267 mnEndPos = nActualFileSize;
2268 }
2269
2271 SAL_INFO("emfio", "\tRecords: " << mnRecordCount);
2272
2273 // the number of "handles", or graphics objects used in the metafile
2274
2275 sal_uInt16 nHandlesCount;
2276 mpInputStream->ReadUInt16(nHandlesCount);
2277 SAL_INFO("emfio", "\tGraphics: " << nHandlesCount);
2278
2279 // the next 2 bytes are reserved, but according to [MS-EMF] section 2.2.9
2280 // it MUST be 0x000 and MUST be ignored... the thing is, having such a specific
2281 // value is actually pretty useful in checking if there is possible corruption
2282
2283 sal_uInt16 nReserved(0);
2284 mpInputStream->ReadUInt16(nReserved);
2285 SAL_INFO("emfio", "\tReserved: 0x" << std::hex << nReserved << std::dec);
2286
2287 if ( nReserved != 0x0000 )
2288 {
2289 SAL_WARN("emfio", "EMF\t\tEMF Header object's reserved field is NOT 0x0000... possible "
2290 "corruption?");
2291 }
2292
2293 // The next 4 bytes specifies the number of characters in the metafile description.
2294 // The 4 bytes after that specific the offset from this record that contains the
2295 // metafile description... zero means no description string.
2296 // For now, we ignore it.
2297
2298 mpInputStream->SeekRel(0x8);
2299
2300 sal_uInt32 nPalEntries(0);
2301 mpInputStream->ReadUInt32(nPalEntries);
2302 SAL_INFO("emfio", "\tPalette entries: " << nPalEntries);
2303 sal_Int32 nPixX(0), nPixY(0), nMillX(0), nMillY(0);
2304 mpInputStream->ReadInt32(nPixX);
2305 mpInputStream->ReadInt32(nPixY);
2306 SAL_INFO("emfio", "\tRef (pixels): " << nPixX << ", " << nPixY);
2307 mpInputStream->ReadInt32(nMillX);
2308 mpInputStream->ReadInt32(nMillY);
2309 SAL_INFO("emfio", "\tRef (mm): " << nMillX << ", " << nMillY);
2310
2311 SetrclFrame(rclFrame);
2312 SetrclBounds(rclBounds);
2313 SetRefPix(Size( nPixX, nPixY ) );
2314 SetRefMill(Size( nMillX, nMillY ) );
2315
2316 return checkSeek(*mpInputStream, mnStartPos + nHeaderSize);
2317 }
2318
2320 {
2321 sal_Int32 nLeft(0), nTop(0), nRight(0), nBottom(0);
2322 mpInputStream->ReadInt32(nLeft);
2323 mpInputStream->ReadInt32(nTop);
2324 mpInputStream->ReadInt32(nRight);
2325 mpInputStream->ReadInt32(nBottom);
2326
2327 SAL_INFO("emfio", "\t\tLeft: " << nLeft << ", top: " << nTop << ", right: " << nRight << ", bottom: " << nBottom);
2328 if (nLeft > nRight || nTop > nBottom)
2329 {
2330 SAL_WARN("emfio", "broken rectangle");
2331 return tools::Rectangle::Normalize(Point(nLeft, nTop), Point(nRight, nBottom));
2332 }
2333
2334 return tools::Rectangle(nLeft, nTop, nRight, nBottom);
2335 }
2336
2337 tools::Rectangle EmfReader::ReadRectangle( sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
2338 {
2339 Point aTL(x1, y1);
2340 Point aBR(o3tl::saturating_add<sal_Int32>(x2, -1), o3tl::saturating_add<sal_Int32>(y2, -1));
2341 return tools::Rectangle(aTL, aBR);
2342 }
2343}
2344
2345/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsEmpty() const
bool Crop(const tools::Rectangle &rRectPixel)
const Size & GetSizePixel() const
bool Crop(const tools::Rectangle &rRectPixel)
Size GetSizePixel() const
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
const std::shared_ptr< VectorGraphicData > & getVectorGraphicData() const
void resize(size_t nSize)
sal_Int32 get(size_t nIndex) const
void set(size_t nIndex, sal_Int32 nValue)
bool empty() const
constexpr tools::Long Y() const
constexpr tools::Long X() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
void ObjectOwnsMemory(bool bOwn)
sal_uInt64 Tell() const
bool good() const
SvStream & ReadInt16(sal_Int16 &rInt16)
std::size_t WriteBytes(const void *pData, std::size_t nSize)
SvStream & WriteUChar(unsigned char nChar)
SvStream & WriteUInt16(sal_uInt16 nUInt16)
SvStream & ReadFloat(float &rFloat)
SvStream & WriteUInt32(sal_uInt32 nUInt32)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
sal_uInt64 Seek(sal_uInt64 nPos)
void Flush()
SvStream & ReadInt32(sal_Int32 &rInt32)
std::size_t ReadBytes(void *pData, std::size_t nSize)
sal_uInt64 SeekRel(sal_Int64 nPos)
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
sal_uInt64 remainingSize()
SvStream & ReadUChar(unsigned char &rChar)
SvStream & WriteStream(SvStream &rStream)
void append(const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
basegfx::B2DTuple maSizeHint
Definition: emfreader.hxx:35
tools::Polygon ReadPolygonWithSkip(const bool skipFirst, sal_uInt32 nNextPos)
Reads polygons from the stream.
Definition: emfreader.cxx:645
void ReadAndDrawPolyLine(sal_uInt32 nNextPos)
Reads a polyline from the WMF file and draws it The <class T> parameter refers to the type of the poi...
Definition: emfreader.cxx:710
bool mbReadOtherGraphicFormat
Another format is read already, can ignore actual EMF data.
Definition: emfreader.hxx:34
tools::Rectangle ReadRectangle()
Definition: emfreader.cxx:2319
EmfReader(SvStream &rStreamWMF, GDIMetaFile &rGDIMetaFile)
Definition: emfreader.cxx:402
bool mbEMFPlusDualMode
Definition: emfreader.hxx:32
void ReadEMFPlusComment(sal_uInt32 length, bool &bHaveDC)
Definition: emfreader.cxx:554
void ReadMultiformatsComment()
Parses EMR_COMMENT_MULTIFORMATS.
Definition: emfreader.cxx:477
tools::Polygon ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints, sal_uInt32 nNextPos)
Reads polygons from the stream.
Definition: emfreader.cxx:667
void ReadGDIComment(sal_uInt32 nCommentId)
Definition: emfreader.cxx:420
void ReadAndDrawPolyPolygon(sal_uInt32 nNextPos)
Reads a poly polygon from the WMF file and draws it.
Definition: emfreader.cxx:757
sal_uInt32 mnRecordCount
Definition: emfreader.hxx:28
void PassEMFPlus(void const *pBuffer, sal_uInt32 nLength)
Definition: mtftools.cxx:2522
void DrawPolygon(tools::Polygon rPolygon, bool bRecordPath)
Definition: mtftools.cxx:1488
bool IsArcDirectionClockWise()
Definition: mtftools.hxx:755
Color ReadColor()
Definition: mtftools.cxx:481
void SetMapMode(MappingMode mnMapMode)
Definition: mtftools.cxx:2259
void ScaleDevExt(double fX, double fY)
Definition: mtftools.cxx:2167
void LineTo(const Point &rPoint, bool bRecordPath=false)
Definition: mtftools.cxx:1308
void ScaleWinExt(double fX, double fY)
Definition: mtftools.cxx:2231
void SetArcDirection(bool bCounterClockWise)
Definition: mtftools.cxx:862
void SetDevOrg(const Point &rPoint)
Definition: mtftools.cxx:2130
WMFRasterOp SetRasterOp(WMFRasterOp nRasterOp)
Definition: mtftools.cxx:1205
void SetWinExt(const Size &rSize, bool bIsEMF=false)
Definition: mtftools.cxx:2205
void SetTextAlign(sal_uInt32 nAlign)
Definition: mtftools.cxx:883
void SetWorldTransform(const XForm &rXForm)
Definition: mtftools.cxx:2280
void DrawPolyLine(tools::Polygon rPolygon, bool bDrawTo=false, bool bRecordPath=false)
Definition: mtftools.cxx:1594
void SetClipPath(const tools::PolyPolygon &rPolyPoly, RegionMode nClippingMode, bool bIsMapped)
Definition: mtftools.cxx:1039
void SetrclBounds(const tools::Rectangle &rRect)
Definition: mtftools.cxx:2237
void StrokeAndFillPath(bool bStroke, bool bFill)
Definition: mtftools.cxx:1252
void IntersectClipRect(const tools::Rectangle &rRect)
Definition: mtftools.cxx:1007
std::vector< BSaveStruct > maBmpSaveList
Definition: mtftools.hxx:695
void CreateObjectIndexed(sal_uInt32 nIndex, std::unique_ptr< GDIObj > pObject)
Definition: mtftools.cxx:954
void SetDefaultClipPath()
Definition: mtftools.cxx:1056
void PassEMFPlusHeaderInfo()
Definition: mtftools.cxx:2489
void SetDevExt(const Size &rSize, bool regular=true)
Definition: mtftools.cxx:2142
BackgroundMode mnBkMode
Definition: mtftools.hxx:661
void SetrclFrame(const tools::Rectangle &rRect)
Definition: mtftools.cxx:2242
void ResolveBitmapActions(std::vector< BSaveStruct > &rSaveList)
Definition: mtftools.cxx:1883
const tools::PolyPolygon & GetPathObj() const
Definition: mtftools.hxx:775
SvStream * mpInputStream
Definition: mtftools.hxx:692
void ClosePath()
Definition: mtftools.hxx:774
void SetRefMill(const Size &rSize)
Definition: mtftools.cxx:2253
sal_uInt32 mnEndPos
Definition: mtftools.hxx:694
void SetWinOrg(const Point &rPoint, bool bIsEMF=false)
Definition: mtftools.cxx:2173
void ClearPath()
Definition: mtftools.hxx:773
void MoveTo(const Point &rPoint, bool bRecordPath=false)
Definition: mtftools.cxx:1294
void ModifyWorldTransform(const XForm &rXForm, ModifyWorldTransformMode nMode)
Definition: mtftools.cxx:2290
void DrawPolyPolygon(tools::PolyPolygon &rPolyPolygon, bool bRecordPath=false)
Definition: mtftools.cxx:1561
void DrawText(Point &rPosition, OUString const &rString, KernArray *pDXArry=nullptr, tools::Long *pDYArry=nullptr, bool bRecordPath=false, GraphicsMode nGraphicsMode=GraphicsMode::GM_COMPATIBLE)
Definition: mtftools.cxx:1649
sal_uInt32 mnStartPos
Definition: mtftools.hxx:693
void SetBkColor(const Color &rColor)
Definition: mtftools.cxx:873
void DeleteObject(sal_uInt32 nIndex)
Definition: mtftools.cxx:996
void Pop(const sal_Int32 nSavedDC=-1)
Definition: mtftools.cxx:2413
void DrawRectWithBGColor(const tools::Rectangle &rRect)
Definition: mtftools.cxx:1322
ScaledFontDetectCorrectHelper maScaledFontHelper
Definition: mtftools.hxx:698
void SetTextLayoutMode(vcl::text::ComplexTextLayoutFlags nLayoutMode)
Definition: mtftools.cxx:857
Point GetWinOrg()
Definition: mtftools.hxx:734
void SelectObject(sal_uInt32 nIndex)
Definition: mtftools.cxx:748
void SetBkMode(BackgroundMode nMode)
Definition: mtftools.cxx:868
void DrawPolyBezier(tools::Polygon rPolygon, bool bDrawTo, bool bRecordPath)
Definition: mtftools.cxx:1617
void SetRefPix(const Size &rSize)
Definition: mtftools.cxx:2247
rtl_TextEncoding GetCharSet() const
Definition: mtftools.hxx:769
void SetTextColor(const Color &rColor)
Definition: mtftools.cxx:878
void MoveClipRegion(const Size &rSize)
Definition: mtftools.cxx:1031
void DrawPixel(const Point &rSource, const Color &rColor)
Definition: mtftools.cxx:1289
void Insert(const tools::Polygon &rPoly, sal_uInt16 nPos=POLYPOLY_APPEND)
void SetSize(sal_uInt16 nNewSize)
void Optimize(PolyOptimizeFlags nOptimizeFlags)
void SaturatingSetSize(const Size &rSize)
static bool IsFuzzing()
bool write(const BitmapEx &rBitmap)
int nCount
sal_uInt32 VCL_DLLPUBLIC getDIBV5HeaderSize()
bool VCL_DLLPUBLIC ReadDIBV5(Bitmap &rTarget, AlphaMask &rTargetAlpha, SvStream &rIStm)
bool VCL_DLLPUBLIC ReadDIB(Bitmap &rTarget, SvStream &rIStm, bool bFileHeader, bool bMSOFormat=false)
OString right
OString top
OString bottom
#define EMR_COMMENT_EMFPLUS
Definition: emfreader.cxx:111
#define EMR_INTERSECTCLIPRECT
Definition: emfreader.cxx:69
#define EMR_POLYPOLYLINE
Definition: emfreader.cxx:46
#define EMR_STRETCHBLT
Definition: emfreader.cxx:121
#define EMR_SAVEDC
Definition: emfreader.cxx:72
#define EMR_POLYTEXTOUTW
Definition: emfreader.cxx:141
#define EMR_FRAMERGN
Definition: emfreader.cxx:116
#define EMR_SELECTCLIPPATH
Definition: emfreader.cxx:106
#define EMR_SETWINDOWEXTEX
Definition: emfreader.cxx:48
#define EMR_SETTEXTCOLOR
Definition: emfreader.cxx:63
#define EMR_SETVIEWPORTEXTEX
Definition: emfreader.cxx:50
#define EMR_EXTTEXTOUTA
Definition: emfreader.cxx:127
#define EMR_SETTEXTALIGN
Definition: emfreader.cxx:61
#define EMR_POLYBEZIER16
Definition: emfreader.cxx:129
#define EMR_CREATEPALETTE
Definition: emfreader.cxx:88
#define EMR_BITBLT
Definition: emfreader.cxx:120
#define EMR_SELECTOBJECT
Definition: emfreader.cxx:76
#define EMR_EXTSELECTCLIPRGN
Definition: emfreader.cxx:119
#define EMR_SMALLTEXTOUT
Definition: emfreader.cxx:156
#define EMR_SETICMPROFILEA
Definition: emfreader.cxx:160
#define EMR_DRAWESCAPE
Definition: emfreader.cxx:153
#define EMR_SETMAPPERFLAGS
Definition: emfreader.cxx:55
#define EMR_POLYLINE
Definition: emfreader.cxx:43
#define EMR_SETMITERLIMIT
Definition: emfreader.cxx:97
#define EMR_POLYDRAW16
Definition: emfreader.cxx:136
#define EMR_POLYLINETO16
Definition: emfreader.cxx:133
#define EMR_SETCOLORADJUSTMENT
Definition: emfreader.cxx:62
#define EMR_NAMEDESCAPE
Definition: emfreader.cxx:158
#define EMR_RESTOREDC
Definition: emfreader.cxx:73
#define EMR_POLYLINE16
Definition: emfreader.cxx:131
#define EMR_POLYGON
Definition: emfreader.cxx:42
#define EMR_PIE
Definition: emfreader.cxx:86
#define EMR_SETMETARGN
Definition: emfreader.cxx:67
#define EMR_STROKEANDFILLPATH
Definition: emfreader.cxx:102
#define EMR_PAINTRGN
Definition: emfreader.cxx:118
#define EMR_LINETO
Definition: emfreader.cxx:93
#define EMR_EXTTEXTOUTW
Definition: emfreader.cxx:128
#define EMR_PLGBLT
Definition: emfreader.cxx:123
#define EMR_COMMENT_PUBLIC
Definition: emfreader.cxx:113
#define EMR_EXTCREATEPEN
Definition: emfreader.cxx:139
#define EMR_MOVETOEX
Definition: emfreader.cxx:66
#define EMR_STARTDOC
Definition: emfreader.cxx:155
#define EMR_EXTESCAPE
Definition: emfreader.cxx:154
#define EMR_EXCLUDECLIPRECT
Definition: emfreader.cxx:68
#define EMR_GLSRECORD
Definition: emfreader.cxx:148
#define EMR_FLATTENPATH
Definition: emfreader.cxx:104
#define EMR_CLOSEFIGURE
Definition: emfreader.cxx:100
#define EMR_CREATEMONOBRUSH
Definition: emfreader.cxx:137
#define EMR_SETBKCOLOR
Definition: emfreader.cxx:64
#define EMR_RECTANGLE
Definition: emfreader.cxx:82
#define EMR_COMMENT_EMFSPOOL
Definition: emfreader.cxx:112
#define EMR_WIDENPATH
Definition: emfreader.cxx:105
#define EMR_EOF
Definition: emfreader.cxx:53
#define EMR_SELECTPALETTE
Definition: emfreader.cxx:87
#define EMR_GLSBOUNDEDRECORD
Definition: emfreader.cxx:149
#define EMR_STRETCHDIBITS
Definition: emfreader.cxx:125
#define EMR_POLYLINETO
Definition: emfreader.cxx:45
#define EMR_SETICMPROFILEW
Definition: emfreader.cxx:161
#define EMR_SETLINKEDUFIS
Definition: emfreader.cxx:167
#define EMR_GRADIENTFILL
Definition: emfreader.cxx:166
#define EMR_ANGLEARC
Definition: emfreader.cxx:80
#define EMR_ELLIPSE
Definition: emfreader.cxx:81
#define EMR_POLYPOLYGON16
Definition: emfreader.cxx:135
#define EMR_SETARCDIRECTION
Definition: emfreader.cxx:96
#define EMR_SETSTRETCHBLTMODE
Definition: emfreader.cxx:60
#define EMR_POLYGON16
Definition: emfreader.cxx:130
#define EMR_SETPALETTEENTRIES
Definition: emfreader.cxx:89
#define EMR_ALPHADIBBLEND
Definition: emfreader.cxx:163
#define EMR_FILLPATH
Definition: emfreader.cxx:101
#define EMR_TRANSPARENTDIB
Definition: emfreader.cxx:165
#define EMR_OFFSETCLIPRGN
Definition: emfreader.cxx:65
#define EMR_REALIZEPALETTE
Definition: emfreader.cxx:91
#define EMR_SETICMMODE
Definition: emfreader.cxx:144
#define EMR_SETCOLORSPACE
Definition: emfreader.cxx:146
#define EMR_DELETEOBJECT
Definition: emfreader.cxx:79
#define EMR_SETPOLYFILLMODE
Definition: emfreader.cxx:58
#define EMR_SETWINDOWORGEX
Definition: emfreader.cxx:49
#define EMR_EXTCREATEFONTINDIRECTW
Definition: emfreader.cxx:126
#define EMR_ARCTO
Definition: emfreader.cxx:94
#define EMR_EXTFLOODFILL
Definition: emfreader.cxx:92
#define EMR_SETPIXELV
Definition: emfreader.cxx:54
#define EMR_SETBRUSHORGEX
Definition: emfreader.cxx:52
#define EMR_INVERTRGN
Definition: emfreader.cxx:117
#define PDF_SIGNATURE
Definition: emfreader.cxx:170
constexpr sal_Int32 ARCDIRECTION_CLOCKWISE
Definition: emfreader.cxx:173
#define EMR_RESIZEPALETTE
Definition: emfreader.cxx:90
#define EMR_POLYBEZIERTO16
Definition: emfreader.cxx:132
#define EMR_CHORD
Definition: emfreader.cxx:85
#define EMR_CREATEPEN
Definition: emfreader.cxx:77
#define EMR_CREATEDIBPATTERNBRUSHPT
Definition: emfreader.cxx:138
#define EMR_ROUNDRECT
Definition: emfreader.cxx:83
#define EMR_COMMENT
Definition: emfreader.cxx:109
#define EMR_SETTEXTJUSTIFICATION
Definition: emfreader.cxx:168
#define EMR_CREATECOLORSPACE
Definition: emfreader.cxx:145
#define EMR_COLORCORRECTPALETTE
Definition: emfreader.cxx:159
#define EMR_SETVIEWPORTORGEX
Definition: emfreader.cxx:51
#define EMR_ABORTPATH
Definition: emfreader.cxx:107
#define EMR_CREATEBRUSHINDIRECT
Definition: emfreader.cxx:78
#define EMR_BEGINPATH
Definition: emfreader.cxx:98
#define EMR_PIXELFORMAT
Definition: emfreader.cxx:150
#define EMR_ENDPATH
Definition: emfreader.cxx:99
#define EMR_POLYPOLYLINE16
Definition: emfreader.cxx:134
#define EMR_SETBKMODE
Definition: emfreader.cxx:57
#define EMR_SETMAPMODE
Definition: emfreader.cxx:56
#define EMR_POLYBEZIER
Definition: emfreader.cxx:41
#define EMR_HEADER
Definition: emfreader.cxx:40
#define EMR_POLYBEZIERTO
Definition: emfreader.cxx:44
#define EMR_MODIFYWORLDTRANSFORM
Definition: emfreader.cxx:75
#define EMR_TRANSPARENTBLT
Definition: emfreader.cxx:164
#define EMR_STROKEPATH
Definition: emfreader.cxx:103
#define EMR_SCALEWINDOWEXTEX
Definition: emfreader.cxx:71
#define EMR_ALPHABLEND
Definition: emfreader.cxx:162
#define EMR_SETWORLDTRANSFORM
Definition: emfreader.cxx:74
#define EMR_ARC
Definition: emfreader.cxx:84
#define EMR_SETROP2
Definition: emfreader.cxx:59
#define EMR_POLYDRAW
Definition: emfreader.cxx:95
#define EMR_POLYPOLYGON
Definition: emfreader.cxx:47
#define EMR_SCALEVIEWPORTEXTEX
Definition: emfreader.cxx:70
#define EMR_FILLRGN
Definition: emfreader.cxx:115
#define EMR_SETDIBITSTODEVICE
Definition: emfreader.cxx:124
#define EMR_DELETECOLORSPACE
Definition: emfreader.cxx:147
#define EMR_POLYTEXTOUTA
Definition: emfreader.cxx:140
#define EMR_MASKBLT
Definition: emfreader.cxx:122
#define EMR_FORCEUFIMAPPING
Definition: emfreader.cxx:157
sal_Int16 nVersion
sal_Int32 nIndex
sal_Int64 n
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
B2DPolyPolygon stripNeutralPolygons(const B2DPolyPolygon &rCandidate)
B2DPolyPolygon solveCrossovers(const B2DPolyPolygon &rCandidate, size_t *pPointLimit=nullptr)
B2DPolyPolygon stripDispensablePolygons(const B2DPolyPolygon &rCandidate, bool bKeepAboveZero=false)
size
const sal_uInt32 EMR_COMMENT_WINDOWS_METAFILE
Definition: emfreader.cxx:418
static SvStream & operator>>(SvStream &rStream, sal_Int16 &n)
Definition: emfreader.cxx:629
@ SRCCOPY
Definition: mtftools.hxx:192
@ SRCAND
Definition: mtftools.hxx:194
@ SRCINVERT
Definition: mtftools.hxx:195
GraphicsMode
Definition: mtftools.hxx:116
constexpr sal_uInt32 ENHMETA_STOCK_OBJECT
Definition: mtftools.hxx:63
@ PS_GEOMETRIC
Definition: mtftools.hxx:228
@ PS_STYLE_MASK
Definition: mtftools.hxx:216
@ PS_COSMETIC
Definition: mtftools.hxx:206
@ PS_INSIDEFRAME
Definition: mtftools.hxx:213
constexpr sal_Int32 LF_FACESIZE
Definition: mtftools.hxx:134
RegionMode
Definition: mtftools.hxx:37
BrushStyle
Definition: mtftools.hxx:308
ModifyWorldTransformMode
Definition: mtftools.hxx:56
WMFRasterOp
Definition: mtftools.hxx:86
const sal_uInt32 EMR_COMMENT_ENDGROUP
Definition: emfreader.cxx:416
BackgroundMode
Definition: mtftools.hxx:47
MappingMode
Definition: mtftools.hxx:99
const sal_uInt32 EMR_COMMENT_MULTIFORMATS
Definition: emfreader.cxx:417
constexpr sal_Int32 RDH_RECTANGLES
Definition: mtftools.hxx:322
static SvStream & operator>>(SvStream &rStream, sal_Int32 &n)
Definition: emfreader.cxx:634
@ ETO_NO_RECT
Definition: mtftools.hxx:267
@ ETO_GLYPH_INDEX
Definition: mtftools.hxx:264
@ ETO_CLIPPED
Definition: mtftools.hxx:262
@ ETO_PDY
Definition: mtftools.hxx:268
@ ETO_RTLREADING
Definition: mtftools.hxx:265
@ ETO_OPAQUE
Definition: mtftools.hxx:261
const sal_uInt32 EMR_COMMENT_BEGINGROUP
Definition: emfreader.cxx:415
int i
std::enable_if< std::is_signed< T >::value, bool >::type checked_add(T a, T b, T &result)
int sprintf(char(&s)[N], char const *format, T &&... arguments)
constexpr T saturating_add(T a, T b)
std::enable_if< std::is_signed< T >::value, bool >::type checked_sub(T a, T b, T &result)
long Long
ComplexTextLayoutFlags
bool ImportPDF(SvStream &rStream, Graphic &rGraphic)
sal_Int32 h
sal_Int32 w
QPRO_FUNC_TYPE nType
TOOLS_DLLPUBLIC OUString read_uInt16s_ToOUString(SvStream &rStrm, std::size_t nUnits)
TOOLS_DLLPUBLIC bool checkSeek(SvStream &rSt, sal_uInt64 nOffset)
sal_uInt8 lfUnderline
Definition: mtftools.hxx:144
sal_Int32 lfEscapement
Definition: mtftools.hxx:140
sal_uInt8 lfPitchAndFamily
Definition: mtftools.hxx:150
sal_Int32 lfWeight
Definition: mtftools.hxx:142
sal_uInt8 lfClipPrecision
Definition: mtftools.hxx:148
sal_uInt8 lfStrikeOut
Definition: mtftools.hxx:145
sal_Int32 lfWidth
Definition: mtftools.hxx:139
sal_Int32 lfOrientation
Definition: mtftools.hxx:141
sal_uInt8 lfItalic
Definition: mtftools.hxx:143
sal_Int32 lfHeight
Definition: mtftools.hxx:138
sal_uInt8 lfCharSet
Definition: mtftools.hxx:146
sal_uInt8 lfOutPrecision
Definition: mtftools.hxx:147
OUString alfFaceName
Definition: mtftools.hxx:151
sal_uInt8 lfQuality
Definition: mtftools.hxx:149
#define SAL_MAX_UINT16
#define SAL_MAX_INT32
#define SAL_MIN_INT32
sal_uInt16 sal_Unicode
#define SAL_MAX_UINT32
ResultType type
sal_uInt64 left
size_t pos