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