2 Enhanced metafile functions
3 Copyright 1998, Douglas Ridgway
15 /*****************************************************************************
16 * GetEnhMetaFile32A (GDI32.174)
20 HENHMETAFILE32 WINAPI
GetEnhMetaFile32A(
21 LPCSTR lpszMetaFile
/* filename of enhanced metafile */
24 HENHMETAFILE32 hmf
= 0;
28 HFILE32 hf
= CreateFile32A(lpszMetaFile
, GENERIC_READ
, 0, 0,
30 if (hf
== INVALID_HANDLE_VALUE32
) {
31 FIXME(metafile
,"could not open %s\n",lpszMetaFile
);
34 if (!ReadFile(hf
, &h
, sizeof(ENHMETAHEADER
), &read
, NULL
)) {
35 FIXME(metafile
,"%s can't be read.\n",lpszMetaFile
);
39 if (read
!=sizeof(ENHMETAHEADER
)) {
40 FIXME(metafile
,"%s is not long enough.\n",lpszMetaFile
);
45 FIXME(metafile
,"%s has invalid emf header (type 0x%08lx).\n",lpszMetaFile
,h
.iType
);
49 if (memcmp(&(h
.dSignature
)," EMF",4)) {
50 FIXME(metafile
,"%s has invalid EMF header (dSignature 0x%08lx).\n",lpszMetaFile
,h
.dSignature
);
54 SetFilePointer(hf
, 0, NULL
, FILE_BEGIN
);
55 /* hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
56 hmf
= GlobalAlloc32(GPTR
, h
.nBytes
);
57 p
= GlobalLock32(hmf
);
58 if (!ReadFile(hf
, p
, h
.nBytes
, &read
, NULL
)) {
59 FIXME(metafile
,"%s could not be read.\n",lpszMetaFile
);
65 FIXME(metafile
,"%s is not long enough (%ld expected, %ld got).\n",lpszMetaFile
,h
.nBytes
,read
);
74 /*****************************************************************************
75 * GetEnhMetaFile32W (GDI32.180)
77 HENHMETAFILE32 WINAPI
GetEnhMetaFile32W(
78 LPCWSTR lpszMetaFile
) /* filename of enhanced metafile */
80 FIXME(metafile
, "(%p): stub\n", lpszMetaFile
);
84 /*****************************************************************************
85 * GetEnhMetaFileHeader (GDI32.178)
87 * If _buf_ is NULL, returns the size of buffer required.
88 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
91 UINT32 WINAPI
GetEnhMetaFileHeader(
92 HENHMETAFILE32 hmf
, /* enhanced metafile */
93 UINT32 bufsize
, /* size of buffer */
94 LPENHMETAHEADER buf
/* buffer */
97 LPENHMETAHEADER p
= GlobalLock32(hmf
);
98 if (!buf
) return sizeof(ENHMETAHEADER
);
99 memmove(buf
, p
, MIN(sizeof(ENHMETAHEADER
), bufsize
));
101 return MIN(sizeof(ENHMETAHEADER
), bufsize
);
105 /*****************************************************************************
106 * GetEnhMetaFileDescription32A (GDI32.176)
108 UINT32 WINAPI
GetEnhMetaFileDescription32A(
109 HENHMETAFILE32 hmf
, /* enhanced metafile */
110 UINT32 size
, /* size of buf */
111 LPSTR buf
/* buffer to receive description */
114 LPENHMETAHEADER p
= GlobalLock32(hmf
);
115 INT32 first
= lstrlen32W( (void *)p
+p
->offDescription
);
117 if (!buf
|| !size
) return p
->nDescription
;
119 lstrcpynWtoA(buf
, (void *)p
+p
->offDescription
, size
);
121 lstrcpynWtoA(buf
, (void *)p
+p
->offDescription
+2*(first
+1), size
-first
-1);
123 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
125 return MIN(size
,p
->nDescription
);
128 /*****************************************************************************
129 * GetEnhMetaFileDescription32W (GDI32.177)
131 * Copies the description string of an enhanced metafile into a buffer
134 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
135 * number of characters copied.
137 UINT32 WINAPI
GetEnhMetaFileDescription32W(
138 HENHMETAFILE32 hmf
, /* enhanced metafile */
139 UINT32 size
, /* size of buf */
140 LPWSTR buf
/* buffer to receive description */
143 LPENHMETAHEADER p
= GlobalLock32(hmf
);
145 if (!buf
|| !size
) return p
->nDescription
;
147 memmove(buf
, (void *)p
+p
->offDescription
, MIN(size
,p
->nDescription
));
149 return MIN(size
,p
->nDescription
);
152 /****************************************************************************
153 * SetEnhMetaFileBits (GDI32.315)
155 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
157 HENHMETAFILE32 WINAPI
SetEnhMetaFileBits(UINT32 bufsize
, const BYTE
*buf
)
159 HENHMETAFILE32 hmf
= GlobalAlloc32(GPTR
, bufsize
);
160 LPENHMETAHEADER h
= GlobalLock32(hmf
);
161 memmove(h
, buf
, bufsize
);
166 /*****************************************************************************
167 * GetEnhMetaFileBits (GDI32.175)
170 UINT32 WINAPI
GetEnhMetaFileBits(
178 /*****************************************************************************
179 * PlayEnhMetaFileRecord (GDI32.264)
181 * Render a single enhanced metafile record in the device context hdc.
184 * TRUE on success, FALSE on error.
186 * Many unimplemented records.
188 BOOL32 WINAPI
PlayEnhMetaFileRecord(
189 HDC32 hdc
, /* device context in which to render EMF record */
190 LPHANDLETABLE32 handletable
, /* array of handles to be used in rendering record */
191 const ENHMETARECORD
*mr
, /* EMF record to render */
192 UINT32 handles
/* size of handle array */
197 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
198 hdc
, handletable
, mr
, handles
);
199 if (!mr
) return FALSE
;
203 TRACE(metafile
, " type=%d\n", type
);
208 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
214 /* application defined and processed */
218 DWORD mode
= mr
->dParm
[0];
219 SetMapMode32(hdc
, mode
);
224 DWORD mode
= mr
->dParm
[0];
225 SetBkMode32(hdc
, mode
);
230 DWORD mode
= mr
->dParm
[0];
231 SetBkColor32(hdc
, mode
);
234 case EMR_SETPOLYFILLMODE
:
236 DWORD mode
= mr
->dParm
[0];
237 SetPolyFillMode32(hdc
, mode
);
242 DWORD mode
= mr
->dParm
[0];
243 SetROP232(hdc
, mode
);
246 case EMR_SETSTRETCHBLTMODE
:
248 DWORD mode
= mr
->dParm
[0];
249 SetStretchBltMode32(hdc
, mode
);
252 case EMR_SETTEXTALIGN
:
254 DWORD align
= mr
->dParm
[0];
255 SetTextAlign32(hdc
, align
);
258 case EMR_SETTEXTCOLOR
:
260 DWORD color
= mr
->dParm
[0];
261 SetTextColor32(hdc
, color
);
271 RestoreDC32(hdc
, mr
->dParm
[0]);
274 case EMR_INTERSECTCLIPRECT
:
276 INT32 left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
277 bottom
= mr
->dParm
[3];
278 IntersectClipRect32(hdc
, left
, top
, right
, bottom
);
281 case EMR_SELECTOBJECT
:
283 DWORD obj
= mr
->dParm
[0];
284 SelectObject32(hdc
, (handletable
->objectHandle
)[obj
]);
287 case EMR_DELETEOBJECT
:
289 DWORD obj
= mr
->dParm
[0];
290 DeleteObject32( (handletable
->objectHandle
)[obj
]);
291 (handletable
->objectHandle
)[obj
] = 0;
294 case EMR_SETWINDOWORGEX
:
296 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
297 SetWindowOrgEx32(hdc
, x
, y
, NULL
);
300 case EMR_SETWINDOWEXTEX
:
302 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
303 SetWindowExtEx32(hdc
, x
, y
, NULL
);
306 case EMR_SETVIEWPORTORGEX
:
308 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
309 SetViewportOrgEx32(hdc
, x
, y
, NULL
);
312 case EMR_SETVIEWPORTEXTEX
:
314 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
315 SetViewportExtEx32(hdc
, x
, y
, NULL
);
320 DWORD obj
= mr
->dParm
[0];
321 (handletable
->objectHandle
)[obj
] =
322 CreatePenIndirect32((LOGPEN32
*) &(mr
->dParm
[1]));
325 case EMR_EXTCREATEPEN
:
327 DWORD obj
= mr
->dParm
[0];
328 DWORD style
= mr
->dParm
[1], brush
= mr
->dParm
[2];
329 LOGBRUSH32
*b
= (LOGBRUSH32
*) &mr
->dParm
[3];
330 FIXME(metafile
, "Some ExtCreatePen args not handled\n");
331 (handletable
->objectHandle
)[obj
] =
332 ExtCreatePen32(style
, brush
, b
, 0, NULL
);
335 case EMR_CREATEBRUSHINDIRECT
:
337 DWORD obj
= mr
->dParm
[0];
338 (handletable
->objectHandle
)[obj
] =
339 CreateBrushIndirect32((LOGBRUSH32
*) &(mr
->dParm
[1]));
342 case EMR_EXTCREATEFONTINDIRECTW
:
344 DWORD obj
= mr
->dParm
[0];
345 (handletable
->objectHandle
)[obj
] =
346 CreateFontIndirect32W((LOGFONT32W
*) &(mr
->dParm
[1]));
351 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
352 MoveToEx32(hdc
, x
, y
, NULL
);
357 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
363 INT32 left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
364 bottom
= mr
->dParm
[3];
365 Rectangle32(hdc
, left
, top
, right
, bottom
);
370 INT32 left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
371 bottom
= mr
->dParm
[3];
372 Ellipse32(hdc
, left
, top
, right
, bottom
);
377 /* 0-3 : a bounding rectangle? */
378 INT32 count
= mr
->dParm
[4];
379 FIXME(metafile
, "Some Polygon16 args not handled\n");
380 Polygon16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
385 /* 0-3 : a bounding rectangle? */
386 INT32 count
= mr
->dParm
[4];
387 FIXME(metafile
, "Some Polyline16 args not handled\n");
388 Polyline16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
393 case EMR_POLYPOLYGON16
:
395 INT32 polygons
= mr
->dParm
[z
];
396 LPPOINT16 pts
= (LPPOINT16
) &mr
->dParm
[x
];
397 LPINT16 counts
= (LPINT16
) &mr
->dParm
[y
];
398 PolyPolygon16(hdc
, pts
, counts
, polygons
);
402 case EMR_STRETCHDIBITS
:
404 LONG xDest
= mr
->dParm
[4];
405 LONG yDest
= mr
->dParm
[5];
406 LONG xSrc
= mr
->dParm
[6];
407 LONG ySrc
= mr
->dParm
[7];
408 LONG cxSrc
= mr
->dParm
[8];
409 LONG cySrc
= mr
->dParm
[9];
410 DWORD offBmiSrc
= mr
->dParm
[10];
411 DWORD offBitsSrc
= mr
->dParm
[12];
412 DWORD iUsageSrc
= mr
->dParm
[14];
413 DWORD dwRop
= mr
->dParm
[15];
414 LONG cxDest
= mr
->dParm
[16];
415 LONG cyDest
= mr
->dParm
[17];
417 StretchDIBits32(hdc
,xDest
,yDest
,cxDest
,cyDest
,
418 xSrc
,ySrc
,cxSrc
,cySrc
,
419 ((char *)mr
)+offBitsSrc
,
420 (const BITMAPINFO
*)(((char *)mr
)+offBmiSrc
),
424 case EMR_EXTTEXTOUTW
:
427 DWORD flags
= mr
->dParm
[4];
429 DWORD x
= mr
->dParm
[7], y
= mr
->dParm
[8];
430 DWORD count
= mr
->dParm
[9];
432 LPWSTR str
= (LPWSTR
)& mr
->dParm
[17];
433 /* trailing info: dx array? */
434 FIXME(metafile
, "Many ExtTextOut args not handled\n");
435 ExtTextOut32W(hdc
, x
, y
, flags
, /* lpRect */ NULL
,
436 str
, count
, /* lpDx */ NULL
);
441 FIXME(metafile
, "type %d is unimplemented\n", type
);
442 /* SetLastError(E_NOTIMPL); */
449 /*****************************************************************************
451 * EnumEnhMetaFile32 (GDI32.79)
453 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
455 * record. Returns when either every record has been used or
456 * when _EnhMetaFunc_ returns FALSE.
460 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
466 BOOL32 WINAPI
EnumEnhMetaFile32(
467 HDC32 hdc
, /* device context to pass to _EnhMetaFunc_ */
468 HENHMETAFILE32 hmf
, /* EMF to walk */
469 ENHMFENUMPROC32 callback
, /* callback function */
470 LPVOID data
, /* optional data for callback function */
471 const RECT32
*rect
/* bounding rectangle for rendered metafile */
475 LPENHMETARECORD p
= GlobalLock32(hmf
);
476 INT32 count
= ((LPENHMETAHEADER
) p
)->nHandles
;
477 HANDLETABLE32
*ht
= (HANDLETABLE32
*)GlobalAlloc32(GPTR
, sizeof(HANDLETABLE32
)*count
);
478 ht
->objectHandle
[0] = hmf
;
480 ret
= (*callback
)(hdc
, ht
, p
, count
, data
);
481 if (p
->iType
== EMR_EOF
) break;
482 p
= (void *) p
+ p
->nSize
;
484 GlobalFree32((HGLOBAL32
)ht
);
490 /**************************************************************************
491 * PlayEnhMetaFile (GDI32.263)
493 * Renders an enhanced metafile into a specified rectangle *lpRect
494 * in device context hdc.
497 * Almost entirely unimplemented
500 BOOL32 WINAPI
PlayEnhMetaFile(
501 HDC32 hdc
, /* DC to render into */
502 HENHMETAFILE32 hmf
, /* metafile to render */
503 const RECT32
*lpRect
/* rectangle to place metafile inside */
506 LPENHMETARECORD p
= GlobalLock32(hmf
);
507 INT32 count
= ((LPENHMETAHEADER
) p
)->nHandles
;
508 HANDLETABLE32
*ht
= (HANDLETABLE32
*)GlobalAlloc32(GPTR
,
509 sizeof(HANDLETABLE32
)*count
);
513 LPENHMETAHEADER h
= (LPENHMETAHEADER
) p
;
514 FLOAT xscale
= (h
->rclBounds
.right
-h
->rclBounds
.left
)/(lpRect
->right
-lpRect
->left
);
515 FLOAT yscale
= (h
->rclBounds
.bottom
-h
->rclBounds
.top
)/(lpRect
->bottom
-lpRect
->top
);
516 XFORM xform
= {xscale
, 0, 0, yscale
, 0, 0};
517 xform
.eDx
= lpRect
->left
;
518 xform
.eDy
= lpRect
->top
;
519 FIXME(metafile
, "play into rect doesn't work\n");
520 savedMode
= SetGraphicsMode(hdc
, GM_ADVANCED
);
521 if (!SetWorldTransform(hdc
, &xform
)) {
522 WARN(metafile
, "World transform failed!\n");
526 ht
->objectHandle
[0] = hmf
;
528 PlayEnhMetaFileRecord(hdc
, ht
, p
, count
);
529 if (p
->iType
== EMR_EOF
) break;
530 p
= (void *) p
+ p
->nSize
; /* casted so that arithmetic is in bytes */
533 if (savedMode
) SetGraphicsMode(hdc
, savedMode
);
534 ret
= TRUE
; /* FIXME: calculate a more accurate return value */
538 /*****************************************************************************
539 * DeleteEnhMetaFile (GDI32.68)
541 * Deletes an enhanced metafile and frees the associated storage.
543 BOOL32 WINAPI
DeleteEnhMetaFile(HENHMETAFILE32 hmf
) {
544 return !GlobalFree32(hmf
);
547 /*****************************************************************************
548 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
552 HENHMETAFILE32 WINAPI
CopyEnhMetaFile32A(
557 LPENHMETAHEADER h
= GlobalLock32(hmf
);
558 HENHMETAFILE32 hmf2
= GlobalAlloc32(GPTR
, h
->nBytes
);
559 LPENHMETAHEADER h2
= GlobalLock32(hmf2
);
561 memmove(h2
, h
, h
->nBytes
);
562 GlobalUnlock32(hmf2
);
566 FIXME(metafile
, "write to file not implemented\n");
571 /*****************************************************************************
572 * GetEnhMetaFilePaletteEntries (GDI32.179)
574 * Copy the palette and report size
577 UINT32 WINAPI
GetEnhMetaFilePaletteEntries(HENHMETAFILE32 hemf
,
581 LPENHMETAHEADER h
= GlobalLock32(hemf
);
584 GlobalUnlock32(hemf
);
587 if ((lppe
)&&(cEntries
>0)){
588 FIXME(metafile
,"Stub\n");
589 GlobalUnlock32(hemf
);
592 GlobalUnlock32(hemf
);
600 /******************************************************************
601 * SetWinMetaFileBits (GDI32.343)
603 * Translate from old style to new style.
606 HENHMETAFILE32 WINAPI
SetWinMetaFileBits(UINT32 cbBuffer
,
607 CONST BYTE
*lpbBuffer
,
609 CONST METAFILEPICT32
*lpmfp
612 FIXME(metafile
,"Stub\n");