Adapted to CreateSystemTimer interface change.
[wine/multimedia.git] / objects / enhmetafile.c
blobc57b127208ddf0350ef86208723535d3c097a57c
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"
12 #include "winerror.h"
14 /*****************************************************************************
15 * GetEnhMetaFile32A (GDI32.174)
19 HENHMETAFILE32 WINAPI GetEnhMetaFile32A(
20 LPCSTR lpszMetaFile /* filename of enhanced metafile */
23 HENHMETAFILE32 hmf = 0;
24 ENHMETAHEADER h;
25 BYTE *p;
26 DWORD read;
27 HFILE32 hf = CreateFile32A(lpszMetaFile, GENERIC_READ, 0, 0,
28 OPEN_EXISTING, 0, 0);
29 if (!ReadFile(hf, &h, sizeof(ENHMETAHEADER), &read, NULL))
30 return 0;
31 if (read!=sizeof(ENHMETAHEADER)) return 0;
32 SetFilePointer(hf, 0, NULL, FILE_BEGIN);
33 /* hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
34 hmf = GlobalAlloc32(GPTR, h.nBytes);
35 p = GlobalLock32(hmf);
36 if (!ReadFile(hf, p, h.nBytes, &read, NULL)) return 0;
37 GlobalUnlock32(hmf);
38 return hmf;
41 /*****************************************************************************
42 * GetEnhMetaFileHeader (GDI32.178)
44 * If _buf_ is NULL, returns the size of buffer required.
45 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
46 * _buf.
48 UINT32 WINAPI GetEnhMetaFileHeader(
49 HENHMETAFILE32 hmf, /* enhanced metafile */
50 UINT32 bufsize, /* size of buffer */
51 LPENHMETAHEADER buf /* buffer */
54 LPENHMETAHEADER p = GlobalLock32(hmf);
55 if (!buf) return sizeof(ENHMETAHEADER);
56 memmove(buf, p, MIN(sizeof(ENHMETAHEADER), bufsize));
57 GlobalUnlock32(hmf);
58 return MIN(sizeof(ENHMETAHEADER), bufsize);
62 /*****************************************************************************
63 * GetEnhMetaFileDescription32A (GDI32.176)
65 UINT32 WINAPI GetEnhMetaFileDescription32A(
66 HENHMETAFILE32 hmf, /* enhanced metafile */
67 UINT32 size, /* size of buf */
68 LPSTR buf /* buffer to receive description */
71 LPENHMETAHEADER p = GlobalLock32(hmf);
72 INT32 first = lstrlen32W( (void *)p+p->offDescription);
74 if (!buf || !size) return p->nDescription;
76 lstrcpynWtoA(buf, (void *)p+p->offDescription, size);
77 buf += first +1;
78 lstrcpynWtoA(buf, (void *)p+p->offDescription+2*(first+1), size-first-1);
80 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
81 GlobalUnlock32(hmf);
82 return MIN(size,p->nDescription);
85 /*****************************************************************************
86 * GetEnhMetaFileDescription32W (GDI32.177)
88 * Copies the description string of an enhanced metafile into a buffer
89 * _buf_.
91 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
92 * number of characters copied.
94 UINT32 WINAPI GetEnhMetaFileDescription32W(
95 HENHMETAFILE32 hmf, /* enhanced metafile */
96 UINT32 size, /* size of buf */
97 LPWSTR buf /* buffer to receive description */
100 LPENHMETAHEADER p = GlobalLock32(hmf);
102 if (!buf || !size) return p->nDescription;
104 memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription));
105 GlobalUnlock32(hmf);
106 return MIN(size,p->nDescription);
109 /****************************************************************************
110 * SetEnhMetaFileBits (GDI32.315)
112 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
114 HENHMETAFILE32 WINAPI SetEnhMetaFileBits(UINT32 bufsize, const BYTE *buf)
116 HENHMETAFILE32 hmf = GlobalAlloc32(GPTR, bufsize);
117 LPENHMETAHEADER h = GlobalLock32(hmf);
118 memmove(h, buf, bufsize);
119 GlobalUnlock32(hmf);
120 return hmf;
123 /*****************************************************************************
124 * GetEnhMetaFileBits (GDI32.175)
127 UINT32 WINAPI GetEnhMetaFileBits(
128 HENHMETAFILE32 hmf,
129 UINT32 bufsize,
130 LPBYTE buf
132 return 0;
135 /*****************************************************************************
136 * PlayEnhMetaFileRecord (GDI32.264)
138 * Render a single enhanced metafile record in the device context hdc.
140 * RETURNS
141 * TRUE on success, FALSE on error.
142 * BUGS
143 * Many unimplemented records.
145 BOOL32 WINAPI PlayEnhMetaFileRecord(
146 HDC32 hdc, /* device context in which to render EMF record */
147 LPHANDLETABLE32 handletable, /* array of handles to be used in rendering record */
148 const ENHMETARECORD *mr, /* EMF record to render */
149 UINT32 handles /* size of handle array */
152 int type;
153 TRACE(metafile,
154 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
155 hdc, handletable, mr, handles);
156 if (!mr) return FALSE;
158 type = mr->iType;
160 TRACE(metafile, " type=%d\n", type);
161 switch(type)
163 case EMR_HEADER:
165 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
166 break;
168 case EMR_EOF:
169 break;
170 case EMR_GDICOMMENT:
171 /* application defined and processed */
172 break;
173 case EMR_SETMAPMODE:
175 DWORD mode = mr->dParm[0];
176 SetMapMode32(hdc, mode);
177 break;
179 case EMR_SETBKMODE:
181 DWORD mode = mr->dParm[0];
182 SetBkMode32(hdc, mode);
183 break;
185 case EMR_SETBKCOLOR:
187 DWORD mode = mr->dParm[0];
188 SetBkColor32(hdc, mode);
189 break;
191 case EMR_SETPOLYFILLMODE:
193 DWORD mode = mr->dParm[0];
194 SetPolyFillMode32(hdc, mode);
195 break;
197 case EMR_SETROP2:
199 DWORD mode = mr->dParm[0];
200 SetROP232(hdc, mode);
201 break;
203 case EMR_SETSTRETCHBLTMODE:
205 DWORD mode = mr->dParm[0];
206 SetStretchBltMode32(hdc, mode);
207 break;
209 case EMR_SETTEXTALIGN:
211 DWORD align = mr->dParm[0];
212 SetTextAlign32(hdc, align);
213 break;
215 case EMR_SETTEXTCOLOR:
217 DWORD color = mr->dParm[0];
218 SetTextColor32(hdc, color);
219 break;
221 case EMR_SAVEDC:
223 SaveDC32(hdc);
224 break;
226 case EMR_RESTOREDC:
228 RestoreDC32(hdc, mr->dParm[0]);
229 break;
231 case EMR_INTERSECTCLIPRECT:
233 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
234 bottom = mr->dParm[3];
235 IntersectClipRect32(hdc, left, top, right, bottom);
236 break;
238 case EMR_SELECTOBJECT:
240 DWORD obj = mr->dParm[0];
241 SelectObject32(hdc, (handletable->objectHandle)[obj]);
242 break;
244 case EMR_DELETEOBJECT:
246 DWORD obj = mr->dParm[0];
247 DeleteObject32( (handletable->objectHandle)[obj]);
248 (handletable->objectHandle)[obj] = 0;
249 break;
251 case EMR_SETWINDOWORGEX:
253 DWORD x = mr->dParm[0], y = mr->dParm[1];
254 SetWindowOrgEx32(hdc, x, y, NULL);
255 break;
257 case EMR_SETWINDOWEXTEX:
259 DWORD x = mr->dParm[0], y = mr->dParm[1];
260 SetWindowExtEx32(hdc, x, y, NULL);
261 break;
263 case EMR_SETVIEWPORTORGEX:
265 DWORD x = mr->dParm[0], y = mr->dParm[1];
266 SetViewportOrgEx32(hdc, x, y, NULL);
267 break;
269 case EMR_SETVIEWPORTEXTEX:
271 DWORD x = mr->dParm[0], y = mr->dParm[1];
272 SetViewportExtEx32(hdc, x, y, NULL);
273 break;
275 case EMR_CREATEPEN:
277 DWORD obj = mr->dParm[0];
278 (handletable->objectHandle)[obj] =
279 CreatePenIndirect32((LOGPEN32 *) &(mr->dParm[1]));
280 break;
282 case EMR_EXTCREATEPEN:
284 DWORD obj = mr->dParm[0];
285 DWORD style = mr->dParm[1], brush = mr->dParm[2];
286 LOGBRUSH32 *b = (LOGBRUSH32 *) &mr->dParm[3];
287 FIXME(metafile, "Some ExtCreatePen args not handled\n");
288 (handletable->objectHandle)[obj] =
289 ExtCreatePen32(style, brush, b, 0, NULL);
290 break;
292 case EMR_CREATEBRUSHINDIRECT:
294 DWORD obj = mr->dParm[0];
295 (handletable->objectHandle)[obj] =
296 CreateBrushIndirect32((LOGBRUSH32 *) &(mr->dParm[1]));
297 break;
299 case EMR_EXTCREATEFONTINDIRECTW:
301 DWORD obj = mr->dParm[0];
302 (handletable->objectHandle)[obj] =
303 CreateFontIndirect32W((LOGFONT32W *) &(mr->dParm[1]));
304 break;
306 case EMR_MOVETOEX:
308 DWORD x = mr->dParm[0], y = mr->dParm[1];
309 MoveToEx32(hdc, x, y, NULL);
310 break;
312 case EMR_LINETO:
314 DWORD x = mr->dParm[0], y = mr->dParm[1];
315 LineTo32(hdc, x, y);
316 break;
318 case EMR_RECTANGLE:
320 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
321 bottom = mr->dParm[3];
322 Rectangle32(hdc, left, top, right, bottom);
323 break;
325 case EMR_ELLIPSE:
327 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
328 bottom = mr->dParm[3];
329 Ellipse32(hdc, left, top, right, bottom);
330 break;
332 case EMR_POLYGON16:
334 /* 0-3 : a bounding rectangle? */
335 INT32 count = mr->dParm[4];
336 FIXME(metafile, "Some Polygon16 args not handled\n");
337 Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
338 break;
340 case EMR_POLYLINE16:
342 /* 0-3 : a bounding rectangle? */
343 INT32 count = mr->dParm[4];
344 FIXME(metafile, "Some Polyline16 args not handled\n");
345 Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
346 break;
349 #if 0
350 case EMR_POLYPOLYGON16:
352 INT32 polygons = mr->dParm[z];
353 LPPOINT16 pts = (LPPOINT16) &mr->dParm[x];
354 LPINT16 counts = (LPINT16) &mr->dParm[y];
355 PolyPolygon16(hdc, pts, counts, polygons);
356 break;
358 #endif
359 case EMR_EXTTEXTOUTW:
361 /* 0-3: ??? */
362 DWORD flags = mr->dParm[4];
363 /* 5, 6: ??? */
364 DWORD x = mr->dParm[7], y = mr->dParm[8];
365 DWORD count = mr->dParm[9];
366 /* 10-16: ??? */
367 LPWSTR str = (LPWSTR)& mr->dParm[17];
368 /* trailing info: dx array? */
369 FIXME(metafile, "Many ExtTextOut args not handled\n");
370 ExtTextOut32W(hdc, x, y, flags, /* lpRect */ NULL,
371 str, count, /* lpDx */ NULL);
372 break;
375 default:
376 FIXME(metafile, "type %d is unimplemented\n", type);
377 /* SetLastError(E_NOTIMPL); */
378 break;
380 return TRUE;
384 /*****************************************************************************
386 * EnumEnhMetaFile32 (GDI32.79)
388 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
389 * for each
390 * record. Returns when either every record has been used or
391 * when _EnhMetaFunc_ returns FALSE.
394 * RETURNS
395 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
396 * returns FALSE.
398 * BUGS
399 * Ignores rect.
401 BOOL32 WINAPI EnumEnhMetaFile32(
402 HDC32 hdc, /* device context to pass to _EnhMetaFunc_ */
403 HENHMETAFILE32 hmf, /* EMF to walk */
404 ENHMFENUMPROC32 callback, /* callback function */
405 LPVOID data, /* optional data for callback function */
406 const RECT32 *rect /* bounding rectangle for rendered metafile */
409 BOOL32 ret = TRUE;
410 LPENHMETARECORD p = GlobalLock32(hmf);
411 INT32 count = ((LPENHMETAHEADER) p)->nHandles;
412 HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR, sizeof(HANDLETABLE32)*count);
413 ht->objectHandle[0] = hmf;
414 while (ret) {
415 ret = (*callback)(hdc, ht, p, count, data);
416 if (p->iType == EMR_EOF) break;
417 p = (void *) p + p->nSize;
419 GlobalFree32((HGLOBAL32)ht);
420 GlobalUnlock32(hmf);
421 return ret;
425 /**************************************************************************
426 * PlayEnhMetaFile (GDI32.263)
428 * Renders an enhanced metafile into a specified rectangle *lpRect
429 * in device context hdc.
431 * BUGS
432 * Almost entirely unimplemented
435 BOOL32 WINAPI PlayEnhMetaFile(
436 HDC32 hdc, /* DC to render into */
437 HENHMETAFILE32 hmf, /* metafile to render */
438 const RECT32 *lpRect /* rectangle to place metafile inside */
441 LPENHMETARECORD p = GlobalLock32(hmf);
442 INT32 count = ((LPENHMETAHEADER) p)->nHandles;
443 HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR,
444 sizeof(HANDLETABLE32)*count);
445 BOOL32 ret = FALSE;
446 INT32 savedMode = 0;
447 if (lpRect) {
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 savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
456 if (!SetWorldTransform(hdc, &xform)) {
457 WARN(metafile, "World transform failed!\n");
461 ht->objectHandle[0] = hmf;
462 while (1) {
463 PlayEnhMetaFileRecord(hdc, ht, p, count);
464 if (p->iType == EMR_EOF) break;
465 p = (void *) p + p->nSize; /* casted so that arithmetic is in bytes */
467 GlobalUnlock32(hmf);
468 if (savedMode) SetGraphicsMode(hdc, savedMode);
469 ret = TRUE; /* FIXME: calculate a more accurate return value */
470 return ret;
473 /*****************************************************************************
474 * DeleteEnhMetaFile (GDI32.68)
476 * Deletes an enhanced metafile and frees the associated storage.
478 BOOL32 WINAPI DeleteEnhMetaFile(HENHMETAFILE32 hmf) {
479 return !GlobalFree32(hmf);
482 /*****************************************************************************
483 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
487 HENHMETAFILE32 WINAPI CopyEnhMetaFile32A(
488 HENHMETAFILE32 hmf,
489 LPCSTR file)
491 if (!file) {
492 LPENHMETAHEADER h = GlobalLock32(hmf);
493 HENHMETAFILE32 hmf2 = GlobalAlloc32(GPTR, h->nBytes);
494 LPENHMETAHEADER h2 = GlobalLock32(hmf2);
495 if (!h2) return 0;
496 memmove(h2, h, h->nBytes);
497 GlobalUnlock32(hmf2);
498 GlobalUnlock32(hmf);
499 return hmf2;
500 } else {
501 FIXME(metafile, "write to file not implemented\n");
502 return 0;
506 /*****************************************************************************
507 * GetEnhMetaFilePaletteEntries (GDI32.179)
509 * Copy the palette and report size
512 UINT32 WINAPI GetEnhMetaFilePaletteEntries(HENHMETAFILE32 hemf,
513 UINT32 cEntries,
514 LPPALETTEENTRY lppe)
516 LPENHMETAHEADER h = GlobalLock32(hemf);
518 if ( h == NULL ){
519 GlobalUnlock32(hemf);
520 return(0);
521 } else {
522 if ((lppe)&&(cEntries>0)){
523 FIXME(metafile,"Stub\n");
524 GlobalUnlock32(hemf);
525 return(GDI_ERROR);
526 } else{
527 GlobalUnlock32(hemf);
528 return(0);
535 /******************************************************************
536 * SetWinMetaFileBits (GDI32.343)
538 * Translate from old style to new style.
541 HENHMETAFILE32 WINAPI SetWinMetaFileBits(UINT32 cbBuffer,
542 CONST BYTE *lpbBuffer,
543 HDC32 hdcRef,
544 CONST METAFILEPICT32 *lpmfp
547 FIXME(metafile,"Stub\n");
548 return 0;