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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "mfdrv/metafiledrv.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
30 /**********************************************************************
34 MFDRV_MoveTo(PHYSDEV dev, INT x, INT y)
36 return MFDRV_MetaParam2(dev,META_MOVETO,x,y);
39 /***********************************************************************
43 MFDRV_LineTo( PHYSDEV dev, INT x, INT y )
45 return MFDRV_MetaParam2(dev, META_LINETO, x, y);
49 /***********************************************************************
53 MFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
54 INT xstart, INT ystart, INT xend, INT yend )
56 return MFDRV_MetaParam8(dev, META_ARC, left, top, right, bottom,
57 xstart, ystart, xend, yend);
61 /***********************************************************************
65 MFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
66 INT xstart, INT ystart, INT xend, INT yend )
68 return MFDRV_MetaParam8(dev, META_PIE, left, top, right, bottom,
69 xstart, ystart, xend, yend);
73 /***********************************************************************
77 MFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
78 INT xstart, INT ystart, INT xend, INT yend )
80 return MFDRV_MetaParam8(dev, META_CHORD, left, top, right, bottom,
81 xstart, ystart, xend, yend);
84 /***********************************************************************
88 MFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
90 return MFDRV_MetaParam4(dev, META_ELLIPSE, left, top, right, bottom);
93 /***********************************************************************
97 MFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom)
99 return MFDRV_MetaParam4(dev, META_RECTANGLE, left, top, right, bottom);
102 /***********************************************************************
106 MFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right,
107 INT bottom, INT ell_width, INT ell_height )
109 return MFDRV_MetaParam6(dev, META_ROUNDRECT, left, top, right, bottom,
110 ell_width, ell_height);
113 /***********************************************************************
117 MFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
119 return MFDRV_MetaParam4(dev, META_SETPIXEL, x, y,HIWORD(color),
124 /******************************************************************
125 * MFDRV_MetaPoly - implements Polygon and Polyline
127 static BOOL MFDRV_MetaPoly(PHYSDEV dev, short func, LPPOINT16 pt, short count)
133 len = sizeof(METARECORD) + (count * 4);
134 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )))
137 mr->rdSize = len / 2;
138 mr->rdFunction = func;
139 *(mr->rdParm) = count;
140 memcpy(mr->rdParm + 1, pt, count * 4);
141 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
142 HeapFree( GetProcessHeap(), 0, mr);
147 /**********************************************************************
151 MFDRV_Polyline( PHYSDEV dev, const POINT* pt, INT count )
157 pt16 = (LPPOINT16)HeapAlloc( GetProcessHeap(), 0, sizeof(POINT16)*count );
158 if(!pt16) return FALSE;
159 for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
160 ret = MFDRV_MetaPoly(dev, META_POLYLINE, pt16, count);
162 HeapFree( GetProcessHeap(), 0, pt16 );
167 /**********************************************************************
171 MFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count )
177 pt16 = (LPPOINT16) HeapAlloc( GetProcessHeap(), 0, sizeof(POINT16)*count );
178 if(!pt16) return FALSE;
179 for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
180 ret = MFDRV_MetaPoly(dev, META_POLYGON, pt16, count);
182 HeapFree( GetProcessHeap(), 0, pt16 );
187 /**********************************************************************
191 MFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polygons)
198 INT16 totalpoint16 = 0;
201 for (i=0;i<polygons;i++) {
202 totalpoint16 += counts[i];
205 /* allocate space for all points */
206 pt16=(LPPOINT16)HeapAlloc( GetProcessHeap(), 0,
207 sizeof(POINT16) * totalpoint16 );
208 pointcounts = (INT16*)HeapAlloc( GetProcessHeap(), 0,
209 sizeof(INT16) * totalpoint16 );
211 /* copy point counts */
212 for (i=0;i<polygons;i++) {
213 pointcounts[i] = counts[i];
216 /* convert all points */
217 for (j = totalpoint16; j--;){
218 CONV_POINT32TO16(&(pt[j]),&(pt16[j]));
221 len = sizeof(METARECORD) + sizeof(WORD) + polygons*sizeof(INT16) + totalpoint16*sizeof(POINT16);
223 if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) {
224 HeapFree( GetProcessHeap(), 0, pt16 );
225 HeapFree( GetProcessHeap(), 0, pointcounts );
230 mr->rdFunction = META_POLYPOLYGON;
231 *(mr->rdParm) = polygons;
232 memcpy(mr->rdParm + 1, pointcounts, polygons*sizeof(INT16));
233 memcpy(mr->rdParm + 1+polygons, pt16 , totalpoint16*sizeof(POINT16));
234 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
236 HeapFree( GetProcessHeap(), 0, pt16 );
237 HeapFree( GetProcessHeap(), 0, pointcounts );
238 HeapFree( GetProcessHeap(), 0, mr);
243 /**********************************************************************
247 MFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType )
249 return MFDRV_MetaParam4(dev,META_FLOODFILL,x,y,HIWORD(color),
254 /******************************************************************
257 * For explanation of the format of the record see MF_Play_MetaCreateRegion in
260 static INT16 MFDRV_CreateRegion(PHYSDEV dev, HRGN hrgn)
265 RECT *pCurRect, *pEndRect;
266 WORD Bands = 0, MaxBands = 0;
267 WORD *Param, *StartBand;
270 if (!(len = GetRegionData( hrgn, 0, NULL ))) return -1;
271 if( !(rgndata = HeapAlloc( GetProcessHeap(), 0, len )) ) {
272 WARN("Can't alloc rgndata buffer\n");
275 GetRegionData( hrgn, len, rgndata );
277 /* Overestimate of length:
278 * Assume every rect is a separate band -> 6 WORDs per rect
280 len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
281 if( !(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )) ) {
282 WARN("Can't alloc METARECORD buffer\n");
283 HeapFree( GetProcessHeap(), 0, rgndata );
287 Param = mr->rdParm + 11;
290 pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
291 for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
293 if( StartBand && pCurRect->top == *(StartBand + 1) )
295 *Param++ = pCurRect->left;
296 *Param++ = pCurRect->right;
302 *StartBand = Param - StartBand - 3;
303 *Param++ = *StartBand;
304 if(*StartBand > MaxBands)
305 MaxBands = *StartBand;
309 *Param++ = pCurRect->top;
310 *Param++ = pCurRect->bottom;
311 *Param++ = pCurRect->left;
312 *Param++ = pCurRect->right;
315 len = Param - (WORD *)mr;
319 mr->rdParm[2] = 0x1234;
321 mr->rdParm[4] = len * 2;
322 mr->rdParm[5] = Bands;
323 mr->rdParm[6] = MaxBands;
324 mr->rdParm[7] = rgndata->rdh.rcBound.left;
325 mr->rdParm[8] = rgndata->rdh.rcBound.top;
326 mr->rdParm[9] = rgndata->rdh.rcBound.right;
327 mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
328 mr->rdFunction = META_CREATEREGION;
329 mr->rdSize = len / 2;
330 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 );
331 HeapFree( GetProcessHeap(), 0, mr );
332 HeapFree( GetProcessHeap(), 0, rgndata );
335 WARN("MFDRV_WriteRecord failed\n");
338 return MFDRV_AddHandleDC( dev );
342 /**********************************************************************
346 MFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn )
349 index = MFDRV_CreateRegion( dev, hrgn );
352 return MFDRV_MetaParam1( dev, META_PAINTREGION, index );
356 /**********************************************************************
360 MFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn )
363 index = MFDRV_CreateRegion( dev, hrgn );
366 return MFDRV_MetaParam1( dev, META_INVERTREGION, index );
370 /**********************************************************************
374 MFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush )
377 iRgn = MFDRV_CreateRegion( dev, hrgn );
380 iBrush = MFDRV_CreateBrushIndirect( dev, hbrush );
383 return MFDRV_MetaParam2( dev, META_FILLREGION, iRgn, iBrush );
386 /**********************************************************************
390 MFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT x, INT y )
393 iRgn = MFDRV_CreateRegion( dev, hrgn );
396 iBrush = MFDRV_CreateBrushIndirect( dev, hbrush );
399 return MFDRV_MetaParam4( dev, META_FRAMEREGION, iRgn, iBrush, x, y );
403 /**********************************************************************
404 * MFDRV_ExtSelectClipRgn
406 INT MFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode )
411 if (mode != RGN_COPY) return ERROR;
412 if (!hrgn) return NULLREGION;
413 iRgn = MFDRV_CreateRegion( dev, hrgn );
414 if(iRgn == -1) return ERROR;
415 ret = MFDRV_MetaParam1( dev, META_SELECTCLIPREGION, iRgn ) ? NULLREGION : ERROR;
416 MFDRV_MetaParam1( dev, META_DELETEOBJECT, iRgn );
421 /**********************************************************************
425 MFDRV_SetBkColor( PHYSDEV dev, COLORREF color )
427 return MFDRV_MetaParam2(dev, META_SETBKCOLOR, HIWORD(color),
428 LOWORD(color)) ? color : CLR_INVALID;
432 /**********************************************************************
436 MFDRV_SetTextColor( PHYSDEV dev, COLORREF color )
438 return MFDRV_MetaParam2(dev, META_SETTEXTCOLOR, HIWORD(color),
439 LOWORD(color)) ? color : CLR_INVALID;
443 /**********************************************************************
445 * Since MetaFiles don't record Beziers and they don't even record
446 * approximations to them using lines, we need this stub function.
449 MFDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count )
454 /**********************************************************************
456 * Since MetaFiles don't record Beziers and they don't even record
457 * approximations to them using lines, we need this stub function.
460 MFDRV_PolyBezierTo( PHYSDEV dev, const POINT *pts, DWORD count )