[Gdi32]
[reactos.git] / reactos / win32ss / gdi / gdi32 / wine / 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., 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 }