Fixed file extension problem in the file dialog.
[wine] / graphics / metafiledrv / graphics.c
1 /*
2  * Metafile driver graphics functions
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  */
6
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "gdi.h"
11 #include "region.h"
12 #include "metafiledrv.h"
13 #include "debugtools.h"
14
15 DEFAULT_DEBUG_CHANNEL(metafile);
16
17 /**********************************************************************
18  *           MFDRV_MoveTo
19  */
20 BOOL
21 MFDRV_MoveTo(DC *dc, INT x, INT y)
22 {
23     return MFDRV_MetaParam2(dc,META_MOVETO,x,y);
24 }
25
26 /***********************************************************************
27  *           MFDRV_LineTo
28  */
29 BOOL
30 MFDRV_LineTo( DC *dc, INT x, INT y )
31 {
32      return MFDRV_MetaParam2(dc, META_LINETO, x, y);
33 }
34
35
36 /***********************************************************************
37  *           MFDRV_Arc
38  */
39 BOOL 
40 MFDRV_Arc( DC *dc, INT left, INT top, INT right, INT bottom,
41            INT xstart, INT ystart, INT xend, INT yend )
42 {
43      return MFDRV_MetaParam8(dc, META_ARC, left, top, right, bottom,
44                              xstart, ystart, xend, yend);
45 }
46
47
48 /***********************************************************************
49  *           MFDRV_Pie
50  */
51 BOOL
52 MFDRV_Pie( DC *dc, INT left, INT top, INT right, INT bottom,
53            INT xstart, INT ystart, INT xend, INT yend )
54 {
55     return MFDRV_MetaParam8(dc, META_PIE, left, top, right, bottom,
56                             xstart, ystart, xend, yend);
57 }
58
59
60 /***********************************************************************
61  *           MFDRV_Chord
62  */
63 BOOL
64 MFDRV_Chord( DC *dc, INT left, INT top, INT right, INT bottom,
65              INT xstart, INT ystart, INT xend, INT yend )
66 {
67     return MFDRV_MetaParam8(dc, META_CHORD, left, top, right, bottom,
68                             xstart, ystart, xend, yend);
69 }
70
71 /***********************************************************************
72  *           MFDRV_Ellipse
73  */
74 BOOL
75 MFDRV_Ellipse( DC *dc, INT left, INT top, INT right, INT bottom )
76 {
77     return MFDRV_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
78 }
79
80 /***********************************************************************
81  *           MFDRV_Rectangle
82  */
83 BOOL
84 MFDRV_Rectangle(DC *dc, INT left, INT top, INT right, INT bottom)
85 {
86     return MFDRV_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
87 }
88
89 /***********************************************************************
90  *           MFDRV_RoundRect
91  */
92 BOOL 
93 MFDRV_RoundRect( DC *dc, INT left, INT top, INT right,
94                  INT bottom, INT ell_width, INT ell_height )
95 {
96     return MFDRV_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
97                             ell_width, ell_height);
98 }
99
100 /***********************************************************************
101  *           MFDRV_SetPixel
102  */
103 COLORREF
104 MFDRV_SetPixel( DC *dc, INT x, INT y, COLORREF color )
105 {
106     return MFDRV_MetaParam4(dc, META_SETPIXEL, x, y,HIWORD(color),
107                             LOWORD(color)); 
108 }
109
110
111 /******************************************************************
112  *         MFDRV_MetaPoly - implements Polygon and Polyline
113  */
114 static BOOL MFDRV_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
115 {
116     BOOL ret;
117     DWORD len;
118     METARECORD *mr;
119
120     len = sizeof(METARECORD) + (count * 4); 
121     if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )))
122         return FALSE;
123
124     mr->rdSize = len / 2;
125     mr->rdFunction = func;
126     *(mr->rdParm) = count;
127     memcpy(mr->rdParm + 1, pt, count * 4);
128     ret = MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
129     HeapFree( GetProcessHeap(), 0, mr);
130     return ret;
131 }
132
133
134 /**********************************************************************
135  *          MFDRV_Polyline
136  */
137 BOOL
138 MFDRV_Polyline( DC *dc, const POINT* pt, INT count )
139 {
140     register int i;
141     LPPOINT16   pt16;
142     BOOL16      ret;
143
144     pt16 = (LPPOINT16)HeapAlloc( GetProcessHeap(), 0, sizeof(POINT16)*count );
145     if(!pt16) return FALSE;
146     for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
147     ret = MFDRV_MetaPoly(dc, META_POLYLINE, pt16, count); 
148
149     HeapFree( GetProcessHeap(), 0, pt16 );
150     return ret;
151 }
152
153
154 /**********************************************************************
155  *          MFDRV_Polygon
156  */
157 BOOL
158 MFDRV_Polygon( DC *dc, const POINT* pt, INT count )
159 {
160     register int i;
161     LPPOINT16   pt16;
162     BOOL16      ret;
163
164     pt16 = (LPPOINT16) HeapAlloc( GetProcessHeap(), 0, sizeof(POINT16)*count );
165     if(!pt16) return FALSE;
166     for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
167     ret = MFDRV_MetaPoly(dc, META_POLYGON, pt16, count); 
168
169     HeapFree( GetProcessHeap(), 0, pt16 );
170     return ret;
171 }
172
173
174 /**********************************************************************
175  *          MFDRV_PolyPolygon
176  */
177 BOOL 
178 MFDRV_PolyPolygon( DC *dc, const POINT* pt, const INT* counts, UINT polygons)
179 {
180     int         i,j;
181     LPPOINT16   pt16;
182     const POINT* curpt=pt;
183     BOOL        ret;
184
185     for (i=0;i<polygons;i++) {
186         pt16=(LPPOINT16)HeapAlloc( GetProcessHeap(), 0, 
187                                    sizeof(POINT16) * counts[i] );
188         if(!pt16) return FALSE;
189         for (j=counts[i];j--;) CONV_POINT32TO16(&(curpt[j]),&(pt16[j]));
190         ret = MFDRV_MetaPoly(dc, META_POLYGON, pt16, counts[i]);
191         HeapFree( GetProcessHeap(), 0, pt16 );
192         if (!ret)
193             return FALSE;
194         curpt+=counts[i];
195     }
196     return TRUE;
197 }
198
199
200 /**********************************************************************
201  *          MFDRV_ExtFloodFill
202  */
203 BOOL 
204 MFDRV_ExtFloodFill( DC *dc, INT x, INT y, COLORREF color, UINT fillType )
205 {
206     return MFDRV_MetaParam4(dc,META_FLOODFILL,x,y,HIWORD(color),
207                             LOWORD(color)); 
208 }
209
210
211 /******************************************************************
212  *         MFDRV_CreateRegion
213  *
214  * For explanation of the format of the record see MF_Play_MetaCreateRegion in
215  * objects/metafile.c 
216  */
217 static INT16 MFDRV_CreateRegion(DC *dc, HRGN hrgn)
218 {
219     DWORD len;
220     METARECORD *mr;
221     RGNDATA *rgndata;
222     RECT *pCurRect, *pEndRect;
223     WORD Bands = 0, MaxBands = 0;
224     WORD *Param, *StartBand;
225     BOOL ret;
226
227     len = GetRegionData( hrgn, 0, NULL );
228     if( !(rgndata = HeapAlloc( GetProcessHeap(), 0, len )) ) {
229         WARN("Can't alloc rgndata buffer\n");
230         return -1;
231     }
232     GetRegionData( hrgn, len, rgndata );
233
234     /* Overestimate of length:
235      * Assume every rect is a separate band -> 6 WORDs per rect
236      */
237     len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
238     if( !(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )) ) {
239         WARN("Can't alloc METARECORD buffer\n");
240         HeapFree( GetProcessHeap(), 0, rgndata );
241         return -1;
242     }
243
244     Param = mr->rdParm + 11;
245     StartBand = NULL;
246
247     pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
248     for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
249     {
250         if( StartBand && pCurRect->top == *(StartBand + 1) )
251         {
252             *Param++ = pCurRect->left;
253             *Param++ = pCurRect->right;
254         }
255         else
256         {
257             if(StartBand)
258             {
259                 *StartBand = Param - StartBand - 3;
260                 *Param++ = *StartBand;
261                 if(*StartBand > MaxBands)
262                     MaxBands = *StartBand;
263                 Bands++;
264             }
265             StartBand = Param++;
266             *Param++ = pCurRect->top;
267             *Param++ = pCurRect->bottom;
268             *Param++ = pCurRect->left;
269             *Param++ = pCurRect->right;
270         }
271     }
272     len = Param - (WORD *)mr;
273     
274     mr->rdParm[0] = 0;
275     mr->rdParm[1] = 6;
276     mr->rdParm[2] = 0x1234;
277     mr->rdParm[3] = 0;
278     mr->rdParm[4] = len * 2;
279     mr->rdParm[5] = Bands;
280     mr->rdParm[6] = MaxBands;
281     mr->rdParm[7] = rgndata->rdh.rcBound.left;
282     mr->rdParm[8] = rgndata->rdh.rcBound.top;
283     mr->rdParm[9] = rgndata->rdh.rcBound.right;
284     mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
285     mr->rdFunction = META_CREATEREGION;
286     mr->rdSize = len / 2;
287     ret = MFDRV_WriteRecord( dc, mr, mr->rdSize * 2 );  
288     HeapFree( GetProcessHeap(), 0, mr );
289     HeapFree( GetProcessHeap(), 0, rgndata );
290     if(!ret) 
291     {
292         WARN("MFDRV_WriteRecord failed\n");
293         return -1;
294     }
295     return MFDRV_AddHandleDC( dc );
296 }
297
298
299 /**********************************************************************
300  *          MFDRV_PaintRgn
301  */
302 BOOL
303 MFDRV_PaintRgn( DC *dc, HRGN hrgn )
304 {
305     INT16 index;
306     index = MFDRV_CreateRegion( dc, hrgn );
307     if(index == -1)
308         return FALSE;
309     return MFDRV_MetaParam1( dc, META_PAINTREGION, index );
310 }
311
312
313 /**********************************************************************
314  *          MFDRV_InvertRgn
315  */
316 BOOL
317 MFDRV_InvertRgn( DC *dc, HRGN hrgn )
318 {
319     INT16 index;
320     index = MFDRV_CreateRegion( dc, hrgn );
321     if(index == -1)
322         return FALSE;
323     return MFDRV_MetaParam1( dc, META_INVERTREGION, index );
324 }
325
326
327 /**********************************************************************
328  *          MFDRV_FillRgn
329  */
330 BOOL
331 MFDRV_FillRgn( DC *dc, HRGN hrgn, HBRUSH hbrush )
332 {
333     INT16 iRgn, iBrush;
334     iRgn = MFDRV_CreateRegion( dc, hrgn );
335     if(iRgn == -1)
336         return FALSE;
337     iBrush = MFDRV_CreateBrushIndirect( dc, hbrush );
338     if(iBrush == -1)
339         return FALSE;
340     return MFDRV_MetaParam2( dc, META_FILLREGION, iRgn, iBrush );
341 }
342
343 /**********************************************************************
344  *          MFDRV_FrameRgn
345  */
346 BOOL
347 MFDRV_FrameRgn( DC *dc, HRGN hrgn, HBRUSH hbrush, INT x, INT y )
348 {
349     INT16 iRgn, iBrush;
350     iRgn = MFDRV_CreateRegion( dc, hrgn );
351     if(iRgn == -1)
352         return FALSE;
353     iBrush = MFDRV_CreateBrushIndirect( dc, hbrush );
354     if(iBrush == -1)
355         return FALSE;
356     return MFDRV_MetaParam4( dc, META_FRAMEREGION, iRgn, iBrush, x, y );
357 }
358
359
360 /**********************************************************************
361  *          MFDRV_SetBkColor
362  */
363 COLORREF
364 MFDRV_SetBkColor( DC *dc, COLORREF color )
365 {
366     return MFDRV_MetaParam2(dc, META_SETBKCOLOR, HIWORD(color), LOWORD(color));
367 }
368
369
370 /**********************************************************************
371  *          MFDRV_SetTextColor
372  */
373 COLORREF
374 MFDRV_SetTextColor( DC *dc, COLORREF color )
375 {
376     return MFDRV_MetaParam2(dc, META_SETTEXTCOLOR, HIWORD(color),
377                             LOWORD(color));
378 }
379
380
381 /**********************************************************************
382  *          MFDRV_PolyBezier
383  * Since MetaFiles don't record Beziers and they don't even record
384  * approximations to them using lines, we need this stub function.
385  */
386 BOOL
387 MFDRV_PolyBezier( DC *dc, const POINT *pts, DWORD count )
388 {
389     return FALSE;
390 }
391
392 /**********************************************************************
393  *          MFDRV_PolyBezierTo
394  * Since MetaFiles don't record Beziers and they don't even record
395  * approximations to them using lines, we need this stub function.
396  */
397 BOOL
398 MFDRV_PolyBezierTo( DC *dc, const POINT *pts, DWORD count )
399 {
400     return FALSE;
401 }