2 * Enhanced metafile functions
3 * Copyright 1998 Douglas Ridgway
11 #include "wine/winestring.h"
13 #include "enhmetafile.h"
17 DEFAULT_DEBUG_CHANNEL(enhmetafile
)
19 /****************************************************************************
20 * EMF_Create_HENHMETAFILE
22 HENHMETAFILE
EMF_Create_HENHMETAFILE(ENHMETAHEADER
*emh
, HFILE hFile
, HANDLE
25 HENHMETAFILE hmf
= GDI_AllocObject( sizeof(ENHMETAFILEOBJ
),
27 ENHMETAFILEOBJ
*metaObj
= (ENHMETAFILEOBJ
*)GDI_HEAP_LOCK( hmf
);
29 metaObj
->hFile
= hFile
;
30 metaObj
->hMapping
= hMapping
;
31 GDI_HEAP_UNLOCK( hmf
);
35 /****************************************************************************
36 * EMF_Delete_HENHMETAFILE
38 static BOOL
EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf
)
40 ENHMETAFILEOBJ
*metaObj
= (ENHMETAFILEOBJ
*)GDI_GetObjPtr( hmf
,
42 if(!metaObj
) return FALSE
;
43 if(metaObj
->hMapping
) {
44 UnmapViewOfFile( metaObj
->emh
);
45 CloseHandle( metaObj
->hMapping
);
46 CloseHandle( metaObj
->hFile
);
48 HeapFree( SystemHeap
, 0, metaObj
->emh
);
49 return GDI_FreeObject( hmf
);
52 /******************************************************************
53 * EMF_GetEnhMetaHeader
55 * Returns ptr to ENHMETAHEADER associated with HENHMETAFILE
56 * Should be followed by call to EMF_ReleaseEnhMetaHeader
58 static ENHMETAHEADER
*EMF_GetEnhMetaHeader( HENHMETAFILE hmf
)
60 ENHMETAFILEOBJ
*metaObj
= (ENHMETAFILEOBJ
*)GDI_GetObjPtr( hmf
,
62 TRACE(enhmetafile
, "hmf %04x -> enhmetaObj %p\n", hmf
, metaObj
);
66 /******************************************************************
67 * EMF_ReleaseEnhMetaHeader
69 * Releases ENHMETAHEADER associated with HENHMETAFILE
71 static BOOL
EMF_ReleaseEnhMetaHeader( HENHMETAFILE hmf
)
73 return GDI_HEAP_UNLOCK( hmf
);
76 /*****************************************************************************
80 static HENHMETAFILE
EMF_GetEnhMetaFile( HFILE hFile
)
85 hMapping
= CreateFileMappingA( hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
86 emh
= MapViewOfFile( hMapping
, FILE_MAP_READ
, 0, 0, 0 );
88 if (emh
->iType
!= EMR_HEADER
|| emh
->dSignature
!= ENHMETA_SIGNATURE
) {
89 WARN(enhmetafile
, "Invalid emf header type 0x%08lx sig 0x%08lx.\n",
90 emh
->iType
, emh
->dSignature
);
91 UnmapViewOfFile( emh
);
92 CloseHandle( hMapping
);
95 return EMF_Create_HENHMETAFILE( emh
, hFile
, hMapping
);
99 /*****************************************************************************
100 * GetEnhMetaFileA (GDI32.174)
104 HENHMETAFILE WINAPI
GetEnhMetaFileA(
105 LPCSTR lpszMetaFile
/* filename of enhanced metafile */
111 hFile
= CreateFileA(lpszMetaFile
, GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0);
112 if (hFile
== INVALID_HANDLE_VALUE
) {
113 WARN(enhmetafile
,"could not open %s\n", lpszMetaFile
);
116 hmf
= EMF_GetEnhMetaFile( hFile
);
118 CloseHandle( hFile
);
122 /*****************************************************************************
123 * GetEnhMetaFile32W (GDI32.180)
125 HENHMETAFILE WINAPI
GetEnhMetaFileW(
126 LPCWSTR lpszMetaFile
) /* filename of enhanced metafile */
131 hFile
= CreateFileW(lpszMetaFile
, GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0);
132 if (hFile
== INVALID_HANDLE_VALUE
) {
133 WARN(enhmetafile
,"could not open %s\n", debugstr_w(lpszMetaFile
));
136 hmf
= EMF_GetEnhMetaFile( hFile
);
138 CloseHandle( hFile
);
142 /*****************************************************************************
143 * GetEnhMetaFileHeader (GDI32.178)
145 * If _buf_ is NULL, returns the size of buffer required.
146 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
149 UINT WINAPI
GetEnhMetaFileHeader(
150 HENHMETAFILE hmf
, /* enhanced metafile */
151 UINT bufsize
, /* size of buffer */
152 LPENHMETAHEADER buf
/* buffer */
157 if (!buf
) return sizeof(ENHMETAHEADER
);
158 emh
= EMF_GetEnhMetaHeader(hmf
);
159 memmove(buf
, emh
, MIN(sizeof(ENHMETAHEADER
), bufsize
));
160 EMF_ReleaseEnhMetaHeader(hmf
);
161 return MIN(sizeof(ENHMETAHEADER
), bufsize
);
165 /*****************************************************************************
166 * GetEnhMetaFileDescription32A (GDI32.176)
168 UINT WINAPI
GetEnhMetaFileDescriptionA(
169 HENHMETAFILE hmf
, /* enhanced metafile */
170 UINT size
, /* size of buf */
171 LPSTR buf
/* buffer to receive description */
174 LPENHMETAHEADER emh
= EMF_GetEnhMetaHeader(hmf
);
177 if(emh
->nDescription
== 0 || emh
->offDescription
== 0) {
178 EMF_ReleaseEnhMetaHeader(hmf
);
181 if (!buf
|| !size
) {
182 EMF_ReleaseEnhMetaHeader(hmf
);
183 return emh
->nDescription
;
186 first
= lstrlenW( (WCHAR
*) ((char *) emh
+ emh
->offDescription
));
188 lstrcpynWtoA(buf
, (WCHAR
*) ((char *) emh
+ emh
->offDescription
), size
);
190 lstrcpynWtoA(buf
, (WCHAR
*) ((char *) emh
+ emh
->offDescription
+2*(first
+1)),
193 EMF_ReleaseEnhMetaHeader(hmf
);
194 return MIN(size
, emh
->nDescription
);
197 /*****************************************************************************
198 * GetEnhMetaFileDescription32W (GDI32.177)
200 * Copies the description string of an enhanced metafile into a buffer
203 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
204 * number of characters copied.
206 UINT WINAPI
GetEnhMetaFileDescriptionW(
207 HENHMETAFILE hmf
, /* enhanced metafile */
208 UINT size
, /* size of buf */
209 LPWSTR buf
/* buffer to receive description */
212 LPENHMETAHEADER emh
= EMF_GetEnhMetaHeader(hmf
);
214 if(emh
->nDescription
== 0 || emh
->offDescription
== 0) {
215 EMF_ReleaseEnhMetaHeader(hmf
);
218 if (!buf
|| !size
) {
219 EMF_ReleaseEnhMetaHeader(hmf
);
220 return emh
->nDescription
;
223 memmove(buf
, (char *) emh
+ emh
->offDescription
,
224 MIN(size
,emh
->nDescription
));
225 EMF_ReleaseEnhMetaHeader(hmf
);
226 return MIN(size
, emh
->nDescription
);
229 /****************************************************************************
230 * SetEnhMetaFileBits (GDI32.315)
232 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
234 HENHMETAFILE WINAPI
SetEnhMetaFileBits(UINT bufsize
, const BYTE
*buf
)
236 ENHMETAHEADER
*emh
= HeapAlloc( SystemHeap
, 0, bufsize
);
237 memmove(emh
, buf
, bufsize
);
238 return EMF_Create_HENHMETAFILE( emh
, 0, 0 );
241 /*****************************************************************************
242 * GetEnhMetaFileBits (GDI32.175)
245 UINT WINAPI
GetEnhMetaFileBits(
253 /*****************************************************************************
254 * PlayEnhMetaFileRecord (GDI32.264)
256 * Render a single enhanced metafile record in the device context hdc.
259 * TRUE on success, FALSE on error.
261 * Many unimplemented records.
263 BOOL WINAPI
PlayEnhMetaFileRecord(
264 HDC hdc
, /* device context in which to render EMF record */
265 LPHANDLETABLE handletable
, /* array of handles to be used in rendering record */
266 const ENHMETARECORD
*mr
, /* EMF record to render */
267 UINT handles
/* size of handle array */
272 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
273 hdc
, handletable
, mr
, handles
);
274 if (!mr
) return FALSE
;
278 TRACE(enhmetafile
, " type=%d\n", type
);
283 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
289 /* application defined and processed */
293 DWORD mode
= mr
->dParm
[0];
294 SetMapMode(hdc
, mode
);
299 DWORD mode
= mr
->dParm
[0];
300 SetBkMode(hdc
, mode
);
305 DWORD mode
= mr
->dParm
[0];
306 SetBkColor(hdc
, mode
);
309 case EMR_SETPOLYFILLMODE
:
311 DWORD mode
= mr
->dParm
[0];
312 SetPolyFillMode(hdc
, mode
);
317 DWORD mode
= mr
->dParm
[0];
321 case EMR_SETSTRETCHBLTMODE
:
323 DWORD mode
= mr
->dParm
[0];
324 SetStretchBltMode(hdc
, mode
);
327 case EMR_SETTEXTALIGN
:
329 DWORD align
= mr
->dParm
[0];
330 SetTextAlign(hdc
, align
);
333 case EMR_SETTEXTCOLOR
:
335 DWORD color
= mr
->dParm
[0];
336 SetTextColor(hdc
, color
);
346 RestoreDC(hdc
, mr
->dParm
[0]);
349 case EMR_INTERSECTCLIPRECT
:
351 INT left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
352 bottom
= mr
->dParm
[3];
353 IntersectClipRect(hdc
, left
, top
, right
, bottom
);
356 case EMR_SELECTOBJECT
:
358 DWORD obj
= mr
->dParm
[0];
359 SelectObject(hdc
, (handletable
->objectHandle
)[obj
]);
362 case EMR_DELETEOBJECT
:
364 DWORD obj
= mr
->dParm
[0];
365 DeleteObject( (handletable
->objectHandle
)[obj
]);
366 (handletable
->objectHandle
)[obj
] = 0;
369 case EMR_SETWINDOWORGEX
:
371 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
372 SetWindowOrgEx(hdc
, x
, y
, NULL
);
375 case EMR_SETWINDOWEXTEX
:
377 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
378 SetWindowExtEx(hdc
, x
, y
, NULL
);
381 case EMR_SETVIEWPORTORGEX
:
383 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
384 SetViewportOrgEx(hdc
, x
, y
, NULL
);
387 case EMR_SETVIEWPORTEXTEX
:
389 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
390 SetViewportExtEx(hdc
, x
, y
, NULL
);
395 DWORD obj
= mr
->dParm
[0];
396 (handletable
->objectHandle
)[obj
] =
397 CreatePenIndirect((LOGPEN
*) &(mr
->dParm
[1]));
400 case EMR_EXTCREATEPEN
:
402 DWORD obj
= mr
->dParm
[0];
403 DWORD style
= mr
->dParm
[1], brush
= mr
->dParm
[2];
404 LOGBRUSH
*b
= (LOGBRUSH
*) &mr
->dParm
[3];
405 FIXME(enhmetafile
, "Some ExtCreatePen args not handled\n");
406 (handletable
->objectHandle
)[obj
] =
407 ExtCreatePen(style
, brush
, b
, 0, NULL
);
410 case EMR_CREATEBRUSHINDIRECT
:
412 DWORD obj
= mr
->dParm
[0];
413 (handletable
->objectHandle
)[obj
] =
414 CreateBrushIndirect((LOGBRUSH
*) &(mr
->dParm
[1]));
417 case EMR_EXTCREATEFONTINDIRECTW
:
419 DWORD obj
= mr
->dParm
[0];
420 (handletable
->objectHandle
)[obj
] =
421 CreateFontIndirectW((LOGFONTW
*) &(mr
->dParm
[1]));
426 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
427 MoveToEx(hdc
, x
, y
, NULL
);
432 DWORD x
= mr
->dParm
[0], y
= mr
->dParm
[1];
438 INT left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
439 bottom
= mr
->dParm
[3];
440 Rectangle(hdc
, left
, top
, right
, bottom
);
445 INT left
= mr
->dParm
[0], top
= mr
->dParm
[1], right
= mr
->dParm
[2],
446 bottom
= mr
->dParm
[3];
447 Ellipse(hdc
, left
, top
, right
, bottom
);
452 /* 0-3 : a bounding rectangle? */
453 INT count
= mr
->dParm
[4];
454 FIXME(enhmetafile
, "Some Polygon16 args not handled\n");
455 Polygon16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
460 /* 0-3 : a bounding rectangle? */
461 INT count
= mr
->dParm
[4];
462 FIXME(enhmetafile
, "Some Polyline16 args not handled\n");
463 Polyline16(hdc
, (POINT16
*)&mr
->dParm
[5], count
);
468 case EMR_POLYPOLYGON16
:
470 INT polygons
= mr
->dParm
[z
];
471 LPPOINT16 pts
= (LPPOINT16
) &mr
->dParm
[x
];
472 LPINT16 counts
= (LPINT16
) &mr
->dParm
[y
];
473 PolyPolygon16(hdc
, pts
, counts
, polygons
);
477 case EMR_STRETCHDIBITS
:
479 LONG xDest
= mr
->dParm
[4];
480 LONG yDest
= mr
->dParm
[5];
481 LONG xSrc
= mr
->dParm
[6];
482 LONG ySrc
= mr
->dParm
[7];
483 LONG cxSrc
= mr
->dParm
[8];
484 LONG cySrc
= mr
->dParm
[9];
485 DWORD offBmiSrc
= mr
->dParm
[10];
486 DWORD offBitsSrc
= mr
->dParm
[12];
487 DWORD iUsageSrc
= mr
->dParm
[14];
488 DWORD dwRop
= mr
->dParm
[15];
489 LONG cxDest
= mr
->dParm
[16];
490 LONG cyDest
= mr
->dParm
[17];
492 StretchDIBits(hdc
,xDest
,yDest
,cxDest
,cyDest
,
493 xSrc
,ySrc
,cxSrc
,cySrc
,
494 ((char *)mr
)+offBitsSrc
,
495 (const BITMAPINFO
*)(((char *)mr
)+offBmiSrc
),
499 case EMR_EXTTEXTOUTW
:
502 DWORD flags
= mr
->dParm
[4];
504 DWORD x
= mr
->dParm
[7], y
= mr
->dParm
[8];
505 DWORD count
= mr
->dParm
[9];
507 LPWSTR str
= (LPWSTR
)& mr
->dParm
[17];
508 /* trailing info: dx array? */
509 FIXME(enhmetafile
, "Many ExtTextOut args not handled\n");
510 ExtTextOutW(hdc
, x
, y
, flags
, /* lpRect */ NULL
,
511 str
, count
, /* lpDx */ NULL
);
516 FIXME(enhmetafile
, "type %d is unimplemented\n", type
);
517 /* SetLastError(E_NOTIMPL); */
524 /*****************************************************************************
526 * EnumEnhMetaFile32 (GDI32.79)
528 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
530 * record. Returns when either every record has been used or
531 * when _EnhMetaFunc_ returns FALSE.
535 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
541 BOOL WINAPI
EnumEnhMetaFile(
542 HDC hdc
, /* device context to pass to _EnhMetaFunc_ */
543 HENHMETAFILE hmf
, /* EMF to walk */
544 ENHMFENUMPROC callback
, /* callback function */
545 LPVOID data
, /* optional data for callback function */
546 const RECT
*rect
/* bounding rectangle for rendered metafile */
550 LPENHMETARECORD p
= (LPENHMETARECORD
) EMF_GetEnhMetaHeader(hmf
);
551 INT count
= ((LPENHMETAHEADER
) p
)->nHandles
;
552 HANDLETABLE
*ht
= HeapAlloc( GetProcessHeap(), 0,
553 sizeof(HANDLETABLE
)*count
);
554 ht
->objectHandle
[0] = hmf
;
556 ret
= (*callback
)(hdc
, ht
, p
, count
, data
);
557 if (p
->iType
== EMR_EOF
) break;
558 p
= (LPENHMETARECORD
) ((char *) p
+ p
->nSize
);
560 HeapFree( GetProcessHeap(), 0, ht
);
561 EMF_ReleaseEnhMetaHeader(hmf
);
566 /**************************************************************************
567 * PlayEnhMetaFile (GDI32.263)
569 * Renders an enhanced metafile into a specified rectangle *lpRect
570 * in device context hdc.
573 * Almost entirely unimplemented
576 BOOL WINAPI
PlayEnhMetaFile(
577 HDC hdc
, /* DC to render into */
578 HENHMETAFILE hmf
, /* metafile to render */
579 const RECT
*lpRect
/* rectangle to place metafile inside */
582 LPENHMETARECORD p
= (LPENHMETARECORD
) EMF_GetEnhMetaHeader(hmf
);
583 INT count
= ((LPENHMETAHEADER
) p
)->nHandles
;
584 HANDLETABLE
*ht
= HeapAlloc( GetProcessHeap(), 0,
585 sizeof(HANDLETABLE
) * count
);
589 LPENHMETAHEADER h
= (LPENHMETAHEADER
) p
;
590 FLOAT xscale
= (h
->rclBounds
.right
- h
->rclBounds
.left
) /
591 (lpRect
->right
- lpRect
->left
);
592 FLOAT yscale
= (h
->rclBounds
.bottom
- h
->rclBounds
.top
) /
593 (lpRect
->bottom
- lpRect
->top
);
599 xform
.eDx
= lpRect
->left
;
600 xform
.eDy
= lpRect
->top
;
601 FIXME(enhmetafile
, "play into rect doesn't work\n");
602 savedMode
= SetGraphicsMode(hdc
, GM_ADVANCED
);
603 if (!SetWorldTransform(hdc
, &xform
)) {
604 WARN(enhmetafile
, "World transform failed!\n");
608 ht
->objectHandle
[0] = hmf
;
610 PlayEnhMetaFileRecord(hdc
, ht
, p
, count
);
611 if (p
->iType
== EMR_EOF
) break;
612 p
= (LPENHMETARECORD
) ((char *) p
+ p
->nSize
); /* casted so that arithmetic is in bytes */
614 HeapFree( GetProcessHeap(), 0, ht
);
615 EMF_ReleaseEnhMetaHeader(hmf
);
616 if (savedMode
) SetGraphicsMode(hdc
, savedMode
);
617 ret
= TRUE
; /* FIXME: calculate a more accurate return value */
621 /*****************************************************************************
622 * DeleteEnhMetaFile (GDI32.68)
624 * Deletes an enhanced metafile and frees the associated storage.
626 BOOL WINAPI
DeleteEnhMetaFile(HENHMETAFILE hmf
)
628 return EMF_Delete_HENHMETAFILE( hmf
);
631 /*****************************************************************************
632 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
636 HENHMETAFILE WINAPI
CopyEnhMetaFileA(
640 ENHMETAHEADER
*emrSrc
= EMF_GetEnhMetaHeader( hmfSrc
), *emrDst
;
644 emrDst
= HeapAlloc( SystemHeap
, 0, emrSrc
->nBytes
);
645 memcpy( emrDst
, emrSrc
, emrSrc
->nBytes
);
646 hmfDst
= EMF_Create_HENHMETAFILE( emrDst
, 0, 0 );
649 hFile
= CreateFileA( file
, GENERIC_WRITE
| GENERIC_READ
, 0, NULL
,
650 CREATE_ALWAYS
, 0, -1);
651 WriteFile( hFile
, emrSrc
, emrSrc
->nBytes
, 0, 0);
652 hmfDst
= EMF_GetEnhMetaFile( hFile
);
654 EMF_ReleaseEnhMetaHeader( hmfSrc
);
659 /*****************************************************************************
660 * GetEnhMetaFilePaletteEntries (GDI32.179)
662 * Copy the palette and report size
665 UINT WINAPI
GetEnhMetaFilePaletteEntries(HENHMETAFILE hemf
,
673 /******************************************************************
674 * SetWinMetaFileBits (GDI32.343)
676 * Translate from old style to new style.
679 HENHMETAFILE WINAPI
SetWinMetaFileBits(UINT cbBuffer
,
680 CONST BYTE
*lpbBuffer
,
682 CONST METAFILEPICT
*lpmfp
685 FIXME(enhmetafile
,"Stub\n");