Fixed bug in SwitchStackTo.
[wine/multimedia.git] / objects / enhmetafile.c
blobdcb3dc2da502a9d5b3179d023ad744e9590e3872
1 /*
2 Enhanced metafile functions
3 Copyright 1998, Douglas Ridgway
4 */
6 #include <string.h>
7 #include "windows.h"
8 #include "gdi.h"
9 #include "winbase.h"
10 #include "winnt.h"
11 #include "debug.h"
13 /*****************************************************************************
14 * GetEnhMetaFile32A (GDI32.174)
18 HENHMETAFILE32 WINAPI GetEnhMetaFile32A(
19 LPCSTR lpszMetaFile /* filename of enhanced metafile */
22 HENHMETAFILE32 hmf = 0;
23 ENHMETAHEADER h;
24 BYTE *p;
25 DWORD read;
26 HFILE32 hf = CreateFile32A(lpszMetaFile, GENERIC_READ, 0, 0,
27 OPEN_EXISTING, 0, 0);
28 if (!ReadFile(hf, &h, sizeof(ENHMETAHEADER), &read, NULL))
29 return 0;
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;
36 GlobalUnlock32(hmf);
37 return hmf;
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
45 * _buf.
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));
56 GlobalUnlock32(hmf);
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);
76 buf += first +1;
77 lstrcpynWtoA(buf, (void *)p+p->offDescription+2*(first+1), size-first-1);
79 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
80 GlobalUnlock32(hmf);
81 return MIN(size,p->nDescription);
84 /*****************************************************************************
85 * GetEnhMetaFileDescription32W (GDI32.177)
87 * Copies the description string of an enhanced metafile into a buffer
88 * _buf_.
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));
104 GlobalUnlock32(hmf);
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);
118 GlobalUnlock32(hmf);
119 return hmf;
122 /*****************************************************************************
123 * GetEnhMetaFileBits (GDI32.175)
126 UINT32 WINAPI GetEnhMetaFileBits(
127 HENHMETAFILE32 hmf,
128 UINT32 bufsize,
129 LPBYTE buf
131 return 0;
134 /*****************************************************************************
135 * PlayEnhMetaFileRecord (GDI32.264)
137 * Render a single enhanced metafile record in the device context hdc.
139 * RETURNS
140 * TRUE on success, FALSE on error.
141 * BUGS
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 */
151 int type;
152 TRACE(metafile,
153 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
154 hdc, handletable, mr, handles);
155 if (!mr) return FALSE;
157 type = mr->iType;
159 TRACE(metafile, " type=%d\n", type);
160 switch(type)
162 case EMR_HEADER:
164 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
165 break;
167 case EMR_EOF:
168 break;
169 case EMR_GDICOMMENT:
170 /* application defined and processed */
171 break;
172 case EMR_SETMAPMODE:
174 DWORD mode = mr->dParm[0];
175 SetMapMode32(hdc, mode);
176 break;
178 case EMR_SETBKMODE:
180 DWORD mode = mr->dParm[0];
181 SetBkMode32(hdc, mode);
182 break;
184 case EMR_SETBKCOLOR:
186 DWORD mode = mr->dParm[0];
187 SetBkColor32(hdc, mode);
188 break;
190 case EMR_SETPOLYFILLMODE:
192 DWORD mode = mr->dParm[0];
193 SetPolyFillMode32(hdc, mode);
194 break;
196 case EMR_SETROP2:
198 DWORD mode = mr->dParm[0];
199 SetROP232(hdc, mode);
200 break;
202 case EMR_SETSTRETCHBLTMODE:
204 DWORD mode = mr->dParm[0];
205 SetStretchBltMode32(hdc, mode);
206 break;
208 case EMR_SETTEXTALIGN:
210 DWORD align = mr->dParm[0];
211 SetTextAlign32(hdc, align);
212 break;
214 case EMR_SETTEXTCOLOR:
216 DWORD color = mr->dParm[0];
217 SetTextColor32(hdc, color);
218 break;
220 case EMR_SAVEDC:
222 SaveDC32(hdc);
223 break;
225 case EMR_RESTOREDC:
227 RestoreDC32(hdc, mr->dParm[0]);
228 break;
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);
235 break;
237 case EMR_SELECTOBJECT:
239 DWORD obj = mr->dParm[0];
240 SelectObject32(hdc, (handletable->objectHandle)[obj]);
241 break;
243 case EMR_DELETEOBJECT:
245 DWORD obj = mr->dParm[0];
246 DeleteObject32( (handletable->objectHandle)[obj]);
247 (handletable->objectHandle)[obj] = 0;
248 break;
250 case EMR_SETWINDOWORGEX:
252 DWORD x = mr->dParm[0], y = mr->dParm[1];
253 SetWindowOrgEx32(hdc, x, y, NULL);
254 break;
256 case EMR_SETWINDOWEXTEX:
258 DWORD x = mr->dParm[0], y = mr->dParm[1];
259 SetWindowExtEx32(hdc, x, y, NULL);
260 break;
262 case EMR_SETVIEWPORTORGEX:
264 DWORD x = mr->dParm[0], y = mr->dParm[1];
265 SetViewportOrgEx32(hdc, x, y, NULL);
266 break;
268 case EMR_SETVIEWPORTEXTEX:
270 DWORD x = mr->dParm[0], y = mr->dParm[1];
271 SetViewportExtEx32(hdc, x, y, NULL);
272 break;
274 case EMR_CREATEPEN:
276 DWORD obj = mr->dParm[0];
277 (handletable->objectHandle)[obj] =
278 CreatePenIndirect32((LOGPEN32 *) &(mr->dParm[1]));
279 break;
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);
289 break;
291 case EMR_CREATEBRUSHINDIRECT:
293 DWORD obj = mr->dParm[0];
294 (handletable->objectHandle)[obj] =
295 CreateBrushIndirect32((LOGBRUSH32 *) &(mr->dParm[1]));
296 break;
298 case EMR_EXTCREATEFONTINDIRECTW:
300 DWORD obj = mr->dParm[0];
301 (handletable->objectHandle)[obj] =
302 CreateFontIndirect32W((LOGFONT32W *) &(mr->dParm[1]));
303 break;
305 case EMR_MOVETOEX:
307 DWORD x = mr->dParm[0], y = mr->dParm[1];
308 MoveToEx32(hdc, x, y, NULL);
309 break;
311 case EMR_LINETO:
313 DWORD x = mr->dParm[0], y = mr->dParm[1];
314 LineTo32(hdc, x, y);
315 break;
317 case EMR_RECTANGLE:
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);
322 break;
324 case EMR_ELLIPSE:
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);
329 break;
331 case EMR_POLYGON16:
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);
337 break;
339 case EMR_POLYLINE16:
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);
345 break;
348 #if 0
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);
355 break;
357 #endif
358 case EMR_EXTTEXTOUTW:
360 /* 0-3: ??? */
361 DWORD flags = mr->dParm[4];
362 /* 5, 6: ??? */
363 DWORD x = mr->dParm[7], y = mr->dParm[8];
364 DWORD count = mr->dParm[9];
365 /* 10-16: ??? */
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);
371 break;
374 default:
375 FIXME(metafile, "type %d is unimplemented\n", type);
376 /* SetLastError(E_NOTIMPL); */
377 break;
379 return TRUE;
383 /*****************************************************************************
385 * EnumEnhMetaFile32 (GDI32.79)
387 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
388 * for each
389 * record. Returns when either every record has been used or
390 * when _EnhMetaFunc_ returns FALSE.
393 * RETURNS
394 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
395 * returns FALSE.
397 * BUGS
398 * Ignores rect.
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 */
408 BOOL32 ret = TRUE;
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;
413 while (ret) {
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);
419 GlobalUnlock32(hmf);
420 return ret;
424 /**************************************************************************
425 * PlayEnhMetaFile (GDI32.263)
427 * Renders an enhanced metafile into a specified rectangle *lpRect
428 * in device context hdc.
430 * BUGS
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);
444 BOOL32 ret = FALSE;
445 INT32 savedMode = 0;
446 if (lpRect) {
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;
461 while (1) {
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 */
466 GlobalUnlock32(hmf);
467 if (savedMode) SetGraphicsMode(hdc, savedMode);
468 ret = TRUE; /* FIXME: calculate a more accurate return value */
469 return ret;
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(
487 HENHMETAFILE32 hmf,
488 LPCSTR file)
490 if (!file) {
491 LPENHMETAHEADER h = GlobalLock32(hmf);
492 HENHMETAFILE32 hmf2 = GlobalAlloc32(GPTR, h->nBytes);
493 LPENHMETAHEADER h2 = GlobalLock32(hmf2);
494 if (!h2) return 0;
495 memmove(h2, h, h->nBytes);
496 GlobalUnlock32(hmf2);
497 GlobalUnlock32(hmf);
498 return hmf2;
499 } else {
500 FIXME(metafile, "write to file not implemented\n");
501 return 0;