Reduced fragment size.
[wine/multimedia.git] / objects / enhmetafile.c
blobd0c7b1091a96d8c42f6f8d871755543f2640575f
1 /*
2 Enhanced metafile functions
3 Copyright 1998, Douglas Ridgway
4 */
6 #include <string.h>
7 #include <assert.h>
8 #include "winbase.h"
9 #include "wingdi.h"
10 #include "wine/winestring.h"
11 #include "winerror.h"
12 #include "debug.h"
14 /*****************************************************************************
15 * GetEnhMetaFile32A (GDI32.174)
19 HENHMETAFILE WINAPI GetEnhMetaFileA(
20 LPCSTR lpszMetaFile /* filename of enhanced metafile */
23 HENHMETAFILE hmf = 0;
24 ENHMETAHEADER h;
25 BYTE *p;
26 DWORD read;
27 HFILE hf = CreateFileA(lpszMetaFile, GENERIC_READ, 0, 0,
28 OPEN_EXISTING, 0, 0);
29 if (hf == INVALID_HANDLE_VALUE) {
30 FIXME(metafile,"could not open %s\n",lpszMetaFile);
31 return 0;
33 if (!ReadFile(hf, &h, sizeof(ENHMETAHEADER), &read, NULL)) {
34 FIXME(metafile,"%s can't be read.\n",lpszMetaFile);
35 CloseHandle(hf);
36 return 0;
38 if (read!=sizeof(ENHMETAHEADER)) {
39 FIXME(metafile,"%s is not long enough.\n",lpszMetaFile);
40 CloseHandle(hf);
41 return 0;
43 if (h.iType!=1) {
44 FIXME(metafile,"%s has invalid emf header (type 0x%08lx).\n",lpszMetaFile,h.iType);
45 CloseHandle(hf);
46 return 0;
48 if (memcmp(&(h.dSignature)," EMF",4)) {
49 FIXME(metafile,"%s has invalid EMF header (dSignature 0x%08lx).\n",lpszMetaFile,h.dSignature);
50 CloseHandle(hf);
51 return 0;
53 SetFilePointer(hf, 0, NULL, FILE_BEGIN);
54 /* hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
55 hmf = GlobalAlloc(GPTR, h.nBytes);
56 p = GlobalLock(hmf);
57 if (!ReadFile(hf, p, h.nBytes, &read, NULL)) {
58 FIXME(metafile,"%s could not be read.\n",lpszMetaFile);
59 GlobalFree(hmf);
60 CloseHandle(hf);
61 return 0;
63 if (read!=h.nBytes) {
64 FIXME(metafile,"%s is not long enough (%ld expected, %ld got).\n",lpszMetaFile,h.nBytes,read);
65 GlobalFree(hmf);
66 CloseHandle(hf);
67 return 0;
69 GlobalUnlock(hmf);
70 return hmf;
73 /*****************************************************************************
74 * GetEnhMetaFile32W (GDI32.180)
76 HENHMETAFILE WINAPI GetEnhMetaFileW(
77 LPCWSTR lpszMetaFile) /* filename of enhanced metafile */
79 FIXME(metafile, "(%p): stub\n", lpszMetaFile);
80 return 0;
83 /*****************************************************************************
84 * GetEnhMetaFileHeader (GDI32.178)
86 * If _buf_ is NULL, returns the size of buffer required.
87 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
88 * _buf.
90 UINT WINAPI GetEnhMetaFileHeader(
91 HENHMETAFILE hmf, /* enhanced metafile */
92 UINT bufsize, /* size of buffer */
93 LPENHMETAHEADER buf /* buffer */
96 LPENHMETAHEADER p = GlobalLock(hmf);
97 if (!buf) return sizeof(ENHMETAHEADER);
98 memmove(buf, p, MIN(sizeof(ENHMETAHEADER), bufsize));
99 GlobalUnlock(hmf);
100 return MIN(sizeof(ENHMETAHEADER), bufsize);
104 /*****************************************************************************
105 * GetEnhMetaFileDescription32A (GDI32.176)
107 UINT WINAPI GetEnhMetaFileDescriptionA(
108 HENHMETAFILE hmf, /* enhanced metafile */
109 UINT size, /* size of buf */
110 LPSTR buf /* buffer to receive description */
113 LPENHMETAHEADER p = GlobalLock(hmf);
114 INT first = lstrlenW( (void *)p+p->offDescription);
116 if (!buf || !size) return p->nDescription;
118 lstrcpynWtoA(buf, (void *)p+p->offDescription, size);
119 buf += first +1;
120 lstrcpynWtoA(buf, (void *)p+p->offDescription+2*(first+1), size-first-1);
122 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
123 GlobalUnlock(hmf);
124 return MIN(size,p->nDescription);
127 /*****************************************************************************
128 * GetEnhMetaFileDescription32W (GDI32.177)
130 * Copies the description string of an enhanced metafile into a buffer
131 * _buf_.
133 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
134 * number of characters copied.
136 UINT WINAPI GetEnhMetaFileDescriptionW(
137 HENHMETAFILE hmf, /* enhanced metafile */
138 UINT size, /* size of buf */
139 LPWSTR buf /* buffer to receive description */
142 LPENHMETAHEADER p = GlobalLock(hmf);
144 if (!buf || !size) return p->nDescription;
146 memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription));
147 GlobalUnlock(hmf);
148 return MIN(size,p->nDescription);
151 /****************************************************************************
152 * SetEnhMetaFileBits (GDI32.315)
154 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
156 HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT bufsize, const BYTE *buf)
158 HENHMETAFILE hmf = GlobalAlloc(GPTR, bufsize);
159 LPENHMETAHEADER h = GlobalLock(hmf);
160 memmove(h, buf, bufsize);
161 GlobalUnlock(hmf);
162 return hmf;
165 /*****************************************************************************
166 * GetEnhMetaFileBits (GDI32.175)
169 UINT WINAPI GetEnhMetaFileBits(
170 HENHMETAFILE hmf,
171 UINT bufsize,
172 LPBYTE buf
174 return 0;
177 /*****************************************************************************
178 * PlayEnhMetaFileRecord (GDI32.264)
180 * Render a single enhanced metafile record in the device context hdc.
182 * RETURNS
183 * TRUE on success, FALSE on error.
184 * BUGS
185 * Many unimplemented records.
187 BOOL WINAPI PlayEnhMetaFileRecord(
188 HDC hdc, /* device context in which to render EMF record */
189 LPHANDLETABLE handletable, /* array of handles to be used in rendering record */
190 const ENHMETARECORD *mr, /* EMF record to render */
191 UINT handles /* size of handle array */
194 int type;
195 TRACE(metafile,
196 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
197 hdc, handletable, mr, handles);
198 if (!mr) return FALSE;
200 type = mr->iType;
202 TRACE(metafile, " type=%d\n", type);
203 switch(type)
205 case EMR_HEADER:
207 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
208 break;
210 case EMR_EOF:
211 break;
212 case EMR_GDICOMMENT:
213 /* application defined and processed */
214 break;
215 case EMR_SETMAPMODE:
217 DWORD mode = mr->dParm[0];
218 SetMapMode(hdc, mode);
219 break;
221 case EMR_SETBKMODE:
223 DWORD mode = mr->dParm[0];
224 SetBkMode(hdc, mode);
225 break;
227 case EMR_SETBKCOLOR:
229 DWORD mode = mr->dParm[0];
230 SetBkColor(hdc, mode);
231 break;
233 case EMR_SETPOLYFILLMODE:
235 DWORD mode = mr->dParm[0];
236 SetPolyFillMode(hdc, mode);
237 break;
239 case EMR_SETROP2:
241 DWORD mode = mr->dParm[0];
242 SetROP2(hdc, mode);
243 break;
245 case EMR_SETSTRETCHBLTMODE:
247 DWORD mode = mr->dParm[0];
248 SetStretchBltMode(hdc, mode);
249 break;
251 case EMR_SETTEXTALIGN:
253 DWORD align = mr->dParm[0];
254 SetTextAlign(hdc, align);
255 break;
257 case EMR_SETTEXTCOLOR:
259 DWORD color = mr->dParm[0];
260 SetTextColor(hdc, color);
261 break;
263 case EMR_SAVEDC:
265 SaveDC(hdc);
266 break;
268 case EMR_RESTOREDC:
270 RestoreDC(hdc, mr->dParm[0]);
271 break;
273 case EMR_INTERSECTCLIPRECT:
275 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
276 bottom = mr->dParm[3];
277 IntersectClipRect(hdc, left, top, right, bottom);
278 break;
280 case EMR_SELECTOBJECT:
282 DWORD obj = mr->dParm[0];
283 SelectObject(hdc, (handletable->objectHandle)[obj]);
284 break;
286 case EMR_DELETEOBJECT:
288 DWORD obj = mr->dParm[0];
289 DeleteObject( (handletable->objectHandle)[obj]);
290 (handletable->objectHandle)[obj] = 0;
291 break;
293 case EMR_SETWINDOWORGEX:
295 DWORD x = mr->dParm[0], y = mr->dParm[1];
296 SetWindowOrgEx(hdc, x, y, NULL);
297 break;
299 case EMR_SETWINDOWEXTEX:
301 DWORD x = mr->dParm[0], y = mr->dParm[1];
302 SetWindowExtEx(hdc, x, y, NULL);
303 break;
305 case EMR_SETVIEWPORTORGEX:
307 DWORD x = mr->dParm[0], y = mr->dParm[1];
308 SetViewportOrgEx(hdc, x, y, NULL);
309 break;
311 case EMR_SETVIEWPORTEXTEX:
313 DWORD x = mr->dParm[0], y = mr->dParm[1];
314 SetViewportExtEx(hdc, x, y, NULL);
315 break;
317 case EMR_CREATEPEN:
319 DWORD obj = mr->dParm[0];
320 (handletable->objectHandle)[obj] =
321 CreatePenIndirect((LOGPEN *) &(mr->dParm[1]));
322 break;
324 case EMR_EXTCREATEPEN:
326 DWORD obj = mr->dParm[0];
327 DWORD style = mr->dParm[1], brush = mr->dParm[2];
328 LOGBRUSH *b = (LOGBRUSH *) &mr->dParm[3];
329 FIXME(metafile, "Some ExtCreatePen args not handled\n");
330 (handletable->objectHandle)[obj] =
331 ExtCreatePen(style, brush, b, 0, NULL);
332 break;
334 case EMR_CREATEBRUSHINDIRECT:
336 DWORD obj = mr->dParm[0];
337 (handletable->objectHandle)[obj] =
338 CreateBrushIndirect((LOGBRUSH *) &(mr->dParm[1]));
339 break;
341 case EMR_EXTCREATEFONTINDIRECTW:
343 DWORD obj = mr->dParm[0];
344 (handletable->objectHandle)[obj] =
345 CreateFontIndirectW((LOGFONTW *) &(mr->dParm[1]));
346 break;
348 case EMR_MOVETOEX:
350 DWORD x = mr->dParm[0], y = mr->dParm[1];
351 MoveToEx(hdc, x, y, NULL);
352 break;
354 case EMR_LINETO:
356 DWORD x = mr->dParm[0], y = mr->dParm[1];
357 LineTo(hdc, x, y);
358 break;
360 case EMR_RECTANGLE:
362 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
363 bottom = mr->dParm[3];
364 Rectangle(hdc, left, top, right, bottom);
365 break;
367 case EMR_ELLIPSE:
369 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
370 bottom = mr->dParm[3];
371 Ellipse(hdc, left, top, right, bottom);
372 break;
374 case EMR_POLYGON16:
376 /* 0-3 : a bounding rectangle? */
377 INT count = mr->dParm[4];
378 FIXME(metafile, "Some Polygon16 args not handled\n");
379 Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
380 break;
382 case EMR_POLYLINE16:
384 /* 0-3 : a bounding rectangle? */
385 INT count = mr->dParm[4];
386 FIXME(metafile, "Some Polyline16 args not handled\n");
387 Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
388 break;
391 #if 0
392 case EMR_POLYPOLYGON16:
394 INT polygons = mr->dParm[z];
395 LPPOINT16 pts = (LPPOINT16) &mr->dParm[x];
396 LPINT16 counts = (LPINT16) &mr->dParm[y];
397 PolyPolygon16(hdc, pts, counts, polygons);
398 break;
400 #endif
401 case EMR_STRETCHDIBITS:
403 LONG xDest = mr->dParm[4];
404 LONG yDest = mr->dParm[5];
405 LONG xSrc = mr->dParm[6];
406 LONG ySrc = mr->dParm[7];
407 LONG cxSrc = mr->dParm[8];
408 LONG cySrc = mr->dParm[9];
409 DWORD offBmiSrc = mr->dParm[10];
410 DWORD offBitsSrc = mr->dParm[12];
411 DWORD iUsageSrc = mr->dParm[14];
412 DWORD dwRop = mr->dParm[15];
413 LONG cxDest = mr->dParm[16];
414 LONG cyDest = mr->dParm[17];
416 StretchDIBits(hdc,xDest,yDest,cxDest,cyDest,
417 xSrc,ySrc,cxSrc,cySrc,
418 ((char *)mr)+offBitsSrc,
419 (const BITMAPINFO *)(((char *)mr)+offBmiSrc),
420 iUsageSrc,dwRop);
421 break;
423 case EMR_EXTTEXTOUTW:
425 /* 0-3: ??? */
426 DWORD flags = mr->dParm[4];
427 /* 5, 6: ??? */
428 DWORD x = mr->dParm[7], y = mr->dParm[8];
429 DWORD count = mr->dParm[9];
430 /* 10-16: ??? */
431 LPWSTR str = (LPWSTR)& mr->dParm[17];
432 /* trailing info: dx array? */
433 FIXME(metafile, "Many ExtTextOut args not handled\n");
434 ExtTextOutW(hdc, x, y, flags, /* lpRect */ NULL,
435 str, count, /* lpDx */ NULL);
436 break;
439 default:
440 FIXME(metafile, "type %d is unimplemented\n", type);
441 /* SetLastError(E_NOTIMPL); */
442 break;
444 return TRUE;
448 /*****************************************************************************
450 * EnumEnhMetaFile32 (GDI32.79)
452 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
453 * for each
454 * record. Returns when either every record has been used or
455 * when _EnhMetaFunc_ returns FALSE.
458 * RETURNS
459 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
460 * returns FALSE.
462 * BUGS
463 * Ignores rect.
465 BOOL WINAPI EnumEnhMetaFile(
466 HDC hdc, /* device context to pass to _EnhMetaFunc_ */
467 HENHMETAFILE hmf, /* EMF to walk */
468 ENHMFENUMPROC callback, /* callback function */
469 LPVOID data, /* optional data for callback function */
470 const RECT *rect /* bounding rectangle for rendered metafile */
473 BOOL ret = TRUE;
474 LPENHMETARECORD p = GlobalLock(hmf);
475 INT count = ((LPENHMETAHEADER) p)->nHandles;
476 HANDLETABLE *ht = (HANDLETABLE *)GlobalAlloc(GPTR, sizeof(HANDLETABLE)*count);
477 ht->objectHandle[0] = hmf;
478 while (ret) {
479 ret = (*callback)(hdc, ht, p, count, data);
480 if (p->iType == EMR_EOF) break;
481 p = (void *) p + p->nSize;
483 GlobalFree((HGLOBAL)ht);
484 GlobalUnlock(hmf);
485 return ret;
489 /**************************************************************************
490 * PlayEnhMetaFile (GDI32.263)
492 * Renders an enhanced metafile into a specified rectangle *lpRect
493 * in device context hdc.
495 * BUGS
496 * Almost entirely unimplemented
499 BOOL WINAPI PlayEnhMetaFile(
500 HDC hdc, /* DC to render into */
501 HENHMETAFILE hmf, /* metafile to render */
502 const RECT *lpRect /* rectangle to place metafile inside */
505 LPENHMETARECORD p = GlobalLock(hmf);
506 INT count = ((LPENHMETAHEADER) p)->nHandles;
507 HANDLETABLE *ht = (HANDLETABLE *)GlobalAlloc(GPTR,
508 sizeof(HANDLETABLE)*count);
509 BOOL ret = FALSE;
510 INT savedMode = 0;
511 if (lpRect) {
512 LPENHMETAHEADER h = (LPENHMETAHEADER) p;
513 FLOAT xscale = (h->rclBounds.right-h->rclBounds.left)/(lpRect->right-lpRect->left);
514 FLOAT yscale = (h->rclBounds.bottom-h->rclBounds.top)/(lpRect->bottom-lpRect->top);
515 XFORM xform = {xscale, 0, 0, yscale, 0, 0};
516 xform.eDx = lpRect->left;
517 xform.eDy = lpRect->top;
518 FIXME(metafile, "play into rect doesn't work\n");
519 savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
520 if (!SetWorldTransform(hdc, &xform)) {
521 WARN(metafile, "World transform failed!\n");
525 ht->objectHandle[0] = hmf;
526 while (1) {
527 PlayEnhMetaFileRecord(hdc, ht, p, count);
528 if (p->iType == EMR_EOF) break;
529 p = (void *) p + p->nSize; /* casted so that arithmetic is in bytes */
531 GlobalUnlock(hmf);
532 if (savedMode) SetGraphicsMode(hdc, savedMode);
533 ret = TRUE; /* FIXME: calculate a more accurate return value */
534 return ret;
537 /*****************************************************************************
538 * DeleteEnhMetaFile (GDI32.68)
540 * Deletes an enhanced metafile and frees the associated storage.
542 BOOL WINAPI DeleteEnhMetaFile(HENHMETAFILE hmf) {
543 return !GlobalFree(hmf);
546 /*****************************************************************************
547 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
551 HENHMETAFILE WINAPI CopyEnhMetaFileA(
552 HENHMETAFILE hmf,
553 LPCSTR file)
555 if (!file) {
556 LPENHMETAHEADER h = GlobalLock(hmf);
557 HENHMETAFILE hmf2 = GlobalAlloc(GPTR, h->nBytes);
558 LPENHMETAHEADER h2 = GlobalLock(hmf2);
559 if (!h2) return 0;
560 memmove(h2, h, h->nBytes);
561 GlobalUnlock(hmf2);
562 GlobalUnlock(hmf);
563 return hmf2;
564 } else {
565 FIXME(metafile, "write to file not implemented\n");
566 return 0;
570 /*****************************************************************************
571 * GetEnhMetaFilePaletteEntries (GDI32.179)
573 * Copy the palette and report size
576 UINT WINAPI GetEnhMetaFilePaletteEntries(HENHMETAFILE hemf,
577 UINT cEntries,
578 LPPALETTEENTRY lppe)
580 LPENHMETAHEADER h = GlobalLock(hemf);
582 if ( h == NULL ){
583 GlobalUnlock(hemf);
584 return(0);
585 } else {
586 if ((lppe)&&(cEntries>0)){
587 FIXME(metafile,"Stub\n");
588 GlobalUnlock(hemf);
589 return(GDI_ERROR);
590 } else{
591 GlobalUnlock(hemf);
592 return(0);
599 /******************************************************************
600 * SetWinMetaFileBits (GDI32.343)
602 * Translate from old style to new style.
605 HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer,
606 CONST BYTE *lpbBuffer,
607 HDC hdcRef,
608 CONST METAFILEPICT *lpmfp
611 FIXME(metafile,"Stub\n");
612 return 0;