Release 940518
[wine/multimedia.git] / windows / graphics.c
bloba80d5cf63b893ee79938435b55944019de261cbf
1 /*
2 * GDI graphics operations
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <math.h>
10 #include <stdlib.h>
11 #include <X11/Xlib.h>
12 #include <X11/Xutil.h>
13 #include <X11/Intrinsic.h>
14 #ifndef PI
15 #define PI M_PI
16 #endif
18 #include "gdi.h"
19 #include "syscolor.h"
21 extern int COLOR_ToPhysical( DC *dc, COLORREF color );
23 /***********************************************************************
24 * LineTo (GDI.19)
26 BOOL LineTo( HDC hdc, short x, short y )
28 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
29 if (!dc)
31 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
32 if (!dc) return FALSE;
33 MF_MetaParam2(dc, META_LINETO, x, y);
34 return TRUE;
37 if (DC_SetupGCForPen( dc ))
38 XDrawLine(XT_display, dc->u.x.drawable, dc->u.x.gc,
39 dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
40 dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
41 dc->w.DCOrgX + XLPTODP( dc, x ),
42 dc->w.DCOrgY + YLPTODP( dc, y ) );
43 dc->w.CursPosX = x;
44 dc->w.CursPosY = y;
45 return TRUE;
49 /***********************************************************************
50 * MoveTo (GDI.20)
52 DWORD MoveTo( HDC hdc, short x, short y )
54 short oldx, oldy;
55 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
56 if (!dc)
58 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
59 if (!dc) return FALSE;
60 MF_MetaParam2(dc, META_MOVETO, x, y);
61 return 0;
64 oldx = dc->w.CursPosX;
65 oldy = dc->w.CursPosY;
66 dc->w.CursPosX = x;
67 dc->w.CursPosY = y;
68 return oldx | (oldy << 16);
72 /***********************************************************************
73 * MoveToEx (GDI.483)
75 BOOL MoveToEx( HDC hdc, short x, short y, LPPOINT pt )
77 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
78 if (!dc) return FALSE;
79 if (pt)
81 pt->x = dc->w.CursPosX;
82 pt->y = dc->w.CursPosY;
84 dc->w.CursPosX = x;
85 dc->w.CursPosY = y;
86 return TRUE;
90 /***********************************************************************
91 * GRAPH_DrawArc
93 * Helper functions for Arc(), Chord() and Pie().
94 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
96 BOOL GRAPH_DrawArc( HDC hdc, int left, int top, int right, int bottom,
97 int xstart, int ystart, int xend, int yend, int lines )
99 int xcenter, ycenter;
100 double start_angle, end_angle, diff_angle;
101 XPoint points[3];
102 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
103 if (!dc)
105 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
106 if (!dc) return FALSE;
107 switch (lines)
109 case 0:
110 MF_MetaParam8(dc, META_ARC, left, top, right, bottom,
111 xstart, ystart, xend, yend);
112 break;
114 case 1:
115 MF_MetaParam8(dc, META_CHORD, left, top, right, bottom,
116 xstart, ystart, xend, yend);
117 break;
119 case 2:
120 MF_MetaParam8(dc, META_PIE, left, top, right, bottom,
121 xstart, ystart, xend, yend);
122 break;
124 return 0;
127 left = XLPTODP( dc, left );
128 top = YLPTODP( dc, top );
129 right = XLPTODP( dc, right );
130 bottom = YLPTODP( dc, bottom );
131 xstart = XLPTODP( dc, xstart );
132 ystart = YLPTODP( dc, ystart );
133 xend = XLPTODP( dc, xend );
134 yend = YLPTODP( dc, yend );
135 if ((left == right) || (top == bottom)) return FALSE;
137 if (!DC_SetupGCForPen( dc )) return TRUE;
139 xcenter = (right + left) / 2;
140 ycenter = (bottom + top) / 2;
141 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
142 (double)(xstart-xcenter)*(bottom-top) );
143 end_angle = atan2( (double)(ycenter-yend)*(right-left),
144 (double)(xend-xcenter)*(bottom-top) );
145 diff_angle = end_angle - start_angle;
146 if (diff_angle < 0.0) diff_angle += 2*PI;
148 XDrawArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
149 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
150 right-left-1, bottom-top-1,
151 (int)(start_angle * 180 * 64 / PI),
152 (int)(diff_angle * 180 * 64 / PI) );
153 if (!lines) return TRUE;
155 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
156 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
157 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
158 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
159 if (lines == 2)
161 points[2] = points[1];
162 points[1].x = dc->w.DCOrgX + xcenter;
163 points[1].y = dc->w.DCOrgY + ycenter;
165 XDrawLines( XT_display, dc->u.x.drawable, dc->u.x.gc,
166 points, lines+1, CoordModeOrigin );
167 return TRUE;
171 /***********************************************************************
172 * Arc (GDI.23)
174 BOOL Arc( HDC hdc, int left, int top, int right, int bottom,
175 int xstart, int ystart, int xend, int yend )
177 return GRAPH_DrawArc( hdc, left, top, right, bottom,
178 xstart, ystart, xend, yend, 0 );
182 /***********************************************************************
183 * Pie (GDI.26)
185 BOOL Pie( HDC hdc, int left, int top, int right, int bottom,
186 int xstart, int ystart, int xend, int yend )
188 return GRAPH_DrawArc( hdc, left, top, right, bottom,
189 xstart, ystart, xend, yend, 2 );
193 /***********************************************************************
194 * Chord (GDI.348)
196 BOOL Chord( HDC hdc, int left, int top, int right, int bottom,
197 int xstart, int ystart, int xend, int yend )
199 return GRAPH_DrawArc( hdc, left, top, right, bottom,
200 xstart, ystart, xend, yend, 1 );
204 /***********************************************************************
205 * Ellipse (GDI.24)
207 BOOL Ellipse( HDC hdc, int left, int top, int right, int bottom )
209 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
210 if (!dc)
212 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
213 if (!dc) return FALSE;
214 MF_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
215 return 0;
218 left = XLPTODP( dc, left );
219 top = YLPTODP( dc, top );
220 right = XLPTODP( dc, right );
221 bottom = YLPTODP( dc, bottom );
222 if ((left == right) || (top == bottom)) return FALSE;
224 if (DC_SetupGCForBrush( dc ))
225 XFillArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
226 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
227 right-left-1, bottom-top-1, 0, 360*64 );
228 if (DC_SetupGCForPen( dc ))
229 XDrawArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
230 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
231 right-left-1, bottom-top-1, 0, 360*64 );
232 return TRUE;
236 /***********************************************************************
237 * Rectangle (GDI.27)
239 BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom )
241 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
242 if (!dc)
244 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
245 if (!dc) return FALSE;
246 MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
247 return TRUE;
250 left = XLPTODP( dc, left );
251 top = YLPTODP( dc, top );
252 right = XLPTODP( dc, right );
253 bottom = YLPTODP( dc, bottom );
255 if (DC_SetupGCForBrush( dc ))
256 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
257 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
258 right-left-1, bottom-top-1 );
259 if (DC_SetupGCForPen( dc ))
260 XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
261 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
262 right-left-1, bottom-top-1 );
263 return TRUE;
267 /***********************************************************************
268 * RoundRect (GDI.28)
270 BOOL RoundRect( HDC hDC, short left, short top, short right, short bottom,
271 short ell_width, short ell_height)
273 int x1, y1, x2, y2;
274 DC * dc = (DC *) GDI_GetObjPtr(hDC, DC_MAGIC);
275 if (!dc)
277 dc = (DC *)GDI_GetObjPtr(hDC, METAFILE_DC_MAGIC);
278 if (!dc) return FALSE;
279 MF_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
280 ell_width, ell_height);
281 return TRUE;
284 printf("RoundRect(%d %d %d %d %d %d\n",
285 left, top, right, bottom, ell_width, ell_height);
287 x1 = XLPTODP(dc, left);
288 y1 = YLPTODP(dc, top);
289 x2 = XLPTODP(dc, right - ell_width);
290 y2 = YLPTODP(dc, bottom - ell_height);
291 if (DC_SetupGCForBrush(dc)) {
292 XFillArc(XT_display, dc->u.x.drawable, dc->u.x.gc,
293 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
294 ell_width, ell_height, 90 * 64, 90 * 64);
295 XFillArc(XT_display, dc->u.x.drawable, dc->u.x.gc,
296 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
297 ell_width, ell_height, 180 * 64, 90 * 64);
298 XFillArc(XT_display, dc->u.x.drawable, dc->u.x.gc,
299 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
300 ell_width, ell_height, 270 * 64, 90 * 64);
301 XFillArc(XT_display, dc->u.x.drawable, dc->u.x.gc,
302 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
303 ell_width, ell_height, 0, 90 * 64);
304 ell_width /= 2; ell_height /= 2;
305 XFillRectangle(XT_display, dc->u.x.drawable, dc->u.x.gc,
306 dc->w.DCOrgX + left + ell_width, dc->w.DCOrgY + top,
307 right - left - 2 * ell_width, bottom - top);
308 XFillRectangle(XT_display, dc->u.x.drawable, dc->u.x.gc,
309 dc->w.DCOrgX + left, dc->w.DCOrgY + top + ell_height,
310 ell_width, bottom - top - 2 * ell_height);
311 XFillRectangle(XT_display, dc->u.x.drawable, dc->u.x.gc,
312 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top + ell_height,
313 ell_width, bottom - top - 2 * ell_height);
314 ell_width *= 2; ell_height *= 2;
316 if (DC_SetupGCForPen(dc)) {
317 XDrawArc(XT_display, dc->u.x.drawable, dc->u.x.gc,
318 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
319 ell_width, ell_height, 90 * 64, 90 * 64);
320 XDrawArc(XT_display, dc->u.x.drawable, dc->u.x.gc,
321 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
322 ell_width, ell_height, 180 * 64, 90 * 64);
323 XDrawArc(XT_display, dc->u.x.drawable, dc->u.x.gc,
324 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
325 ell_width, ell_height, 270 * 64, 90 * 64);
326 XDrawArc(XT_display, dc->u.x.drawable, dc->u.x.gc,
327 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
328 ell_width, ell_height, 0, 90 * 64);
330 ell_width /= 2; ell_height /= 2;
331 MoveTo(hDC, left, top + ell_height);
332 LineTo(hDC, left, bottom - ell_height);
333 MoveTo(hDC, left + ell_width, bottom);
334 LineTo(hDC, right - ell_width, bottom);
335 MoveTo(hDC, right, bottom - ell_height);
336 LineTo(hDC, right, top + ell_height);
337 MoveTo(hDC, right - ell_width, top);
338 LineTo(hDC, left + ell_width, top);
339 return TRUE;
343 /***********************************************************************
344 * FillRect (USER.81)
346 int FillRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
348 HBRUSH prevBrush;
350 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
351 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
352 PatBlt( hdc, rect->left, rect->top,
353 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
354 SelectObject( hdc, prevBrush );
355 return 1;
359 /***********************************************************************
360 * InvertRect (USER.82)
362 void InvertRect( HDC hdc, LPRECT rect )
364 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
365 PatBlt( hdc, rect->left, rect->top,
366 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
370 /***********************************************************************
371 * FrameRect (USER.83)
373 int FrameRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
375 HBRUSH prevBrush;
376 int left, top, right, bottom;
378 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
379 if (!dc) return FALSE;
381 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
382 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
384 left = XLPTODP( dc, rect->left );
385 top = YLPTODP( dc, rect->top );
386 right = XLPTODP( dc, rect->right );
387 bottom = YLPTODP( dc, rect->bottom );
389 if (DC_SetupGCForBrush( dc )) {
390 PatBlt( hdc, rect->left, rect->top, 1,
391 rect->bottom - rect->top, PATCOPY );
392 PatBlt( hdc, rect->right - 1, rect->top, 1,
393 rect->bottom - rect->top, PATCOPY );
394 PatBlt( hdc, rect->left, rect->top,
395 rect->right - rect->left, 1, PATCOPY );
396 PatBlt( hdc, rect->left, rect->bottom - 1,
397 rect->right - rect->left, 1, PATCOPY );
399 SelectObject( hdc, prevBrush );
400 return 1;
404 /***********************************************************************
405 * SetPixel (GDI.31)
407 COLORREF SetPixel( HDC hdc, short x, short y, COLORREF color )
409 int pixel;
410 PALETTEENTRY entry;
412 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
413 if (!dc)
415 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
416 if (!dc) return 0;
417 MF_MetaParam4(dc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color));
418 return 1;
421 x = dc->w.DCOrgX + XLPTODP( dc, x );
422 y = dc->w.DCOrgY + YLPTODP( dc, y );
423 pixel = COLOR_ToPhysical( dc, color );
424 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
426 XSetForeground( XT_display, dc->u.x.gc, pixel );
427 XSetFunction( XT_display, dc->u.x.gc, GXcopy );
428 XDrawPoint( XT_display, dc->u.x.drawable, dc->u.x.gc, x, y );
430 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
434 /***********************************************************************
435 * GetPixel (GDI.83)
437 COLORREF GetPixel( HDC hdc, short x, short y )
439 PALETTEENTRY entry;
440 XImage * image;
442 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
443 if (!dc) return 0;
445 x = dc->w.DCOrgX + XLPTODP( dc, x );
446 y = dc->w.DCOrgY + YLPTODP( dc, y );
447 if ((x < 0) || (y < 0)) return 0;
449 if (!(dc->w.flags & DC_MEMORY))
451 XWindowAttributes win_attr;
453 if (!XGetWindowAttributes( XT_display, dc->u.x.drawable, &win_attr ))
454 return 0;
455 if (win_attr.map_state != IsViewable) return 0;
456 if ((x >= win_attr.width) || (y >= win_attr.height)) return 0;
459 image = XGetImage( XT_display, dc->u.x.drawable, x, y,
460 1, 1, AllPlanes, ZPixmap );
461 GetPaletteEntries( dc->w.hPalette, XGetPixel( image, 0, 0 ), 1, &entry );
462 XDestroyImage( image );
463 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
467 /***********************************************************************
468 * PaintRgn (GDI.43)
470 BOOL PaintRgn( HDC hdc, HRGN hrgn )
472 RECT box;
473 HRGN tmpVisRgn, prevVisRgn;
474 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
475 if (!dc) return FALSE;
477 /* Modify visible region */
479 prevVisRgn = SaveVisRgn( hdc );
480 if (prevVisRgn)
482 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 )))
484 RestoreVisRgn( hdc );
485 return FALSE;
487 CombineRgn( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
488 SelectVisRgn( hdc, tmpVisRgn );
489 DeleteObject( tmpVisRgn );
491 else SelectVisRgn( hdc, hrgn );
493 /* Fill the region */
495 GetClipBox( hdc, &box );
496 if (DC_SetupGCForBrush( dc ))
497 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
498 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
499 box.right-box.left, box.bottom-box.top );
501 /* Restore the visible region */
503 if (prevVisRgn) RestoreVisRgn( hdc );
504 else SelectVisRgn( hdc, 0 );
505 return TRUE;
509 /***********************************************************************
510 * FillRgn (GDI.40)
512 BOOL FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
514 BOOL retval;
515 HBRUSH prevBrush = SelectObject( hdc, hbrush );
516 if (!prevBrush) return FALSE;
517 retval = PaintRgn( hdc, hrgn );
518 SelectObject( hdc, prevBrush );
519 return retval;
523 /***********************************************************************
524 * DrawFocusRect (USER.466)
526 void DrawFocusRect( HDC hdc, LPRECT rc )
528 HPEN hOldPen;
529 int oldDrawMode, oldBkMode;
530 int left, top, right, bottom;
531 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
532 if (!dc) return;
534 left = XLPTODP( dc, rc->left );
535 top = YLPTODP( dc, rc->top );
536 right = XLPTODP( dc, rc->right );
537 bottom = YLPTODP( dc, rc->bottom );
539 hOldPen = (HPEN)SelectObject(hdc, sysColorObjects.hpenWindowText );
540 oldDrawMode = SetROP2(hdc, R2_XORPEN);
541 oldBkMode = SetBkMode(hdc, TRANSPARENT);
543 if (DC_SetupGCForPen( dc ))
544 XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
545 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
546 right-left-1, bottom-top-1 );
548 SetBkMode(hdc, oldBkMode);
549 SetROP2(hdc, oldDrawMode);
550 SelectObject(hdc, (HANDLE)hOldPen);
554 /**********************************************************************
555 * DrawReliefRect (Not a MSWin Call)
557 void DrawReliefRect( HDC hdc, RECT rect, int thickness, BOOL pressed )
559 HBRUSH hbrushOld;
560 int i;
562 hbrushOld = SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnShadow :
563 sysColorObjects.hbrushBtnHighlight );
564 for (i = 0; i < thickness; i++)
566 PatBlt( hdc, rect.left + i, rect.top,
567 1, rect.bottom - rect.top - i, PATCOPY );
568 PatBlt( hdc, rect.left, rect.top + i,
569 rect.right - rect.left - i, 1, PATCOPY );
572 SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
573 sysColorObjects.hbrushBtnShadow );
574 for (i = 0; i < thickness; i++)
576 PatBlt( hdc, rect.right - i - 1, rect.top + i,
577 1, rect.bottom - rect.top - i, PATCOPY );
578 PatBlt( hdc, rect.left + i, rect.bottom - i - 1,
579 rect.right - rect.left - i, 1, PATCOPY );
582 SelectObject( hdc, hbrushOld );
586 /**********************************************************************
587 * Polyline (GDI.37)
589 BOOL Polyline (HDC hdc, LPPOINT pt, int count)
591 register int i;
592 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
593 if (!dc)
595 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
596 if (!dc) return FALSE;
597 MF_MetaPoly(dc, META_POLYLINE, pt, count);
598 return TRUE;
601 if (DC_SetupGCForPen( dc ))
603 for (i = 0; i < count-1; i ++)
604 XDrawLine (XT_display, dc->u.x.drawable, dc->u.x.gc,
605 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
606 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
607 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
608 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
609 XDrawLine (XT_display, dc->u.x.drawable, dc->u.x.gc,
610 dc->w.DCOrgX + XLPTODP(dc, pt [count-1].x),
611 dc->w.DCOrgY + YLPTODP(dc, pt [count-1].y),
612 dc->w.DCOrgX + XLPTODP(dc, pt [0].x),
613 dc->w.DCOrgY + YLPTODP(dc, pt [0].y));
616 return (TRUE);
620 /**********************************************************************
621 * Polygon (GDI.36)
623 BOOL Polygon (HDC hdc, LPPOINT pt, int count)
625 register int i;
626 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
627 XPoint *points = (XPoint *) malloc (sizeof (XPoint) * count+1);
629 if (!dc)
631 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
632 if (!dc) return FALSE;
633 MF_MetaPoly(dc, META_POLYGON, pt, count);
634 return TRUE;
637 if (DC_SetupGCForBrush( dc ))
640 for (i = 0; i < count; i++)
642 points [i].x = dc->w.DCOrgX + XLPTODP(dc, pt [i].x);
643 points [i].y = dc->w.DCOrgY + YLPTODP(dc, pt [i].y);
645 points [count] = points [0];
647 XFillPolygon( XT_display, dc->u.x.drawable, dc->u.x.gc,
648 points, count, Complex, CoordModeOrigin);
650 if (DC_SetupGCForPen ( dc ))
652 XDrawLines( XT_display, dc->u.x.drawable, dc->u.x.gc,
653 points, count, CoordModeOrigin );
656 free ((void *) points);
657 return (TRUE);
660 /**********************************************************************
661 * FloodFill_rec -- FloodFill helper function
663 * Just does a recursive flood fill:
664 * this is /not/ efficent -- a better way would be to draw
665 * an entire line at a time, but this will do for now.
667 static BOOL FloodFill_rec(XImage *image, int x, int y,
668 int orgx, int orgy, int endx, int endy,
669 Pixel borderp, Pixel fillp)
671 Pixel testp;
673 if (x > endx || x < orgx || y > endy || y < orgy)
674 return FALSE;
675 XPutPixel(image, x, y, fillp);
677 testp = XGetPixel(image, x+1, y+1);
678 if (testp != borderp && testp != fillp)
679 FloodFill_rec(image, x+1, y+1, orgx, orgy,
680 endx, endy, borderp, fillp);
682 testp = XGetPixel(image, x+1, y-1);
683 if (testp != borderp && testp != fillp)
684 FloodFill_rec(image, x+1, y-1, orgx, orgy,
685 endx, endy, borderp, fillp);
686 testp = XGetPixel(image, x-1, y+1);
687 if (testp != borderp && testp != fillp)
688 FloodFill_rec(image, x-1, y+1, orgx, orgy,
689 endx, endy, borderp, fillp);
690 testp = XGetPixel(image, x-1, y-1);
691 if (testp != borderp && testp != fillp)
692 FloodFill_rec(image, x-1, y-1, orgx, orgy,
693 endx, endy, borderp, fillp);
694 return TRUE;
698 /**********************************************************************
699 * FloodFill (GDI.25)
701 BOOL FloodFill(HDC hdc, short x, short y, DWORD crColor)
703 Pixel boundrypixel;
704 int imagex, imagey;
705 XImage *image;
706 DC *dc;
708 #ifdef DEBUG_GRAPHICS
709 printf("FloodFill %x %d,%d %x\n", hdc, x, y, crColor);
710 #endif
711 dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
712 if (!dc)
714 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
715 if (!dc) return FALSE;
716 MF_MetaParam4(dc, META_FLOODFILL, x, y, HIWORD(crColor),
717 LOWORD(crColor));
718 return TRUE;
721 x = dc->w.DCOrgX + XLPTODP(dc, x);
722 y = dc->w.DCOrgY + YLPTODP(dc, y);
724 if (x < dc->w.DCOrgX || x > dc->w.DCOrgX + dc->w.DCSizeX ||
725 y < dc->w.DCOrgY || y > dc->w.DCOrgY + dc->w.DCSizeY)
726 return FALSE;
728 if (!DC_SetupGCForBrush(dc))
729 return FALSE;
731 boundrypixel = GetNearestPaletteIndex( dc->w.hPalette, crColor );
733 image = XGetImage(display, dc->u.x.drawable,
734 dc->w.DCOrgX, dc->w.DCOrgY,
735 dc->w.DCSizeX, dc->w.DCSizeY, AllPlanes, ZPixmap);
736 if (XGetPixel(image, x, y) == boundrypixel)
737 return FALSE;
738 if (!FloodFill_rec(image, x, y,
739 0, 0,
740 dc->w.DCOrgX + dc->w.DCSizeX,
741 dc->w.DCOrgY + dc->w.DCSizeY,
742 boundrypixel, dc->u.x.brush.pixel)) {
743 XDestroyImage(image);
744 return FALSE;
747 XPutImage(display, dc->u.x.drawable, dc->u.x.gc, image,
748 0, 0,
749 dc->w.DCOrgX, dc->w.DCOrgY,
750 dc->w.DCSizeX, dc->w.DCSizeY);
751 XDestroyImage(image);
753 return TRUE;