push 5b1efc32b5a8acb1d5b5e60584746392dd0c436e
[wine/hacks.git] / dlls / gdi32 / mfdrv / graphics.c
blobe2cc6eb6674fb34cc09d562def51926b730349d1
1 /*
2 * Metafile driver graphics functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "mfdrv/metafiledrv.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
33 /**********************************************************************
34 * MFDRV_MoveTo
36 BOOL CDECL
37 MFDRV_MoveTo(PHYSDEV dev, INT x, INT y)
39 return MFDRV_MetaParam2(dev,META_MOVETO,x,y);
42 /***********************************************************************
43 * MFDRV_LineTo
45 BOOL CDECL
46 MFDRV_LineTo( PHYSDEV dev, INT x, INT y )
48 return MFDRV_MetaParam2(dev, META_LINETO, x, y);
52 /***********************************************************************
53 * MFDRV_Arc
55 BOOL CDECL
56 MFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
57 INT xstart, INT ystart, INT xend, INT yend )
59 return MFDRV_MetaParam8(dev, META_ARC, left, top, right, bottom,
60 xstart, ystart, xend, yend);
64 /***********************************************************************
65 * MFDRV_Pie
67 BOOL CDECL
68 MFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
69 INT xstart, INT ystart, INT xend, INT yend )
71 return MFDRV_MetaParam8(dev, META_PIE, left, top, right, bottom,
72 xstart, ystart, xend, yend);
76 /***********************************************************************
77 * MFDRV_Chord
79 BOOL CDECL
80 MFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
81 INT xstart, INT ystart, INT xend, INT yend )
83 return MFDRV_MetaParam8(dev, META_CHORD, left, top, right, bottom,
84 xstart, ystart, xend, yend);
87 /***********************************************************************
88 * MFDRV_Ellipse
90 BOOL CDECL
91 MFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
93 return MFDRV_MetaParam4(dev, META_ELLIPSE, left, top, right, bottom);
96 /***********************************************************************
97 * MFDRV_Rectangle
99 BOOL CDECL
100 MFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom)
102 return MFDRV_MetaParam4(dev, META_RECTANGLE, left, top, right, bottom);
105 /***********************************************************************
106 * MFDRV_RoundRect
108 BOOL CDECL
109 MFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right,
110 INT bottom, INT ell_width, INT ell_height )
112 return MFDRV_MetaParam6(dev, META_ROUNDRECT, left, top, right, bottom,
113 ell_width, ell_height);
116 /***********************************************************************
117 * MFDRV_SetPixel
119 COLORREF CDECL
120 MFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
122 return MFDRV_MetaParam4(dev, META_SETPIXEL, x, y,HIWORD(color),
123 LOWORD(color));
127 /******************************************************************
128 * MFDRV_MetaPoly - implements Polygon and Polyline
130 static BOOL MFDRV_MetaPoly(PHYSDEV dev, short func, POINTS *pt, short count)
132 BOOL ret;
133 DWORD len;
134 METARECORD *mr;
136 len = sizeof(METARECORD) + (count * 4);
137 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )))
138 return FALSE;
140 mr->rdSize = len / 2;
141 mr->rdFunction = func;
142 *(mr->rdParm) = count;
143 memcpy(mr->rdParm + 1, pt, count * 4);
144 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
145 HeapFree( GetProcessHeap(), 0, mr);
146 return ret;
150 /**********************************************************************
151 * MFDRV_Polyline
153 BOOL CDECL
154 MFDRV_Polyline( PHYSDEV dev, const POINT* pt, INT count )
156 int i;
157 POINTS *pts;
158 BOOL ret;
160 pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS)*count );
161 if(!pts) return FALSE;
162 for (i=count;i--;)
164 pts[i].x = pt[i].x;
165 pts[i].y = pt[i].y;
167 ret = MFDRV_MetaPoly(dev, META_POLYLINE, pts, count);
169 HeapFree( GetProcessHeap(), 0, pts );
170 return ret;
174 /**********************************************************************
175 * MFDRV_Polygon
177 BOOL CDECL
178 MFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count )
180 int i;
181 POINTS *pts;
182 BOOL ret;
184 pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS)*count );
185 if(!pts) return FALSE;
186 for (i=count;i--;)
188 pts[i].x = pt[i].x;
189 pts[i].y = pt[i].y;
191 ret = MFDRV_MetaPoly(dev, META_POLYGON, pts, count);
193 HeapFree( GetProcessHeap(), 0, pts );
194 return ret;
198 /**********************************************************************
199 * MFDRV_PolyPolygon
201 BOOL CDECL
202 MFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polygons)
204 BOOL ret;
205 DWORD len;
206 METARECORD *mr;
207 unsigned int i,j;
208 POINTS *pts;
209 INT16 totalpoint16 = 0;
210 INT16 * pointcounts;
212 for (i=0;i<polygons;i++) {
213 totalpoint16 += counts[i];
216 /* allocate space for all points */
217 pts=HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * totalpoint16 );
218 pointcounts = HeapAlloc( GetProcessHeap(), 0, sizeof(INT16) * totalpoint16 );
220 /* copy point counts */
221 for (i=0;i<polygons;i++) {
222 pointcounts[i] = counts[i];
225 /* convert all points */
226 for (j = totalpoint16; j--;){
227 pts[j].x = pt[j].x;
228 pts[j].y = pt[j].y;
231 len = sizeof(METARECORD) + sizeof(WORD) + polygons*sizeof(INT16) + totalpoint16*sizeof(*pts);
233 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) {
234 HeapFree( GetProcessHeap(), 0, pts );
235 HeapFree( GetProcessHeap(), 0, pointcounts );
236 return FALSE;
239 mr->rdSize = len /2;
240 mr->rdFunction = META_POLYPOLYGON;
241 *(mr->rdParm) = polygons;
242 memcpy(mr->rdParm + 1, pointcounts, polygons*sizeof(INT16));
243 memcpy(mr->rdParm + 1+polygons, pts , totalpoint16*sizeof(*pts));
244 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
246 HeapFree( GetProcessHeap(), 0, pts );
247 HeapFree( GetProcessHeap(), 0, pointcounts );
248 HeapFree( GetProcessHeap(), 0, mr);
249 return ret;
253 /**********************************************************************
254 * MFDRV_ExtFloodFill
256 BOOL CDECL
257 MFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType )
259 return MFDRV_MetaParam4(dev,META_FLOODFILL,x,y,HIWORD(color),
260 LOWORD(color));
264 /******************************************************************
265 * MFDRV_CreateRegion
267 * For explanation of the format of the record see MF_Play_MetaCreateRegion in
268 * objects/metafile.c
270 static INT16 MFDRV_CreateRegion(PHYSDEV dev, HRGN hrgn)
272 DWORD len;
273 METARECORD *mr;
274 RGNDATA *rgndata;
275 RECT *pCurRect, *pEndRect;
276 WORD Bands = 0, MaxBands = 0;
277 WORD *Param, *StartBand;
278 BOOL ret;
280 if (!(len = GetRegionData( hrgn, 0, NULL ))) return -1;
281 if( !(rgndata = HeapAlloc( GetProcessHeap(), 0, len )) ) {
282 WARN("Can't alloc rgndata buffer\n");
283 return -1;
285 GetRegionData( hrgn, len, rgndata );
287 /* Overestimate of length:
288 * Assume every rect is a separate band -> 6 WORDs per rect
290 len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
291 if( !(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )) ) {
292 WARN("Can't alloc METARECORD buffer\n");
293 HeapFree( GetProcessHeap(), 0, rgndata );
294 return -1;
297 Param = mr->rdParm + 11;
298 StartBand = NULL;
300 pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
301 for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
303 if( StartBand && pCurRect->top == *(StartBand + 1) )
305 *Param++ = pCurRect->left;
306 *Param++ = pCurRect->right;
308 else
310 if(StartBand)
312 *StartBand = Param - StartBand - 3;
313 *Param++ = *StartBand;
314 if(*StartBand > MaxBands)
315 MaxBands = *StartBand;
316 Bands++;
318 StartBand = Param++;
319 *Param++ = pCurRect->top;
320 *Param++ = pCurRect->bottom;
321 *Param++ = pCurRect->left;
322 *Param++ = pCurRect->right;
325 len = Param - (WORD *)mr;
327 mr->rdParm[0] = 0;
328 mr->rdParm[1] = 6;
329 mr->rdParm[2] = 0x1234;
330 mr->rdParm[3] = 0;
331 mr->rdParm[4] = len * 2;
332 mr->rdParm[5] = Bands;
333 mr->rdParm[6] = MaxBands;
334 mr->rdParm[7] = rgndata->rdh.rcBound.left;
335 mr->rdParm[8] = rgndata->rdh.rcBound.top;
336 mr->rdParm[9] = rgndata->rdh.rcBound.right;
337 mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
338 mr->rdFunction = META_CREATEREGION;
339 mr->rdSize = len / 2;
340 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 );
341 HeapFree( GetProcessHeap(), 0, mr );
342 HeapFree( GetProcessHeap(), 0, rgndata );
343 if(!ret)
345 WARN("MFDRV_WriteRecord failed\n");
346 return -1;
348 return MFDRV_AddHandle( dev, hrgn );
352 /**********************************************************************
353 * MFDRV_PaintRgn
355 BOOL CDECL
356 MFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn )
358 INT16 index;
359 index = MFDRV_CreateRegion( dev, hrgn );
360 if(index == -1)
361 return FALSE;
362 return MFDRV_MetaParam1( dev, META_PAINTREGION, index );
366 /**********************************************************************
367 * MFDRV_InvertRgn
369 BOOL CDECL
370 MFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn )
372 INT16 index;
373 index = MFDRV_CreateRegion( dev, hrgn );
374 if(index == -1)
375 return FALSE;
376 return MFDRV_MetaParam1( dev, META_INVERTREGION, index );
380 /**********************************************************************
381 * MFDRV_FillRgn
383 BOOL CDECL
384 MFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush )
386 INT16 iRgn, iBrush;
387 iRgn = MFDRV_CreateRegion( dev, hrgn );
388 if(iRgn == -1)
389 return FALSE;
390 iBrush = MFDRV_CreateBrushIndirect( dev, hbrush );
391 if(!iBrush)
392 return FALSE;
393 return MFDRV_MetaParam2( dev, META_FILLREGION, iRgn, iBrush );
396 /**********************************************************************
397 * MFDRV_FrameRgn
399 BOOL CDECL
400 MFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT x, INT y )
402 INT16 iRgn, iBrush;
403 iRgn = MFDRV_CreateRegion( dev, hrgn );
404 if(iRgn == -1)
405 return FALSE;
406 iBrush = MFDRV_CreateBrushIndirect( dev, hbrush );
407 if(!iBrush)
408 return FALSE;
409 return MFDRV_MetaParam4( dev, META_FRAMEREGION, iRgn, iBrush, x, y );
413 /**********************************************************************
414 * MFDRV_ExtSelectClipRgn
416 INT CDECL MFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode )
418 INT16 iRgn;
419 INT ret;
421 if (mode != RGN_COPY) return ERROR;
422 if (!hrgn) return NULLREGION;
423 iRgn = MFDRV_CreateRegion( dev, hrgn );
424 if(iRgn == -1) return ERROR;
425 ret = MFDRV_MetaParam1( dev, META_SELECTCLIPREGION, iRgn ) ? NULLREGION : ERROR;
426 MFDRV_MetaParam1( dev, META_DELETEOBJECT, iRgn );
427 MFDRV_RemoveHandle( dev, iRgn );
428 return ret;
432 /**********************************************************************
433 * MFDRV_SetBkColor
435 COLORREF CDECL
436 MFDRV_SetBkColor( PHYSDEV dev, COLORREF color )
438 return MFDRV_MetaParam2(dev, META_SETBKCOLOR, HIWORD(color),
439 LOWORD(color)) ? color : CLR_INVALID;
443 /**********************************************************************
444 * MFDRV_SetTextColor
446 COLORREF CDECL
447 MFDRV_SetTextColor( PHYSDEV dev, COLORREF color )
449 return MFDRV_MetaParam2(dev, META_SETTEXTCOLOR, HIWORD(color),
450 LOWORD(color)) ? color : CLR_INVALID;
454 /**********************************************************************
455 * MFDRV_PolyBezier
456 * Since MetaFiles don't record Beziers and they don't even record
457 * approximations to them using lines, we need this stub function.
459 BOOL CDECL
460 MFDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count )
462 return FALSE;
465 /**********************************************************************
466 * MFDRV_PolyBezierTo
467 * Since MetaFiles don't record Beziers and they don't even record
468 * approximations to them using lines, we need this stub function.
470 BOOL CDECL
471 MFDRV_PolyBezierTo( PHYSDEV dev, const POINT *pts, DWORD count )
473 return FALSE;