Change (32 bit) HMETAFILEs to GDI objects (HMETAFILE16s remain as
[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 "gdi.h"
9 #include "dc.h"
10 #include "region.h"
11 #include "xmalloc.h"
12 #include "metafiledrv.h"
13 #include "heap.h"
14 #include "debug.h"
15
16 /**********************************************************************
17  *           MFDRV_MoveToEx
18  */
19 BOOL
20 MFDRV_MoveToEx(DC *dc,INT x,INT y,LPPOINT pt)
21 {
22     if (!MFDRV_MetaParam2(dc,META_MOVETO,x,y))
23         return FALSE;
24
25     if (pt)
26     {
27         pt->x = dc->w.CursPosX;
28         pt->y = dc->w.CursPosY;
29     }
30     dc->w.CursPosX = x;
31     dc->w.CursPosY = y;
32     return TRUE;
33 }
34
35 /***********************************************************************
36  *           MFDRV_LineTo
37  */
38 BOOL
39 MFDRV_LineTo( DC *dc, INT x, INT y )
40 {
41      return MFDRV_MetaParam2(dc, META_LINETO, x, y);
42 }
43
44
45 /***********************************************************************
46  *           MFDRV_Arc
47  */
48 BOOL 
49 MFDRV_Arc( DC *dc, INT left, INT top, INT right, INT bottom,
50            INT xstart, INT ystart, INT xend, INT yend )
51 {
52      return MFDRV_MetaParam8(dc, META_ARC, left, top, right, bottom,
53                              xstart, ystart, xend, yend);
54 }
55
56
57 /***********************************************************************
58  *           MFDRV_Pie
59  */
60 BOOL
61 MFDRV_Pie( DC *dc, INT left, INT top, INT right, INT bottom,
62            INT xstart, INT ystart, INT xend, INT yend )
63 {
64     return MFDRV_MetaParam8(dc, META_PIE, left, top, right, bottom,
65                             xstart, ystart, xend, yend);
66 }
67
68
69 /***********************************************************************
70  *           MFDRV_Chord
71  */
72 BOOL
73 MFDRV_Chord( DC *dc, INT left, INT top, INT right, INT bottom,
74              INT xstart, INT ystart, INT xend, INT yend )
75 {
76     return MFDRV_MetaParam8(dc, META_CHORD, left, top, right, bottom,
77                             xstart, ystart, xend, yend);
78 }
79
80 /***********************************************************************
81  *           MFDRV_Ellipse
82  */
83 BOOL
84 MFDRV_Ellipse( DC *dc, INT left, INT top, INT right, INT bottom )
85 {
86     return MFDRV_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
87 }
88
89 /***********************************************************************
90  *           MFDRV_Rectangle
91  */
92 BOOL
93 MFDRV_Rectangle(DC *dc, INT left, INT top, INT right, INT bottom)
94 {
95     return MFDRV_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
96 }
97
98 /***********************************************************************
99  *           MFDRV_RoundRect
100  */
101 BOOL 
102 MFDRV_RoundRect( DC *dc, INT left, INT top, INT right,
103                  INT bottom, INT ell_width, INT ell_height )
104 {
105     return MFDRV_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
106                             ell_width, ell_height);
107 }
108
109 /***********************************************************************
110  *           MFDRV_SetPixel
111  */
112 COLORREF
113 MFDRV_SetPixel( DC *dc, INT x, INT y, COLORREF color )
114 {
115     return MFDRV_MetaParam4(dc, META_SETPIXEL, x, y,HIWORD(color),
116                             LOWORD(color)); 
117 }
118
119
120 /******************************************************************
121  *         MFDRV_MetaPoly - implements Polygon and Polyline
122  */
123 static BOOL MFDRV_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
124 {
125     BOOL ret;
126     DWORD len;
127     METARECORD *mr;
128
129     len = sizeof(METARECORD) + (count * 4); 
130     if (!(mr = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, len )))
131         return FALSE;
132
133     mr->rdSize = len / 2;
134     mr->rdFunction = func;
135     *(mr->rdParm) = count;
136     memcpy(mr->rdParm + 1, pt, count * 4);
137     ret = MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
138     HeapFree( SystemHeap, 0, mr);
139     return ret;
140 }
141
142
143 /**********************************************************************
144  *          MFDRV_Polyline
145  */
146 BOOL
147 MFDRV_Polyline( DC *dc, const POINT* pt, INT count )
148 {
149     register int i;
150     LPPOINT16   pt16;
151     BOOL16      ret;
152
153     pt16 = (LPPOINT16)xmalloc(sizeof(POINT16)*count);
154     for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
155     ret = MFDRV_MetaPoly(dc, META_POLYLINE, pt16, count); 
156
157     free(pt16);
158     return ret;
159 }
160
161
162 /**********************************************************************
163  *          MFDRV_Polygon
164  */
165 BOOL
166 MFDRV_Polygon( DC *dc, const POINT* pt, INT count )
167 {
168     register int i;
169     LPPOINT16   pt16;
170     BOOL16      ret;
171
172     pt16 = (LPPOINT16)xmalloc(sizeof(POINT16)*count);
173     for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
174     ret = MFDRV_MetaPoly(dc, META_POLYGON, pt16, count); 
175
176     free(pt16);
177     return ret;
178 }
179
180
181 /**********************************************************************
182  *          MFDRV_PolyPolygon
183  */
184 BOOL 
185 MFDRV_PolyPolygon( DC *dc, const POINT* pt, const INT* counts, UINT polygons)
186 {
187     int         i,j;
188     LPPOINT16   pt16;
189     const POINT* curpt=pt;
190     BOOL        ret;
191
192     for (i=0;i<polygons;i++) {
193         pt16=(LPPOINT16)xmalloc(sizeof(POINT16)*counts[i]);
194         for (j=counts[i];j--;) CONV_POINT32TO16(&(curpt[j]),&(pt16[j]));
195         ret = MFDRV_MetaPoly(dc, META_POLYGON, pt16, counts[i]);
196         free(pt16);
197         if (!ret)
198             return FALSE;
199         curpt+=counts[i];
200     }
201     return TRUE;
202 }
203
204
205 /**********************************************************************
206  *          MFDRV_ExtFloodFill
207  */
208 BOOL 
209 MFDRV_ExtFloodFill( DC *dc, INT x, INT y, COLORREF color, UINT fillType )
210 {
211     return MFDRV_MetaParam4(dc,META_FLOODFILL,x,y,HIWORD(color),
212                             LOWORD(color)); 
213 }
214
215
216 /******************************************************************
217  *         MFDRV_CreateRegion
218  *
219  * For explanation of the format of the record see MF_Play_MetaCreateRegion in
220  * objects/metafile.c 
221  */
222 static INT16 MFDRV_CreateRegion(DC *dc, HRGN hrgn)
223 {
224     DWORD len;
225     METARECORD *mr;
226     RGNDATA *rgndata;
227     RECT *pCurRect, *pEndRect;
228     WORD Bands = 0, MaxBands = 0;
229     WORD *Param, *StartBand;
230     BOOL ret;
231
232     len = GetRegionData( hrgn, 0, NULL );
233     if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
234         WARN(metafile, "Can't alloc rgndata buffer\n");
235         return -1;
236     }
237     GetRegionData( hrgn, len, rgndata );
238
239     /* Overestimate of length:
240      * Assume every rect is a separate band -> 6 WORDs per rect
241      */
242     len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
243     if( !(mr = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, len )) ) {
244         WARN(metafile, "Can't alloc METARECORD buffer\n");
245         HeapFree( SystemHeap, 0, rgndata );
246         return -1;
247     }
248
249     Param = mr->rdParm + 11;
250     StartBand = NULL;
251
252     pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
253     for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
254     {
255         if( StartBand && pCurRect->top == *(StartBand + 1) )
256         {
257             *Param++ = pCurRect->left;
258             *Param++ = pCurRect->right;
259         }
260         else
261         {
262             if(StartBand)
263             {
264                 *StartBand = Param - StartBand - 3;
265                 *Param++ = *StartBand;
266                 if(*StartBand > MaxBands)
267                     MaxBands = *StartBand;
268                 Bands++;
269             }
270             StartBand = Param++;
271             *Param++ = pCurRect->top;
272             *Param++ = pCurRect->bottom;
273             *Param++ = pCurRect->left;
274             *Param++ = pCurRect->right;
275         }
276     }
277     len = Param - (WORD *)mr;
278     
279     mr->rdParm[0] = 0;
280     mr->rdParm[1] = 6;
281     mr->rdParm[2] = 0x1234;
282     mr->rdParm[3] = 0;
283     mr->rdParm[4] = len * 2;
284     mr->rdParm[5] = Bands;
285     mr->rdParm[6] = MaxBands;
286     mr->rdParm[7] = rgndata->rdh.rcBound.left;
287     mr->rdParm[8] = rgndata->rdh.rcBound.top;
288     mr->rdParm[9] = rgndata->rdh.rcBound.right;
289     mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
290     mr->rdFunction = META_CREATEREGION;
291     mr->rdSize = len / 2;
292     ret = MFDRV_WriteRecord( dc, mr, mr->rdSize * 2 );  
293     HeapFree( SystemHeap, 0, mr );
294     HeapFree( SystemHeap, 0, rgndata );
295     if(!ret) 
296     {
297         WARN(metafile, "MFDRV_WriteRecord failed\n");
298         return -1;
299     }
300     return MFDRV_AddHandleDC( dc );
301 }
302
303
304 /**********************************************************************
305  *          MFDRV_PaintRgn
306  */
307 BOOL
308 MFDRV_PaintRgn( DC *dc, HRGN hrgn )
309 {
310     INT16 index;
311     index = MFDRV_CreateRegion( dc, hrgn );
312     if(index == -1)
313         return FALSE;
314     return MFDRV_MetaParam1( dc, META_PAINTREGION, index );
315 }
316
317
318 /**********************************************************************
319  *          MFDRV_SetBkColor
320  */
321 COLORREF
322 MFDRV_SetBkColor( DC *dc, COLORREF color )
323 {
324     return MFDRV_MetaParam2(dc, META_SETBKCOLOR, HIWORD(color), LOWORD(color));
325 }
326
327
328 /**********************************************************************
329  *          MFDRV_SetTextColor
330  */
331 COLORREF
332 MFDRV_SetTextColor( DC *dc, COLORREF color )
333 {
334     return MFDRV_MetaParam2(dc, META_SETTEXTCOLOR, HIWORD(color),
335                             LOWORD(color));
336 }
337