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