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