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