- consolidate both cases of !pending in WaitNetEvent
[wine/multimedia.git] / objects / enhmetafile.c
blob8457605f5ddcd9d14f16609cccf4b7db1a7b8039
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 DEFAULT_DEBUG_CHANNEL(metafile)
16 /*****************************************************************************
17 * GetEnhMetaFile32A (GDI32.174)
21 HENHMETAFILE WINAPI GetEnhMetaFileA(
22 LPCSTR lpszMetaFile /* filename of enhanced metafile */
25 HENHMETAFILE hmf = 0;
26 ENHMETAHEADER h;
27 BYTE *p;
28 DWORD read;
29 HFILE hf = CreateFileA(lpszMetaFile, GENERIC_READ, 0, 0,
30 OPEN_EXISTING, 0, 0);
31 if (hf == INVALID_HANDLE_VALUE) {
32 FIXME(metafile,"could not open %s\n",lpszMetaFile);
33 return 0;
35 if (!ReadFile(hf, &h, sizeof(ENHMETAHEADER), &read, NULL)) {
36 FIXME(metafile,"%s can't be read.\n",lpszMetaFile);
37 CloseHandle(hf);
38 return 0;
40 if (read!=sizeof(ENHMETAHEADER)) {
41 FIXME(metafile,"%s is not long enough.\n",lpszMetaFile);
42 CloseHandle(hf);
43 return 0;
45 if (h.iType!=1) {
46 FIXME(metafile,"%s has invalid emf header (type 0x%08lx).\n",lpszMetaFile,h.iType);
47 CloseHandle(hf);
48 return 0;
50 if (memcmp(&(h.dSignature)," EMF",4)) {
51 FIXME(metafile,"%s has invalid EMF header (dSignature 0x%08lx).\n",lpszMetaFile,h.dSignature);
52 CloseHandle(hf);
53 return 0;
55 SetFilePointer(hf, 0, NULL, FILE_BEGIN);
56 /* hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
57 hmf = GlobalAlloc(GPTR, h.nBytes);
58 p = GlobalLock(hmf);
59 if (!ReadFile(hf, p, h.nBytes, &read, NULL)) {
60 FIXME(metafile,"%s could not be read.\n",lpszMetaFile);
61 GlobalFree(hmf);
62 CloseHandle(hf);
63 return 0;
65 if (read!=h.nBytes) {
66 FIXME(metafile,"%s is not long enough (%ld expected, %ld got).\n",lpszMetaFile,h.nBytes,read);
67 GlobalFree(hmf);
68 CloseHandle(hf);
69 return 0;
71 GlobalUnlock(hmf);
72 return hmf;
75 /*****************************************************************************
76 * GetEnhMetaFile32W (GDI32.180)
78 HENHMETAFILE WINAPI GetEnhMetaFileW(
79 LPCWSTR lpszMetaFile) /* filename of enhanced metafile */
81 FIXME(metafile, "(%p): stub\n", lpszMetaFile);
82 return 0;
85 /*****************************************************************************
86 * GetEnhMetaFileHeader (GDI32.178)
88 * If _buf_ is NULL, returns the size of buffer required.
89 * Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into
90 * _buf.
92 UINT WINAPI GetEnhMetaFileHeader(
93 HENHMETAFILE hmf, /* enhanced metafile */
94 UINT bufsize, /* size of buffer */
95 LPENHMETAHEADER buf /* buffer */
98 LPENHMETAHEADER p = GlobalLock(hmf);
99 if (!buf) return sizeof(ENHMETAHEADER);
100 memmove(buf, p, MIN(sizeof(ENHMETAHEADER), bufsize));
101 GlobalUnlock(hmf);
102 return MIN(sizeof(ENHMETAHEADER), bufsize);
106 /*****************************************************************************
107 * GetEnhMetaFileDescription32A (GDI32.176)
109 UINT WINAPI GetEnhMetaFileDescriptionA(
110 HENHMETAFILE hmf, /* enhanced metafile */
111 UINT size, /* size of buf */
112 LPSTR buf /* buffer to receive description */
115 LPENHMETAHEADER p = GlobalLock(hmf);
116 INT first = lstrlenW( (void *)p+p->offDescription);
118 if (!buf || !size) return p->nDescription;
120 lstrcpynWtoA(buf, (void *)p+p->offDescription, size);
121 buf += first +1;
122 lstrcpynWtoA(buf, (void *)p+p->offDescription+2*(first+1), size-first-1);
124 /* memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
125 GlobalUnlock(hmf);
126 return MIN(size,p->nDescription);
129 /*****************************************************************************
130 * GetEnhMetaFileDescription32W (GDI32.177)
132 * Copies the description string of an enhanced metafile into a buffer
133 * _buf_.
135 * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
136 * number of characters copied.
138 UINT WINAPI GetEnhMetaFileDescriptionW(
139 HENHMETAFILE hmf, /* enhanced metafile */
140 UINT size, /* size of buf */
141 LPWSTR buf /* buffer to receive description */
144 LPENHMETAHEADER p = GlobalLock(hmf);
146 if (!buf || !size) return p->nDescription;
148 memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription));
149 GlobalUnlock(hmf);
150 return MIN(size,p->nDescription);
153 /****************************************************************************
154 * SetEnhMetaFileBits (GDI32.315)
156 * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
158 HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT bufsize, const BYTE *buf)
160 HENHMETAFILE hmf = GlobalAlloc(GPTR, bufsize);
161 LPENHMETAHEADER h = GlobalLock(hmf);
162 memmove(h, buf, bufsize);
163 GlobalUnlock(hmf);
164 return hmf;
167 /*****************************************************************************
168 * GetEnhMetaFileBits (GDI32.175)
171 UINT WINAPI GetEnhMetaFileBits(
172 HENHMETAFILE hmf,
173 UINT bufsize,
174 LPBYTE buf
176 return 0;
179 /*****************************************************************************
180 * PlayEnhMetaFileRecord (GDI32.264)
182 * Render a single enhanced metafile record in the device context hdc.
184 * RETURNS
185 * TRUE on success, FALSE on error.
186 * BUGS
187 * Many unimplemented records.
189 BOOL WINAPI PlayEnhMetaFileRecord(
190 HDC hdc, /* device context in which to render EMF record */
191 LPHANDLETABLE handletable, /* array of handles to be used in rendering record */
192 const ENHMETARECORD *mr, /* EMF record to render */
193 UINT handles /* size of handle array */
196 int type;
197 TRACE(metafile,
198 "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
199 hdc, handletable, mr, handles);
200 if (!mr) return FALSE;
202 type = mr->iType;
204 TRACE(metafile, " type=%d\n", type);
205 switch(type)
207 case EMR_HEADER:
209 /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
210 break;
212 case EMR_EOF:
213 break;
214 case EMR_GDICOMMENT:
215 /* application defined and processed */
216 break;
217 case EMR_SETMAPMODE:
219 DWORD mode = mr->dParm[0];
220 SetMapMode(hdc, mode);
221 break;
223 case EMR_SETBKMODE:
225 DWORD mode = mr->dParm[0];
226 SetBkMode(hdc, mode);
227 break;
229 case EMR_SETBKCOLOR:
231 DWORD mode = mr->dParm[0];
232 SetBkColor(hdc, mode);
233 break;
235 case EMR_SETPOLYFILLMODE:
237 DWORD mode = mr->dParm[0];
238 SetPolyFillMode(hdc, mode);
239 break;
241 case EMR_SETROP2:
243 DWORD mode = mr->dParm[0];
244 SetROP2(hdc, mode);
245 break;
247 case EMR_SETSTRETCHBLTMODE:
249 DWORD mode = mr->dParm[0];
250 SetStretchBltMode(hdc, mode);
251 break;
253 case EMR_SETTEXTALIGN:
255 DWORD align = mr->dParm[0];
256 SetTextAlign(hdc, align);
257 break;
259 case EMR_SETTEXTCOLOR:
261 DWORD color = mr->dParm[0];
262 SetTextColor(hdc, color);
263 break;
265 case EMR_SAVEDC:
267 SaveDC(hdc);
268 break;
270 case EMR_RESTOREDC:
272 RestoreDC(hdc, mr->dParm[0]);
273 break;
275 case EMR_INTERSECTCLIPRECT:
277 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
278 bottom = mr->dParm[3];
279 IntersectClipRect(hdc, left, top, right, bottom);
280 break;
282 case EMR_SELECTOBJECT:
284 DWORD obj = mr->dParm[0];
285 SelectObject(hdc, (handletable->objectHandle)[obj]);
286 break;
288 case EMR_DELETEOBJECT:
290 DWORD obj = mr->dParm[0];
291 DeleteObject( (handletable->objectHandle)[obj]);
292 (handletable->objectHandle)[obj] = 0;
293 break;
295 case EMR_SETWINDOWORGEX:
297 DWORD x = mr->dParm[0], y = mr->dParm[1];
298 SetWindowOrgEx(hdc, x, y, NULL);
299 break;
301 case EMR_SETWINDOWEXTEX:
303 DWORD x = mr->dParm[0], y = mr->dParm[1];
304 SetWindowExtEx(hdc, x, y, NULL);
305 break;
307 case EMR_SETVIEWPORTORGEX:
309 DWORD x = mr->dParm[0], y = mr->dParm[1];
310 SetViewportOrgEx(hdc, x, y, NULL);
311 break;
313 case EMR_SETVIEWPORTEXTEX:
315 DWORD x = mr->dParm[0], y = mr->dParm[1];
316 SetViewportExtEx(hdc, x, y, NULL);
317 break;
319 case EMR_CREATEPEN:
321 DWORD obj = mr->dParm[0];
322 (handletable->objectHandle)[obj] =
323 CreatePenIndirect((LOGPEN *) &(mr->dParm[1]));
324 break;
326 case EMR_EXTCREATEPEN:
328 DWORD obj = mr->dParm[0];
329 DWORD style = mr->dParm[1], brush = mr->dParm[2];
330 LOGBRUSH *b = (LOGBRUSH *) &mr->dParm[3];
331 FIXME(metafile, "Some ExtCreatePen args not handled\n");
332 (handletable->objectHandle)[obj] =
333 ExtCreatePen(style, brush, b, 0, NULL);
334 break;
336 case EMR_CREATEBRUSHINDIRECT:
338 DWORD obj = mr->dParm[0];
339 (handletable->objectHandle)[obj] =
340 CreateBrushIndirect((LOGBRUSH *) &(mr->dParm[1]));
341 break;
343 case EMR_EXTCREATEFONTINDIRECTW:
345 DWORD obj = mr->dParm[0];
346 (handletable->objectHandle)[obj] =
347 CreateFontIndirectW((LOGFONTW *) &(mr->dParm[1]));
348 break;
350 case EMR_MOVETOEX:
352 DWORD x = mr->dParm[0], y = mr->dParm[1];
353 MoveToEx(hdc, x, y, NULL);
354 break;
356 case EMR_LINETO:
358 DWORD x = mr->dParm[0], y = mr->dParm[1];
359 LineTo(hdc, x, y);
360 break;
362 case EMR_RECTANGLE:
364 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
365 bottom = mr->dParm[3];
366 Rectangle(hdc, left, top, right, bottom);
367 break;
369 case EMR_ELLIPSE:
371 INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
372 bottom = mr->dParm[3];
373 Ellipse(hdc, left, top, right, bottom);
374 break;
376 case EMR_POLYGON16:
378 /* 0-3 : a bounding rectangle? */
379 INT count = mr->dParm[4];
380 FIXME(metafile, "Some Polygon16 args not handled\n");
381 Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
382 break;
384 case EMR_POLYLINE16:
386 /* 0-3 : a bounding rectangle? */
387 INT count = mr->dParm[4];
388 FIXME(metafile, "Some Polyline16 args not handled\n");
389 Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
390 break;
393 #if 0
394 case EMR_POLYPOLYGON16:
396 INT polygons = mr->dParm[z];
397 LPPOINT16 pts = (LPPOINT16) &mr->dParm[x];
398 LPINT16 counts = (LPINT16) &mr->dParm[y];
399 PolyPolygon16(hdc, pts, counts, polygons);
400 break;
402 #endif
403 case EMR_STRETCHDIBITS:
405 LONG xDest = mr->dParm[4];
406 LONG yDest = mr->dParm[5];
407 LONG xSrc = mr->dParm[6];
408 LONG ySrc = mr->dParm[7];
409 LONG cxSrc = mr->dParm[8];
410 LONG cySrc = mr->dParm[9];
411 DWORD offBmiSrc = mr->dParm[10];
412 DWORD offBitsSrc = mr->dParm[12];
413 DWORD iUsageSrc = mr->dParm[14];
414 DWORD dwRop = mr->dParm[15];
415 LONG cxDest = mr->dParm[16];
416 LONG cyDest = mr->dParm[17];
418 StretchDIBits(hdc,xDest,yDest,cxDest,cyDest,
419 xSrc,ySrc,cxSrc,cySrc,
420 ((char *)mr)+offBitsSrc,
421 (const BITMAPINFO *)(((char *)mr)+offBmiSrc),
422 iUsageSrc,dwRop);
423 break;
425 case EMR_EXTTEXTOUTW:
427 /* 0-3: ??? */
428 DWORD flags = mr->dParm[4];
429 /* 5, 6: ??? */
430 DWORD x = mr->dParm[7], y = mr->dParm[8];
431 DWORD count = mr->dParm[9];
432 /* 10-16: ??? */
433 LPWSTR str = (LPWSTR)& mr->dParm[17];
434 /* trailing info: dx array? */
435 FIXME(metafile, "Many ExtTextOut args not handled\n");
436 ExtTextOutW(hdc, x, y, flags, /* lpRect */ NULL,
437 str, count, /* lpDx */ NULL);
438 break;
441 default:
442 FIXME(metafile, "type %d is unimplemented\n", type);
443 /* SetLastError(E_NOTIMPL); */
444 break;
446 return TRUE;
450 /*****************************************************************************
452 * EnumEnhMetaFile32 (GDI32.79)
454 * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
455 * for each
456 * record. Returns when either every record has been used or
457 * when _EnhMetaFunc_ returns FALSE.
460 * RETURNS
461 * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
462 * returns FALSE.
464 * BUGS
465 * Ignores rect.
467 BOOL WINAPI EnumEnhMetaFile(
468 HDC hdc, /* device context to pass to _EnhMetaFunc_ */
469 HENHMETAFILE hmf, /* EMF to walk */
470 ENHMFENUMPROC callback, /* callback function */
471 LPVOID data, /* optional data for callback function */
472 const RECT *rect /* bounding rectangle for rendered metafile */
475 BOOL ret = TRUE;
476 LPENHMETARECORD p = GlobalLock(hmf);
477 INT count = ((LPENHMETAHEADER) p)->nHandles;
478 HANDLETABLE *ht = (HANDLETABLE *)GlobalAlloc(GPTR, sizeof(HANDLETABLE)*count);
479 ht->objectHandle[0] = hmf;
480 while (ret) {
481 ret = (*callback)(hdc, ht, p, count, data);
482 if (p->iType == EMR_EOF) break;
483 p = (void *) p + p->nSize;
485 GlobalFree((HGLOBAL)ht);
486 GlobalUnlock(hmf);
487 return ret;
491 /**************************************************************************
492 * PlayEnhMetaFile (GDI32.263)
494 * Renders an enhanced metafile into a specified rectangle *lpRect
495 * in device context hdc.
497 * BUGS
498 * Almost entirely unimplemented
501 BOOL WINAPI PlayEnhMetaFile(
502 HDC hdc, /* DC to render into */
503 HENHMETAFILE hmf, /* metafile to render */
504 const RECT *lpRect /* rectangle to place metafile inside */
507 LPENHMETARECORD p = GlobalLock(hmf);
508 INT count = ((LPENHMETAHEADER) p)->nHandles;
509 HANDLETABLE *ht = (HANDLETABLE *)GlobalAlloc(GPTR,
510 sizeof(HANDLETABLE)*count);
511 BOOL ret = FALSE;
512 INT savedMode = 0;
513 if (lpRect) {
514 LPENHMETAHEADER h = (LPENHMETAHEADER) p;
515 FLOAT xscale = (h->rclBounds.right-h->rclBounds.left)/(lpRect->right-lpRect->left);
516 FLOAT yscale = (h->rclBounds.bottom-h->rclBounds.top)/(lpRect->bottom-lpRect->top);
517 XFORM xform = {xscale, 0, 0, yscale, 0, 0};
518 xform.eDx = lpRect->left;
519 xform.eDy = lpRect->top;
520 FIXME(metafile, "play into rect doesn't work\n");
521 savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
522 if (!SetWorldTransform(hdc, &xform)) {
523 WARN(metafile, "World transform failed!\n");
527 ht->objectHandle[0] = hmf;
528 while (1) {
529 PlayEnhMetaFileRecord(hdc, ht, p, count);
530 if (p->iType == EMR_EOF) break;
531 p = (void *) p + p->nSize; /* casted so that arithmetic is in bytes */
533 GlobalUnlock(hmf);
534 if (savedMode) SetGraphicsMode(hdc, savedMode);
535 ret = TRUE; /* FIXME: calculate a more accurate return value */
536 return ret;
539 /*****************************************************************************
540 * DeleteEnhMetaFile (GDI32.68)
542 * Deletes an enhanced metafile and frees the associated storage.
544 BOOL WINAPI DeleteEnhMetaFile(HENHMETAFILE hmf) {
545 return !GlobalFree(hmf);
548 /*****************************************************************************
549 * CopyEnhMetaFileA (GDI32.21) Duplicate an enhanced metafile
553 HENHMETAFILE WINAPI CopyEnhMetaFileA(
554 HENHMETAFILE hmf,
555 LPCSTR file)
557 if (!file) {
558 LPENHMETAHEADER h = GlobalLock(hmf);
559 HENHMETAFILE hmf2 = GlobalAlloc(GPTR, h->nBytes);
560 LPENHMETAHEADER h2 = GlobalLock(hmf2);
561 if (!h2) return 0;
562 memmove(h2, h, h->nBytes);
563 GlobalUnlock(hmf2);
564 GlobalUnlock(hmf);
565 return hmf2;
566 } else {
567 FIXME(metafile, "write to file not implemented\n");
568 return 0;
572 /*****************************************************************************
573 * GetEnhMetaFilePaletteEntries (GDI32.179)
575 * Copy the palette and report size
578 UINT WINAPI GetEnhMetaFilePaletteEntries(HENHMETAFILE hemf,
579 UINT cEntries,
580 LPPALETTEENTRY lppe)
582 LPENHMETAHEADER h = GlobalLock(hemf);
584 if ( h == NULL ){
585 GlobalUnlock(hemf);
586 return(0);
587 } else {
588 if ((lppe)&&(cEntries>0)){
589 FIXME(metafile,"Stub\n");
590 GlobalUnlock(hemf);
591 return(GDI_ERROR);
592 } else{
593 GlobalUnlock(hemf);
594 return(0);
601 /******************************************************************
602 * SetWinMetaFileBits (GDI32.343)
604 * Translate from old style to new style.
607 HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer,
608 CONST BYTE *lpbBuffer,
609 HDC hdcRef,
610 CONST METAFILEPICT *lpmfp
613 FIXME(metafile,"Stub\n");
614 return 0;