graphics.c 12.3 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * Metafile driver graphics functions
 *
 * Copyright 1993, 1994 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
Alexandre Julliard's avatar
Alexandre Julliard committed
19 20
 */

21
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
22
#include <stdlib.h>
23 24
#include <string.h>

25 26 27
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
28
#include "mfdrv/metafiledrv.h"
29
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
30

31
WINE_DEFAULT_DEBUG_CHANNEL(metafile);
32

Alexandre Julliard's avatar
Alexandre Julliard committed
33
/**********************************************************************
34
 *	     MFDRV_MoveTo
Alexandre Julliard's avatar
Alexandre Julliard committed
35
 */
36
BOOL MFDRV_MoveTo(PHYSDEV dev, INT x, INT y)
Alexandre Julliard's avatar
Alexandre Julliard committed
37
{
38
    return MFDRV_MetaParam2(dev,META_MOVETO,x,y);
Alexandre Julliard's avatar
Alexandre Julliard committed
39 40 41 42 43
}

/***********************************************************************
 *           MFDRV_LineTo
 */
44
BOOL MFDRV_LineTo( PHYSDEV dev, INT x, INT y )
Alexandre Julliard's avatar
Alexandre Julliard committed
45
{
46
     return MFDRV_MetaParam2(dev, META_LINETO, x, y);
Alexandre Julliard's avatar
Alexandre Julliard committed
47 48 49 50 51 52
}


/***********************************************************************
 *           MFDRV_Arc
 */
53 54
BOOL MFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
                INT xstart, INT ystart, INT xend, INT yend )
Alexandre Julliard's avatar
Alexandre Julliard committed
55
{
56
     return MFDRV_MetaParam8(dev, META_ARC, left, top, right, bottom,
57
			     xstart, ystart, xend, yend);
Alexandre Julliard's avatar
Alexandre Julliard committed
58 59 60 61 62 63
}


/***********************************************************************
 *           MFDRV_Pie
 */
64 65
BOOL MFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
                INT xstart, INT ystart, INT xend, INT yend )
Alexandre Julliard's avatar
Alexandre Julliard committed
66
{
67
    return MFDRV_MetaParam8(dev, META_PIE, left, top, right, bottom,
68
			    xstart, ystart, xend, yend);
Alexandre Julliard's avatar
Alexandre Julliard committed
69 70 71 72 73 74
}


/***********************************************************************
 *           MFDRV_Chord
 */
75 76
BOOL MFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
                  INT xstart, INT ystart, INT xend, INT yend )
Alexandre Julliard's avatar
Alexandre Julliard committed
77
{
78
    return MFDRV_MetaParam8(dev, META_CHORD, left, top, right, bottom,
79
			    xstart, ystart, xend, yend);
Alexandre Julliard's avatar
Alexandre Julliard committed
80 81 82 83 84
}

/***********************************************************************
 *           MFDRV_Ellipse
 */
85
BOOL MFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
Alexandre Julliard's avatar
Alexandre Julliard committed
86
{
87
    return MFDRV_MetaParam4(dev, META_ELLIPSE, left, top, right, bottom);
Alexandre Julliard's avatar
Alexandre Julliard committed
88 89 90 91 92
}

/***********************************************************************
 *           MFDRV_Rectangle
 */
93
BOOL MFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom)
Alexandre Julliard's avatar
Alexandre Julliard committed
94
{
95
    return MFDRV_MetaParam4(dev, META_RECTANGLE, left, top, right, bottom);
Alexandre Julliard's avatar
Alexandre Julliard committed
96 97 98 99 100
}

/***********************************************************************
 *           MFDRV_RoundRect
 */
101 102
BOOL MFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right,
                      INT bottom, INT ell_width, INT ell_height )
Alexandre Julliard's avatar
Alexandre Julliard committed
103
{
104
    return MFDRV_MetaParam6(dev, META_ROUNDRECT, left, top, right, bottom,
105
			    ell_width, ell_height);
Alexandre Julliard's avatar
Alexandre Julliard committed
106 107 108 109 110
}

/***********************************************************************
 *           MFDRV_SetPixel
 */
111
COLORREF MFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
Alexandre Julliard's avatar
Alexandre Julliard committed
112
{
113
    return MFDRV_MetaParam4(dev, META_SETPIXEL, x, y,HIWORD(color),
114
			    LOWORD(color));
115 116 117 118 119 120
}


/******************************************************************
 *         MFDRV_MetaPoly - implements Polygon and Polyline
 */
121
static BOOL MFDRV_MetaPoly(PHYSDEV dev, short func, POINTS *pt, short count)
122 123 124 125 126
{
    BOOL ret;
    DWORD len;
    METARECORD *mr;

127
    len = sizeof(METARECORD) + (count * 4);
128
    if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )))
