Some small fixes to enhmetafiles.
[wine/testsucceed.git] / objects / enhmetafile.c
blob1af461e34f632cf09979470c3293461e0e61c2dd
1 /*
2 Enhanced metafile functions
3 Copyright 1998, Douglas Ridgway
4 */
6 #include <string.h>
7 #include <assert.h>
8 #include "windows.h"
9 #include "gdi.h"
10 #include "winbase.h"
11 #include "winnt.h"
12 #include "debug.h"
13 #include "winerror.h"
15 /*****************************************************************************
16 * GetEnhMetaFile32A (GDI32.174)
20 HENHMETAFILE32 WINAPI GetEnhMetaFile32A(
21 LPCSTR lpszMetaFile /* filename of enhanced metafile */
24 HENHMETAFILE32 hmf = 0;
25 ENHMETAHEADER h;
26 BYTE *p;
27 DWORD read;
28 HFILE32 hf = CreateFile32A(lpszMetaFile, GENERIC_READ, 0, 0,
29 OPEN_EXISTING, 0, 0);
30 if (hf == INVALID_HANDLE_VALUE32) {
31 FIXME(metafile,"could not open %s\n",lpszMetaFile);
32 return 0;
34 if (!ReadFile(hf, &h, sizeof(ENHMETAHEADER), &read, NULL))
35 return 0;
36 if (read!=sizeof(ENHMETAHEADER)) return 0;
37 SetFilePointer(hf, 0, NULL, FILE_BEGIN);
38 /* hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
39 hmf = GlobalAlloc32(GPTR, h.nBytes);
40 p = GlobalLock32(hmf);
41 if (!ReadFile(hf, p, h.nBytes, &read, NULL)) return 0;
42 assert(read==h.nBytes);
43 GlobalUnlock32(hmf);
44 return hmf;
47 /*****************************************************************************
48 * GetEnhMetaFile32W (GDI32.180)
50 HENHMETAFILE32 WINAPI GetEnhMetaFile32W(
51 LPCWSTR lpszMetaFile) /* filename of enhanced metafile */
53 FIXME(metafile, "(%p): stub\n", lpszMetaFile);
54 return 0;
57 /*****************************************************************************
58 * GetEnhMetaFileHeader (GDI32.178)
60 * If _buf_ is NULL, returns the size of buffer required.
61 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
62 * _buf.
64 UINT32 WINAPI GetEnhMetaFileHeader(
65 HENHMETAFILE32 hmf, /* enhanced metafile */
66 UINT32 bufsize, /* size of buffer */
67 LPENHMETAHEADER buf /* buffer */
70 LPENHMETAHEADER p = GlobalLock32(hmf);
71 if (!buf) return sizeof(ENHMETAHEADER);
72 memmove(buf, p, MIN(sizeof(ENHMETAHEADER), bufsize));
73 GlobalUnlock32(hmf);
74 return MIN(sizeof(ENHMETAHEADER), bufsize);
78 /*****************************************************************************
79 * GetEnhMetaFileDescription32A (GDI32.176)
81 UINT32 WINAPI GetEnhMetaFileDescription32A(
82 HENHMETAFILE32 hmf, /* enhanced metafile */
83 UINT32 size, /* size of buf */
84 LPSTR buf /* buffer to receive description */
87 LPENHMETAHEADER p = GlobalLock32(hmf);
88 INT32 first = lstrlen32W( (void *)p+p->offDescription);
90 if (!buf || !size) return p->nDescription;
92 lstrcpynWtoA(buf, (void *)p+p->offDescription, size);
93 buf += first +1;
94 lstrcpynWtoA(buf, (void *)p+p->offDescription+2*(first+1), size-first-1);
96 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
97 GlobalUnlock32(hmf);
98 return MIN(size,p->nDescription);
101 /*****************************************************************************
102 * GetEnhMetaFileDescription32W (GDI32.177)
104 * Copies the description string of an enhanced metafile into a buffer
105 * _buf_.
107 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
108 * number of characters copied.
110 UINT32 WINAPI GetEnhMetaFileDescription32W(
111 HENHMETAFILE32 hmf, /* enhanced metafile */
112 UINT32 size, /* size of buf */
113 LPWSTR buf /* buffer to receive description */
116 LPENHMETAHEADER p = GlobalLock32(hmf);
118 if (!buf || !size) return p->nDescription;
120 memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription));
121 GlobalUnlock32(hmf);
122 return MIN(size,p->nDescription);
125 /****************************************************************************
126 * SetEnhMetaFileBits (GDI32.315)
128 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
130 HENHMETAFILE32 WINAPI SetEnhMetaFileBits(UINT32 bufsize, const BYTE *buf)
132 HENHMETAFILE32 hmf = GlobalAlloc32(GPTR, bufsize);
133 LPENHMETAHEADER h = GlobalLock32(hmf);
134 memmove(h, buf, bufsize);
135 GlobalUnlock32(hmf);
136 return hmf;
139 /*****************************************************************************
140 * GetEnhMetaFileBits (GDI32.175)
143 UINT32 WINAPI GetEnhMetaFileBits(
144 HENHMETAFILE32 hmf,
145 UINT32 bufsize,
146 LPBYTE buf
148 return 0;
151 /*****************************************************************************
152 * PlayEnhMetaFileRecord (GDI32.264)
154 * Render a single enhanced metafile record in the device context hdc.
156 * RETURNS
157 * TRUE on success, FALSE on error.
158 * BUGS
159 * Many unimplemented records.
161 BOOL32 WINAPI PlayEnhMetaFileRecord(
162 HDC32 hdc, /* device context in which to render EMF record */
163 LPHANDLETABLE32 handletable, /* array of handles to be used in rendering record */
164 const ENHMETARECORD *mr, /* EMF record to render */
165 UINT32 handles /* size of handle array */
168 int type;
169 TRACE(metafile,
170 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
171 hdc, handletable, mr, handles);
172 if (!mr) return FALSE;
174 type = mr->iType;
176 TRACE(metafile, " type=%d\n", type);
177 switch(type)
179 case EMR_HEADER:
181 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
182 break;
184 case EMR_EOF:
185 break;
186 case EMR_GDICOMMENT:
187 /* application defined and processed */
188 break;
189 case EMR_SETMAPMODE:
191 DWORD mode = mr->dParm[0];
192 SetMapMode32(hdc, mode);
193 break;
195 case EMR_SETBKMODE:
197 DWORD mode = mr->dParm[0];
198 SetBkMode32(hdc, mode);
199 break;
201 case EMR_SETBKCOLOR:
203 DWORD mode = mr->dParm[0];
204 SetBkColor32(hdc, mode);
205 break;
207 case EMR_SETPOLYFILLMODE:
209 DWORD mode = mr->dParm[0];
210 SetPolyFillMode32(hdc, mode);
211 break;
213 case EMR_SETROP2:
215 DWORD mode = mr->dParm[0];
216 SetROP232(hdc, mode);
217 break;
219 case EMR_SETSTRETCHBLTMODE:
221 DWORD mode = mr->dParm[0];
222 SetStretchBltMode32(hdc, mode);
223 break;
225 case EMR_SETTEXTALIGN:
227 DWORD align = mr->dParm[0];
228 SetTextAlign32(hdc, align);
229 break;
231 case EMR_SETTEXTCOLOR:
233 DWORD color = mr->dParm[0];
234 SetTextColor32(hdc, color);
235 break;
237 case EMR_SAVEDC:
239 SaveDC32(hdc);
240 break;
242 case EMR_RESTOREDC:
244 RestoreDC32(hdc, mr->dParm[0]);
245 break;
247 case EMR_INTERSECTCLIPRECT:
249 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
250 bottom = mr->dParm[3];
251 IntersectClipRect32(hdc, left, top, right, bottom);
252 break;
254 case EMR_SELECTOBJECT:
256 DWORD obj = mr->dParm[0];
257 SelectObject32(hdc, (handletable->objectHandle)[obj]);
258 break;
260 case EMR_DELETEOBJECT:
262 DWORD obj = mr->dParm[0];
263 DeleteObject32( (handletable->objectHandle)[obj]);
264 (handletable->objectHandle)[obj] = 0;
265 break;
267 case EMR_SETWINDOWORGEX:
269 DWORD x = mr->dParm[0], y = mr->dParm[1];
270 SetWindowOrgEx32(hdc, x, y, NULL);
271 break;
273 case EMR_SETWINDOWEXTEX:
275 DWORD x = mr->dParm[0], y = mr->dParm[1];
276 SetWindowExtEx32(hdc, x, y, NULL);
277 break;
279 case EMR_SETVIEWPORTORGEX:
281 DWORD x = mr->dParm[0], y = mr->dParm[1];
282 SetViewportOrgEx32(hdc, x, y, NULL);
283 break;
285 case EMR_SETVIEWPORTEXTEX:
287 DWORD x = mr->dParm[0], y = mr->dParm[1];
288 SetViewportExtEx32(hdc, x, y, NULL);
289 break;
291 case EMR_CREATEPEN:
293 DWORD obj = mr->dParm[0];
294 (handletable->objectHandle)[obj] =
295 CreatePenIndirect32((LOGPEN32 *) &(mr->dParm[1]));
296 break;
298 case EMR_EXTCREATEPEN:
300 DWORD obj = mr->dParm[0];
301 DWORD style = mr->dParm[1], brush = mr->dParm[2];
302 LOGBRUSH32 *b = (LOGBRUSH32 *) &mr->dParm[3];
303 FIXME(metafile, "Some ExtCreatePen args not handled\n");
304 (handletable->objectHandle)[obj] =
305 ExtCreatePen32(style, brush, b, 0, NULL);
306 break;
308 case EMR_CREATEBRUSHINDIRECT:
310 DWORD obj = mr->dParm[0];
311 (handletable->objectHandle)[obj] =
312 CreateBrushIndirect32((LOGBRUSH32 *) &(mr->dParm[1]));
313 break;
315 case EMR_EXTCREATEFONTINDIRECTW:
317 DWORD obj = mr->dParm[0];
318 (handletable->objectHandle)[obj] =
319 CreateFontIndirect32W((LOGFONT32W *) &(mr->dParm[1]));
320 break;
322 case EMR_MOVETOEX:
324 DWORD x = mr->dParm[0], y = mr->dParm[1];
325 MoveToEx32(hdc, x, y, NULL);
326 break;
328 case EMR_LINETO:
330 DWORD x = mr->dParm[0], y = mr->dParm[1];
331 LineTo32(hdc, x, y);
332 break;
334 case EMR_RECTANGLE:
336 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
337 bottom = mr->dParm[3];
338 Rectangle32(hdc, left, top, right, bottom);
339 break;
341 case EMR_ELLIPSE:
343 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
344 bottom = mr->dParm[3];
345 Ellipse32(hdc, left, top, right, bottom);
346 break;
348 case EMR_POLYGON16:
350 /* 0-3 : a bounding rectangle? */
351 INT32 count = mr->dParm[4];
352 FIXME(metafile, "Some Polygon16 args not handled\n");
353 Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
354 break;
356 case EMR_POLYLINE16:
358 /* 0-3 : a bounding rectangle? */
359 INT32 count = mr->dParm[4];
360 FIXME(metafile, "Some Polyline16 args not handled\n");
361 Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
362 break;
365 #if 0
366 case EMR_POLYPOLYGON16:
368 INT32 polygons = mr->dParm[z];
369 LPPOINT16 pts = (LPPOINT16) &mr->dParm[x];
370 LPINT16 counts = (LPINT16) &mr->dParm[y];
371 PolyPolygon16(hdc, pts, counts, polygons);
372 break;
374 #endif
375 case EMR_EXTTEXTOUTW:
377 /* 0-3: ??? */
378 DWORD flags = mr->dParm[4];
379 /* 5, 6: ??? */
380 DWORD x = mr->dParm[7], y = mr->dParm[8];
381 DWORD count = mr->dParm[9];
382 /* 10-16: ??? */
383 LPWSTR str = (LPWSTR)& mr->dParm[17];
384 /* trailing info: dx array? */
385 FIXME(metafile, "Many ExtTextOut args not handled\n");
386 ExtTextOut32W(hdc, x, y, flags, /* lpRect */ NULL,
387 str, count, /* lpDx */ NULL);
388 break;
391 default:
392 FIXME(metafile, "type %d is unimplemented\n", type);
393 /* SetLastError(E_NOTIMPL); */
394 break;
396 return TRUE;
400 /*****************************************************************************
402 * EnumEnhMetaFile32 (GDI32.79)
404 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
405 * for each
406 * record. Returns when either every record has been used or
407 * when _EnhMetaFunc_ returns FALSE.
410 * RETURNS
411 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
412 * returns FALSE.
414 * BUGS
415 * Ignores rect.
417 BOOL32 WINAPI EnumEnhMetaFile32(
418 HDC32 hdc, /* device context to pass to _EnhMetaFunc_ */
419 HENHMETAFILE32 hmf, /* EMF to walk */
420 ENHMFENUMPROC32 callback, /* callback function */
421 LPVOID data, /* optional data for callback function */
422 const RECT32 *rect /* bounding rectangle for rendered metafile */
425 BOOL32 ret = TRUE;
426 LPENHMETARECORD p = GlobalLock32(hmf);
427 INT32 count = ((LPENHMETAHEADER) p)->nHandles;
428 HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR, sizeof(HANDLETABLE32)*count);
429 ht->objectHandle[0] = hmf;
430 while (ret) {
431 ret = (*callback)(hdc, ht, p, count, data);
432 if (p->iType == EMR_EOF) break;
433 p = (void *) p + p->nSize;
435 GlobalFree32((HGLOBAL32)ht);
436 GlobalUnlock32(hmf);
437 return ret;
441 /**************************************************************************
442 * PlayEnhMetaFile (GDI32.263)
444 * Renders an enhanced metafile into a specified rectangle *lpRect
445 * in device context hdc.
447 * BUGS
448 * Almost entirely unimplemented
451 BOOL32 WINAPI PlayEnhMetaFile(
452 HDC32 hdc, /* DC to render into */
453 HENHMETAFILE32 hmf, /* metafile to render */
454 const RECT32 *lpRect /* rectangle to place metafile inside */
457 LPENHMETARECORD p = GlobalLock32(hmf);
458 INT32 count = ((LPENHMETAHEADER) p)->nHandles;
459 HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR,
460 sizeof(HANDLETABLE32)*count);
461 BOOL32 ret = FALSE;
462 INT32 savedMode = 0;
463 if (lpRect) {
464 LPENHMETAHEADER h = (LPENHMETAHEADER) p;
465 FLOAT xscale = (h->rclBounds.right-h->rclBounds.left)/(lpRect->right-lpRect->left);
466 FLOAT yscale = (h->rclBounds.bottom-h->rclBounds.top)/(lpRect->bottom-lpRect->top);
467 XFORM xform = {xscale, 0, 0, yscale, 0, 0};
468 xform.eDx = lpRect->left;
469 xform.eDy = lpRect->top;
470 FIXME(metafile, "play into rect doesn't work\n");
471 savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
472 if (!SetWorldTransform(hdc, &xform)) {
473 WARN(metafile, "World transform failed!\n");
477 ht->objectHandle[0] = hmf;
478 while (1) {
479 PlayEnhMetaFileRecord(hdc, ht, p, count);
480 if (p->iType == EMR_EOF) break;
481 p = (void *) p + p->nSize; /* casted so that arithmetic is in bytes */
483 GlobalUnlock32(hmf);
484 if (savedMode) SetGraphicsMode(hdc, savedMode);
485 ret = TRUE; /* FIXME: calculate a more accurate return value */
486 return ret;
489 /*****************************************************************************
490 * DeleteEnhMetaFile (GDI32.68)
492 * Deletes an enhanced metafile and frees the associated storage.
494 BOOL32 WINAPI DeleteEnhMetaFile(HENHMETAFILE32 hmf) {
495 return !GlobalFree32(hmf);
498 /*****************************************************************************
499 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
503 HENHMETAFILE32 WINAPI CopyEnhMetaFile32A(
504 HENHMETAFILE32 hmf,
505 LPCSTR file)
507 if (!file) {
508 LPENHMETAHEADER h = GlobalLock32(hmf);
509 HENHMETAFILE32 hmf2 = GlobalAlloc32(GPTR, h->nBytes);
510 LPENHMETAHEADER h2 = GlobalLock32(hmf2);
511 if (!h2) return 0;
512 memmove(h2, h, h->nBytes);
513 GlobalUnlock32(hmf2);
514 GlobalUnlock32(hmf);
515 return hmf2;
516 } else {
517 FIXME(metafile, "write to file not implemented\n");
518 return 0;
522 /*****************************************************************************
523 * GetEnhMetaFilePaletteEntries (GDI32.179)
525 * Copy the palette and report size
528 UINT32 WINAPI GetEnhMetaFilePaletteEntries(HENHMETAFILE32 hemf,
529 UINT32 cEntries,
530 LPPALETTEENTRY lppe)
532 LPENHMETAHEADER h = GlobalLock32(hemf);
534 if ( h == NULL ){
535 GlobalUnlock32(hemf);
536 return(0);
537 } else {
538 if ((lppe)&&(cEntries>0)){
539 FIXME(metafile,"Stub\n");
540 GlobalUnlock32(hemf);
541 return(GDI_ERROR);
542 } else{
543 GlobalUnlock32(hemf);
544 return(0);
551 /******************************************************************
552 * SetWinMetaFileBits (GDI32.343)
554 * Translate from old style to new style.
557 HENHMETAFILE32 WINAPI SetWinMetaFileBits(UINT32 cbBuffer,
558 CONST BYTE *lpbBuffer,
559 HDC32 hdcRef,
560 CONST METAFILEPICT32 *lpmfp
563 FIXME(metafile,"Stub\n");
564 return 0;