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