2 Enhanced metafile functions
3 Copyright 1998, Douglas Ridgway
10 #include "wine/winestring.h"
14 DEFAULT_DEBUG_CHANNEL(metafile
)
16 /*****************************************************************************
17 * GetEnhMetaFile32A (GDI32.174)
21 HENHMETAFILE WINAPI
GetEnhMetaFileA(
22 LPCSTR lpszMetaFile
/* filename of enhanced metafile */
29 HFILE hf
= CreateFileA(lpszMetaFile
, GENERIC_READ
, 0, 0,
31 if (hf
== INVALID_HANDLE_VALUE
) {
32 FIXME(metafile
,"could not open %s\n",lpszMetaFile
);
35 if (!ReadFile(hf
, &h
, sizeof(ENHMETAHEADER
), &read
, NULL
)) {
36 FIXME(metafile
,"%s can't be read.\n",lpszMetaFile
);
40 if (read
!=sizeof(ENHMETAHEADER
)) {
41 FIXME(metafile
,"%s is not long enough.\n",lpszMetaFile
);
46 FIXME(metafile
,"%s has invalid emf header (type 0x%08lx).\n",lpszMetaFile
,h
.iType
);
50 if (memcmp(&(h
.dSignature
)," EMF",4)) {
51 FIXME(metafile
,"%s has invalid EMF header (dSignature 0x%08lx).\n",lpszMetaFile
,h
.dSignature
);
55 SetFilePointer(hf
, 0, NULL
, FILE_BEGIN
);
56 /* hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
57 hmf
= GlobalAlloc(GPTR
, h
.nBytes
);
59 if (!ReadFile(hf
, p
, h
.nBytes
, &read
, NULL
)) {
60 FIXME(metafile
,"%s could not be read.\n",lpszMetaFile
);
66 FIXME(metafile
,"%s is not long enough (%ld expected, %ld got).\n",lpszMetaFile
,h
.nBytes
,read
);
75 /*****************************************************************************
76 * GetEnhMetaFile32W (GDI32.180)
78 HENHMETAFILE WINAPI
GetEnhMetaFileW(
79 LPCWSTR lpszMetaFile
) /* filename of enhanced metafile */
81 FIXME(metafile
, "(%p): stub\n", lpszMetaFile
);
85 /*****************************************************************************
86 * GetEnhMetaFileHeader (GDI32.178)
88 * If _buf_ is NULL, returns the size of buffer required.
89 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
92 UINT WINAPI
GetEnhMetaFileHeader(
93 HENHMETAFILE hmf
, /* enhanced metafile */
94 UINT bufsize
, /* size of buffer */
95 LPENHMETAHEADER buf
/* buffer */
98 LPENHMETAHEADER p
= GlobalLock(hmf
);
99 if (!buf
) return sizeof(ENHMETAHEADER
);
100 memmove(buf
, p
, MIN(sizeof(ENHMETAHEADER
), bufsize
));
102 return MIN(sizeof(ENHMETAHEADER
), bufsize
);
106 /*****************************************************************************
107 * GetEnhMetaFileDescription32A (GDI32.176)
109 UINT WINAPI
GetEnhMetaFileDescriptionA(
110 HENHMETAFILE hmf
, /* enhanced metafile */
111 UINT size
, /* size of buf */
112 LPSTR buf
/* buffer to receive description */
115 LPENHMETAHEADER p
= GlobalLock(hmf
);
116 INT first
= lstrlenW( (void *)p
+p
->offDescription
);
118 if (!buf
|| !size
) return p
->nDescription
;
120 lstrcpynWtoA(buf
, (void *)p
+p
->offDescription
, size
);
122 lstrcpynWtoA(buf
, (void *)p
+p
->offDescription
+2*(first
+1), size
-first
-1);
124 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
126 return MIN(size
,p
->nDescription
);
129 /*****************************************************************************
130 * GetEnhMetaFileDescription32W (GDI32.177)
132 * Copies the description string of an enhanced metafile into a buffer
135 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
136 * number of characters copied.
138 UINT WINAPI
GetEnhMetaFileDescriptionW(
139 HENHMETAFILE hmf
, /* enhanced metafile */
140 UINT size
, /* size of buf */
141 LPWSTR buf
/* buffer to receive description */
144 LPENHMETAHEADER p
= GlobalLock(hmf
);
146 if (!buf
|| !size
) return p
->nDescription
;
148 memmove(buf
, (void *)p
+p
->offDescription
, MIN(size
,p
->nDescription
));
150 return MIN(size
,p
->nDescription
);
153 /****************************************************************************
154 * SetEnhMetaFileBits (GDI32.315)
156 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
158 HENHMETAFILE WINAPI
SetEnhMetaFileBits(UINT bufsize
, const BYTE
*buf
)
160 HENHMETAFILE hmf
= GlobalAlloc(GPTR
, bufsize
);
161 LPENHMETAHEADER h
= GlobalLock(hmf
);
162 memmove(h
, buf
, bufsize
);
167 /*****************************************************************************
168 * GetEnhMetaFileBits (GDI32.175)
171 UINT WINAPI
GetEnhMetaFileBits(
179 /*****************************************************************************
180 * PlayEnhMetaFileRecord (GDI32.264)
182 * Render a single enhanced metafile record in the device context hdc.
185 * TRUE on success, FALSE on error.
187 * Many unimplemented records.
189 BOOL WINAPI
PlayEnhMetaFileRecord(
190 HDC hdc
, /* device context in which to render EMF record */
191 LPHANDLETABLE handletable
, /* array of handles to be used in rendering record */
192 const ENHMETARECORD
*mr
, /* EMF record to render */
193 UINT handles
/* size of handle array */
198 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
199 hdc
, handletable
, mr
, handles
);
200 if (!mr
) return FALSE
;
204 TRACE(metafile
, " type=%d\n", type
);
209 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
215 /* application defined and processed */
219 DWORD mode
= mr
->dParm
[0];
220 SetMapMode(hdc
, mode
);
225 DWORD mode
= mr
->dParm
[0];
226 SetBkMode(hdc
, mode
);
231 DWORD mode
= mr
->dParm
[0];
232 SetBkColor(hdc
, mode
);
235 case EMR_SETPOLYFILLMODE
:
237 DWORD mode
= mr
->dParm
[0];
238 SetPolyFillMode(hdc
, mode
);
243 DWORD mode
= mr
->dParm
[0];
247 case EMR_SETSTRETCHBLTMODE
:
249 DWORD mode
= mr
->dParm
[0];
250 SetStretchBltMode(hdc
, mode
);
253 case EMR_SETTEXTALIGN
:
255 DWORD align
= mr
->dParm
[0];
256 SetTextAlign(hdc
, align
);
259 case EMR_SETTEXTCOLOR
:
261 DWORD color
= mr
->dParm
[0];
262 SetTextColor(hdc
, color
);
272 RestoreDC(hdc
, mr
->dParm
[0]);
275 case EMR_INTERSECTCLIPRECT
:
277 INT left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
278 bottom
= mr
->dParm
[3];
279 IntersectClipRect(hdc
, left
, top
, right
, bottom
);
282 case EMR_SELECTOBJECT
:
284 DWORD obj
= mr
->dParm
[0];
285 SelectObject(hdc
, (handletable
->objectHandle
)[obj
]);
288 case EMR_DELETEOBJECT
:
290 DWORD obj
= mr
->dParm
[0];
291 DeleteObject( (handletable
->objectHandle
)[obj
]);
292 (handletable
->objectHandle
)[obj
] = 0;
295 case EMR_SETWINDOWORGEX
:
297 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
298 SetWindowOrgEx(hdc
, x
, y
, NULL
);
301 case EMR_SETWINDOWEXTEX
:
303 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
304 SetWindowExtEx(hdc
, x
, y
, NULL
);
307 case EMR_SETVIEWPORTORGEX
:
309 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
310 SetViewportOrgEx(hdc
, x
, y
, NULL
);
313 case EMR_SETVIEWPORTEXTEX
:
315 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
316 SetViewportExtEx(hdc
, x
, y
, NULL
);
321 DWORD obj
= mr
->dParm
[0];
322 (handletable
->objectHandle
)[obj
] =
323 CreatePenIndirect((LOGPEN
*) &(mr
->dParm
[1]));
326 case EMR_EXTCREATEPEN
:
328 DWORD obj
= mr
->dParm
[0];
329 DWORD style
= mr
->dParm
[1], brush
= mr
->dParm
[2];
330 LOGBRUSH
*b
= (LOGBRUSH
*) &mr
->dParm
[3];
331 FIXME(metafile
, "Some ExtCreatePen args not handled\n");
332 (handletable
->objectHandle
)[obj
] =
333 ExtCreatePen(style
, brush
, b
, 0, NULL
);
336 case EMR_CREATEBRUSHINDIRECT
:
338 DWORD obj
= mr
->dParm
[0];
339 (handletable
->objectHandle
)[obj
] =
340 CreateBrushIndirect((LOGBRUSH
*) &(mr
->dParm
[1]));
343 case EMR_EXTCREATEFONTINDIRECTW
:
345 DWORD obj
= mr
->dParm
[0];
346 (handletable
->objectHandle
)[obj
] =
347 CreateFontIndirectW((LOGFONTW
*) &(mr
->dParm
[1]));
352 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
353 MoveToEx(hdc
, x
, y
, NULL
);
358 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
364 INT left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
365 bottom
= mr
->dParm
[3];
366 Rectangle(hdc
, left
, top
, right
, bottom
);
371 INT left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
372 bottom
= mr
->dParm
[3];
373 Ellipse(hdc
, left
, top
, right
, bottom
);
378 /* 0-3 : a bounding rectangle? */
379 INT count
= mr
->dParm
[4];
380 FIXME(metafile
, "Some Polygon16 args not handled\n");
381 Polygon16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
386 /* 0-3 : a bounding rectangle? */
387 INT count
= mr
->dParm
[4];
388 FIXME(metafile
, "Some Polyline16 args not handled\n");
389 Polyline16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
394 case EMR_POLYPOLYGON16
:
396 INT polygons
= mr
->dParm
[z
];
397 LPPOINT16 pts
= (LPPOINT16
) &mr
->dParm
[x
];
398 LPINT16 counts
= (LPINT16
) &mr
->dParm
[y
];
399 PolyPolygon16(hdc
, pts
, counts
, polygons
);
403 case EMR_STRETCHDIBITS
:
405 LONG xDest
= mr
->dParm
[4];
406 LONG yDest
= mr
->dParm
[5];
407 LONG xSrc
= mr
->dParm
[6];
408 LONG ySrc
= mr
->dParm
[7];
409 LONG cxSrc
= mr
->dParm
[8];
410 LONG cySrc
= mr
->dParm
[9];
411 DWORD offBmiSrc
= mr
->dParm
[10];
412 DWORD offBitsSrc
= mr
->dParm
[12];
413 DWORD iUsageSrc
= mr
->dParm
[14];
414 DWORD dwRop
= mr
->dParm
[15];
415 LONG cxDest
= mr
->dParm
[16];
416 LONG cyDest
= mr
->dParm
[17];
418 StretchDIBits(hdc
,xDest
,yDest
,cxDest
,cyDest
,
419 xSrc
,ySrc
,cxSrc
,cySrc
,
420 ((char *)mr
)+offBitsSrc
,
421 (const BITMAPINFO
*)(((char *)mr
)+offBmiSrc
),
425 case EMR_EXTTEXTOUTW
:
428 DWORD flags
= mr
->dParm
[4];
430 DWORD x
= mr
->dParm
[7], y
= mr
->dParm
[8];
431 DWORD count
= mr
->dParm
[9];
433 LPWSTR str
= (LPWSTR
)& mr
->dParm
[17];
434 /* trailing info: dx array? */
435 FIXME(metafile
, "Many ExtTextOut args not handled\n");
436 ExtTextOutW(hdc
, x
, y
, flags
, /* lpRect */ NULL
,
437 str
, count
, /* lpDx */ NULL
);
442 FIXME(metafile
, "type %d is unimplemented\n", type
);
443 /* SetLastError(E_NOTIMPL); */
450 /*****************************************************************************
452 * EnumEnhMetaFile32 (GDI32.79)
454 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
456 * record. Returns when either every record has been used or
457 * when _EnhMetaFunc_ returns FALSE.
461 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
467 BOOL WINAPI
EnumEnhMetaFile(
468 HDC hdc
, /* device context to pass to _EnhMetaFunc_ */
469 HENHMETAFILE hmf
, /* EMF to walk */
470 ENHMFENUMPROC callback
, /* callback function */
471 LPVOID data
, /* optional data for callback function */
472 const RECT
*rect
/* bounding rectangle for rendered metafile */
476 LPENHMETARECORD p
= GlobalLock(hmf
);
477 INT count
= ((LPENHMETAHEADER
) p
)->nHandles
;
478 HANDLETABLE
*ht
= (HANDLETABLE
*)GlobalAlloc(GPTR
, sizeof(HANDLETABLE
)*count
);
479 ht
->objectHandle
[0] = hmf
;
481 ret
= (*callback
)(hdc
, ht
, p
, count
, data
);
482 if (p
->iType
== EMR_EOF
) break;
483 p
= (void *) p
+ p
->nSize
;
485 GlobalFree((HGLOBAL
)ht
);
491 /**************************************************************************
492 * PlayEnhMetaFile (GDI32.263)
494 * Renders an enhanced metafile into a specified rectangle *lpRect
495 * in device context hdc.
498 * Almost entirely unimplemented
501 BOOL WINAPI
PlayEnhMetaFile(
502 HDC hdc
, /* DC to render into */
503 HENHMETAFILE hmf
, /* metafile to render */
504 const RECT
*lpRect
/* rectangle to place metafile inside */
507 LPENHMETARECORD p
= GlobalLock(hmf
);
508 INT count
= ((LPENHMETAHEADER
) p
)->nHandles
;
509 HANDLETABLE
*ht
= (HANDLETABLE
*)GlobalAlloc(GPTR
,
510 sizeof(HANDLETABLE
)*count
);
514 LPENHMETAHEADER h
= (LPENHMETAHEADER
) p
;
515 FLOAT xscale
= (h
->rclBounds
.right
-h
->rclBounds
.left
)/(lpRect
->right
-lpRect
->left
);
516 FLOAT yscale
= (h
->rclBounds
.bottom
-h
->rclBounds
.top
)/(lpRect
->bottom
-lpRect
->top
);
517 XFORM xform
= {xscale
, 0, 0, yscale
, 0, 0};
518 xform
.eDx
= lpRect
->left
;
519 xform
.eDy
= lpRect
->top
;
520 FIXME(metafile
, "play into rect doesn't work\n");
521 savedMode
= SetGraphicsMode(hdc
, GM_ADVANCED
);
522 if (!SetWorldTransform(hdc
, &xform
)) {
523 WARN(metafile
, "World transform failed!\n");
527 ht
->objectHandle
[0] = hmf
;
529 PlayEnhMetaFileRecord(hdc
, ht
, p
, count
);
530 if (p
->iType
== EMR_EOF
) break;
531 p
= (void *) p
+ p
->nSize
; /* casted so that arithmetic is in bytes */
534 if (savedMode
) SetGraphicsMode(hdc
, savedMode
);
535 ret
= TRUE
; /* FIXME: calculate a more accurate return value */
539 /*****************************************************************************
540 * DeleteEnhMetaFile (GDI32.68)
542 * Deletes an enhanced metafile and frees the associated storage.
544 BOOL WINAPI
DeleteEnhMetaFile(HENHMETAFILE hmf
) {
545 return !GlobalFree(hmf
);
548 /*****************************************************************************
549 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
553 HENHMETAFILE WINAPI
CopyEnhMetaFileA(
558 LPENHMETAHEADER h
= GlobalLock(hmf
);
559 HENHMETAFILE hmf2
= GlobalAlloc(GPTR
, h
->nBytes
);
560 LPENHMETAHEADER h2
= GlobalLock(hmf2
);
562 memmove(h2
, h
, h
->nBytes
);
567 FIXME(metafile
, "write to file not implemented\n");
572 /*****************************************************************************
573 * GetEnhMetaFilePaletteEntries (GDI32.179)
575 * Copy the palette and report size
578 UINT WINAPI
GetEnhMetaFilePaletteEntries(HENHMETAFILE hemf
,
582 LPENHMETAHEADER h
= GlobalLock(hemf
);
588 if ((lppe
)&&(cEntries
>0)){
589 FIXME(metafile
,"Stub\n");
601 /******************************************************************
602 * SetWinMetaFileBits (GDI32.343)
604 * Translate from old style to new style.
607 HENHMETAFILE WINAPI
SetWinMetaFileBits(UINT cbBuffer
,
608 CONST BYTE
*lpbBuffer
,
610 CONST METAFILEPICT
*lpmfp
613 FIXME(metafile
,"Stub\n");