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