2 Enhanced metafile functions
3 Copyright 1998, Douglas Ridgway
14 /*****************************************************************************
15 * GetEnhMetaFile32A (GDI32.174)
19 HENHMETAFILE32 WINAPI
GetEnhMetaFile32A(
20 LPCSTR lpszMetaFile
/* filename of enhanced metafile */
23 HENHMETAFILE32 hmf
= 0;
27 HFILE32 hf
= CreateFile32A(lpszMetaFile
, GENERIC_READ
, 0, 0,
29 if (!ReadFile(hf
, &h
, sizeof(ENHMETAHEADER
), &read
, NULL
))
31 if (read
!=sizeof(ENHMETAHEADER
)) return 0;
32 SetFilePointer(hf
, 0, NULL
, FILE_BEGIN
);
33 /* hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
34 hmf
= GlobalAlloc32(GPTR
, h
.nBytes
);
35 p
= GlobalLock32(hmf
);
36 if (!ReadFile(hf
, p
, h
.nBytes
, &read
, NULL
)) return 0;
41 /*****************************************************************************
42 * GetEnhMetaFileHeader (GDI32.178)
44 * If _buf_ is NULL, returns the size of buffer required.
45 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
48 UINT32 WINAPI
GetEnhMetaFileHeader(
49 HENHMETAFILE32 hmf
, /* enhanced metafile */
50 UINT32 bufsize
, /* size of buffer */
51 LPENHMETAHEADER buf
/* buffer */
54 LPENHMETAHEADER p
= GlobalLock32(hmf
);
55 if (!buf
) return sizeof(ENHMETAHEADER
);
56 memmove(buf
, p
, MIN(sizeof(ENHMETAHEADER
), bufsize
));
58 return MIN(sizeof(ENHMETAHEADER
), bufsize
);
62 /*****************************************************************************
63 * GetEnhMetaFileDescription32A (GDI32.176)
65 UINT32 WINAPI
GetEnhMetaFileDescription32A(
66 HENHMETAFILE32 hmf
, /* enhanced metafile */
67 UINT32 size
, /* size of buf */
68 LPSTR buf
/* buffer to receive description */
71 LPENHMETAHEADER p
= GlobalLock32(hmf
);
72 INT32 first
= lstrlen32W( (void *)p
+p
->offDescription
);
74 if (!buf
|| !size
) return p
->nDescription
;
76 lstrcpynWtoA(buf
, (void *)p
+p
->offDescription
, size
);
78 lstrcpynWtoA(buf
, (void *)p
+p
->offDescription
+2*(first
+1), size
-first
-1);
80 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
82 return MIN(size
,p
->nDescription
);
85 /*****************************************************************************
86 * GetEnhMetaFileDescription32W (GDI32.177)
88 * Copies the description string of an enhanced metafile into a buffer
91 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
92 * number of characters copied.
94 UINT32 WINAPI
GetEnhMetaFileDescription32W(
95 HENHMETAFILE32 hmf
, /* enhanced metafile */
96 UINT32 size
, /* size of buf */
97 LPWSTR buf
/* buffer to receive description */
100 LPENHMETAHEADER p
= GlobalLock32(hmf
);
102 if (!buf
|| !size
) return p
->nDescription
;
104 memmove(buf
, (void *)p
+p
->offDescription
, MIN(size
,p
->nDescription
));
106 return MIN(size
,p
->nDescription
);
109 /****************************************************************************
110 * SetEnhMetaFileBits (GDI32.315)
112 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
114 HENHMETAFILE32 WINAPI
SetEnhMetaFileBits(UINT32 bufsize
, const BYTE
*buf
)
116 HENHMETAFILE32 hmf
= GlobalAlloc32(GPTR
, bufsize
);
117 LPENHMETAHEADER h
= GlobalLock32(hmf
);
118 memmove(h
, buf
, bufsize
);
123 /*****************************************************************************
124 * GetEnhMetaFileBits (GDI32.175)
127 UINT32 WINAPI
GetEnhMetaFileBits(
135 /*****************************************************************************
136 * PlayEnhMetaFileRecord (GDI32.264)
138 * Render a single enhanced metafile record in the device context hdc.
141 * TRUE on success, FALSE on error.
143 * Many unimplemented records.
145 BOOL32 WINAPI
PlayEnhMetaFileRecord(
146 HDC32 hdc
, /* device context in which to render EMF record */
147 LPHANDLETABLE32 handletable
, /* array of handles to be used in rendering record */
148 const ENHMETARECORD
*mr
, /* EMF record to render */
149 UINT32 handles
/* size of handle array */
154 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
155 hdc
, handletable
, mr
, handles
);
156 if (!mr
) return FALSE
;
160 TRACE(metafile
, " type=%d\n", type
);
165 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
171 /* application defined and processed */
175 DWORD mode
= mr
->dParm
[0];
176 SetMapMode32(hdc
, mode
);
181 DWORD mode
= mr
->dParm
[0];
182 SetBkMode32(hdc
, mode
);
187 DWORD mode
= mr
->dParm
[0];
188 SetBkColor32(hdc
, mode
);
191 case EMR_SETPOLYFILLMODE
:
193 DWORD mode
= mr
->dParm
[0];
194 SetPolyFillMode32(hdc
, mode
);
199 DWORD mode
= mr
->dParm
[0];
200 SetROP232(hdc
, mode
);
203 case EMR_SETSTRETCHBLTMODE
:
205 DWORD mode
= mr
->dParm
[0];
206 SetStretchBltMode32(hdc
, mode
);
209 case EMR_SETTEXTALIGN
:
211 DWORD align
= mr
->dParm
[0];
212 SetTextAlign32(hdc
, align
);
215 case EMR_SETTEXTCOLOR
:
217 DWORD color
= mr
->dParm
[0];
218 SetTextColor32(hdc
, color
);
228 RestoreDC32(hdc
, mr
->dParm
[0]);
231 case EMR_INTERSECTCLIPRECT
:
233 INT32 left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
234 bottom
= mr
->dParm
[3];
235 IntersectClipRect32(hdc
, left
, top
, right
, bottom
);
238 case EMR_SELECTOBJECT
:
240 DWORD obj
= mr
->dParm
[0];
241 SelectObject32(hdc
, (handletable
->objectHandle
)[obj
]);
244 case EMR_DELETEOBJECT
:
246 DWORD obj
= mr
->dParm
[0];
247 DeleteObject32( (handletable
->objectHandle
)[obj
]);
248 (handletable
->objectHandle
)[obj
] = 0;
251 case EMR_SETWINDOWORGEX
:
253 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
254 SetWindowOrgEx32(hdc
, x
, y
, NULL
);
257 case EMR_SETWINDOWEXTEX
:
259 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
260 SetWindowExtEx32(hdc
, x
, y
, NULL
);
263 case EMR_SETVIEWPORTORGEX
:
265 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
266 SetViewportOrgEx32(hdc
, x
, y
, NULL
);
269 case EMR_SETVIEWPORTEXTEX
:
271 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
272 SetViewportExtEx32(hdc
, x
, y
, NULL
);
277 DWORD obj
= mr
->dParm
[0];
278 (handletable
->objectHandle
)[obj
] =
279 CreatePenIndirect32((LOGPEN32
*) &(mr
->dParm
[1]));
282 case EMR_EXTCREATEPEN
:
284 DWORD obj
= mr
->dParm
[0];
285 DWORD style
= mr
->dParm
[1], brush
= mr
->dParm
[2];
286 LOGBRUSH32
*b
= (LOGBRUSH32
*) &mr
->dParm
[3];
287 FIXME(metafile
, "Some ExtCreatePen args not handled\n");
288 (handletable
->objectHandle
)[obj
] =
289 ExtCreatePen32(style
, brush
, b
, 0, NULL
);
292 case EMR_CREATEBRUSHINDIRECT
:
294 DWORD obj
= mr
->dParm
[0];
295 (handletable
->objectHandle
)[obj
] =
296 CreateBrushIndirect32((LOGBRUSH32
*) &(mr
->dParm
[1]));
299 case EMR_EXTCREATEFONTINDIRECTW
:
301 DWORD obj
= mr
->dParm
[0];
302 (handletable
->objectHandle
)[obj
] =
303 CreateFontIndirect32W((LOGFONT32W
*) &(mr
->dParm
[1]));
308 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
309 MoveToEx32(hdc
, x
, y
, NULL
);
314 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
320 INT32 left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
321 bottom
= mr
->dParm
[3];
322 Rectangle32(hdc
, left
, top
, right
, bottom
);
327 INT32 left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
328 bottom
= mr
->dParm
[3];
329 Ellipse32(hdc
, left
, top
, right
, bottom
);
334 /* 0-3 : a bounding rectangle? */
335 INT32 count
= mr
->dParm
[4];
336 FIXME(metafile
, "Some Polygon16 args not handled\n");
337 Polygon16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
342 /* 0-3 : a bounding rectangle? */
343 INT32 count
= mr
->dParm
[4];
344 FIXME(metafile
, "Some Polyline16 args not handled\n");
345 Polyline16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
350 case EMR_POLYPOLYGON16
:
352 INT32 polygons
= mr
->dParm
[z
];
353 LPPOINT16 pts
= (LPPOINT16
) &mr
->dParm
[x
];
354 LPINT16 counts
= (LPINT16
) &mr
->dParm
[y
];
355 PolyPolygon16(hdc
, pts
, counts
, polygons
);
359 case EMR_EXTTEXTOUTW
:
362 DWORD flags
= mr
->dParm
[4];
364 DWORD x
= mr
->dParm
[7], y
= mr
->dParm
[8];
365 DWORD count
= mr
->dParm
[9];
367 LPWSTR str
= (LPWSTR
)& mr
->dParm
[17];
368 /* trailing info: dx array? */
369 FIXME(metafile
, "Many ExtTextOut args not handled\n");
370 ExtTextOut32W(hdc
, x
, y
, flags
, /* lpRect */ NULL
,
371 str
, count
, /* lpDx */ NULL
);
376 FIXME(metafile
, "type %d is unimplemented\n", type
);
377 /* SetLastError(E_NOTIMPL); */
384 /*****************************************************************************
386 * EnumEnhMetaFile32 (GDI32.79)
388 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
390 * record. Returns when either every record has been used or
391 * when _EnhMetaFunc_ returns FALSE.
395 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
401 BOOL32 WINAPI
EnumEnhMetaFile32(
402 HDC32 hdc
, /* device context to pass to _EnhMetaFunc_ */
403 HENHMETAFILE32 hmf
, /* EMF to walk */
404 ENHMFENUMPROC32 callback
, /* callback function */
405 LPVOID data
, /* optional data for callback function */
406 const RECT32
*rect
/* bounding rectangle for rendered metafile */
410 LPENHMETARECORD p
= GlobalLock32(hmf
);
411 INT32 count
= ((LPENHMETAHEADER
) p
)->nHandles
;
412 HANDLETABLE32
*ht
= (HANDLETABLE32
*)GlobalAlloc32(GPTR
, sizeof(HANDLETABLE32
)*count
);
413 ht
->objectHandle
[0] = hmf
;
415 ret
= (*callback
)(hdc
, ht
, p
, count
, data
);
416 if (p
->iType
== EMR_EOF
) break;
417 p
= (void *) p
+ p
->nSize
;
419 GlobalFree32((HGLOBAL32
)ht
);
425 /**************************************************************************
426 * PlayEnhMetaFile (GDI32.263)
428 * Renders an enhanced metafile into a specified rectangle *lpRect
429 * in device context hdc.
432 * Almost entirely unimplemented
435 BOOL32 WINAPI
PlayEnhMetaFile(
436 HDC32 hdc
, /* DC to render into */
437 HENHMETAFILE32 hmf
, /* metafile to render */
438 const RECT32
*lpRect
/* rectangle to place metafile inside */
441 LPENHMETARECORD p
= GlobalLock32(hmf
);
442 INT32 count
= ((LPENHMETAHEADER
) p
)->nHandles
;
443 HANDLETABLE32
*ht
= (HANDLETABLE32
*)GlobalAlloc32(GPTR
,
444 sizeof(HANDLETABLE32
)*count
);
448 LPENHMETAHEADER h
= (LPENHMETAHEADER
) p
;
449 FLOAT xscale
= (h
->rclBounds
.right
-h
->rclBounds
.left
)/(lpRect
->right
-lpRect
->left
);
450 FLOAT yscale
= (h
->rclBounds
.bottom
-h
->rclBounds
.top
)/(lpRect
->bottom
-lpRect
->top
);
451 XFORM xform
= {xscale
, 0, 0, yscale
, 0, 0};
452 xform
.eDx
= lpRect
->left
;
453 xform
.eDy
= lpRect
->top
;
454 FIXME(metafile
, "play into rect doesn't work\n");
455 savedMode
= SetGraphicsMode(hdc
, GM_ADVANCED
);
456 if (!SetWorldTransform(hdc
, &xform
)) {
457 WARN(metafile
, "World transform failed!\n");
461 ht
->objectHandle
[0] = hmf
;
463 PlayEnhMetaFileRecord(hdc
, ht
, p
, count
);
464 if (p
->iType
== EMR_EOF
) break;
465 p
= (void *) p
+ p
->nSize
; /* casted so that arithmetic is in bytes */
468 if (savedMode
) SetGraphicsMode(hdc
, savedMode
);
469 ret
= TRUE
; /* FIXME: calculate a more accurate return value */
473 /*****************************************************************************
474 * DeleteEnhMetaFile (GDI32.68)
476 * Deletes an enhanced metafile and frees the associated storage.
478 BOOL32 WINAPI
DeleteEnhMetaFile(HENHMETAFILE32 hmf
) {
479 return !GlobalFree32(hmf
);
482 /*****************************************************************************
483 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
487 HENHMETAFILE32 WINAPI
CopyEnhMetaFile32A(
492 LPENHMETAHEADER h
= GlobalLock32(hmf
);
493 HENHMETAFILE32 hmf2
= GlobalAlloc32(GPTR
, h
->nBytes
);
494 LPENHMETAHEADER h2
= GlobalLock32(hmf2
);
496 memmove(h2
, h
, h
->nBytes
);
497 GlobalUnlock32(hmf2
);
501 FIXME(metafile
, "write to file not implemented\n");
506 /*****************************************************************************
507 * GetEnhMetaFilePaletteEntries (GDI32.179)
509 * Copy the palette and report size
512 UINT32 WINAPI
GetEnhMetaFilePaletteEntries(HENHMETAFILE32 hemf
,
516 LPENHMETAHEADER h
= GlobalLock32(hemf
);
519 GlobalUnlock32(hemf
);
522 if ((lppe
)&&(cEntries
>0)){
523 FIXME(metafile
,"Stub\n");
524 GlobalUnlock32(hemf
);
527 GlobalUnlock32(hemf
);
535 /******************************************************************
536 * SetWinMetaFileBits (GDI32.343)
538 * Translate from old style to new style.
541 HENHMETAFILE32 WINAPI
SetWinMetaFileBits(UINT32 cbBuffer
,
542 CONST BYTE
*lpbBuffer
,
544 CONST METAFILEPICT32
*lpmfp
547 FIXME(metafile
,"Stub\n");