Release 980301
[wine/hacks.git] / graphics / x11drv / graphics.c
blob091829ec2018c4c7d1704b699914f8330848e8fe
1 /*
2 * X11 graphics driver graphics functions
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include <math.h>
8 #if defined(__EMX__)
9 #include <float.h>
10 #endif
11 #include <stdlib.h>
12 #include "ts_xlib.h"
13 #include "ts_xutil.h"
14 #include <X11/Intrinsic.h>
15 #ifndef PI
16 #define PI M_PI
17 #endif
18 #include <string.h>
20 #include "x11drv.h"
21 #include "bitmap.h"
22 #include "gdi.h"
23 #include "graphics.h"
24 #include "dc.h"
25 #include "bitmap.h"
26 #include "callback.h"
27 #include "metafile.h"
28 #include "palette.h"
29 #include "color.h"
30 #include "region.h"
31 #include "struct32.h"
32 #include "debug.h"
33 #include "xmalloc.h"
36 /**********************************************************************
37 * X11DRV_MoveToEx
39 BOOL32
40 X11DRV_MoveToEx(DC *dc,INT32 x,INT32 y,LPPOINT32 pt) {
41 if (pt)
43 pt->x = dc->w.CursPosX;
44 pt->y = dc->w.CursPosY;
46 dc->w.CursPosX = x;
47 dc->w.CursPosY = y;
48 return TRUE;
51 /***********************************************************************
52 * X11DRV_LineTo
54 BOOL32
55 X11DRV_LineTo( DC *dc, INT32 x, INT32 y )
57 if (DC_SetupGCForPen( dc ))
58 TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
59 dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
60 dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
61 dc->w.DCOrgX + XLPTODP( dc, x ),
62 dc->w.DCOrgY + YLPTODP( dc, y ) );
63 dc->w.CursPosX = x;
64 dc->w.CursPosY = y;
65 return TRUE;
70 /***********************************************************************
71 * GRAPH_DrawArc
73 * Helper functions for Arc(), Chord() and Pie().
74 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
76 static BOOL32
77 X11DRV_DrawArc( DC *dc, INT32 left, INT32 top, INT32 right,
78 INT32 bottom, INT32 xstart, INT32 ystart,
79 INT32 xend, INT32 yend, INT32 lines )
81 INT32 xcenter, ycenter, istart_angle, idiff_angle, tmp;
82 double start_angle, end_angle;
83 XPoint points[3];
85 left = XLPTODP( dc, left );
86 top = YLPTODP( dc, top );
87 right = XLPTODP( dc, right );
88 bottom = YLPTODP( dc, bottom );
89 xstart = XLPTODP( dc, xstart );
90 ystart = YLPTODP( dc, ystart );
91 xend = XLPTODP( dc, xend );
92 yend = YLPTODP( dc, yend );
93 if ((left == right) || (top == bottom)) return FALSE;
95 xcenter = (right + left) / 2;
96 ycenter = (bottom + top) / 2;
97 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
98 (double)(xstart-xcenter)*(bottom-top) );
99 end_angle = atan2( (double)(ycenter-yend)*(right-left),
100 (double)(xend-xcenter)*(bottom-top) );
101 istart_angle = (INT32)(start_angle * 180 * 64 / PI);
102 idiff_angle = (INT32)((end_angle - start_angle) * 180 * 64 / PI );
103 if (idiff_angle <= 0) idiff_angle += 360 * 64;
104 if (left > right) { tmp=left; left=right; right=tmp; }
105 if (top > bottom) { tmp=top; top=bottom; bottom=tmp; }
107 /* Fill arc with brush if Chord() or Pie() */
109 if ((lines > 0) && DC_SetupGCForBrush( dc ))
111 TSXSetArcMode( display, dc->u.x.gc, (lines==1) ? ArcChord : ArcPieSlice);
112 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
113 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
114 right-left-1, bottom-top-1, istart_angle, idiff_angle );
117 /* Draw arc and lines */
119 if (!DC_SetupGCForPen( dc )) return TRUE;
120 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
121 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
122 right-left-1, bottom-top-1, istart_angle, idiff_angle );
123 if (!lines) return TRUE;
125 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
126 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
127 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
128 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
129 if (lines == 2)
131 points[2] = points[1];
132 points[1].x = dc->w.DCOrgX + xcenter;
133 points[1].y = dc->w.DCOrgY + ycenter;
135 TSXDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
136 points, lines+1, CoordModeOrigin );
137 return TRUE;
141 /***********************************************************************
142 * X11DRV_Arc
144 BOOL32
145 X11DRV_Arc( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
146 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
148 return X11DRV_DrawArc( dc, left, top, right, bottom,
149 xstart, ystart, xend, yend, 0 );
153 /***********************************************************************
154 * X11DRV_Pie
156 BOOL32
157 X11DRV_Pie( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
158 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
160 return X11DRV_DrawArc( dc, left, top, right, bottom,
161 xstart, ystart, xend, yend, 2 );
164 /***********************************************************************
165 * X11DRV_Chord
167 BOOL32
168 X11DRV_Chord( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
169 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
171 return X11DRV_DrawArc( dc, left, top, right, bottom,
172 xstart, ystart, xend, yend, 1 );
176 /***********************************************************************
177 * X11DRV_Ellipse
179 BOOL32
180 X11DRV_Ellipse( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom )
182 left = XLPTODP( dc, left );
183 top = YLPTODP( dc, top );
184 right = XLPTODP( dc, right );
185 bottom = YLPTODP( dc, bottom );
186 if ((left == right) || (top == bottom)) return FALSE;
188 if (right < left) { INT32 tmp = right; right = left; left = tmp; }
189 if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
191 if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
192 (dc->u.x.pen.width < right-left-1) &&
193 (dc->u.x.pen.width < bottom-top-1))
195 left += dc->u.x.pen.width / 2;
196 right -= (dc->u.x.pen.width + 1) / 2;
197 top += dc->u.x.pen.width / 2;
198 bottom -= (dc->u.x.pen.width + 1) / 2;
201 if (DC_SetupGCForBrush( dc ))
202 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
203 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
204 right-left-1, bottom-top-1, 0, 360*64 );
205 if (DC_SetupGCForPen( dc ))
206 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
207 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
208 right-left-1, bottom-top-1, 0, 360*64 );
209 return TRUE;
213 /***********************************************************************
214 * X11DRV_Rectangle
216 BOOL32
217 X11DRV_Rectangle(DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom)
219 INT32 width;
220 left = XLPTODP( dc, left );
221 top = YLPTODP( dc, top );
222 right = XLPTODP( dc, right );
223 bottom = YLPTODP( dc, bottom );
225 if (right < left) { INT32 tmp = right; right = left; left = tmp; }
226 if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
228 if ((left == right) || (top == bottom))
230 if (DC_SetupGCForPen( dc ))
231 TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
232 dc->w.DCOrgX + left,
233 dc->w.DCOrgY + top,
234 dc->w.DCOrgX + right,
235 dc->w.DCOrgY + bottom);
236 return TRUE;
238 width = dc->u.x.pen.width;
239 if (!width) width = 1;
240 if(dc->u.x.pen.style == PS_NULL) width = 0;
242 if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
243 (width < right-left) && (width < bottom-top))
245 left += width / 2;
246 right -= (width + 1) / 2;
247 top += width / 2;
248 bottom -= (width + 1) / 2;
251 if ((right > left + width) && (bottom > top + width))
253 if (DC_SetupGCForBrush( dc ))
254 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
255 dc->w.DCOrgX + left + (width + 1) / 2,
256 dc->w.DCOrgY + top + (width + 1) / 2,
257 right-left-width-1, bottom-top-width-1);
259 if (DC_SetupGCForPen( dc ))
260 TSXDrawRectangle( 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;
266 /***********************************************************************
267 * X11DRV_RoundRect
269 BOOL32
270 X11DRV_RoundRect( DC *dc, INT32 left, INT32 top, INT32 right,
271 INT32 bottom, INT32 ell_width, INT32 ell_height )
273 dprintf_info(graphics, "X11DRV_RoundRect(%d %d %d %d %d %d\n",
274 left, top, right, bottom, ell_width, ell_height);
276 left = XLPTODP( dc, left );
277 top = YLPTODP( dc, top );
278 right = XLPTODP( dc, right );
279 bottom = YLPTODP( dc, bottom );
280 ell_width = abs( ell_width * dc->vportExtX / dc->wndExtX );
281 ell_height = abs( ell_height * dc->vportExtY / dc->wndExtY );
283 /* Fix the coordinates */
285 if (right < left) { INT32 tmp = right; right = left; left = tmp; }
286 if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
287 if (ell_width > right - left) ell_width = right - left;
288 if (ell_height > bottom - top) ell_height = bottom - top;
290 if (DC_SetupGCForBrush( dc ))
292 if (ell_width && ell_height)
294 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
295 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
296 ell_width, ell_height, 90 * 64, 90 * 64 );
297 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
298 dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
299 ell_width, ell_height, 180 * 64, 90 * 64 );
300 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
301 dc->w.DCOrgX + right - ell_width,
302 dc->w.DCOrgY + bottom - ell_height,
303 ell_width, ell_height, 270 * 64, 90 * 64 );
304 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
305 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
306 ell_width, ell_height, 0, 90 * 64 );
308 if (ell_width < right - left)
310 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
311 dc->w.DCOrgX + left + ell_width / 2,
312 dc->w.DCOrgY + top,
313 right - left - ell_width, ell_height / 2 );
314 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
315 dc->w.DCOrgX + left + ell_width / 2,
316 dc->w.DCOrgY + bottom - (ell_height+1) / 2,
317 right - left - ell_width, (ell_height+1) / 2 );
319 if (ell_height < bottom - top)
321 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
322 dc->w.DCOrgX + left,
323 dc->w.DCOrgY + top + ell_height / 2,
324 right - left, bottom - top - ell_height );
327 if (DC_SetupGCForPen(dc))
329 if (ell_width && ell_height)
331 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
332 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
333 ell_width, ell_height, 90 * 64, 90 * 64 );
334 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
335 dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
336 ell_width, ell_height, 180 * 64, 90 * 64 );
337 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
338 dc->w.DCOrgX + right - ell_width,
339 dc->w.DCOrgY + bottom - ell_height,
340 ell_width, ell_height, 270 * 64, 90 * 64 );
341 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
342 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
343 ell_width, ell_height, 0, 90 * 64 );
345 if (ell_width < right - left)
347 TSXDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
348 dc->w.DCOrgX + left + ell_width / 2,
349 dc->w.DCOrgY + top,
350 dc->w.DCOrgX + right - ell_width / 2,
351 dc->w.DCOrgY + top );
352 TSXDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
353 dc->w.DCOrgX + left + ell_width / 2,
354 dc->w.DCOrgY + bottom,
355 dc->w.DCOrgX + right - ell_width / 2,
356 dc->w.DCOrgY + bottom );
358 if (ell_height < bottom - top)
360 TSXDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
361 dc->w.DCOrgX + right,
362 dc->w.DCOrgY + top + ell_height / 2,
363 dc->w.DCOrgX + right,
364 dc->w.DCOrgY + bottom - ell_height / 2 );
365 TSXDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
366 dc->w.DCOrgX + left,
367 dc->w.DCOrgY + top + ell_height / 2,
368 dc->w.DCOrgX + left,
369 dc->w.DCOrgY + bottom - ell_height / 2 );
372 return TRUE;
376 /***********************************************************************
377 * X11DRV_SetPixel
379 COLORREF
380 X11DRV_SetPixel( DC *dc, INT32 x, INT32 y, COLORREF color )
382 Pixel pixel;
384 x = dc->w.DCOrgX + XLPTODP( dc, x );
385 y = dc->w.DCOrgY + YLPTODP( dc, y );
386 pixel = COLOR_ToPhysical( dc, color );
388 TSXSetForeground( display, dc->u.x.gc, pixel );
389 TSXSetFunction( display, dc->u.x.gc, GXcopy );
390 TSXDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
392 /* inefficient but simple... */
394 return COLOR_ToLogical(pixel);
398 /***********************************************************************
399 * X11DRV_GetPixel
401 COLORREF
402 X11DRV_GetPixel( DC *dc, INT32 x, INT32 y )
404 static Pixmap pixmap = 0;
405 XImage * image;
406 int pixel;
408 x = dc->w.DCOrgX + XLPTODP( dc, x );
409 y = dc->w.DCOrgY + YLPTODP( dc, y );
410 EnterCriticalSection( &X11DRV_CritSection );
411 if (dc->w.flags & DC_MEMORY)
413 image = XGetImage( display, dc->u.x.drawable, x, y, 1, 1,
414 AllPlanes, ZPixmap );
416 else
418 /* If we are reading from the screen, use a temporary copy */
419 /* to avoid a BadMatch error */
420 if (!pixmap) pixmap = XCreatePixmap( display, rootWindow,
421 1, 1, dc->w.bitsPerPixel );
422 XCopyArea( display, dc->u.x.drawable, pixmap, BITMAP_colorGC,
423 x, y, 1, 1, 0, 0 );
424 image = XGetImage( display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
426 pixel = XGetPixel( image, 0, 0 );
427 XDestroyImage( image );
428 LeaveCriticalSection( &X11DRV_CritSection );
430 return COLOR_ToLogical(pixel);
434 /***********************************************************************
435 * X11DRV_PaintRgn
437 BOOL32
438 X11DRV_PaintRgn( DC *dc, HRGN32 hrgn )
440 RECT32 box;
441 HRGN32 tmpVisRgn, prevVisRgn;
442 HDC32 hdc = dc->hSelf; /* FIXME: should not mix dc/hdc this way */
444 if (!(tmpVisRgn = CreateRectRgn32( 0, 0, 0, 0 ))) return FALSE;
446 /* Transform region into device co-ords */
447 if (!REGION_LPTODP( hdc, tmpVisRgn, hrgn )) {
448 DeleteObject32( tmpVisRgn );
449 return FALSE;
452 /* Modify visible region */
453 if (!(prevVisRgn = SaveVisRgn( hdc ))) {
454 DeleteObject32( tmpVisRgn );
455 return FALSE;
457 CombineRgn32( tmpVisRgn, prevVisRgn, tmpVisRgn, RGN_AND );
458 SelectVisRgn( hdc, tmpVisRgn );
459 DeleteObject32( tmpVisRgn );
461 /* Fill the region */
463 GetRgnBox32( dc->w.hGCClipRgn, &box );
464 if (DC_SetupGCForBrush( dc ))
465 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
466 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
467 box.right-box.left, box.bottom-box.top );
469 /* Restore the visible region */
471 RestoreVisRgn( hdc );
472 return TRUE;
475 /**********************************************************************
476 * X11DRV_Polyline
478 BOOL32
479 X11DRV_Polyline( DC *dc, const LPPOINT32 pt, INT32 count )
481 register int i;
483 if (DC_SetupGCForPen( dc ))
484 for (i = 0; i < count-1; i ++)
485 TSXDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
486 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
487 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
488 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
489 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
490 return TRUE;
494 /**********************************************************************
495 * X11DRV_Polygon
497 BOOL32
498 X11DRV_Polygon( DC *dc, LPPOINT32 pt, INT32 count )
500 register int i;
501 XPoint *points;
503 points = (XPoint *) xmalloc (sizeof (XPoint) * (count+1));
504 for (i = 0; i < count; i++)
506 points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
507 points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
509 points[count] = points[0];
511 if (DC_SetupGCForBrush( dc ))
512 TSXFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
513 points, count+1, Complex, CoordModeOrigin);
515 if (DC_SetupGCForPen ( dc ))
516 TSXDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
517 points, count+1, CoordModeOrigin );
519 free( points );
520 return TRUE;
524 /**********************************************************************
525 * X11DRV_PolyPolygon
527 BOOL32
528 X11DRV_PolyPolygon( DC *dc, LPPOINT32 pt, LPINT32 counts, UINT32 polygons)
530 HRGN32 hrgn;
532 /* FIXME: The points should be converted to device coords before */
533 /* creating the region. But as CreatePolyPolygonRgn is not */
534 /* really correct either, it doesn't matter much... */
535 /* At least the outline will be correct :-) */
536 hrgn = CreatePolyPolygonRgn32( pt, counts, polygons, dc->w.polyFillMode );
537 X11DRV_PaintRgn( dc, hrgn );
538 DeleteObject32( hrgn );
540 /* Draw the outline of the polygons */
542 if (DC_SetupGCForPen ( dc ))
544 int i, j, max = 0;
545 XPoint *points;
547 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
548 points = (XPoint *) xmalloc( sizeof(XPoint) * (max+1) );
550 for (i = 0; i < polygons; i++)
552 for (j = 0; j < counts[i]; j++)
554 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
555 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
556 pt++;
558 points[j] = points[0];
559 TSXDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
560 points, j + 1, CoordModeOrigin );
562 free( points );
564 return TRUE;
568 /**********************************************************************
569 * X11DRV_InternalFloodFill
571 * Internal helper function for flood fill.
572 * (xorg,yorg) is the origin of the X image relative to the drawable.
573 * (x,y) is relative to the origin of the X image.
575 static void X11DRV_InternalFloodFill(XImage *image, DC *dc,
576 int x, int y,
577 int xOrg, int yOrg,
578 Pixel pixel, WORD fillType )
580 int left, right;
582 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
583 (XGetPixel(image,x,y) != pixel) : \
584 (XGetPixel(image,x,y) == pixel))
586 if (!TO_FLOOD(x,y)) return;
588 /* Find left and right boundaries */
590 left = right = x;
591 while ((left > 0) && TO_FLOOD( left-1, y )) left--;
592 while ((right < image->width) && TO_FLOOD( right, y )) right++;
593 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
594 xOrg + left, yOrg + y, right-left, 1 );
596 /* Set the pixels of this line so we don't fill it again */
598 for (x = left; x < right; x++)
600 if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
601 else XPutPixel( image, x, y, ~pixel );
604 /* Fill the line above */
606 if (--y >= 0)
608 x = left;
609 while (x < right)
611 while ((x < right) && !TO_FLOOD(x,y)) x++;
612 if (x >= right) break;
613 while ((x < right) && TO_FLOOD(x,y)) x++;
614 X11DRV_InternalFloodFill(image, dc, x-1, y,
615 xOrg, yOrg, pixel, fillType );
619 /* Fill the line below */
621 if ((y += 2) < image->height)
623 x = left;
624 while (x < right)
626 while ((x < right) && !TO_FLOOD(x,y)) x++;
627 if (x >= right) break;
628 while ((x < right) && TO_FLOOD(x,y)) x++;
629 X11DRV_InternalFloodFill(image, dc, x-1, y,
630 xOrg, yOrg, pixel, fillType );
633 #undef TO_FLOOD
637 /**********************************************************************
638 * X11DRV_DoFloodFill
640 * Main flood-fill routine.
642 * The Xlib critical section must be entered before calling this function.
645 struct FloodFill_params
647 DC *dc;
648 INT32 x;
649 INT32 y;
650 COLORREF color;
651 UINT32 fillType;
654 static BOOL32 X11DRV_DoFloodFill( const struct FloodFill_params *params )
656 XImage *image;
657 RECT32 rect;
658 DC *dc = params->dc;
660 if (GetRgnBox32( dc->w.hGCClipRgn, &rect ) == ERROR) return FALSE;
662 if (!(image = XGetImage( display, dc->u.x.drawable,
663 dc->w.DCOrgX + rect.left,
664 dc->w.DCOrgY + rect.top,
665 rect.right - rect.left,
666 rect.bottom - rect.top,
667 AllPlanes, ZPixmap ))) return FALSE;
669 if (DC_SetupGCForBrush( dc ))
671 /* ROP mode is always GXcopy for flood-fill */
672 XSetFunction( display, dc->u.x.gc, GXcopy );
673 X11DRV_InternalFloodFill(image, dc,
674 XLPTODP(dc,params->x) - rect.left,
675 YLPTODP(dc,params->y) - rect.top,
676 dc->w.DCOrgX + rect.left,
677 dc->w.DCOrgY + rect.top,
678 COLOR_ToPhysical( dc, params->color ),
679 params->fillType );
682 XDestroyImage( image );
683 return TRUE;
687 /**********************************************************************
688 * X11DRV_ExtFloodFill
690 BOOL32
691 X11DRV_ExtFloodFill( DC *dc, INT32 x, INT32 y, COLORREF color,
692 UINT32 fillType )
694 BOOL32 result;
695 struct FloodFill_params params = { dc, x, y, color, fillType };
697 dprintf_info(graphics, "X11DRV_ExtFloodFill %d,%d %06lx %d\n",
698 x, y, color, fillType );
700 if (!PtVisible32( dc->hSelf, x, y )) return FALSE;
701 EnterCriticalSection( &X11DRV_CritSection );
702 result = CALL_LARGE_STACK( X11DRV_DoFloodFill, &params );
703 LeaveCriticalSection( &X11DRV_CritSection );
704 return result;