2 * Dump an Enhanced Meta File
4 * Copyright 2005 Mike McCormack
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "gdiplusenums.h"
39 } EmfPlusRecordHeader
;
41 static const char *debugstr_wn(const WCHAR
*wstr
, unsigned int n
)
47 if (!wstr
) return "(null)";
52 while (i
< n
&& i
< sizeof(buf
) - 2 && wstr
[i
])
54 if (wstr
[i
] < 127) *p
++ = wstr
[i
];
63 static unsigned int read_int(const unsigned char *buffer
)
71 #define EMRCASE(x) case x: printf("%-20s %08x\n", #x, length); break
72 #define EMRPLUSCASE(x) case x: printf(" %-20s %04x %08x %08x\n", #x, header->Flags, header->Size, header->DataSize); break
74 static unsigned offset
= 0;
76 static int dump_emfrecord(void)
78 const unsigned char* ptr
;
79 unsigned int type
, length
, i
;
85 length
= read_int(ptr
+ 4);
91 const ENHMETAHEADER
*header
= PRD(offset
, sizeof(*header
));
93 printf("%-20s %08x\n", "EMR_HEADER", length
);
94 printf("bounds (%d,%d - %d,%d) frame (%d,%d - %d,%d) signature %#x version %#x bytes %#x records %#x\n"
95 "handles %#x reserved %#x palette entries %#x px %dx%d mm %dx%d μm %dx%d opengl %d description %s\n",
96 header
->rclBounds
.left
, header
->rclBounds
.top
, header
->rclBounds
.right
, header
->rclBounds
.bottom
,
97 header
->rclFrame
.left
, header
->rclFrame
.top
, header
->rclFrame
.right
, header
->rclFrame
.bottom
,
98 header
->dSignature
, header
->nVersion
, header
->nBytes
, header
->nRecords
, header
->nHandles
, header
->sReserved
,
99 header
->nPalEntries
, header
->szlDevice
.cx
, header
->szlDevice
.cy
, header
->szlMillimeters
.cx
,
100 header
->szlMillimeters
.cy
, header
->szlMicrometers
.cx
, header
->szlMicrometers
.cy
, header
->bOpenGL
,
101 debugstr_wn((LPCWSTR
)((const BYTE
*)header
+ header
->offDescription
), header
->nDescription
));
105 EMRCASE(EMR_POLYBEZIER
);
106 EMRCASE(EMR_POLYGON
);
107 EMRCASE(EMR_POLYLINE
);
108 EMRCASE(EMR_POLYBEZIERTO
);
109 EMRCASE(EMR_POLYLINETO
);
110 EMRCASE(EMR_POLYPOLYLINE
);
111 EMRCASE(EMR_POLYPOLYGON
);
112 EMRCASE(EMR_SETWINDOWEXTEX
);
113 EMRCASE(EMR_SETWINDOWORGEX
);
114 EMRCASE(EMR_SETVIEWPORTEXTEX
);
115 EMRCASE(EMR_SETVIEWPORTORGEX
);
116 EMRCASE(EMR_SETBRUSHORGEX
);
118 EMRCASE(EMR_SETPIXELV
);
119 EMRCASE(EMR_SETMAPPERFLAGS
);
120 EMRCASE(EMR_SETMAPMODE
);
121 EMRCASE(EMR_SETBKMODE
);
122 EMRCASE(EMR_SETPOLYFILLMODE
);
123 EMRCASE(EMR_SETROP2
);
124 EMRCASE(EMR_SETSTRETCHBLTMODE
);
125 EMRCASE(EMR_SETTEXTALIGN
);
126 EMRCASE(EMR_SETCOLORADJUSTMENT
);
127 EMRCASE(EMR_SETTEXTCOLOR
);
128 EMRCASE(EMR_SETBKCOLOR
);
129 EMRCASE(EMR_OFFSETCLIPRGN
);
130 EMRCASE(EMR_MOVETOEX
);
131 EMRCASE(EMR_SETMETARGN
);
132 EMRCASE(EMR_EXCLUDECLIPRECT
);
134 case EMR_INTERSECTCLIPRECT
:
136 const EMRINTERSECTCLIPRECT
*clip
= PRD(offset
, sizeof(*clip
));
138 printf("%-20s %08x\n", "EMR_INTERSECTCLIPRECT", length
);
139 printf("rect %d,%d - %d, %d\n",
140 clip
->rclClip
.left
, clip
->rclClip
.top
,
141 clip
->rclClip
.right
, clip
->rclClip
.bottom
);
145 EMRCASE(EMR_SCALEVIEWPORTEXTEX
);
146 EMRCASE(EMR_SCALEWINDOWEXTEX
);
148 EMRCASE(EMR_RESTOREDC
);
149 EMRCASE(EMR_SETWORLDTRANSFORM
);
150 EMRCASE(EMR_MODIFYWORLDTRANSFORM
);
151 EMRCASE(EMR_SELECTOBJECT
);
152 EMRCASE(EMR_CREATEPEN
);
153 EMRCASE(EMR_CREATEBRUSHINDIRECT
);
154 EMRCASE(EMR_DELETEOBJECT
);
155 EMRCASE(EMR_ANGLEARC
);
156 EMRCASE(EMR_ELLIPSE
);
157 EMRCASE(EMR_RECTANGLE
);
158 EMRCASE(EMR_ROUNDRECT
);
162 EMRCASE(EMR_SELECTPALETTE
);
163 EMRCASE(EMR_CREATEPALETTE
);
164 EMRCASE(EMR_SETPALETTEENTRIES
);
165 EMRCASE(EMR_RESIZEPALETTE
);
166 EMRCASE(EMR_REALIZEPALETTE
);
167 EMRCASE(EMR_EXTFLOODFILL
);
170 EMRCASE(EMR_POLYDRAW
);
171 EMRCASE(EMR_SETARCDIRECTION
);
172 EMRCASE(EMR_SETMITERLIMIT
);
173 EMRCASE(EMR_BEGINPATH
);
174 EMRCASE(EMR_ENDPATH
);
175 EMRCASE(EMR_CLOSEFIGURE
);
176 EMRCASE(EMR_FILLPATH
);
177 EMRCASE(EMR_STROKEANDFILLPATH
);
178 EMRCASE(EMR_STROKEPATH
);
179 EMRCASE(EMR_FLATTENPATH
);
180 EMRCASE(EMR_WIDENPATH
);
181 EMRCASE(EMR_SELECTCLIPPATH
);
182 EMRCASE(EMR_ABORTPATH
);
186 printf("%-20s %08x\n", "EMR_GDICOMMENT", length
);
188 /* Handle EMF+ records */
189 if (length
>= 16 && !memcmp((char*)PRD(offset
+ 12, sizeof(unsigned int)), "EMF+", 4))
191 const EmfPlusRecordHeader
*header
;
192 const unsigned int *data_size
;
196 data_size
= PRD(offset
, sizeof(*data_size
));
197 printf("data size = %x\n", *data_size
);
201 while (length
>= sizeof(*header
))
203 header
= PRD(offset
, sizeof(*header
));
206 EMRPLUSCASE(EmfPlusRecordTypeInvalid
);
207 EMRPLUSCASE(EmfPlusRecordTypeHeader
);
208 EMRPLUSCASE(EmfPlusRecordTypeEndOfFile
);
209 EMRPLUSCASE(EmfPlusRecordTypeComment
);
210 EMRPLUSCASE(EmfPlusRecordTypeGetDC
);
211 EMRPLUSCASE(EmfPlusRecordTypeMultiFormatStart
);
212 EMRPLUSCASE(EmfPlusRecordTypeMultiFormatSection
);
213 EMRPLUSCASE(EmfPlusRecordTypeMultiFormatEnd
);
214 EMRPLUSCASE(EmfPlusRecordTypeObject
);
215 EMRPLUSCASE(EmfPlusRecordTypeClear
);
216 EMRPLUSCASE(EmfPlusRecordTypeFillRects
);
217 EMRPLUSCASE(EmfPlusRecordTypeDrawRects
);
218 EMRPLUSCASE(EmfPlusRecordTypeFillPolygon
);
219 EMRPLUSCASE(EmfPlusRecordTypeDrawLines
);
220 EMRPLUSCASE(EmfPlusRecordTypeFillEllipse
);
221 EMRPLUSCASE(EmfPlusRecordTypeDrawEllipse
);
222 EMRPLUSCASE(EmfPlusRecordTypeFillPie
);
223 EMRPLUSCASE(EmfPlusRecordTypeDrawPie
);
224 EMRPLUSCASE(EmfPlusRecordTypeDrawArc
);
225 EMRPLUSCASE(EmfPlusRecordTypeFillRegion
);
226 EMRPLUSCASE(EmfPlusRecordTypeFillPath
);
227 EMRPLUSCASE(EmfPlusRecordTypeDrawPath
);
228 EMRPLUSCASE(EmfPlusRecordTypeFillClosedCurve
);
229 EMRPLUSCASE(EmfPlusRecordTypeDrawClosedCurve
);
230 EMRPLUSCASE(EmfPlusRecordTypeDrawCurve
);
231 EMRPLUSCASE(EmfPlusRecordTypeDrawBeziers
);
232 EMRPLUSCASE(EmfPlusRecordTypeDrawImage
);
233 EMRPLUSCASE(EmfPlusRecordTypeDrawImagePoints
);
234 EMRPLUSCASE(EmfPlusRecordTypeDrawString
);
235 EMRPLUSCASE(EmfPlusRecordTypeSetRenderingOrigin
);
236 EMRPLUSCASE(EmfPlusRecordTypeSetAntiAliasMode
);
237 EMRPLUSCASE(EmfPlusRecordTypeSetTextRenderingHint
);
238 EMRPLUSCASE(EmfPlusRecordTypeSetTextContrast
);
239 EMRPLUSCASE(EmfPlusRecordTypeSetInterpolationMode
);
240 EMRPLUSCASE(EmfPlusRecordTypeSetPixelOffsetMode
);
241 EMRPLUSCASE(EmfPlusRecordTypeSetCompositingMode
);
242 EMRPLUSCASE(EmfPlusRecordTypeSetCompositingQuality
);
243 EMRPLUSCASE(EmfPlusRecordTypeSave
);
244 EMRPLUSCASE(EmfPlusRecordTypeRestore
);
245 EMRPLUSCASE(EmfPlusRecordTypeBeginContainer
);
246 EMRPLUSCASE(EmfPlusRecordTypeBeginContainerNoParams
);
247 EMRPLUSCASE(EmfPlusRecordTypeEndContainer
);
248 EMRPLUSCASE(EmfPlusRecordTypeSetWorldTransform
);
249 EMRPLUSCASE(EmfPlusRecordTypeResetWorldTransform
);
250 EMRPLUSCASE(EmfPlusRecordTypeMultiplyWorldTransform
);
251 EMRPLUSCASE(EmfPlusRecordTypeTranslateWorldTransform
);
252 EMRPLUSCASE(EmfPlusRecordTypeScaleWorldTransform
);
253 EMRPLUSCASE(EmfPlusRecordTypeRotateWorldTransform
);
254 EMRPLUSCASE(EmfPlusRecordTypeSetPageTransform
);
255 EMRPLUSCASE(EmfPlusRecordTypeResetClip
);
256 EMRPLUSCASE(EmfPlusRecordTypeSetClipRect
);
257 EMRPLUSCASE(EmfPlusRecordTypeSetClipPath
);
258 EMRPLUSCASE(EmfPlusRecordTypeSetClipRegion
);
259 EMRPLUSCASE(EmfPlusRecordTypeOffsetClip
);
260 EMRPLUSCASE(EmfPlusRecordTypeDrawDriverString
);
261 EMRPLUSCASE(EmfPlusRecordTypeStrokeFillPath
);
262 EMRPLUSCASE(EmfPlusRecordTypeSerializableObject
);
263 EMRPLUSCASE(EmfPlusRecordTypeSetTSGraphics
);
264 EMRPLUSCASE(EmfPlusRecordTypeSetTSClip
);
265 EMRPLUSCASE(EmfPlusRecordTotal
);
268 printf(" unknown EMF+ record %x %04x %08x\n", header
->Type
, header
->Flags
, header
->Size
);
272 if (length
<sizeof(*header
) || header
->Size
%4)
275 length
-= sizeof(*header
);
276 offset
+= sizeof(*header
);
278 for (i
=0; i
<header
->Size
-sizeof(*header
); i
+=4)
282 if (!(ptr
= PRD(offset
, 4))) return -1;
285 printf("%08x ", read_int(ptr
));
286 if ((i
% 16 == 12) || (i
+ 4 == header
->Size
- sizeof(*header
)))
297 EMRCASE(EMR_FILLRGN
);
298 EMRCASE(EMR_FRAMERGN
);
299 EMRCASE(EMR_INVERTRGN
);
300 EMRCASE(EMR_PAINTRGN
);
302 case EMR_EXTSELECTCLIPRGN
:
304 const EMREXTSELECTCLIPRGN
*clip
= PRD(offset
, sizeof(*clip
));
305 const RGNDATA
*data
= (const RGNDATA
*)clip
->RgnData
;
306 DWORD i
, rc_count
= 0;
309 if (length
>= sizeof(*clip
) + sizeof(*data
))
310 rc_count
= data
->rdh
.nCount
;
312 printf("%-20s %08x\n", "EMR_EXTSELECTCLIPRGN", length
);
313 printf("mode %d, rects %d\n", clip
->iMode
, rc_count
);
314 for (i
= 0, rc
= (const RECT
*)data
->Buffer
; i
< rc_count
; i
++, rc
++)
315 printf(" (%d,%d)-(%d,%d)", rc
->left
, rc
->top
, rc
->right
, rc
->bottom
);
316 if (rc_count
!= 0) printf("\n");
324 const EMRSTRETCHBLT
*blt
= PRD(offset
, sizeof(*blt
));
325 const BITMAPINFOHEADER
*bmih
= (const BITMAPINFOHEADER
*)((const unsigned char *)blt
+ blt
->offBmiSrc
);
327 printf("%-20s %08x\n", "EMR_STRETCHBLT", length
);
328 printf("bounds (%d,%d - %d,%d) dst %d,%d %dx%d src %d,%d %dx%d rop %#x xform (%f, %f, %f, %f, %f, %f)\n"
329 "bk_color %#x usage %#x bmi_offset %#x bmi_size %#x bits_offset %#x bits_size %#x\n",
330 blt
->rclBounds
.left
, blt
->rclBounds
.top
, blt
->rclBounds
.right
, blt
->rclBounds
.bottom
,
331 blt
->xDest
, blt
->yDest
, blt
->cxDest
, blt
->cyDest
,
332 blt
->xSrc
, blt
->ySrc
, blt
->cxSrc
, blt
->cySrc
, blt
->dwRop
,
333 blt
->xformSrc
.eM11
, blt
->xformSrc
.eM12
, blt
->xformSrc
.eM21
,
334 blt
->xformSrc
.eM22
, blt
->xformSrc
.eDx
, blt
->xformSrc
.eDy
,
335 blt
->crBkColorSrc
, blt
->iUsageSrc
, blt
->offBmiSrc
, blt
->cbBmiSrc
,
336 blt
->offBitsSrc
, blt
->cbBitsSrc
);
337 printf("BITMAPINFOHEADER biSize %#x biWidth %d biHeight %d biPlanes %d biBitCount %d biCompression %#x\n"
338 "biSizeImage %#x biXPelsPerMeter %d biYPelsPerMeter %d biClrUsed %#x biClrImportant %#x\n",
339 bmih
->biSize
, bmih
->biWidth
, bmih
->biHeight
, bmih
->biPlanes
, bmih
->biBitCount
,
340 bmih
->biCompression
, bmih
->biSizeImage
, bmih
->biXPelsPerMeter
, bmih
->biYPelsPerMeter
,
341 bmih
->biClrUsed
, bmih
->biClrImportant
);
345 EMRCASE(EMR_MASKBLT
);
347 EMRCASE(EMR_SETDIBITSTODEVICE
);
348 EMRCASE(EMR_STRETCHDIBITS
);
350 case EMR_EXTCREATEFONTINDIRECTW
:
352 const EMREXTCREATEFONTINDIRECTW
*pf
= PRD(offset
, sizeof(*pf
));
353 const LOGFONTW
*plf
= &pf
->elfw
.elfLogFont
;
355 printf("%-20s %08x\n", "EMR_EXTCREATEFONTINDIRECTW", length
);
356 printf("(%d %d %d %d %x out %d clip %x quality %d charset %d) %s %s %s %s\n",
357 plf
->lfHeight
, plf
->lfWidth
,
358 plf
->lfEscapement
, plf
->lfOrientation
,
359 plf
->lfPitchAndFamily
,
360 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
361 plf
->lfQuality
, plf
->lfCharSet
,
362 debugstr_wn(plf
->lfFaceName
, LF_FACESIZE
),
363 plf
->lfWeight
> 400 ? "Bold" : "",
364 plf
->lfItalic
? "Italic" : "",
365 plf
->lfUnderline
? "Underline" : "");
369 EMRCASE(EMR_EXTTEXTOUTA
);
371 case EMR_EXTTEXTOUTW
:
373 const EMREXTTEXTOUTW
*etoW
= PRD(offset
, sizeof(*etoW
));
374 const int *dx
= (const int *)((const BYTE
*)etoW
+ etoW
->emrtext
.offDx
);
376 printf("%-20s %08x\n", "EMR_EXTTEXTOUTW", length
);
377 printf("bounds (%d,%d - %d,%d) mode %#x x_scale %f y_scale %f pt (%d,%d) rect (%d,%d - %d,%d) flags %#x, %s\n",
378 etoW
->rclBounds
.left
, etoW
->rclBounds
.top
, etoW
->rclBounds
.right
, etoW
->rclBounds
.bottom
,
379 etoW
->iGraphicsMode
, etoW
->exScale
, etoW
->eyScale
,
380 etoW
->emrtext
.ptlReference
.x
, etoW
->emrtext
.ptlReference
.y
,
381 etoW
->emrtext
.rcl
.left
, etoW
->emrtext
.rcl
.top
,
382 etoW
->emrtext
.rcl
.right
, etoW
->emrtext
.rcl
.bottom
,
383 etoW
->emrtext
.fOptions
,
384 debugstr_wn((LPCWSTR
)((const BYTE
*)etoW
+ etoW
->emrtext
.offString
), etoW
->emrtext
.nChars
));
385 printf("dx_offset %u {", etoW
->emrtext
.offDx
);
386 for (i
= 0; i
< etoW
->emrtext
.nChars
; ++i
)
389 if (i
!= etoW
->emrtext
.nChars
- 1)
396 EMRCASE(EMR_POLYBEZIER16
);
397 EMRCASE(EMR_POLYGON16
);
398 EMRCASE(EMR_POLYLINE16
);
399 EMRCASE(EMR_POLYBEZIERTO16
);
400 EMRCASE(EMR_POLYLINETO16
);
401 EMRCASE(EMR_POLYPOLYLINE16
);
402 EMRCASE(EMR_POLYPOLYGON16
);
403 EMRCASE(EMR_POLYDRAW16
);
404 EMRCASE(EMR_CREATEMONOBRUSH
);
405 EMRCASE(EMR_CREATEDIBPATTERNBRUSHPT
);
406 EMRCASE(EMR_EXTCREATEPEN
);
407 EMRCASE(EMR_POLYTEXTOUTA
);
408 EMRCASE(EMR_POLYTEXTOUTW
);
409 EMRCASE(EMR_SETICMMODE
);
410 EMRCASE(EMR_CREATECOLORSPACE
);
411 EMRCASE(EMR_SETCOLORSPACE
);
412 EMRCASE(EMR_DELETECOLORSPACE
);
413 EMRCASE(EMR_GLSRECORD
);
414 EMRCASE(EMR_GLSBOUNDEDRECORD
);
415 EMRCASE(EMR_PIXELFORMAT
);
416 EMRCASE(EMR_DRAWESCAPE
);
417 EMRCASE(EMR_EXTESCAPE
);
418 EMRCASE(EMR_STARTDOC
);
419 EMRCASE(EMR_SMALLTEXTOUT
);
420 EMRCASE(EMR_FORCEUFIMAPPING
);
421 EMRCASE(EMR_NAMEDESCAPE
);
422 EMRCASE(EMR_COLORCORRECTPALETTE
);
423 EMRCASE(EMR_SETICMPROFILEA
);
424 EMRCASE(EMR_SETICMPROFILEW
);
428 const EMRALPHABLEND
*blend
= PRD(offset
, sizeof(*blend
));
429 const BITMAPINFOHEADER
*bmih
= (const BITMAPINFOHEADER
*)((const unsigned char *)blend
+ blend
->offBmiSrc
);
431 printf("%-20s %08x\n", "EMR_ALPHABLEND", length
);
432 printf("bounds (%d,%d - %d,%d) dst %d,%d %dx%d src %d,%d %dx%d rop %#x xform (%f, %f, %f, %f, %f, %f)\n"
433 "bk_color %#x usage %#x bmi_offset %#x bmi_size %#x bits_offset %#x bits_size %#x\n",
434 blend
->rclBounds
.left
, blend
->rclBounds
.top
, blend
->rclBounds
.right
, blend
->rclBounds
.bottom
,
435 blend
->xDest
, blend
->yDest
, blend
->cxDest
, blend
->cyDest
,
436 blend
->xSrc
, blend
->ySrc
, blend
->cxSrc
, blend
->cySrc
, blend
->dwRop
,
437 blend
->xformSrc
.eM11
, blend
->xformSrc
.eM12
, blend
->xformSrc
.eM21
,
438 blend
->xformSrc
.eM22
, blend
->xformSrc
.eDx
, blend
->xformSrc
.eDy
,
439 blend
->crBkColorSrc
, blend
->iUsageSrc
, blend
->offBmiSrc
, blend
->cbBmiSrc
,
440 blend
->offBitsSrc
, blend
->cbBitsSrc
);
441 printf("BITMAPINFOHEADER biSize %#x biWidth %d biHeight %d biPlanes %d biBitCount %d biCompression %#x\n"
442 "biSizeImage %#x biXPelsPerMeter %d biYPelsPerMeter %d biClrUsed %#x biClrImportant %#x\n",
443 bmih
->biSize
, bmih
->biWidth
, bmih
->biHeight
, bmih
->biPlanes
, bmih
->biBitCount
,
444 bmih
->biCompression
, bmih
->biSizeImage
, bmih
->biXPelsPerMeter
, bmih
->biYPelsPerMeter
,
445 bmih
->biClrUsed
, bmih
->biClrImportant
);
449 EMRCASE(EMR_SETLAYOUT
);
450 EMRCASE(EMR_TRANSPARENTBLT
);
451 EMRCASE(EMR_RESERVED_117
);
452 EMRCASE(EMR_GRADIENTFILL
);
453 EMRCASE(EMR_SETLINKEDUFI
);
454 EMRCASE(EMR_SETTEXTJUSTIFICATION
);
455 EMRCASE(EMR_COLORMATCHTOTARGETW
);
456 EMRCASE(EMR_CREATECOLORSPACEW
);
459 printf("%u %08x\n", type
, length
);
463 if ( (length
< 8) || (length
% 4) )
470 for(i
=0; i
<length
; i
+=4)
474 if (!(ptr
= PRD(offset
, 4))) return -1;
476 printf("%08x ", read_int(ptr
));
477 if ( (i
% 16 == 12) || (i
+ 4 == length
))
484 enum FileSig
get_kind_emf(void)
486 const ENHMETAHEADER
* hdr
;
488 hdr
= PRD(0, sizeof(*hdr
));
489 if (hdr
&& hdr
->iType
== EMR_HEADER
&& hdr
->dSignature
== ENHMETA_SIGNATURE
)
497 while (!dump_emfrecord());