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