2 * X11 graphics driver graphics functions
4 * Copyright 1993,1994 Alexandre Julliard
9 * FIXME: none of these functions obey the GM_ADVANCED
20 #include <X11/Intrinsic.h>
42 /**********************************************************************
46 X11DRV_MoveToEx(DC *dc,INT32 x,INT32 y,LPPOINT32 pt) {
49 pt->x = dc->w.CursPosX;
50 pt->y = dc->w.CursPosY;
57 /***********************************************************************
61 X11DRV_LineTo( DC *dc, INT32 x, INT32 y )
63 if (DC_SetupGCForPen( dc ))
64 TSXDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
65 dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
66 dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
67 dc->w.DCOrgX + XLPTODP( dc, x ),
68 dc->w.DCOrgY + YLPTODP( dc, y ) );
76 /***********************************************************************
79 * Helper functions for Arc(), Chord() and Pie().
80 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
82 * FIXME: incorrect with thick pen and/or PS_INSIDEFRAME style
83 * see ellipse and rectangle functions
86 X11DRV_DrawArc( DC *dc, INT32 left, INT32 top, INT32 right,
87 INT32 bottom, INT32 xstart, INT32 ystart,
88 INT32 xend, INT32 yend, INT32 lines )
90 INT32 xcenter, ycenter, istart_angle, idiff_angle, tmp;
91 double start_angle, end_angle;
94 left = XLPTODP( dc, left );
95 top = YLPTODP( dc, top );
96 right = XLPTODP( dc, right );
97 bottom = YLPTODP( dc, bottom );
98 xstart = XLPTODP( dc, xstart );
99 ystart = YLPTODP( dc, ystart );
100 xend = XLPTODP( dc, xend );
101 yend = YLPTODP( dc, yend );
103 if ((left == right) || (top == bottom)) return TRUE;
105 if (left > right) { tmp=left; left=right; right=tmp; }
106 if (top > bottom) { tmp=top; top=bottom; bottom=tmp; }
107 xcenter = (right + left) / 2;
108 ycenter = (bottom + top) / 2;
109 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
110 (double)(xstart-xcenter)*(bottom-top) );
111 end_angle = atan2( (double)(ycenter-yend)*(right-left),
112 (double)(xend-xcenter)*(bottom-top) );
113 if ((xstart==xend)&&(ystart==yend))
114 { /* A lazy program delivers xstart=xend=ystart=yend=0) */
118 else /* notorious cases */
119 if ((start_angle == PI)&&( end_angle <0))
122 if ((end_angle == PI)&&( start_angle <0))
124 istart_angle = (INT32)(start_angle * 180 * 64 / PI);
125 idiff_angle = (INT32)((end_angle - start_angle) * 180 * 64 / PI );
126 if (idiff_angle <= 0) idiff_angle += 360 * 64;
128 /* Fill arc with brush if Chord() or Pie() */
130 if ((lines > 0) && DC_SetupGCForBrush( dc ))
132 TSXSetArcMode( display, dc->u.x.gc, (lines==1) ? ArcChord : ArcPieSlice);
133 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
134 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
135 right-left-1, bottom-top-1, istart_angle, idiff_angle );
138 /* Draw arc and lines */
140 if (!DC_SetupGCForPen( dc )) return TRUE;
141 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
142 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
143 right-left-1, bottom-top-1, istart_angle, idiff_angle );
144 if (!lines) return TRUE;
146 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
147 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
148 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
149 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
152 points[2] = points[1];
153 points[1].x = dc->w.DCOrgX + xcenter;
154 points[1].y = dc->w.DCOrgY + ycenter;
156 TSXDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
157 points, lines+1, CoordModeOrigin );
162 /***********************************************************************
166 X11DRV_Arc( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
167 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
169 return X11DRV_DrawArc( dc, left, top, right, bottom,
170 xstart, ystart, xend, yend, 0 );
174 /***********************************************************************
178 X11DRV_Pie( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
179 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
181 return X11DRV_DrawArc( dc, left, top, right, bottom,
182 xstart, ystart, xend, yend, 2 );
185 /***********************************************************************
189 X11DRV_Chord( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
190 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
192 return X11DRV_DrawArc( dc, left, top, right, bottom,
193 xstart, ystart, xend, yend, 1 );
197 /***********************************************************************
201 X11DRV_Ellipse( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom )
203 INT32 width, oldwidth;
205 left = XLPTODP( dc, left );
206 top = YLPTODP( dc, top );
207 right = XLPTODP( dc, right );
208 bottom = YLPTODP( dc, bottom );
209 if ((left == right) || (top == bottom)) return TRUE;
211 if (right < left) { INT32 tmp = right; right = left; left = tmp; }
212 if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
214 oldwidth = width = dc->u.x.pen.width;
215 if (!width) width = 1;
216 if(dc->u.x.pen.style == PS_NULL) width = 0;
218 if ((dc->u.x.pen.style == PS_INSIDEFRAME))
220 if (2*width > (right-left)) width=(right-left + 1)/2;
221 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
223 right -= (width - 1) / 2;
225 bottom -= (width - 1) / 2;
227 if(width == 1) width=0;
228 dc->u.x.pen.width=width;
230 if (DC_SetupGCForBrush( dc ))
231 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
232 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
233 right-left-1, bottom-top-1, 0, 360*64 );
234 if (DC_SetupGCForPen( dc ))
235 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
236 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
237 right-left-1, bottom-top-1, 0, 360*64 );
238 dc->u.x.pen.width=oldwidth;
243 /***********************************************************************
247 X11DRV_Rectangle(DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom)
249 INT32 width, oldwidth, oldjoinstyle;
251 TRACE(graphics, "(%d %d %d %d)\n",
252 left, top, right, bottom);
254 left = XLPTODP( dc, left );
255 top = YLPTODP( dc, top );
256 right = XLPTODP( dc, right );
257 bottom = YLPTODP( dc, bottom );
259 if ((left == right) || (top == bottom)) return TRUE;
261 if (right < left) { INT32 tmp = right; right = left; left = tmp; }
262 if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
264 oldwidth = width = dc->u.x.pen.width;
265 if (!width) width = 1;
266 if(dc->u.x.pen.style == PS_NULL) width = 0;
268 if ((dc->u.x.pen.style == PS_INSIDEFRAME))
270 if (2*width > (right-left)) width=(right-left + 1)/2;
271 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
273 right -= (width - 1) / 2;
275 bottom -= (width - 1) / 2;
277 if(width == 1) width=0;
278 dc->u.x.pen.width=width;
279 oldjoinstyle=dc->u.x.pen.linejoin;
280 if(dc->u.x.pen.type!=PS_GEOMETRIC)
281 dc->u.x.pen.linejoin=PS_JOIN_MITER;
283 if ((right > left + width) && (bottom > top + width))
285 if (DC_SetupGCForBrush( dc ))
286 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
287 dc->w.DCOrgX + left + (width + 1) / 2,
288 dc->w.DCOrgY + top + (width + 1) / 2,
289 right-left-width-1, bottom-top-width-1);
291 if (DC_SetupGCForPen( dc ))
292 TSXDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
293 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
294 right-left-1, bottom-top-1 );
296 dc->u.x.pen.width=oldwidth;
297 dc->u.x.pen.linejoin=oldjoinstyle;
301 /***********************************************************************
305 X11DRV_RoundRect( DC *dc, INT32 left, INT32 top, INT32 right,
306 INT32 bottom, INT32 ell_width, INT32 ell_height )
308 INT32 width, oldwidth;
310 TRACE(graphics, "(%d %d %d %d %d %d\n",
311 left, top, right, bottom, ell_width, ell_height);
313 left = XLPTODP( dc, left );
314 top = YLPTODP( dc, top );
315 right = XLPTODP( dc, right );
316 bottom = YLPTODP( dc, bottom );
318 if ((left == right) || (top == bottom))
321 ell_width = abs( ell_width * dc->vportExtX / dc->wndExtX );
322 ell_height = abs( ell_height * dc->vportExtY / dc->wndExtY );
324 /* Fix the coordinates */
326 if (right < left) { INT32 tmp = right; right = left; left = tmp; }
327 if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
329 oldwidth=width = dc->u.x.pen.width;
330 if (!width) width = 1;
331 if(dc->u.x.pen.style == PS_NULL) width = 0;
333 if ((dc->u.x.pen.style == PS_INSIDEFRAME))
335 if (2*width > (right-left)) width=(right-left + 1)/2;
336 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
338 right -= (width - 1) / 2;
340 bottom -= (width - 1) / 2;
342 if(width == 1) width=0;
343 dc->u.x.pen.width=width;
345 if (DC_SetupGCForBrush( dc ))
347 if (ell_width > (right-left) )
348 if (ell_height > (bottom-top) )
349 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
350 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
351 right - left - 1, bottom - top - 1,
354 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
355 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
356 right - left - 1, ell_height, 0, 180 * 64 );
357 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
359 dc->w.DCOrgY + bottom - ell_height - 1,
360 right - left - 1, ell_height, 180 * 64, 180 * 64 );
362 else if (ell_height > (bottom-top) ){
363 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
364 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
365 ell_width, bottom - top - 1, 90 * 64, 180 * 64 );
366 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
367 dc->w.DCOrgX + right - ell_width -1, dc->w.DCOrgY + top,
368 ell_width, bottom - top - 1, 270 * 64, 180 * 64 );
370 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
371 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
372 ell_width, ell_height, 90 * 64, 90 * 64 );
373 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
375 dc->w.DCOrgY + bottom - ell_height - 1,
376 ell_width, ell_height, 180 * 64, 90 * 64 );
377 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
378 dc->w.DCOrgX + right - ell_width - 1,
379 dc->w.DCOrgY + bottom - ell_height - 1,
380 ell_width, ell_height, 270 * 64, 90 * 64 );
381 TSXFillArc( display, dc->u.x.drawable, dc->u.x.gc,
382 dc->w.DCOrgX + right - ell_width - 1,
384 ell_width, ell_height, 0, 90 * 64 );
386 if (ell_width < right - left)
388 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
389 dc->w.DCOrgX + left + ell_width / 2,
391 right - left - ell_width, ell_height / 2 );
392 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
393 dc->w.DCOrgX + left + ell_width / 2,
394 dc->w.DCOrgY + bottom - (ell_height+1) / 2,
395 right - left - ell_width,
396 (ell_height+1) / 2 - 1 );
398 if (ell_height < bottom - top)
400 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
402 dc->w.DCOrgY + top + ell_height / 2,
403 right - left - 1, bottom - top - ell_height );
406 if (DC_SetupGCForPen(dc)) {
407 if (ell_width > (right-left) )
408 if (ell_height > (bottom-top) )
409 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
410 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
411 right - left - 1, bottom -top - 1, 0 , 360 * 64 );
413 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
414 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
415 right - left - 1, ell_height - 1, 0 , 180 * 64 );
416 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
418 dc->w.DCOrgY + bottom - ell_height,
419 right - left - 1, ell_height - 1, 180 * 64 , 180 * 64 );
421 else if (ell_height > (bottom-top) ){
422 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
423 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
424 ell_width - 1 , bottom - top - 1, 90 * 64 , 180 * 64 );
425 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
426 dc->w.DCOrgX + right - ell_width,
428 ell_width - 1 , bottom - top - 1, 270 * 64 , 180 * 64 );
430 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
431 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
432 ell_width - 1, ell_height - 1, 90 * 64, 90 * 64 );
433 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
434 dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
435 ell_width - 1, ell_height - 1, 180 * 64, 90 * 64 );
436 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
437 dc->w.DCOrgX + right - ell_width,
438 dc->w.DCOrgY + bottom - ell_height,
439 ell_width - 1, ell_height - 1, 270 * 64, 90 * 64 );
440 TSXDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
441 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
442 ell_width - 1, ell_height - 1, 0, 90 * 64 );
444 if (ell_width < right - left)
446 TSXDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
447 dc->w.DCOrgX + left + ell_width / 2 - 2,
449 dc->w.DCOrgX + right - ell_width / 2,
451 TSXDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
452 dc->w.DCOrgX + left + ell_width / 2 - 2,
453 dc->w.DCOrgY + bottom - 1,
454 dc->w.DCOrgX + right - ell_width / 2,
455 dc->w.DCOrgY + bottom - 1);
457 if (ell_height < bottom - top)
459 TSXDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
460 dc->w.DCOrgX + right - 1,
461 dc->w.DCOrgY + top + ell_height / 2 - 1,
462 dc->w.DCOrgX + right - 1,
463 dc->w.DCOrgY + bottom - ell_height / 2);
464 TSXDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
466 dc->w.DCOrgY + top + ell_height / 2 - 1,
468 dc->w.DCOrgY + bottom - ell_height / 2);
471 dc->u.x.pen.width=oldwidth;
476 /***********************************************************************
480 X11DRV_SetPixel( DC *dc, INT32 x, INT32 y, COLORREF color )
484 x = dc->w.DCOrgX + XLPTODP( dc, x );
485 y = dc->w.DCOrgY + YLPTODP( dc, y );
486 pixel = COLOR_ToPhysical( dc, color );
488 TSXSetForeground( display, dc->u.x.gc, pixel );
489 TSXSetFunction( display, dc->u.x.gc, GXcopy );
490 TSXDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
492 /* inefficient but simple... */
494 return COLOR_ToLogical(pixel);
498 /***********************************************************************
502 X11DRV_GetPixel( DC *dc, INT32 x, INT32 y )
504 static Pixmap pixmap = 0;
508 x = dc->w.DCOrgX + XLPTODP( dc, x );
509 y = dc->w.DCOrgY + YLPTODP( dc, y );
510 EnterCriticalSection( &X11DRV_CritSection );
511 if (dc->w.flags & DC_MEMORY)
513 image = XGetImage( display, dc->u.x.drawable, x, y, 1, 1,
514 AllPlanes, ZPixmap );
518 /* If we are reading from the screen, use a temporary copy */
519 /* to avoid a BadMatch error */
520 if (!pixmap) pixmap = XCreatePixmap( display, rootWindow,
521 1, 1, dc->w.bitsPerPixel );
522 XCopyArea( display, dc->u.x.drawable, pixmap, BITMAP_colorGC,
524 image = XGetImage( display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
526 pixel = XGetPixel( image, 0, 0 );
527 XDestroyImage( image );
528 LeaveCriticalSection( &X11DRV_CritSection );
530 return COLOR_ToLogical(pixel);
534 /***********************************************************************
538 X11DRV_PaintRgn( DC *dc, HRGN32 hrgn )
541 HRGN32 tmpVisRgn, prevVisRgn;
542 HDC32 hdc = dc->hSelf; /* FIXME: should not mix dc/hdc this way */
544 if (!(tmpVisRgn = CreateRectRgn32( 0, 0, 0, 0 ))) return FALSE;
546 /* Transform region into device co-ords */
547 if (!REGION_LPTODP( hdc, tmpVisRgn, hrgn )) {
548 DeleteObject32( tmpVisRgn );
552 /* Modify visible region */
553 if (!(prevVisRgn = SaveVisRgn( hdc ))) {
554 DeleteObject32( tmpVisRgn );
557 CombineRgn32( tmpVisRgn, prevVisRgn, tmpVisRgn, RGN_AND );
558 SelectVisRgn( hdc, tmpVisRgn );
559 DeleteObject32( tmpVisRgn );
561 /* Fill the region */
563 GetRgnBox32( dc->w.hGCClipRgn, &box );
564 if (DC_SetupGCForBrush( dc ))
565 TSXFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
566 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
567 box.right-box.left, box.bottom-box.top );
569 /* Restore the visible region */
571 RestoreVisRgn( hdc );
575 /**********************************************************************
579 X11DRV_Polyline( DC *dc, const LPPOINT32 pt, INT32 count )
583 if (DC_SetupGCForPen( dc ))
584 for (i = 0; i < count-1; i ++)
585 TSXDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
586 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
587 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
588 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
589 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
594 /**********************************************************************
598 X11DRV_Polygon( DC *dc, LPPOINT32 pt, INT32 count )
603 points = (XPoint *) xmalloc (sizeof (XPoint) * (count+1));
604 for (i = 0; i < count; i++)
606 points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
607 points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
609 points[count] = points[0];
611 if (DC_SetupGCForBrush( dc ))
612 TSXFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
613 points, count+1, Complex, CoordModeOrigin);
615 if (DC_SetupGCForPen ( dc ))
616 TSXDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
617 points, count+1, CoordModeOrigin );
624 /**********************************************************************
628 X11DRV_PolyPolygon( DC *dc, LPPOINT32 pt, LPINT32 counts, UINT32 polygons)
632 /* FIXME: The points should be converted to device coords before */
633 /* creating the region. But as CreatePolyPolygonRgn is not */
634 /* really correct either, it doesn't matter much... */
635 /* At least the outline will be correct :-) */
636 hrgn = CreatePolyPolygonRgn32( pt, counts, polygons, dc->w.polyFillMode );
637 X11DRV_PaintRgn( dc, hrgn );
638 DeleteObject32( hrgn );
640 /* Draw the outline of the polygons */
642 if (DC_SetupGCForPen ( dc ))
647 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
648 points = (XPoint *) xmalloc( sizeof(XPoint) * (max+1) );
650 for (i = 0; i < polygons; i++)
652 for (j = 0; j < counts[i]; j++)
654 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
655 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
658 points[j] = points[0];
659 TSXDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
660 points, j + 1, CoordModeOrigin );
668 /**********************************************************************
669 * X11DRV_PolyPolyline
672 X11DRV_PolyPolyline( DC *dc, LPPOINT32 pt, LPINT32 counts, UINT32 polylines )
674 if (DC_SetupGCForPen ( dc ))
679 for (i = 0; i < polylines; i++) if (counts[i] > max) max = counts[i];
680 points = (XPoint *) xmalloc( sizeof(XPoint) * (max+1) );
682 for (i = 0; i < polylines; i++)
684 for (j = 0; j < counts[i]; j++)
686 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
687 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
690 points[j] = points[0];
691 TSXDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
692 points, j + 1, CoordModeOrigin );
700 /**********************************************************************
701 * X11DRV_InternalFloodFill
703 * Internal helper function for flood fill.
704 * (xorg,yorg) is the origin of the X image relative to the drawable.
705 * (x,y) is relative to the origin of the X image.
707 static void X11DRV_InternalFloodFill(XImage *image, DC *dc,
710 Pixel pixel, WORD fillType )
714 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
715 (XGetPixel(image,x,y) != pixel) : \
716 (XGetPixel(image,x,y) == pixel))
718 if (!TO_FLOOD(x,y)) return;
720 /* Find left and right boundaries */
723 while ((left > 0) && TO_FLOOD( left-1, y )) left--;
724 while ((right < image->width) && TO_FLOOD( right, y )) right++;
725 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
726 xOrg + left, yOrg + y, right-left, 1 );
728 /* Set the pixels of this line so we don't fill it again */
730 for (x = left; x < right; x++)
732 if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
733 else XPutPixel( image, x, y, ~pixel );
736 /* Fill the line above */
743 while ((x < right) && !TO_FLOOD(x,y)) x++;
744 if (x >= right) break;
745 while ((x < right) && TO_FLOOD(x,y)) x++;
746 X11DRV_InternalFloodFill(image, dc, x-1, y,
747 xOrg, yOrg, pixel, fillType );
751 /* Fill the line below */
753 if ((y += 2) < image->height)
758 while ((x < right) && !TO_FLOOD(x,y)) x++;
759 if (x >= right) break;
760 while ((x < right) && TO_FLOOD(x,y)) x++;
761 X11DRV_InternalFloodFill(image, dc, x-1, y,
762 xOrg, yOrg, pixel, fillType );
769 /**********************************************************************
772 * Main flood-fill routine.
774 * The Xlib critical section must be entered before calling this function.
777 struct FloodFill_params
786 static BOOL32 X11DRV_DoFloodFill( const struct FloodFill_params *params )
792 if (GetRgnBox32( dc->w.hGCClipRgn, &rect ) == ERROR) return FALSE;
794 if (!(image = XGetImage( display, dc->u.x.drawable,
795 dc->w.DCOrgX + rect.left,
796 dc->w.DCOrgY + rect.top,
797 rect.right - rect.left,
798 rect.bottom - rect.top,
799 AllPlanes, ZPixmap ))) return FALSE;
801 if (DC_SetupGCForBrush( dc ))
803 /* ROP mode is always GXcopy for flood-fill */
804 XSetFunction( display, dc->u.x.gc, GXcopy );
805 X11DRV_InternalFloodFill(image, dc,
806 XLPTODP(dc,params->x) - rect.left,
807 YLPTODP(dc,params->y) - rect.top,
808 dc->w.DCOrgX + rect.left,
809 dc->w.DCOrgY + rect.top,
810 COLOR_ToPhysical( dc, params->color ),
814 XDestroyImage( image );
819 /**********************************************************************
820 * X11DRV_ExtFloodFill
823 X11DRV_ExtFloodFill( DC *dc, INT32 x, INT32 y, COLORREF color,
827 struct FloodFill_params params = { dc, x, y, color, fillType };
829 TRACE(graphics, "X11DRV_ExtFloodFill %d,%d %06lx %d\n",
830 x, y, color, fillType );
832 if (!PtVisible32( dc->hSelf, x, y )) return FALSE;
833 EnterCriticalSection( &X11DRV_CritSection );
834 result = CALL_LARGE_STACK( X11DRV_DoFloodFill, ¶ms );
835 LeaveCriticalSection( &X11DRV_CritSection );