129 130 131 132 133 134
	return FALSE;

    mr->rdSize = len / 2;
    mr->rdFunction = func;
    *(mr->rdParm) = count;
    memcpy(mr->rdParm + 1, pt, count * 4);
135
    ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
136
    HeapFree( GetProcessHeap(), 0, mr);
137
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
138 139 140 141 142 143
}


/**********************************************************************
 *          MFDRV_Polyline
 */
144
BOOL MFDRV_Polyline( PHYSDEV dev, const POINT* pt, INT count )
Alexandre Julliard's avatar
Alexandre Julliard committed
145
{
146 147 148
    int i;
    POINTS *pts;
    BOOL ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
149

150 151
    pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS)*count );
    if(!pts) return FALSE;
152 153
    for (i=count;i--;)
    {
154 155
        pts[i].x = pt[i].x;
        pts[i].y = pt[i].y;
156
    }
157
    ret = MFDRV_MetaPoly(dev, META_POLYLINE, pts, count);
Alexandre Julliard's avatar
Alexandre Julliard committed
158

159
    HeapFree( GetProcessHeap(), 0, pts );
Alexandre Julliard's avatar
Alexandre Julliard committed
160 161 162 163 164 165 166
    return ret;
}


/**********************************************************************
 *          MFDRV_Polygon
 */
167
BOOL MFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count )
Alexandre Julliard's avatar
Alexandre Julliard committed
168
{
169 170 171
    int i;
    POINTS *pts;
    BOOL ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
172

173 174
    pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS)*count );
    if(!pts) return FALSE;
175 176
    for (i=count;i--;)
    {
177 178
        pts[i].x = pt[i].x;
        pts[i].y = pt[i].y;
179
    }
180
    ret = MFDRV_MetaPoly(dev, META_POLYGON, pts, count);
Alexandre Julliard's avatar
Alexandre Julliard committed
181

182
    HeapFree( GetProcessHeap(), 0, pts );
Alexandre Julliard's avatar
Alexandre Julliard committed
183 184 185 186 187
    return ret;
}


/**********************************************************************
188
 *          MFDRV_PolyPolygon
Alexandre Julliard's avatar
Alexandre Julliard committed
189
 */
190
BOOL MFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polygons)
Alexandre Julliard's avatar
Alexandre Julliard committed
191
{
192 193 194
    BOOL ret;
    DWORD len;
    METARECORD *mr;
195
    unsigned int i,j;
196
    POINTS *pts;
197 198 199 200 201 202 203 204
    INT16 totalpoint16 = 0;
    INT16 * pointcounts;

    for (i=0;i<polygons;i++) {
         totalpoint16 += counts[i];
    }

    /* allocate space for all points */
205
    pts=HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * totalpoint16 );
206
    pointcounts = HeapAlloc( GetProcessHeap(), 0, sizeof(INT16) * totalpoint16 );
Alexandre Julliard's avatar
Alexandre Julliard committed
207

208
    /* copy point counts */
Alexandre Julliard's avatar
Alexandre Julliard committed
209
    for (i=0;i<polygons;i++) {
210 211 212 213 214
          pointcounts[i] = counts[i];
    }

    /* convert all points */
    for (j = totalpoint16; j--;){
215 216
        pts[j].x = pt[j].x;
        pts[j].y = pt[j].y;
Alexandre Julliard's avatar
Alexandre Julliard committed
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 224 225 226 227 228 229 230
         HeapFree( GetProcessHeap(), 0, pointcounts );
         return FALSE;
    }

    mr->rdSize = len /2;
    mr->rdFunction = META_POLYPOLYGON;
    *(mr->rdParm) = polygons;
    memcpy(mr->rdParm + 1, pointcounts, polygons*sizeof(INT16));
231
    memcpy(mr->rdParm + 1+polygons, pts , totalpoint16*sizeof(*pts));
232 233
    ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);

234
    HeapFree( GetProcessHeap(), 0, pts );
235 236 237
    HeapFree( GetProcessHeap(), 0, pointcounts );
    HeapFree( GetProcessHeap(), 0, mr);
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
238 239 240 241 242 243
}


/**********************************************************************
 *          MFDRV_ExtFloodFill
 */
244
BOOL MFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType )
Alexandre Julliard's avatar
Alexandre Julliard committed
245
{
246
    return MFDRV_MetaParam4(dev,META_FLOODFILL,x,y,HIWORD(color),
247
			    LOWORD(color));
248 249 250 251 252 253 254
}


