Release 990214.
[wine/multimedia.git] / objects / enhmetafile.c
blob676fb9b106895925fb28067a1fc7ff155bcd8eed
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 FIXME(metafile,"%s can't be read.\n",lpszMetaFile);
36 CloseHandle(hf);
37 return 0;
39 if (read!=sizeof(ENHMETAHEADER)) {
40 FIXME(metafile,"%s is not long enough.\n",lpszMetaFile);
41 CloseHandle(hf);
42 return 0;
44 if (h.iType!=1) {
45 FIXME(metafile,"%s has invalid emf header (type 0x%08lx).\n",lpszMetaFile,h.iType);
46 CloseHandle(hf);
47 return 0;
49 if (memcmp(&(h.dSignature)," EMF",4)) {
50 FIXME(metafile,"%s has invalid EMF header (dSignature 0x%08lx).\n",lpszMetaFile,h.dSignature);
51 CloseHandle(hf);
52 return 0;
54 SetFilePointer(hf, 0, NULL, FILE_BEGIN);
55 /* hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
56 hmf = GlobalAlloc32(GPTR, h.nBytes);
57 p = GlobalLock32(hmf);
58 if (!ReadFile(hf, p, h.nBytes, &read, NULL)) {
59 FIXME(metafile,"%s could not be read.\n",lpszMetaFile);
60 GlobalFree32(hmf);
61 CloseHandle(hf);
62 return 0;
64 if (read!=h.nBytes) {
65 FIXME(metafile,"%s is not long enough (%ld expected, %ld got).\n",lpszMetaFile,h.nBytes,read);
66 GlobalFree32(hmf);
67 CloseHandle(hf);
68 return 0;
70 GlobalUnlock32(hmf);
71 return hmf;
74 /*****************************************************************************
75 * GetEnhMetaFile32W (GDI32.180)
77 HENHMETAFILE32 WINAPI GetEnhMetaFile32W(
78 LPCWSTR lpszMetaFile) /* filename of enhanced metafile */
80 FIXME(metafile, "(%p): stub\n", lpszMetaFile);
81 return 0;
84 /*****************************************************************************
85 * GetEnhMetaFileHeader (GDI32.178)
87 * If _buf_ is NULL, returns the size of buffer required.
88 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
89 * _buf.
91 UINT32 WINAPI GetEnhMetaFileHeader(
92 HENHMETAFILE32 hmf, /* enhanced metafile */
93 UINT32 bufsize, /* size of buffer */
94 LPENHMETAHEADER buf /* buffer */
97 LPENHMETAHEADER p = GlobalLock32(hmf);
98 if (!buf) return sizeof(ENHMETAHEADER);
99 memmove(buf, p, MIN(sizeof(ENHMETAHEADER), bufsize));
100 GlobalUnlock32(hmf);
101 return MIN(sizeof(ENHMETAHEADER), bufsize);
105 /*****************************************************************************
106 * GetEnhMetaFileDescription32A (GDI32.176)
108 UINT32 WINAPI GetEnhMetaFileDescription32A(
109 HENHMETAFILE32 hmf, /* enhanced metafile */
110 UINT32 size, /* size of buf */
111 LPSTR buf /* buffer to receive description */
114 LPENHMETAHEADER p = GlobalLock32(hmf);
115 INT32 first = lstrlen32W( (void *)p+p->offDescription);
117 if (!buf || !size) return p->nDescription;
119 lstrcpynWtoA(buf, (void *)p+p->offDescription, size);
120 buf += first +1;
121 lstrcpynWtoA(buf, (void *)p+p->offDescription+2*(first+1), size-first-1);
123 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
124 GlobalUnlock32(hmf);
125 return MIN(size,p->nDescription);
128 /*****************************************************************************
129 * GetEnhMetaFileDescription32W (GDI32.177)
131 * Copies the description string of an enhanced metafile into a buffer
132 * _buf_.
134 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
135 * number of characters copied.
137 UINT32 WINAPI GetEnhMetaFileDescription32W(
138 HENHMETAFILE32 hmf, /* enhanced metafile */
139 UINT32 size, /* size of buf */
140 LPWSTR buf /* buffer to receive description */
143 LPENHMETAHEADER p = GlobalLock32(hmf);
145 if (!buf || !size) return p->nDescription;
147 memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription));
148 GlobalUnlock32(hmf);
149 return MIN(size,p->nDescription);
152 /****************************************************************************
153 * SetEnhMetaFileBits (GDI32.315)
155 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
157 HENHMETAFILE32 WINAPI SetEnhMetaFileBits(UINT32 bufsize, const BYTE *buf)
159 HENHMETAFILE32 hmf = GlobalAlloc32(GPTR, bufsize);
160 LPENHMETAHEADER h = GlobalLock32(hmf);
161 memmove(h, buf, bufsize);
162 GlobalUnlock32(hmf);
163 return hmf;
166 /*****************************************************************************
167 * GetEnhMetaFileBits (GDI32.175)
170 UINT32 WINAPI GetEnhMetaFileBits(
171 HENHMETAFILE32 hmf,
172 UINT32 bufsize,
173 LPBYTE buf
175 return 0;
178 /*****************************************************************************
179 * PlayEnhMetaFileRecord (GDI32.264)
181 * Render a single enhanced metafile record in the device context hdc.
183 * RETURNS
184 * TRUE on success, FALSE on error.
185 * BUGS
186 * Many unimplemented records.
188 BOOL32 WINAPI PlayEnhMetaFileRecord(
189 HDC32 hdc, /* device context in which to render EMF record */
190 LPHANDLETABLE32 handletable, /* array of handles to be used in rendering record */
191 const ENHMETARECORD *mr, /* EMF record to render */
192 UINT32 handles /* size of handle array */
195 int type;
196 TRACE(metafile,
197 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
198 hdc, handletable, mr, handles);
199 if (!mr) return FALSE;
201 type = mr->iType;
203 TRACE(metafile, " type=%d\n", type);
204 switch(type)
206 case EMR_HEADER:
208 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
209 break;
211 case EMR_EOF:
212 break;
213 case EMR_GDICOMMENT:
214 /* application defined and processed */
215 break;
216 case EMR_SETMAPMODE:
218 DWORD mode = mr->dParm[0];
219 SetMapMode32(hdc, mode);
220 break;
222 case EMR_SETBKMODE:
224 DWORD mode = mr->dParm[0];
225 SetBkMode32(hdc, mode);
226 break;
228 case EMR_SETBKCOLOR:
230 DWORD mode = mr->dParm[0];
231 SetBkColor32(hdc, mode);
232 break;
234 case EMR_SETPOLYFILLMODE:
236 DWORD mode = mr->dParm[0];
237 SetPolyFillMode32(hdc, mode);
238 break;
240 case EMR_SETROP2:
242 DWORD mode = mr->dParm[0];
243 SetROP232(hdc, mode);
244 break;
246 case EMR_SETSTRETCHBLTMODE:
248 DWORD mode = mr->dParm[0];
249 SetStretchBltMode32(hdc, mode);
250 break;
252 case EMR_SETTEXTALIGN:
254 DWORD align = mr->dParm[0];
255 SetTextAlign32(hdc, align);
256 break;
258 case EMR_SETTEXTCOLOR:
260 DWORD color = mr->dParm[0];
261 SetTextColor32(hdc, color);
262 break;
264 case EMR_SAVEDC:
266 SaveDC32(hdc);
267 break;
269 case EMR_RESTOREDC:
271 RestoreDC32(hdc, mr->dParm[0]);
272 break;
274 case EMR_INTERSECTCLIPRECT:
276 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
277 bottom = mr->dParm[3];
278 IntersectClipRect32(hdc, left, top, right, bottom);
279 break;
281 case EMR_SELECTOBJECT:
283 DWORD obj = mr->dParm[0];
284 SelectObject32(hdc, (handletable->objectHandle)[obj]);
285 break;
287 case EMR_DELETEOBJECT:
289 DWORD obj = mr->dParm[0];
290 DeleteObject32( (handletable->objectHandle)[obj]);
291 (handletable->objectHandle)[obj] = 0;
292 break;
294 case EMR_SETWINDOWORGEX:
296 DWORD x = mr->dParm[0], y = mr->dParm[1];
297 SetWindowOrgEx32(hdc, x, y, NULL);
298 break;
300 case EMR_SETWINDOWEXTEX:
302 DWORD x = mr->dParm[0], y = mr->dParm[1];
303 SetWindowExtEx32(hdc, x, y, NULL);
304 break;
306 case EMR_SETVIEWPORTORGEX:
308 DWORD x = mr->dParm[0], y = mr->dParm[1];
309 SetViewportOrgEx32(hdc, x, y, NULL);
310 break;
312 case EMR_SETVIEWPORTEXTEX:
314 DWORD x = mr->dParm[0], y = mr->dParm[1];
315 SetViewportExtEx32(hdc, x, y, NULL);
316 break;
318 case EMR_CREATEPEN:
320 DWORD obj = mr->dParm[0];
321 (handletable->objectHandle)[obj] =
322 CreatePenIndirect32((LOGPEN32 *) &(mr->dParm[1]));
323 break;
325 case EMR_EXTCREATEPEN:
327 DWORD obj = mr->dParm[0];
328 DWORD style = mr->dParm[1], brush = mr->dParm[2];
329 LOGBRUSH32 *b = (LOGBRUSH32 *) &mr->dParm[3];
330 FIXME(metafile, "Some ExtCreatePen args not handled\n");
331 (handletable->objectHandle)[obj] =
332 ExtCreatePen32(style, brush, b, 0, NULL);
333 break;
335 case EMR_CREATEBRUSHINDIRECT:
337 DWORD obj = mr->dParm[0];
338 (handletable->objectHandle)[obj] =
339 CreateBrushIndirect32((LOGBRUSH32 *) &(mr->dParm[1]));
340 break;
342 case EMR_EXTCREATEFONTINDIRECTW:
344 DWORD obj = mr->dParm[0];
345 (handletable->objectHandle)[obj] =
346 CreateFontIndirect32W((LOGFONT32W *) &(mr->dParm[1]));
347 break;
349 case EMR_MOVETOEX:
351 DWORD x = mr->dParm[0], y = mr->dParm[1];
352 MoveToEx32(hdc, x, y, NULL);
353 break;
355 case EMR_LINETO:
357 DWORD x = mr->dParm[0], y = mr->dParm[1];
358 LineTo32(hdc, x, y);
359 break;
361 case EMR_RECTANGLE:
363 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
364 bottom = mr->dParm[3];
365 Rectangle32(hdc, left, top, right, bottom);
366 break;
368 case EMR_ELLIPSE:
370 INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
371 bottom = mr->dParm[3];
372 Ellipse32(hdc, left, top, right, bottom);
373 break;
375 case EMR_POLYGON16:
377 /* 0-3 : a bounding rectangle? */
378 INT32 count = mr->dParm[4];
379 FIXME(metafile, "Some Polygon16 args not handled\n");
380 Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
381 break;
383 case EMR_POLYLINE16:
385 /* 0-3 : a bounding rectangle? */
386 INT32 count = mr->dParm[4];
387 FIXME(metafile, "Some Polyline16 args not handled\n");
388 Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
389 break;
392 #if 0
393 case EMR_POLYPOLYGON16:
395 INT32 polygons = mr->dParm[z];
396 LPPOINT16 pts = (LPPOINT16) &mr->dParm[x];
397 LPINT16 counts = (LPINT16) &mr->dParm[y];
398 PolyPolygon16(hdc, pts, counts, polygons);
399 break;
401 #endif
402 case EMR_STRETCHDIBITS:
404 LONG xDest = mr->dParm[4];
405 LONG yDest = mr->dParm[5];
406 LONG xSrc = mr->dParm[6];
407 LONG ySrc = mr->dParm[7];
408 LONG cxSrc = mr->dParm[8];
409 LONG cySrc = mr->dParm[9];
410 DWORD offBmiSrc = mr->dParm[10];
411 DWORD offBitsSrc = mr->dParm[12];
412 DWORD iUsageSrc = mr->dParm[14];
413 DWORD dwRop = mr->dParm[15];
414 LONG cxDest = mr->dParm[16];
415 LONG cyDest = mr->dParm[17];
417 StretchDIBits32(hdc,xDest,yDest,cxDest,cyDest,
418 xSrc,ySrc,cxSrc,cySrc,
419 ((char *)mr)+offBitsSrc,
420 (const BITMAPINFO *)(((char *)mr)+offBmiSrc),
421 iUsageSrc,dwRop);
422 break;
424 case EMR_EXTTEXTOUTW:
426 /* 0-3: ??? */
427 DWORD flags = mr->dParm[4];
428 /* 5, 6: ??? */
429 DWORD x = mr->dParm[7], y = mr->dParm[8];
430 DWORD count = mr->dParm[9];
431 /* 10-16: ??? */
432 LPWSTR str = (LPWSTR)& mr->dParm[17];
433 /* trailing info: dx array? */
434 FIXME(metafile, "Many ExtTextOut args not handled\n");
435 ExtTextOut32W(hdc, x, y, flags, /* lpRect */ NULL,
436 str, count, /* lpDx */ NULL);
437 break;
440 default:
441 FIXME(metafile, "type %d is unimplemented\n", type);
442 /* SetLastError(E_NOTIMPL); */
443 break;
445 return TRUE;
449 /*****************************************************************************
451 * EnumEnhMetaFile32 (GDI32.79)
453 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
454 * for each
455 * record. Returns when either every record has been used or
456 * when _EnhMetaFunc_ returns FALSE.
459 * RETURNS
460 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
461 * returns FALSE.
463 * BUGS
464 * Ignores rect.
466 BOOL32 WINAPI EnumEnhMetaFile32(
467 HDC32 hdc, /* device context to pass to _EnhMetaFunc_ */
468 HENHMETAFILE32 hmf, /* EMF to walk */
469 ENHMFENUMPROC32 callback, /* callback function */
470 LPVOID data, /* optional data for callback function */
471 const RECT32 *rect /* bounding rectangle for rendered metafile */
474 BOOL32 ret = TRUE;
475 LPENHMETARECORD p = GlobalLock32(hmf);
476 INT32 count = ((LPENHMETAHEADER) p)->nHandles;
477 HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR, sizeof(HANDLETABLE32)*count);
478 ht->objectHandle[0] = hmf;
479 while (ret) {
480 ret = (*callback)(hdc, ht, p, count, data);
481 if (p->iType == EMR_EOF) break;
482 p = (void *) p + p->nSize;
484 GlobalFree32((HGLOBAL32)ht);
485 GlobalUnlock32(hmf);
486 return ret;
490 /**************************************************************************
491 * PlayEnhMetaFile (GDI32.263)
493 * Renders an enhanced metafile into a specified rectangle *lpRect
494 * in device context hdc.
496 * BUGS
497 * Almost entirely unimplemented
500 BOOL32 WINAPI PlayEnhMetaFile(
501 HDC32 hdc, /* DC to render into */
502 HENHMETAFILE32 hmf, /* metafile to render */
503 const RECT32 *lpRect /* rectangle to place metafile inside */
506 LPENHMETARECORD p = GlobalLock32(hmf);
507 INT32 count = ((LPENHMETAHEADER) p)->nHandles;
508 HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR,
509 sizeof(HANDLETABLE32)*count);
510 BOOL32 ret = FALSE;
511 INT32 savedMode = 0;
512 if (lpRect) {
513 LPENHMETAHEADER h = (LPENHMETAHEADER) p;
514 FLOAT xscale = (h->rclBounds.right-h->rclBounds.left)/(lpRect->right-lpRect->left);
515 FLOAT yscale = (h->rclBounds.bottom-h->rclBounds.top)/(lpRect->bottom-lpRect->top);
516 XFORM xform = {xscale, 0, 0, yscale, 0, 0};
517 xform.eDx = lpRect->left;
518 xform.eDy = lpRect->top;
519 FIXME(metafile, "play into rect doesn't work\n");
520 savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
521 if (!SetWorldTransform(hdc, &xform)) {
522 WARN(metafile, "World transform failed!\n");
526 ht->objectHandle[0] = hmf;
527 while (1) {
528 PlayEnhMetaFileRecord(hdc, ht, p, count);
529 if (p->iType == EMR_EOF) break;
530 p = (void *) p + p->nSize; /* casted so that arithmetic is in bytes */
532 GlobalUnlock32(hmf);
533 if (savedMode) SetGraphicsMode(hdc, savedMode);
534 ret = TRUE; /* FIXME: calculate a more accurate return value */
535 return ret;
538 /*****************************************************************************
539 * DeleteEnhMetaFile (GDI32.68)
541 * Deletes an enhanced metafile and frees the associated storage.
543 BOOL32 WINAPI DeleteEnhMetaFile(HENHMETAFILE32 hmf) {
544 return !GlobalFree32(hmf);
547 /*****************************************************************************
548 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
552 HENHMETAFILE32 WINAPI CopyEnhMetaFile32A(
553 HENHMETAFILE32 hmf,
554 LPCSTR file)
556 if (!file) {
557 LPENHMETAHEADER h = GlobalLock32(hmf);
558 HENHMETAFILE32 hmf2 = GlobalAlloc32(GPTR, h->nBytes);
559 LPENHMETAHEADER h2 = GlobalLock32(hmf2);
560 if (!h2) return 0;
561 memmove(h2, h, h->nBytes);
562 GlobalUnlock32(hmf2);
563 GlobalUnlock32(hmf);
564 return hmf2;
565 } else {
566 FIXME(metafile, "write to file not implemented\n");
567 return 0;
571 /*****************************************************************************
572 * GetEnhMetaFilePaletteEntries (GDI32.179)
574 * Copy the palette and report size
577 UINT32 WINAPI GetEnhMetaFilePaletteEntries(HENHMETAFILE32 hemf,
578 UINT32 cEntries,
579 LPPALETTEENTRY lppe)
581 LPENHMETAHEADER h = GlobalLock32(hemf);
583 if ( h == NULL ){
584 GlobalUnlock32(hemf);
585 return(0);
586 } else {
587 if ((lppe)&&(cEntries>0)){
588 FIXME(metafile,"Stub\n");
589 GlobalUnlock32(hemf);
590 return(GDI_ERROR);
591 } else{
592 GlobalUnlock32(hemf);
593 return(0);
600 /******************************************************************
601 * SetWinMetaFileBits (GDI32.343)
603 * Translate from old style to new style.
606 HENHMETAFILE32 WINAPI SetWinMetaFileBits(UINT32 cbBuffer,
607 CONST BYTE *lpbBuffer,
608 HDC32 hdcRef,
609 CONST METAFILEPICT32 *lpmfp
612 FIXME(metafile,"Stub\n");
613 return 0;