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