/******************************************************************
 *         MFDRV_CreateRegion
 *
 * 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 260 261 262 263 264 265 266
{
    DWORD len;
    METARECORD *mr;
    RGNDATA *rgndata;
    RECT *pCurRect, *pEndRect;
    WORD Bands = 0, MaxBands = 0;
    WORD *Param, *StartBand;
    BOOL ret;

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 271 272 273 274 275 276 277
	return -1;
    }
    GetRegionData( hrgn, len, rgndata );

    /* Overestimate of length:
     * Assume every rect is a separate band -> 6 WORDs per rect
     */
    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 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
	return -1;
    }

    Param = mr->rdParm + 11;
    StartBand = NULL;

    pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
    for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
    {
        if( StartBand && pCurRect->top == *(StartBand + 1) )
        {
	    *Param++ = pCurRect->left;
	    *Param++ = pCurRect->right;
	}
	else
	{
	    if(StartBand)
	    {
	        *StartBand = Param - StartBand - 3;
		*Param++ = *StartBand;
		if(*StartBand > MaxBands)
		    MaxBands = *StartBand;
		Bands++;
	    }
	    StartBand = Param++;
	    *Param++ = pCurRect->top;
	    *Param++ = pCurRect->bottom;
	    *Param++ = pCurRect->left;
	    *Param++ = pCurRect->right;
	}
    }
312 313 314 315 316 317 318 319 320

    if (StartBand)
    {
        *StartBand = Param - StartBand - 3;
        *Param++ = *StartBand;
        if(*StartBand > MaxBands)
            MaxBands = *StartBand;
        Bands++;
    }
321

322 323
    mr->rdParm[0] = 0;
    mr->rdParm[1] = 6;
324
    mr->rdParm[2] = 0x2f6;
325
    mr->rdParm[3] = 0;
326
    mr->rdParm[4] = (Param - &mr->rdFunction) * sizeof(WORD);
327 328 329 330 331 332 333
    mr->rdParm[5] = Bands;
    mr->rdParm[6] = MaxBands;
    mr->rdParm[7] = rgndata->rdh.rcBound.left;
    mr->rdParm[8] = rgndata->rdh.rcBound.top;
    mr->rdParm[9] = rgndata->rdh.rcBound.right;
    mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
    mr->rdFunction = META_CREATEREGION;
334
    mr->rdSize = Param - (WORD *)mr;
335
    ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 );
336 337
    HeapFree( GetProcessHeap(), 0, mr );
    HeapFree( GetProcessHeap(), 0, rgndata );
338
    if(!ret)
339
    {
340
        WARN("MFDRV_WriteRecord failed\n");
341 342
	return -1;
    }
343
    return MFDRV_AddHandle( dev, hrgn );
Alexandre Julliard's avatar
Alexandre Julliard committed
344
}
Alexandre Julliard's avatar
Alexandre Julliard committed
345 346 347 348 349


/**********************************************************************
 *          MFDRV_PaintRgn
 */
350
BOOL MFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn )
Alexandre Julliard's avatar
Alexandre Julliard committed
351 352
{
    INT16 index;
353
    index = MFDRV_CreateRegion( dev, hrgn );
Alexandre Julliard's avatar
Alexandre Julliard committed
354 355
    if(index == -1)
        return FALSE;
356
    return MFDRV_MetaParam1( dev, META_PAINTREGION, index );
Alexandre Julliard's avatar
Alexandre Julliard committed
357 358
}

Alexandre Julliard's avatar
Alexandre Julliard committed
359

360 361 362
/**********************************************************************
 *          MFDRV_InvertRgn
 */
363
BOOL MFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn )
364 365
{
    INT16 index;
366
    index = MFDRV_CreateRegion( dev, hrgn );
367 368
    if(index == -1)
        return FALSE;
369
    return MFDRV_MetaParam1( dev, META_INVERTREGION, index );
370 371 372 373 374 375
}


/**********************************************************************
 *          MFDRV_FillRgn
 */
376
BOOL MFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush )
377 378
{
    INT16 iRgn, iBrush;
379
    iRgn = MFDRV_CreateRegion( dev, hrgn );
380 381
    if(iRgn == -1)
        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 390
}

/**********************************************************************
 *          MFDRV_FrameRgn
 */
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 396
    if(iRgn == -1)
        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 406
/**********************************************************************
 *          MFDRV_ExtSelectClipRgn
 */
407
INT MFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode )
408 409
{
    INT16 iRgn;
410
    INT ret;
411

412 413
    if (mode != RGN_COPY) return ERROR;
    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 425 426 427
/**********************************************************************
 *          MFDRV_PolyBezier
 * Since MetaFiles don't record Beziers and they don't even record
 * approximations to them using lines, we need this stub function.
 */
428
BOOL MFDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count )
429 430 431 432 433 434 435 436 437
{
    return FALSE;
}

/**********************************************************************
 *          MFDRV_PolyBezierTo
 * Since MetaFiles don't record Beziers and they don't even record
 * approximations to them using lines, we need this stub function.
 */
438
BOOL MFDRV_PolyBezierTo( PHYSDEV dev, const POINT *pts, DWORD count )
439 440 441
{
    return FALSE;
}