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