Release 980712
[wine] / objects / enhmetafile.c
1 /*
2   Enhanced metafile functions
3   Copyright 1998, Douglas Ridgway
4 */
5
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
13 /*****************************************************************************
14  *          GetEnhMetaFile32A (GDI32.174)
15  *
16  *
17  */
18 HENHMETAFILE32 WINAPI GetEnhMetaFile32A( 
19              LPCSTR lpszMetaFile  /* filename of enhanced metafile */
20     )
21 {
22   HENHMETAFILE32 hmf = 0;
23   ENHMETAHEADER h;
24   BYTE *p;
25   DWORD read;
26   HFILE32 hf = CreateFile32A(lpszMetaFile, GENERIC_READ, 0, 0, 
27                              OPEN_EXISTING, 0, 0);
28   if (!ReadFile(hf, &h, sizeof(ENHMETAHEADER), &read, NULL)) 
29     return 0;
30   if (read!=sizeof(ENHMETAHEADER)) return 0;
31   SetFilePointer(hf, 0, NULL, FILE_BEGIN); 
32   /*  hmf = CreateFileMapping32A( hf, NULL, NULL, NULL, NULL, "temp"); */
33   hmf = GlobalAlloc32(GPTR, h.nBytes);
34   p = GlobalLock32(hmf);
35   if (!ReadFile(hf, p, h.nBytes, &read, NULL)) return 0;
36   GlobalUnlock32(hmf);
37   return hmf;
38 }
39
40 /*****************************************************************************
41  *        GetEnhMetaFileHeader  (GDI32.178)
42  *
43  *  If _buf_ is NULL, returns the size of buffer required.
44  *  Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into 
45  *  _buf.
46  */
47 UINT32 WINAPI GetEnhMetaFileHeader( 
48        HENHMETAFILE32 hmf, /* enhanced metafile */
49        UINT32 bufsize,     /* size of buffer */
50        LPENHMETAHEADER buf /* buffer */ 
51     )
52 {
53   LPENHMETAHEADER p = GlobalLock32(hmf);
54   if (!buf) return sizeof(ENHMETAHEADER);
55   memmove(buf, p, MIN(sizeof(ENHMETAHEADER), bufsize));
56   GlobalUnlock32(hmf);
57   return MIN(sizeof(ENHMETAHEADER), bufsize);
58 }
59
60
61 /*****************************************************************************
62  *          GetEnhMetaFileDescription32A  (GDI32.176)
63  */
64 UINT32 WINAPI GetEnhMetaFileDescription32A( 
65        HENHMETAFILE32 hmf, /* enhanced metafile */
66        UINT32 size, /* size of buf */ 
67        LPSTR buf /* buffer to receive description */
68     )
69 {
70   LPENHMETAHEADER p = GlobalLock32(hmf);
71   INT32 first  = lstrlen32W( (void *)p+p->offDescription);
72
73   if (!buf || !size) return p->nDescription;
74
75   lstrcpynWtoA(buf, (void *)p+p->offDescription, size);
76   buf += first +1;
77   lstrcpynWtoA(buf, (void *)p+p->offDescription+2*(first+1), size-first-1);
78
79   /*  memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription)); */
80   GlobalUnlock32(hmf);
81   return MIN(size,p->nDescription);
82 }
83
84 /*****************************************************************************
85  *          GetEnhMetaFileDescription32W  (GDI32.177)
86  *
87  *  Copies the description string of an enhanced metafile into a buffer 
88  *  _buf_.
89  *
90  *  If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
91  *  number of characters copied.
92  */
93 UINT32 WINAPI GetEnhMetaFileDescription32W( 
94        HENHMETAFILE32 hmf, /* enhanced metafile */
95        UINT32 size, /* size of buf */ 
96        LPWSTR buf /* buffer to receive description */
97     )
98 {
99   LPENHMETAHEADER p = GlobalLock32(hmf);
100
101   if (!buf || !size) return p->nDescription;
102
103   memmove(buf, (void *)p+p->offDescription, MIN(size,p->nDescription));
104   GlobalUnlock32(hmf);
105   return MIN(size,p->nDescription);
106 }
107
108 /****************************************************************************
109  *    SetEnhMetaFileBits (GDI32.315)
110  *
111  *  Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
112  */
113 HENHMETAFILE32 WINAPI SetEnhMetaFileBits(UINT32 bufsize, const BYTE *buf)
114 {
115   HENHMETAFILE32 hmf = GlobalAlloc32(GPTR, bufsize);
116   LPENHMETAHEADER h = GlobalLock32(hmf);
117   memmove(h, buf, bufsize);
118   GlobalUnlock32(hmf);
119   return hmf;
120 }
121
122 /*****************************************************************************
123  *  GetEnhMetaFileBits (GDI32.175)
124  *
125  */
126 UINT32 WINAPI GetEnhMetaFileBits(
127     HENHMETAFILE32 hmf, 
128     UINT32 bufsize, 
129     LPBYTE buf  
130 ) {
131   return 0;
132 }
133
134 /*****************************************************************************
135  *           PlayEnhMetaFileRecord  (GDI32.264)
136  *
137  *  Render a single enhanced metafile record in the device context hdc.
138  *
139  *  RETURNS
140  *    TRUE on success, FALSE on error.
141  *  BUGS
142  *    Many unimplemented records.
143  */
144 BOOL32 WINAPI PlayEnhMetaFileRecord( 
145      HDC32 hdc, /* device context in which to render EMF record */
146      LPHANDLETABLE32 handletable, /* array of handles to be used in rendering record */
147      const ENHMETARECORD *mr, /* EMF record to render */
148      UINT32 handles  /* size of handle array */
149      ) 
150 {
151   int type;
152   TRACE(metafile, 
153         "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n", 
154           hdc, handletable, mr, handles);
155   if (!mr) return FALSE;
156
157   type = mr->iType;
158
159   TRACE(metafile, " type=%d\n", type);
160   switch(type) 
161     {
162     case EMR_HEADER:
163       {
164         /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
165         break;
166       }
167     case EMR_EOF:
168       break;
169     case EMR_GDICOMMENT:
170       /* application defined and processed */
171       break;
172     case EMR_SETMAPMODE:
173       {
174         DWORD mode = mr->dParm[0];
175         SetMapMode32(hdc, mode);
176         break;
177       }
178     case EMR_SETBKMODE:
179       {
180         DWORD mode = mr->dParm[0];
181         SetBkMode32(hdc, mode);
182         break;
183       }
184     case EMR_SETBKCOLOR:
185       {
186         DWORD mode = mr->dParm[0];
187         SetBkColor32(hdc, mode);
188         break;
189       }
190     case EMR_SETPOLYFILLMODE:
191       {
192         DWORD mode = mr->dParm[0];
193         SetPolyFillMode32(hdc, mode);
194         break;
195       }
196     case EMR_SETROP2:
197       {
198         DWORD mode = mr->dParm[0];
199         SetROP232(hdc, mode);
200         break;
201       }
202     case EMR_SETSTRETCHBLTMODE:
203       {
204         DWORD mode = mr->dParm[0];
205         SetStretchBltMode32(hdc, mode);
206         break;
207       }
208     case EMR_SETTEXTALIGN:
209       {
210         DWORD align = mr->dParm[0];
211         SetTextAlign32(hdc, align);
212         break;
213       }
214     case EMR_SETTEXTCOLOR:
215       {
216         DWORD color = mr->dParm[0];
217         SetTextColor32(hdc, color);
218         break;
219       }
220     case EMR_SAVEDC:
221       {
222         SaveDC32(hdc);
223         break;
224       }
225     case EMR_RESTOREDC:
226       {
227         RestoreDC32(hdc, mr->dParm[0]);
228         break;
229       }
230     case EMR_INTERSECTCLIPRECT:
231       {
232         INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
233               bottom = mr->dParm[3];
234         IntersectClipRect32(hdc, left, top, right, bottom);
235         break;
236       }
237     case EMR_SELECTOBJECT:
238       {
239         DWORD obj = mr->dParm[0];
240         SelectObject32(hdc, (handletable->objectHandle)[obj]);
241         break;
242       }
243     case EMR_DELETEOBJECT:
244       {
245         DWORD obj = mr->dParm[0];
246         DeleteObject32( (handletable->objectHandle)[obj]);
247         (handletable->objectHandle)[obj] = 0;
248         break;
249       }
250     case EMR_SETWINDOWORGEX:
251       {
252         DWORD x = mr->dParm[0], y = mr->dParm[1];
253         SetWindowOrgEx32(hdc, x, y, NULL);
254         break;
255       }
256     case EMR_SETWINDOWEXTEX:
257       {
258         DWORD x = mr->dParm[0], y = mr->dParm[1];
259         SetWindowExtEx32(hdc, x, y, NULL);
260         break;
261       }
262     case EMR_SETVIEWPORTORGEX:
263       {
264         DWORD x = mr->dParm[0], y = mr->dParm[1];
265         SetViewportOrgEx32(hdc, x, y, NULL);
266         break;
267       }
268     case EMR_SETVIEWPORTEXTEX:
269       {
270         DWORD x = mr->dParm[0], y = mr->dParm[1];
271         SetViewportExtEx32(hdc, x, y, NULL);
272         break;
273       }
274     case EMR_CREATEPEN:
275       {
276         DWORD obj = mr->dParm[0];
277         (handletable->objectHandle)[obj] = 
278           CreatePenIndirect32((LOGPEN32 *) &(mr->dParm[1]));
279         break;
280       }
281     case EMR_EXTCREATEPEN:
282       {
283         DWORD obj = mr->dParm[0];
284         DWORD style = mr->dParm[1], brush = mr->dParm[2];
285         LOGBRUSH32 *b = (LOGBRUSH32 *) &mr->dParm[3];
286         FIXME(metafile, "Some ExtCreatePen args not handled\n");
287         (handletable->objectHandle)[obj] = 
288           ExtCreatePen32(style, brush, b, 0, NULL);
289         break;
290       }
291     case EMR_CREATEBRUSHINDIRECT:
292       {
293         DWORD obj = mr->dParm[0];
294         (handletable->objectHandle)[obj] = 
295           CreateBrushIndirect32((LOGBRUSH32 *) &(mr->dParm[1]));
296         break;
297       }
298     case EMR_EXTCREATEFONTINDIRECTW:
299         {
300         DWORD obj = mr->dParm[0];
301         (handletable->objectHandle)[obj] = 
302           CreateFontIndirect32W((LOGFONT32W *) &(mr->dParm[1]));
303         break;
304         }
305     case EMR_MOVETOEX:
306       {
307         DWORD x = mr->dParm[0], y = mr->dParm[1];
308         MoveToEx32(hdc, x, y, NULL);
309         break;
310       }
311     case EMR_LINETO:
312       {
313         DWORD x = mr->dParm[0], y = mr->dParm[1];
314         LineTo32(hdc, x, y);
315         break;
316       }
317     case EMR_RECTANGLE:
318       {
319         INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
320               bottom = mr->dParm[3];
321         Rectangle32(hdc, left, top, right, bottom);
322         break;
323       }
324     case EMR_ELLIPSE:
325       {
326         INT32 left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
327               bottom = mr->dParm[3];
328         Ellipse32(hdc, left, top, right, bottom);
329         break;
330       }
331     case EMR_POLYGON16:
332       {
333         /* 0-3 : a bounding rectangle? */
334         INT32 count = mr->dParm[4];
335         FIXME(metafile, "Some Polygon16 args not handled\n");
336         Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
337         break;
338       }
339     case EMR_POLYLINE16:
340       {
341         /* 0-3 : a bounding rectangle? */
342         INT32 count = mr->dParm[4];
343         FIXME(metafile, "Some Polyline16 args not handled\n");
344         Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
345         break;
346       }
347
348 #if 0
349     case EMR_POLYPOLYGON16:
350       {
351         INT32 polygons = mr->dParm[z];
352         LPPOINT16 pts = (LPPOINT16) &mr->dParm[x];
353         LPINT16 counts = (LPINT16) &mr->dParm[y];
354         PolyPolygon16(hdc, pts, counts, polygons);
355         break;
356       }
357 #endif
358     case EMR_EXTTEXTOUTW:
359       {
360         /* 0-3: ??? */
361         DWORD flags = mr->dParm[4];
362         /* 5, 6: ??? */
363         DWORD x = mr->dParm[7], y = mr->dParm[8];
364         DWORD count = mr->dParm[9];
365         /* 10-16: ??? */
366         LPWSTR str = (LPWSTR)& mr->dParm[17];
367         /* trailing info: dx array? */
368         FIXME(metafile, "Many ExtTextOut args not handled\n");
369         ExtTextOut32W(hdc, x, y, flags, /* lpRect */ NULL, 
370                       str, count, /* lpDx */ NULL); 
371         break;
372       }
373
374     default:
375       FIXME(metafile, "type %d is unimplemented\n", type);
376       /*  SetLastError(E_NOTIMPL); */
377       break;
378     }
379   return TRUE;
380 }
381
382
383 /*****************************************************************************
384  *
385  *        EnumEnhMetaFile32  (GDI32.79)
386  *
387  *  Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
388  *  for each
389  *  record. Returns when either every record has been used or 
390  *  when _EnhMetaFunc_ returns FALSE.
391  *
392  *
393  * RETURNS
394  *  TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
395  *  returns FALSE.
396  *
397  * BUGS
398  *   Ignores rect.
399  */
400 BOOL32 WINAPI EnumEnhMetaFile32( 
401      HDC32 hdc, /* device context to pass to _EnhMetaFunc_ */
402      HENHMETAFILE32 hmf, /* EMF to walk */
403      ENHMFENUMPROC32 callback, /* callback function */ 
404      LPVOID data, /* optional data for callback function */
405      const RECT32 *rect  /* bounding rectangle for rendered metafile */
406     )
407 {
408   BOOL32 ret = TRUE;
409   LPENHMETARECORD p = GlobalLock32(hmf);
410   INT32 count = ((LPENHMETAHEADER) p)->nHandles;
411   HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR, sizeof(HANDLETABLE32)*count);
412   ht->objectHandle[0] = hmf;
413   while (ret) {
414     ret = (*callback)(hdc, ht, p, count, data); 
415     if (p->iType == EMR_EOF) break;
416     p = (void *) p + p->nSize;
417   }
418   GlobalFree32((HGLOBAL32)ht);
419   GlobalUnlock32(hmf);
420   return ret;
421 }
422
423
424 /**************************************************************************
425  *    PlayEnhMetaFile  (GDI32.263)
426  *
427  *    Renders an enhanced metafile into a specified rectangle *lpRect
428  *    in device context hdc.
429  *
430  * BUGS
431  *    Almost entirely unimplemented
432  *
433  */
434 BOOL32 WINAPI PlayEnhMetaFile( 
435        HDC32 hdc, /* DC to render into */
436        HENHMETAFILE32 hmf, /* metafile to render */
437        const RECT32 *lpRect  /* rectangle to place metafile inside */
438       )
439 {
440   LPENHMETARECORD p = GlobalLock32(hmf);
441   INT32 count = ((LPENHMETAHEADER) p)->nHandles;
442   HANDLETABLE32 *ht = (HANDLETABLE32 *)GlobalAlloc32(GPTR, 
443                                     sizeof(HANDLETABLE32)*count);
444   BOOL32 ret = FALSE;
445   INT32 savedMode = 0;
446   if (lpRect) {
447     LPENHMETAHEADER h = (LPENHMETAHEADER) p;
448     FLOAT xscale = (h->rclBounds.right-h->rclBounds.left)/(lpRect->right-lpRect->left);
449     FLOAT yscale = (h->rclBounds.bottom-h->rclBounds.top)/(lpRect->bottom-lpRect->top);
450     XFORM xform = {xscale, 0, 0, yscale, 0, 0};
451         xform.eDx = lpRect->left;
452           xform.eDy = lpRect->top; 
453     FIXME(metafile, "play into rect doesn't work\n");
454     savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
455     if (!SetWorldTransform(hdc, &xform)) {
456       WARN(metafile, "World transform failed!\n");
457     }
458   }
459
460   ht->objectHandle[0] = hmf;
461   while (1) {
462     PlayEnhMetaFileRecord(hdc, ht, p, count);
463     if (p->iType == EMR_EOF) break;
464     p = (void *) p + p->nSize; /* casted so that arithmetic is in bytes */
465   }
466   GlobalUnlock32(hmf);
467   if (savedMode) SetGraphicsMode(hdc, savedMode);
468   ret = TRUE; /* FIXME: calculate a more accurate return value */
469   return ret;
470 }
471
472 /*****************************************************************************
473  *  DeleteEnhMetaFile (GDI32.68)
474  *
475  *  Deletes an enhanced metafile and frees the associated storage.
476  */
477 BOOL32 WINAPI DeleteEnhMetaFile(HENHMETAFILE32 hmf) {
478   return !GlobalFree32(hmf);
479 }
480
481 /*****************************************************************************
482  *  CopyEnhMetaFileA (GDI32.21)  Duplicate an enhanced metafile
483  *
484  *   
485  */
486 HENHMETAFILE32 WINAPI CopyEnhMetaFile32A(
487     HENHMETAFILE32 hmf, 
488     LPCSTR file)
489 {
490   if (!file) {
491     LPENHMETAHEADER h = GlobalLock32(hmf);
492     HENHMETAFILE32 hmf2 = GlobalAlloc32(GPTR, h->nBytes);
493     LPENHMETAHEADER h2 = GlobalLock32(hmf2);
494     if (!h2) return 0;
495     memmove(h2, h, h->nBytes);
496     GlobalUnlock32(hmf2);
497     GlobalUnlock32(hmf);
498     return hmf2;
499   } else {
500     FIXME(metafile, "write to file not implemented\n");
501     return 0;
502   }
503 }
504
505