Fixes several bugs in gdi path handling.
[wine.git] / graphics / metafiledrv / graphics.c
blobc96e6803cc1366b958b3e1dc3376860b517d33a1
1 /*
2 * Metafile driver graphics functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
10 #include "gdi.h"
11 #include "dc.h"
12 #include "region.h"
13 #include "metafiledrv.h"
14 #include "heap.h"
15 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(metafile)
19 /**********************************************************************
20 * MFDRV_MoveToEx
22 BOOL
23 MFDRV_MoveToEx(DC *dc,INT x,INT y,LPPOINT pt)
25 return MFDRV_MetaParam2(dc,META_MOVETO,x,y);
28 /***********************************************************************
29 * MFDRV_LineTo
31 BOOL
32 MFDRV_LineTo( DC *dc, INT x, INT y )
34 return MFDRV_MetaParam2(dc, META_LINETO, x, y);
38 /***********************************************************************
39 * MFDRV_Arc
41 BOOL
42 MFDRV_Arc( DC *dc, INT left, INT top, INT right, INT bottom,
43 INT xstart, INT ystart, INT xend, INT yend )
45 return MFDRV_MetaParam8(dc, META_ARC, left, top, right, bottom,
46 xstart, ystart, xend, yend);
50 /***********************************************************************
51 * MFDRV_Pie
53 BOOL
54 MFDRV_Pie( DC *dc, INT left, INT top, INT right, INT bottom,
55 INT xstart, INT ystart, INT xend, INT yend )
57 return MFDRV_MetaParam8(dc, META_PIE, left, top, right, bottom,
58 xstart, ystart, xend, yend);
62 /***********************************************************************
63 * MFDRV_Chord
65 BOOL
66 MFDRV_Chord( DC *dc, INT left, INT top, INT right, INT bottom,
67 INT xstart, INT ystart, INT xend, INT yend )
69 return MFDRV_MetaParam8(dc, META_CHORD, left, top, right, bottom,
70 xstart, ystart, xend, yend);
73 /***********************************************************************
74 * MFDRV_Ellipse
76 BOOL
77 MFDRV_Ellipse( DC *dc, INT left, INT top, INT right, INT bottom )
79 return MFDRV_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
82 /***********************************************************************
83 * MFDRV_Rectangle
85 BOOL
86 MFDRV_Rectangle(DC *dc, INT left, INT top, INT right, INT bottom)
88 return MFDRV_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
91 /***********************************************************************
92 * MFDRV_RoundRect
94 BOOL
95 MFDRV_RoundRect( DC *dc, INT left, INT top, INT right,
96 INT bottom, INT ell_width, INT ell_height )
98 return MFDRV_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
99 ell_width, ell_height);
102 /***********************************************************************
103 * MFDRV_SetPixel
105 COLORREF
106 MFDRV_SetPixel( DC *dc, INT x, INT y, COLORREF color )
108 return MFDRV_MetaParam4(dc, META_SETPIXEL, x, y,HIWORD(color),
109 LOWORD(color));
113 /******************************************************************
114 * MFDRV_MetaPoly - implements Polygon and Polyline
116 static BOOL MFDRV_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
118 BOOL ret;
119 DWORD len;
120 METARECORD *mr;
122 len = sizeof(METARECORD) + (count * 4);
123 if (!(mr = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, len )))
124 return FALSE;
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( SystemHeap, 0, mr);
132 return ret;
136 /**********************************************************************
137 * MFDRV_Polyline
139 BOOL
140 MFDRV_Polyline( DC *dc, const POINT* pt, INT count )
142 register int i;
143 LPPOINT16 pt16;
144 BOOL16 ret;
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);
151 HeapFree( GetProcessHeap(), 0, pt16 );
152 return ret;
156 /**********************************************************************
157 * MFDRV_Polygon
159 BOOL
160 MFDRV_Polygon( DC *dc, const POINT* pt, INT count )
162 register int i;
163 LPPOINT16 pt16;
164 BOOL16 ret;
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);
171 HeapFree( GetProcessHeap(), 0, pt16 );
172 return ret;
176 /**********************************************************************
177 * MFDRV_PolyPolygon
179 BOOL
180 MFDRV_PolyPolygon( DC *dc, const POINT* pt, const INT* counts, UINT polygons)
182 int i,j;
183 LPPOINT16 pt16;
184 const POINT* curpt=pt;
185 BOOL ret;
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];
198 return TRUE;
202 /**********************************************************************
203 * MFDRV_ExtFloodFill
205 BOOL
206 MFDRV_ExtFloodFill( DC *dc, INT x, INT y, COLORREF color, UINT fillType )
208 return MFDRV_MetaParam4(dc,META_FLOODFILL,x,y,HIWORD(color),
209 LOWORD(color));
213 /******************************************************************
214 * MFDRV_CreateRegion
216 * For explanation of the format of the record see MF_Play_MetaCreateRegion in
217 * objects/metafile.c
219 static INT16 MFDRV_CreateRegion(DC *dc, HRGN hrgn)
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;
229 len = GetRegionData( hrgn, 0, NULL );
230 if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
231 WARN("Can't alloc rgndata buffer\n");
232 return -1;
234 GetRegionData( hrgn, len, rgndata );
236 /* Overestimate of length:
237 * Assume every rect is a separate band -> 6 WORDs per rect
239 len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
240 if( !(mr = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, len )) ) {
241 WARN("Can't alloc METARECORD buffer\n");
242 HeapFree( SystemHeap, 0, rgndata );
243 return -1;
246 Param = mr->rdParm + 11;
247 StartBand = NULL;
249 pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
250 for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
252 if( StartBand && pCurRect->top == *(StartBand + 1) )
254 *Param++ = pCurRect->left;
255 *Param++ = pCurRect->right;
257 else
259 if(StartBand)
261 *StartBand = Param - StartBand - 3;
262 *Param++ = *StartBand;
263 if(*StartBand > MaxBands)
264 MaxBands = *StartBand;
265 Bands++;
267 StartBand = Param++;
268 *Param++ = pCurRect->top;
269 *Param++ = pCurRect->bottom;
270 *Param++ = pCurRect->left;
271 *Param++ = pCurRect->right;
274 len = Param - (WORD *)mr;
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( SystemHeap, 0, mr );
291 HeapFree( SystemHeap, 0, rgndata );
292 if(!ret)
294 WARN("MFDRV_WriteRecord failed\n");
295 return -1;
297 return MFDRV_AddHandleDC( dc );
301 /**********************************************************************
302 * MFDRV_PaintRgn
304 BOOL
305 MFDRV_PaintRgn( DC *dc, HRGN hrgn )
307 INT16 index;
308 index = MFDRV_CreateRegion( dc, hrgn );
309 if(index == -1)
310 return FALSE;
311 return MFDRV_MetaParam1( dc, META_PAINTREGION, index );
315 /**********************************************************************
316 * MFDRV_InvertRgn
318 BOOL
319 MFDRV_InvertRgn( DC *dc, HRGN hrgn )
321 INT16 index;
322 index = MFDRV_CreateRegion( dc, hrgn );
323 if(index == -1)
324 return FALSE;
325 return MFDRV_MetaParam1( dc, META_INVERTREGION, index );
329 /**********************************************************************
330 * MFDRV_FillRgn
332 BOOL
333 MFDRV_FillRgn( DC *dc, HRGN hrgn, HBRUSH hbrush )
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 );
345 /**********************************************************************
346 * MFDRV_FrameRgn
348 BOOL
349 MFDRV_FrameRgn( DC *dc, HRGN hrgn, HBRUSH hbrush, INT x, INT y )
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 );
362 /**********************************************************************
363 * MFDRV_SetBkColor
365 COLORREF
366 MFDRV_SetBkColor( DC *dc, COLORREF color )
368 return MFDRV_MetaParam2(dc, META_SETBKCOLOR, HIWORD(color), LOWORD(color));
372 /**********************************************************************
373 * MFDRV_SetTextColor
375 COLORREF
376 MFDRV_SetTextColor( DC *dc, COLORREF color )
378 return MFDRV_MetaParam2(dc, META_SETTEXTCOLOR, HIWORD(color),
379 LOWORD(color));