2 Enhanced metafile functions
3 Copyright 1998, Douglas Ridgway
13 /*****************************************************************************
14 * GetEnhMetaFile32A (GDI32.174)
18 HENHMETAFILE32 WINAPI
GetEnhMetaFile32A(
19 LPCSTR lpszMetaFile
/* filename of enhanced metafile */
22 HENHMETAFILE32 hmf
= 0;
26 HFILE32 hf
= CreateFile32A(lpszMetaFile
, GENERIC_READ
, 0, 0,
28 if (!ReadFile(hf
, &h
, sizeof(ENHMETAHEADER
), &read
, NULL
))
30 if (read
!=sizeof(ENHMETAHEADER
)) return 0;
31 SetFilePointer(hf
, 0, NULL
, FILE_BEGIN
);
32 /* hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
33 hmf
= GlobalAlloc32(GPTR
, h
.nBytes
);
34 p
= GlobalLock32(hmf
);
35 if (!ReadFile(hf
, p
, h
.nBytes
, &read
, NULL
)) return 0;
40 /*****************************************************************************
41 * GetEnhMetaFileHeader (GDI32.178)
43 * If _buf_ is NULL, returns the size of buffer required.
44 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
47 UINT32 WINAPI
GetEnhMetaFileHeader(
48 HENHMETAFILE32 hmf
, /* enhanced metafile */
49 UINT32 bufsize
, /* size of buffer */
50 LPENHMETAHEADER buf
/* buffer */
53 LPENHMETAHEADER p
= GlobalLock32(hmf
);
54 if (!buf
) return sizeof(ENHMETAHEADER
);
55 memmove(buf
, p
, MIN(sizeof(ENHMETAHEADER
), bufsize
));
57 return MIN(sizeof(ENHMETAHEADER
), bufsize
);
61 /*****************************************************************************
62 * GetEnhMetaFileDescription32A (GDI32.176)
64 UINT32 WINAPI
GetEnhMetaFileDescription32A(
65 HENHMETAFILE32 hmf
, /* enhanced metafile */
66 UINT32 size
, /* size of buf */
67 LPSTR buf
/* buffer to receive description */
70 LPENHMETAHEADER p
= GlobalLock32(hmf
);
71 INT32 first
= lstrlen32W( (void *)p
+p
->offDescription
);
73 if (!buf
|| !size
) return p
->nDescription
;
75 lstrcpynWtoA(buf
, (void *)p
+p
->offDescription
, size
);
77 lstrcpynWtoA(buf
, (void *)p
+p
->offDescription
+2*(first
+1), size
-first
-1);
79 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
81 return MIN(size
,p
->nDescription
);
84 /*****************************************************************************
85 * GetEnhMetaFileDescription32W (GDI32.177)
87 * Copies the description string of an enhanced metafile into a buffer
90 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
91 * number of characters copied.
93 UINT32 WINAPI
GetEnhMetaFileDescription32W(
94 HENHMETAFILE32 hmf
, /* enhanced metafile */
95 UINT32 size
, /* size of buf */
96 LPWSTR buf
/* buffer to receive description */
99 LPENHMETAHEADER p
= GlobalLock32(hmf
);
101 if (!buf
|| !size
) return p
->nDescription
;
103 memmove(buf
, (void *)p
+p
->offDescription
, MIN(size
,p
->nDescription
));
105 return MIN(size
,p
->nDescription
);
108 /****************************************************************************
109 * SetEnhMetaFileBits (GDI32.315)
111 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
113 HENHMETAFILE32 WINAPI
SetEnhMetaFileBits(UINT32 bufsize
, const BYTE
*buf
)
115 HENHMETAFILE32 hmf
= GlobalAlloc32(GPTR
, bufsize
);
116 LPENHMETAHEADER h
= GlobalLock32(hmf
);
117 memmove(h
, buf
, bufsize
);
122 /*****************************************************************************
123 * GetEnhMetaFileBits (GDI32.175)
126 UINT32 WINAPI
GetEnhMetaFileBits(
134 /*****************************************************************************
135 * PlayEnhMetaFileRecord (GDI32.264)
137 * Render a single enhanced metafile record in the device context hdc.
140 * TRUE on success, FALSE on error.
142 * Many unimplemented records.
144 BOOL32 WINAPI
PlayEnhMetaFileRecord(
145 HDC32 hdc
, /* device context in which to render EMF record */
146 LPHANDLETABLE32 handletable
, /* array of handles to be used in rendering record */
147 const ENHMETARECORD
*mr
, /* EMF record to render */
148 UINT32 handles
/* size of handle array */
153 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
154 hdc
, handletable
, mr
, handles
);
155 if (!mr
) return FALSE
;
159 TRACE(metafile
, " type=%d\n", type
);
164 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
170 /* application defined and processed */
174 DWORD mode
= mr
->dParm
[0];
175 SetMapMode32(hdc
, mode
);
180 DWORD mode
= mr
->dParm
[0];
181 SetBkMode32(hdc
, mode
);
186 DWORD mode
= mr
->dParm
[0];
187 SetBkColor32(hdc
, mode
);
190 case EMR_SETPOLYFILLMODE
:
192 DWORD mode
= mr
->dParm
[0];
193 SetPolyFillMode32(hdc
, mode
);
198 DWORD mode
= mr
->dParm
[0];
199 SetROP232(hdc
, mode
);
202 case EMR_SETSTRETCHBLTMODE
:
204 DWORD mode
= mr
->dParm
[0];
205 SetStretchBltMode32(hdc
, mode
);
208 case EMR_SETTEXTALIGN
:
210 DWORD align
= mr
->dParm
[0];
211 SetTextAlign32(hdc
, align
);
214 case EMR_SETTEXTCOLOR
:
216 DWORD color
= mr
->dParm
[0];
217 SetTextColor32(hdc
, color
);
227 RestoreDC32(hdc
, mr
->dParm
[0]);
230 case EMR_INTERSECTCLIPRECT
:
232 INT32 left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
233 bottom
= mr
->dParm
[3];
234 IntersectClipRect32(hdc
, left
, top
, right
, bottom
);
237 case EMR_SELECTOBJECT
:
239 DWORD obj
= mr
->dParm
[0];
240 SelectObject32(hdc
, (handletable
->objectHandle
)[obj
]);
243 case EMR_DELETEOBJECT
:
245 DWORD obj
= mr
->dParm
[0];
246 DeleteObject32( (handletable
->objectHandle
)[obj
]);
247 (handletable
->objectHandle
)[obj
] = 0;
250 case EMR_SETWINDOWORGEX
:
252 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
253 SetWindowOrgEx32(hdc
, x
, y
, NULL
);
256 case EMR_SETWINDOWEXTEX
:
258 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
259 SetWindowExtEx32(hdc
, x
, y
, NULL
);
262 case EMR_SETVIEWPORTORGEX
:
264 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
265 SetViewportOrgEx32(hdc
, x
, y
, NULL
);
268 case EMR_SETVIEWPORTEXTEX
:
270 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
271 SetViewportExtEx32(hdc
, x
, y
, NULL
);
276 DWORD obj
= mr
->dParm
[0];
277 (handletable
->objectHandle
)[obj
] =
278 CreatePenIndirect32((LOGPEN32
*) &(mr
->dParm
[1]));
281 case EMR_EXTCREATEPEN
:
283 DWORD obj
= mr
->dParm
[0];
284 DWORD style
= mr
->dParm
[1], brush
= mr
->dParm
[2];
285 LOGBRUSH32
*b
= (LOGBRUSH32
*) &mr
->dParm
[3];
286 FIXME(metafile
, "Some ExtCreatePen args not handled\n");
287 (handletable
->objectHandle
)[obj
] =
288 ExtCreatePen32(style
, brush
, b
, 0, NULL
);
291 case EMR_CREATEBRUSHINDIRECT
:
293 DWORD obj
= mr
->dParm
[0];
294 (handletable
->objectHandle
)[obj
] =
295 CreateBrushIndirect32((LOGBRUSH32
*) &(mr
->dParm
[1]));
298 case EMR_EXTCREATEFONTINDIRECTW
:
300 DWORD obj
= mr
->dParm
[0];
301 (handletable
->objectHandle
)[obj
] =
302 CreateFontIndirect32W((LOGFONT32W
*) &(mr
->dParm
[1]));
307 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
308 MoveToEx32(hdc
, x
, y
, NULL
);
313 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
319 INT32 left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
320 bottom
= mr
->dParm
[3];
321 Rectangle32(hdc
, left
, top
, right
, bottom
);
326 INT32 left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
327 bottom
= mr
->dParm
[3];
328 Ellipse32(hdc
, left
, top
, right
, bottom
);
333 /* 0-3 : a bounding rectangle? */
334 INT32 count
= mr
->dParm
[4];
335 FIXME(metafile
, "Some Polygon16 args not handled\n");
336 Polygon16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
341 /* 0-3 : a bounding rectangle? */
342 INT32 count
= mr
->dParm
[4];
343 FIXME(metafile
, "Some Polyline16 args not handled\n");
344 Polyline16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
349 case EMR_POLYPOLYGON16
:
351 INT32 polygons
= mr
->dParm
[z
];
352 LPPOINT16 pts
= (LPPOINT16
) &mr
->dParm
[x
];
353 LPINT16 counts
= (LPINT16
) &mr
->dParm
[y
];
354 PolyPolygon16(hdc
, pts
, counts
, polygons
);
358 case EMR_EXTTEXTOUTW
:
361 DWORD flags
= mr
->dParm
[4];
363 DWORD x
= mr
->dParm
[7], y
= mr
->dParm
[8];
364 DWORD count
= mr
->dParm
[9];
366 LPWSTR str
= (LPWSTR
)& mr
->dParm
[17];
367 /* trailing info: dx array? */
368 FIXME(metafile
, "Many ExtTextOut args not handled\n");
369 ExtTextOut32W(hdc
, x
, y
, flags
, /* lpRect */ NULL
,
370 str
, count
, /* lpDx */ NULL
);
375 FIXME(metafile
, "type %d is unimplemented\n", type
);
376 /* SetLastError(E_NOTIMPL); */
383 /*****************************************************************************
385 * EnumEnhMetaFile32 (GDI32.79)
387 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
389 * record. Returns when either every record has been used or
390 * when _EnhMetaFunc_ returns FALSE.
394 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
400 BOOL32 WINAPI
EnumEnhMetaFile32(
401 HDC32 hdc
, /* device context to pass to _EnhMetaFunc_ */
402 HENHMETAFILE32 hmf
, /* EMF to walk */
403 ENHMFENUMPROC32 callback
, /* callback function */
404 LPVOID data
, /* optional data for callback function */
405 const RECT32
*rect
/* bounding rectangle for rendered metafile */
409 LPENHMETARECORD p
= GlobalLock32(hmf
);
410 INT32 count
= ((LPENHMETAHEADER
) p
)->nHandles
;
411 HANDLETABLE32
*ht
= (HANDLETABLE32
*)GlobalAlloc32(GPTR
, sizeof(HANDLETABLE32
)*count
);
412 ht
->objectHandle
[0] = hmf
;
414 ret
= (*callback
)(hdc
, ht
, p
, count
, data
);
415 if (p
->iType
== EMR_EOF
) break;
416 p
= (void *) p
+ p
->nSize
;
418 GlobalFree32((HGLOBAL32
)ht
);
424 /**************************************************************************
425 * PlayEnhMetaFile (GDI32.263)
427 * Renders an enhanced metafile into a specified rectangle *lpRect
428 * in device context hdc.
431 * Almost entirely unimplemented
434 BOOL32 WINAPI
PlayEnhMetaFile(
435 HDC32 hdc
, /* DC to render into */
436 HENHMETAFILE32 hmf
, /* metafile to render */
437 const RECT32
*lpRect
/* rectangle to place metafile inside */
440 LPENHMETARECORD p
= GlobalLock32(hmf
);
441 INT32 count
= ((LPENHMETAHEADER
) p
)->nHandles
;
442 HANDLETABLE32
*ht
= (HANDLETABLE32
*)GlobalAlloc32(GPTR
,
443 sizeof(HANDLETABLE32
)*count
);
447 LPENHMETAHEADER h
= (LPENHMETAHEADER
) p
;
448 FLOAT xscale
= (h
->rclBounds
.right
-h
->rclBounds
.left
)/(lpRect
->right
-lpRect
->left
);
449 FLOAT yscale
= (h
->rclBounds
.bottom
-h
->rclBounds
.top
)/(lpRect
->bottom
-lpRect
->top
);
450 XFORM xform
= {xscale
, 0, 0, yscale
, 0, 0};
451 xform
.eDx
= lpRect
->left
;
452 xform
.eDy
= lpRect
->top
;
453 FIXME(metafile
, "play into rect doesn't work\n");
454 savedMode
= SetGraphicsMode(hdc
, GM_ADVANCED
);
455 if (!SetWorldTransform(hdc
, &xform
)) {
456 WARN(metafile
, "World transform failed!\n");
460 ht
->objectHandle
[0] = hmf
;
462 PlayEnhMetaFileRecord(hdc
, ht
, p
, count
);
463 if (p
->iType
== EMR_EOF
) break;
464 p
= (void *) p
+ p
->nSize
; /* casted so that arithmetic is in bytes */
467 if (savedMode
) SetGraphicsMode(hdc
, savedMode
);
468 ret
= TRUE
; /* FIXME: calculate a more accurate return value */
472 /*****************************************************************************
473 * DeleteEnhMetaFile (GDI32.68)
475 * Deletes an enhanced metafile and frees the associated storage.
477 BOOL32 WINAPI
DeleteEnhMetaFile(HENHMETAFILE32 hmf
) {
478 return !GlobalFree32(hmf
);
481 /*****************************************************************************
482 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
486 HENHMETAFILE32 WINAPI
CopyEnhMetaFile32A(
491 LPENHMETAHEADER h
= GlobalLock32(hmf
);
492 HENHMETAFILE32 hmf2
= GlobalAlloc32(GPTR
, h
->nBytes
);
493 LPENHMETAHEADER h2
= GlobalLock32(hmf2
);
495 memmove(h2
, h
, h
->nBytes
);
496 GlobalUnlock32(hmf2
);
500 FIXME(metafile
, "write to file not implemented\n");