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.xxx)
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(
146 /* device context in which to render EMF record */
147 LPHANDLETABLE32 handletable,
148 /* array of handles to be used in rendering record */
149 const ENHMETARECORD *mr, /* EMF record to render */
150 UINT32 handles /* size of handle array */
155 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
156 hdc, handletable, mr, handles);
157 if (!mr) return FALSE;
161 TRACE(metafile, " type=%d\n", type);
166 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
172 /* application defined and processed */
176 DWORD mode = mr->dParm[0];
177 SetMapMode32(hdc, mode);
182 DWORD mode = mr->dParm[0];
183 SetBkMode32(hdc, mode);
188 DWORD mode = mr->dParm[0];
189 SetBkColor32(hdc, mode);
192 case EMR_SETPOLYFILLMODE:
194 DWORD mode = mr->dParm[0];
195 SetPolyFillMode32(hdc, mode);
200 DWORD mode = mr->dParm[0];
201 SetROP232(hdc, mode);
204 case EMR_SETSTRETCHBLTMODE:
206 DWORD mode = mr->dParm[0];
207 SetStretchBltMode32(hdc, mode);
210 case EMR_SETTEXTALIGN:
212 DWORD align = mr->dParm[0];
213 SetTextAlign32(hdc, align);
216 case EMR_SETTEXTCOLOR:
218 DWORD color = mr->dParm[0];
219 SetTextColor32(hdc, color);
229 RestoreDC32(hdc, mr->dParm[0]);
232 case EMR_INTERSECTCLIPRECT:
234 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
235 bottom = mr->dParm[3];
236 IntersectClipRect32(hdc, left, top, right, bottom);
239 case EMR_SELECTOBJECT:
241 DWORD obj = mr->dParm[0];
242 SelectObject32(hdc, (handletable->objectHandle)[obj]);
245 case EMR_DELETEOBJECT:
247 DWORD obj = mr->dParm[0];
248 DeleteObject32( (handletable->objectHandle)[obj]);
249 (handletable->objectHandle)[obj] = 0;
252 case EMR_SETWINDOWORGEX:
254 DWORD x = mr->dParm[0], y = mr->dParm[1];
255 SetWindowOrgEx32(hdc, x, y, NULL);
258 case EMR_SETWINDOWEXTEX:
260 DWORD x = mr->dParm[0], y = mr->dParm[1];
261 SetWindowExtEx32(hdc, x, y, NULL);
264 case EMR_SETVIEWPORTORGEX:
266 DWORD x = mr->dParm[0], y = mr->dParm[1];
267 SetViewportOrgEx32(hdc, x, y, NULL);
270 case EMR_SETVIEWPORTEXTEX:
272 DWORD x = mr->dParm[0], y = mr->dParm[1];
273 SetViewportExtEx32(hdc, x, y, NULL);
278 DWORD obj = mr->dParm[0];
279 (handletable->objectHandle)[obj] =
280 CreatePenIndirect32((LOGPEN32 *) &(mr->dParm[1]));
283 case EMR_EXTCREATEPEN:
285 DWORD obj = mr->dParm[0];
286 DWORD style = mr->dParm[1], brush = mr->dParm[2];
287 LOGBRUSH32 *b = (LOGBRUSH32 *) &mr->dParm[3];
288 FIXME(metafile, "Some ExtCreatePen args not handled\n");
289 (handletable->objectHandle)[obj] =
290 ExtCreatePen32(style, brush, b, 0, NULL);
293 case EMR_CREATEBRUSHINDIRECT:
295 DWORD obj = mr->dParm[0];
296 (handletable->objectHandle)[obj] =
297 CreateBrushIndirect32((LOGBRUSH32 *) &(mr->dParm[1]));
300 case EMR_EXTCREATEFONTINDIRECTW:
302 DWORD obj = mr->dParm[0];
303 (handletable->objectHandle)[obj] =
304 CreateFontIndirect32W((LOGFONT32W *) &(mr->dParm[1]));
309 DWORD x = mr->dParm[0], y = mr->dParm[1];
310 MoveToEx32(hdc, x, y, NULL);
315 DWORD x = mr->dParm[0], y = mr->dParm[1];
321 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
322 bottom = mr->dParm[3];
323 Rectangle32(hdc, left, top, right, bottom);
328 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
329 bottom = mr->dParm[3];
330 Ellipse32(hdc, left, top, right, bottom);
335 /* 0-3 : a bounding rectangle? */
336 INT32 count = mr->dParm[4];
337 FIXME(metafile, "Some Polygon16 args not handled\n");
338 Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
343 /* 0-3 : a bounding rectangle? */
344 INT32 count = mr->dParm[4];
345 FIXME(metafile, "Some Polyline16 args not handled\n");
346 Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
351 case EMR_POLYPOLYGON16:
353 INT32 polygons = mr->dParm[z];
354 LPPOINT16 pts = (LPPOINT16) &mr->dParm[x];
355 LPINT16 counts = (LPINT16) &mr->dParm[y];
356 PolyPolygon16(hdc, pts, counts, polygons);
360 case EMR_EXTTEXTOUTW:
363 DWORD flags = mr->dParm[4];
365 DWORD x = mr->dParm[7], y = mr->dParm[8];
366 DWORD count = mr->dParm[9];
368 LPWSTR str = (LPWSTR)& mr->dParm[17];
369 /* trailing info: dx array? */
370 FIXME(metafile, "Many ExtTextOut args not handled\n");
371 ExtTextOut32W(hdc, x, y, flags, /* lpRect */ NULL,
372 str, count, /* lpDx */ NULL);
377 FIXME(metafile, "type %d is unimplemented\n", type);
378 /* SetLastError(E_NOTIMPL); */
385 /*****************************************************************************
387 * EnumEnhMetaFile32 (GDI32.79)
389 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
391 * record. Returns when either every record has been used or
392 * when _EnhMetaFunc_ returns FALSE.
396 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
402 BOOL32 WINAPI EnumEnhMetaFile32(
403 HDC32 hdc, /* device context to pass to _EnhMetaFunc_ */
404 HENHMETAFILE32 hmf, /* EMF to walk */
405 ENHMFENUMPROC32 callback, /* callback function */
406 LPVOID data, /* optional data for callback function */
407 const RECT32 *rect /* bounding rectangle for rendered metafile */
411 LPENHMETARECORD p = GlobalLock32(hmf);
412 INT32 count = ((LPENHMETAHEADER) p)->nHandles;
413 HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR, sizeof(HANDLETABLE32)*count);
414 ht->objectHandle[0] = hmf;
416 ret = (*callback)(hdc, ht, p, count, data);
417 if (p->iType == EMR_EOF) break;
418 p = (void *) p + p->nSize;
420 GlobalFree32((HGLOBAL32)ht);
426 /**************************************************************************
427 * PlayEnhMetaFile (GDI32.263)
429 * Renders an enhanced metafile into a specified rectangle *lpRect
430 * in device context hdc.
433 * Almost entirely unimplemented
436 BOOL32 WINAPI PlayEnhMetaFile(
437 HDC32 hdc, /* DC to render into */
438 HENHMETAFILE32 hmf, /* metafile to render */
439 const RECT32 *lpRect /* rectangle to place metafile inside */
442 LPENHMETARECORD p = GlobalLock32(hmf);
443 INT32 count = ((LPENHMETAHEADER) p)->nHandles;
444 HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR,
445 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 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 ret = TRUE; /* FIXME: calculate a more accurate return value */
471 /*****************************************************************************
472 * DeleteEnhMetaFile (GDI32.68)
474 * Deletes an enhanced metafile and frees the associated storage.
476 BOOL32 WINAPI DeleteEnhMetaFile(HENHMETAFILE32 hmf) {
477 return !GlobalFree32(hmf);
480 /*****************************************************************************
481 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
485 HENHMETAFILE32 WINAPI CopyEnhMetaFile32A(
490 LPENHMETAHEADER h = GlobalLock32(hmf);
491 HENHMETAFILE32 hmf2 = GlobalAlloc32(GPTR, h->nBytes);
492 LPENHMETAHEADER h2 = GlobalLock32(hmf2);
494 memmove(h2, h, h->nBytes);
495 GlobalUnlock32(hmf2);
499 FIXME(metafile, "write to file not implemented\n");