Allocate DC objects on the process heap, and removed WIN_DC_INFO
[wine] / graphics / x11drv / graphics.c
1 /*
2  * X11 graphics driver graphics functions
3  *
4  * Copyright 1993,1994 Alexandre Julliard
5  */
6
7 /*
8  * FIXME: none of these functions obey the GM_ADVANCED
9  * graphics mode
10  */
11
12 #include "config.h"
13
14 #include <X11/Intrinsic.h>
15
16 #include "ts_xlib.h"
17 #include "ts_xutil.h"
18
19 #include <math.h>
20 #ifdef HAVE_FLOAT_H
21 # include <float.h>
22 #endif
23 #include <stdlib.h>
24 #ifndef PI
25 #define PI M_PI
26 #endif
27 #include <string.h>
28
29 #include "x11drv.h"
30 #include "x11font.h"
31 #include "bitmap.h"
32 #include "gdi.h"
33 #include "callback.h"
34 #include "metafile.h"
35 #include "palette.h"
36 #include "color.h"
37 #include "region.h"
38 #include "debugtools.h"
39
40 DEFAULT_DEBUG_CHANNEL(graphics);
41
42 #define ABS(x)    ((x)<0?(-(x)):(x))
43
44   /* ROP code to GC function conversion */
45 const int X11DRV_XROPfunction[16] =
46 {
47     GXclear,        /* R2_BLACK */
48     GXnor,          /* R2_NOTMERGEPEN */
49     GXandInverted,  /* R2_MASKNOTPEN */
50     GXcopyInverted, /* R2_NOTCOPYPEN */
51     GXandReverse,   /* R2_MASKPENNOT */
52     GXinvert,       /* R2_NOT */
53     GXxor,          /* R2_XORPEN */
54     GXnand,         /* R2_NOTMASKPEN */
55     GXand,          /* R2_MASKPEN */
56     GXequiv,        /* R2_NOTXORPEN */
57     GXnoop,         /* R2_NOP */
58     GXorInverted,   /* R2_MERGENOTPEN */
59     GXcopy,         /* R2_COPYPEN */
60     GXorReverse,    /* R2_MERGEPENNOT */
61     GXor,           /* R2_MERGEPEN */
62     GXset           /* R2_WHITE */
63 };
64
65
66 /***********************************************************************
67  *           X11DRV_SetupGCForPatBlt
68  *
69  * Setup the GC for a PatBlt operation using current brush.
70  * If fMapColors is TRUE, X pixels are mapped to Windows colors.
71  * Return FALSE if brush is BS_NULL, TRUE otherwise.
72  */
73 BOOL X11DRV_SetupGCForPatBlt( DC * dc, GC gc, BOOL fMapColors )
74 {
75     XGCValues val;
76     unsigned long mask;
77     Pixmap pixmap = 0;
78     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
79
80     if (physDev->brush.style == BS_NULL) return FALSE;
81     if (physDev->brush.pixel == -1)
82     {
83         /* Special case used for monochrome pattern brushes.
84          * We need to swap foreground and background because
85          * Windows does it the wrong way...
86          */
87         val.foreground = physDev->backgroundPixel;
88         val.background = physDev->textPixel;
89     }
90     else
91     {
92         val.foreground = physDev->brush.pixel;
93         val.background = physDev->backgroundPixel;
94     }
95     if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
96     {
97         val.foreground = X11DRV_PALETTE_XPixelToPalette[val.foreground];
98         val.background = X11DRV_PALETTE_XPixelToPalette[val.background];
99     }
100
101     val.function = X11DRV_XROPfunction[dc->ROPmode-1];
102     /*
103     ** Let's replace GXinvert by GXxor with (black xor white)
104     ** This solves the selection color and leak problems in excel
105     ** FIXME : Let's do that only if we work with X-pixels, not with Win-pixels
106     */
107     if (val.function == GXinvert)
108         {
109         val.foreground = BlackPixelOfScreen(X11DRV_GetXScreen()) ^ WhitePixelOfScreen(X11DRV_GetXScreen());
110         val.function = GXxor;
111         }
112     val.fill_style = physDev->brush.fillStyle;
113     switch(val.fill_style)
114     {
115     case FillStippled:
116     case FillOpaqueStippled:
117         if (dc->backgroundMode==OPAQUE) val.fill_style = FillOpaqueStippled;
118         val.stipple = physDev->brush.pixmap;
119         mask = GCStipple;
120         break;
121
122     case FillTiled:
123         if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
124         {
125             register int x, y;
126             XImage *image;
127             EnterCriticalSection( &X11DRV_CritSection );
128             pixmap = XCreatePixmap( display, X11DRV_GetXRootWindow(), 
129                                     8, 8, X11DRV_GetDepth() );
130             image = XGetImage( display, physDev->brush.pixmap, 0, 0, 8, 8,
131                                AllPlanes, ZPixmap );
132             for (y = 0; y < 8; y++)
133                 for (x = 0; x < 8; x++)
134                     XPutPixel( image, x, y,
135                                X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y)] );
136             XPutImage( display, pixmap, gc, image, 0, 0, 0, 0, 8, 8 );
137             XDestroyImage( image );
138             LeaveCriticalSection( &X11DRV_CritSection );
139             val.tile = pixmap;
140         }
141         else val.tile = physDev->brush.pixmap;
142         mask = GCTile;
143         break;
144
145     default:
146         mask = 0;
147         break;
148     }
149     val.ts_x_origin = dc->DCOrgX + dc->brushOrgX;
150     val.ts_y_origin = dc->DCOrgY + dc->brushOrgY;
151     val.fill_rule = (dc->polyFillMode==WINDING) ? WindingRule : EvenOddRule;
152     TSXChangeGC( display, gc, 
153                GCFunction | GCForeground | GCBackground | GCFillStyle |
154                GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
155                &val );
156     if (pixmap) TSXFreePixmap( display, pixmap );
157     return TRUE;
158 }
159
160
161 /***********************************************************************
162  *           X11DRV_SetupGCForBrush
163  *
164  * Setup physDev->gc for drawing operations using current brush.
165  * Return FALSE if brush is BS_NULL, TRUE otherwise.
166  */
167 BOOL X11DRV_SetupGCForBrush( DC * dc )
168 {
169     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
170     return X11DRV_SetupGCForPatBlt( dc, physDev->gc, FALSE );
171 }
172
173
174 /***********************************************************************
175  *           X11DRV_SetupGCForPen
176  *
177  * Setup physDev->gc for drawing operations using current pen.
178  * Return FALSE if pen is PS_NULL, TRUE otherwise.
179  */
180 BOOL X11DRV_SetupGCForPen( DC * dc )
181 {
182     XGCValues val;
183     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
184
185     if (physDev->pen.style == PS_NULL) return FALSE;
186
187     switch (dc->ROPmode)
188     {
189     case R2_BLACK :
190         val.foreground = BlackPixelOfScreen( X11DRV_GetXScreen() );
191         val.function = GXcopy;
192         break;
193     case R2_WHITE :
194         val.foreground = WhitePixelOfScreen( X11DRV_GetXScreen() );
195         val.function = GXcopy;
196         break;
197     case R2_XORPEN :
198         val.foreground = physDev->pen.pixel;
199         /* It is very unlikely someone wants to XOR with 0 */
200         /* This fixes the rubber-drawings in paintbrush */
201         if (val.foreground == 0)
202             val.foreground = BlackPixelOfScreen( X11DRV_GetXScreen() )
203                             ^ WhitePixelOfScreen( X11DRV_GetXScreen() );
204         val.function = GXxor;
205         break;
206     default :
207         val.foreground = physDev->pen.pixel;
208         val.function   = X11DRV_XROPfunction[dc->ROPmode-1];
209     }
210     val.background = physDev->backgroundPixel;
211     val.fill_style = FillSolid;
212     if ((physDev->pen.width <= 1) &&
213         (physDev->pen.style != PS_SOLID) &&
214         (physDev->pen.style != PS_INSIDEFRAME))
215     {
216         TSXSetDashes( display, physDev->gc, 0, physDev->pen.dashes,
217                       physDev->pen.dash_len );
218         val.line_style = (dc->backgroundMode == OPAQUE) ?
219                               LineDoubleDash : LineOnOffDash;
220     }
221     else val.line_style = LineSolid;
222     val.line_width = physDev->pen.width;
223     if (val.line_width <= 1) {
224         val.cap_style = CapNotLast;
225     } else {
226         switch (physDev->pen.endcap)
227         {
228         case PS_ENDCAP_SQUARE:
229             val.cap_style = CapProjecting;
230             break;
231         case PS_ENDCAP_FLAT:
232             val.cap_style = CapButt;
233             break;
234         case PS_ENDCAP_ROUND:
235         default:
236             val.cap_style = CapRound;
237         }
238     }
239     switch (physDev->pen.linejoin)
240     {
241     case PS_JOIN_BEVEL:
242         val.join_style = JoinBevel;
243         break;
244     case PS_JOIN_MITER:
245         val.join_style = JoinMiter;
246         break;
247     case PS_JOIN_ROUND:
248     default:
249         val.join_style = JoinRound;
250     }
251     TSXChangeGC( display, physDev->gc, 
252                GCFunction | GCForeground | GCBackground | GCLineWidth |
253                GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
254     return TRUE;
255 }
256
257
258 /***********************************************************************
259  *           X11DRV_SetupGCForText
260  *
261  * Setup physDev->gc for text drawing operations.
262  * Return FALSE if the font is null, TRUE otherwise.
263  */
264 BOOL X11DRV_SetupGCForText( DC * dc )
265 {
266     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
267     XFontStruct* xfs = XFONT_GetFontStruct( physDev->font );
268
269     if( xfs )
270     {
271         XGCValues val;
272
273         val.function   = GXcopy;  /* Text is always GXcopy */
274         val.foreground = physDev->textPixel;
275         val.background = physDev->backgroundPixel;
276         val.fill_style = FillSolid;
277         val.font       = xfs->fid;
278
279         TSXChangeGC( display, physDev->gc,
280                    GCFunction | GCForeground | GCBackground | GCFillStyle |
281                    GCFont, &val );
282         return TRUE;
283     } 
284     WARN("Physical font failure\n" );
285     return FALSE;
286 }
287
288 /***********************************************************************
289  *           X11DRV_LineTo
290  */
291 BOOL
292 X11DRV_LineTo( DC *dc, INT x, INT y )
293 {
294     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
295
296     if (X11DRV_SetupGCForPen( dc )) {
297         /* Update the pixmap from the DIB section */
298         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
299         TSXDrawLine(display, physDev->drawable, physDev->gc, 
300                   dc->DCOrgX + XLPTODP( dc, dc->CursPosX ),
301                   dc->DCOrgY + YLPTODP( dc, dc->CursPosY ),
302                   dc->DCOrgX + XLPTODP( dc, x ),
303                   dc->DCOrgY + YLPTODP( dc, y ) );
304         /* Update the DIBSection from the pixmap */
305         X11DRV_DIB_UpdateDIBSection(dc, TRUE); 
306     }
307     return TRUE;
308 }
309
310
311
312 /***********************************************************************
313  *           X11DRV_DrawArc
314  *
315  * Helper functions for Arc(), Chord() and Pie().
316  * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
317  *
318  */
319 static BOOL
320 X11DRV_DrawArc( DC *dc, INT left, INT top, INT right,
321                 INT bottom, INT xstart, INT ystart,
322                 INT xend, INT yend, INT lines )
323 {
324     INT xcenter, ycenter, istart_angle, idiff_angle;
325     INT width, oldwidth, oldendcap;
326     double start_angle, end_angle;
327     XPoint points[4];
328     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
329     BOOL update = FALSE;
330
331     left   = XLPTODP( dc, left );
332     top    = YLPTODP( dc, top );
333     right  = XLPTODP( dc, right );
334     bottom = YLPTODP( dc, bottom );
335     xstart = XLPTODP( dc, xstart );
336     ystart = YLPTODP( dc, ystart );
337     xend   = XLPTODP( dc, xend );
338     yend   = YLPTODP( dc, yend );
339
340     if (right < left) { INT tmp = right; right = left; left = tmp; }
341     if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
342     if ((left == right) || (top == bottom)
343             ||(lines && ((right-left==1)||(bottom-top==1)))) return TRUE;
344
345     if( dc->ArcDirection == AD_CLOCKWISE )
346         { INT tmp = xstart; xstart = xend; xend = tmp;
347           tmp = ystart; ystart = yend; yend = tmp; } 
348         
349     oldwidth = width = physDev->pen.width;
350     oldendcap = physDev->pen.endcap;
351     if (!width) width = 1;
352     if(physDev->pen.style == PS_NULL) width = 0;
353
354     if ((physDev->pen.style == PS_INSIDEFRAME))
355     {
356         if (2*width > (right-left)) width=(right-left + 1)/2;
357         if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
358         left   += width / 2;
359         right  -= (width - 1) / 2;
360         top    += width / 2;
361         bottom -= (width - 1) / 2;
362     }
363     if(width == 0) width = 1; /* more accurate */
364     physDev->pen.width = width;
365     physDev->pen.endcap = PS_ENDCAP_SQUARE;
366
367     xcenter = (right + left) / 2;
368     ycenter = (bottom + top) / 2;
369     start_angle = atan2( (double)(ycenter-ystart)*(right-left),
370                          (double)(xstart-xcenter)*(bottom-top) );
371     end_angle   = atan2( (double)(ycenter-yend)*(right-left),
372                          (double)(xend-xcenter)*(bottom-top) );
373     if ((xstart==xend)&&(ystart==yend))
374       { /* A lazy program delivers xstart=xend=ystart=yend=0) */
375         start_angle = 0;
376         end_angle = 2* PI;
377       }
378     else /* notorious cases */
379       if ((start_angle == PI)&&( end_angle <0))
380         start_angle = - PI;
381     else
382       if ((end_angle == PI)&&( start_angle <0))
383         end_angle = - PI;
384     istart_angle = (INT)(start_angle * 180 * 64 / PI + 0.5);
385     idiff_angle  = (INT)((end_angle - start_angle) * 180 * 64 / PI + 0.5);
386     if (idiff_angle <= 0) idiff_angle += 360 * 64;
387
388     /* Update the pixmap from the DIB section */
389     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
390
391       /* Fill arc with brush if Chord() or Pie() */
392
393     if ((lines > 0) && X11DRV_SetupGCForBrush( dc )) {
394         TSXSetArcMode( display, physDev->gc,
395                        (lines==1) ? ArcChord : ArcPieSlice);
396         TSXFillArc( display, physDev->drawable, physDev->gc,
397                  dc->DCOrgX + left, dc->DCOrgY + top,
398                  right-left-1, bottom-top-1, istart_angle, idiff_angle );
399         update = TRUE;
400     }
401
402       /* Draw arc and lines */
403
404     if (X11DRV_SetupGCForPen( dc )){
405         TSXDrawArc( display, physDev->drawable, physDev->gc,
406                 dc->DCOrgX + left, dc->DCOrgY + top,
407                 right-left-1, bottom-top-1, istart_angle, idiff_angle );
408         if (lines) {
409             /* use the truncated values */
410             start_angle=(double)istart_angle*PI/64./180.;
411             end_angle=(double)(istart_angle+idiff_angle)*PI/64./180.;
412             /* calculate the endpoints and round correctly */
413             points[0].x = (int) floor(dc->DCOrgX + (right+left)/2.0 +
414                     cos(start_angle) * (right-left-width*2+2) / 2. + 0.5);
415             points[0].y = (int) floor(dc->DCOrgY + (top+bottom)/2.0 -
416                     sin(start_angle) * (bottom-top-width*2+2) / 2. + 0.5);
417             points[1].x = (int) floor(dc->DCOrgX + (right+left)/2.0 +
418                     cos(end_angle) * (right-left-width*2+2) / 2. + 0.5);
419             points[1].y = (int) floor(dc->DCOrgY + (top+bottom)/2.0 -
420                     sin(end_angle) * (bottom-top-width*2+2) / 2. + 0.5);
421                     
422             /* OK this stuff is optimized for Xfree86 
423              * which is probably the most used server by
424              * wine users. Other X servers will not 
425              * display correctly. (eXceed for instance)
426              * so if you feel you must change make sure that
427              * you either use Xfree86 or seperate your changes 
428              * from these (compile switch or whatever)
429              */
430             if (lines == 2) {
431                 INT dx1,dy1;
432                 points[3] = points[1];
433                 points[1].x = dc->DCOrgX + xcenter;
434                 points[1].y = dc->DCOrgY + ycenter;
435                 points[2] = points[1];
436                 dx1=points[1].x-points[0].x;
437                 dy1=points[1].y-points[0].y;
438                 if(((top-bottom) | -2) == -2)
439                     if(dy1>0) points[1].y--;
440                 if(dx1<0) {
441                     if (((-dx1)*64)<=ABS(dy1)*37) points[0].x--;
442                     if(((-dx1*9))<(dy1*16)) points[0].y--;
443                     if( dy1<0 && ((dx1*9)) < (dy1*16)) points[0].y--;
444                 } else {
445                     if(dy1 < 0)  points[0].y--;
446                     if(((right-left) | -2) == -2) points[1].x--;
447                 }
448                 dx1=points[3].x-points[2].x;
449                 dy1=points[3].y-points[2].y;
450                 if(((top-bottom) | -2 ) == -2)
451                     if(dy1 < 0) points[2].y--;
452                 if( dx1<0){ 
453                     if( dy1>0) points[3].y--;
454                     if(((right-left) | -2) == -2 ) points[2].x--;
455                 }else {
456                     points[3].y--;
457                     if( dx1 * 64 < dy1 * -37 ) points[3].x--;
458                 }
459                 lines++;
460             }
461             TSXDrawLines( display, physDev->drawable, physDev->gc,
462                 points, lines+1, CoordModeOrigin );
463         }
464         update = TRUE;
465     }
466
467     /* Update the DIBSection of the pixmap */
468     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
469
470     physDev->pen.width = oldwidth;
471     physDev->pen.endcap = oldendcap;
472     return TRUE;
473 }
474
475
476 /***********************************************************************
477  *           X11DRV_Arc
478  */
479 BOOL
480 X11DRV_Arc( DC *dc, INT left, INT top, INT right, INT bottom,
481             INT xstart, INT ystart, INT xend, INT yend )
482 {
483     return X11DRV_DrawArc( dc, left, top, right, bottom,
484                            xstart, ystart, xend, yend, 0 );
485 }
486
487
488 /***********************************************************************
489  *           X11DRV_Pie
490  */
491 BOOL
492 X11DRV_Pie( DC *dc, INT left, INT top, INT right, INT bottom,
493             INT xstart, INT ystart, INT xend, INT yend )
494 {
495     return X11DRV_DrawArc( dc, left, top, right, bottom,
496                            xstart, ystart, xend, yend, 2 );
497 }
498
499 /***********************************************************************
500  *           X11DRV_Chord
501  */
502 BOOL
503 X11DRV_Chord( DC *dc, INT left, INT top, INT right, INT bottom,
504               INT xstart, INT ystart, INT xend, INT yend )
505 {
506     return X11DRV_DrawArc( dc, left, top, right, bottom,
507                            xstart, ystart, xend, yend, 1 );
508 }
509
510
511 /***********************************************************************
512  *           X11DRV_Ellipse
513  */
514 BOOL
515 X11DRV_Ellipse( DC *dc, INT left, INT top, INT right, INT bottom )
516 {
517     INT width, oldwidth;
518     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
519     BOOL update = FALSE;
520
521     left   = XLPTODP( dc, left );
522     top    = YLPTODP( dc, top );
523     right  = XLPTODP( dc, right );
524     bottom = YLPTODP( dc, bottom );
525     if ((left == right) || (top == bottom)) return TRUE;
526
527     if (right < left) { INT tmp = right; right = left; left = tmp; }
528     if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
529     
530     oldwidth = width = physDev->pen.width;
531     if (!width) width = 1;
532     if(physDev->pen.style == PS_NULL) width = 0;
533
534     if ((physDev->pen.style == PS_INSIDEFRAME))
535     {
536         if (2*width > (right-left)) width=(right-left + 1)/2;
537         if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
538         left   += width / 2;
539         right  -= (width - 1) / 2;
540         top    += width / 2;
541         bottom -= (width - 1) / 2;
542     }
543     if(width == 0) width = 1; /* more accurate */
544     physDev->pen.width = width;
545
546     /* Update the pixmap from the DIB section */
547     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
548
549     if (X11DRV_SetupGCForBrush( dc ))
550     {
551         TSXFillArc( display, physDev->drawable, physDev->gc,
552                   dc->DCOrgX + left, dc->DCOrgY + top,
553                   right-left-1, bottom-top-1, 0, 360*64 );
554         update = TRUE;
555     }
556     if (X11DRV_SetupGCForPen( dc ))
557     {
558         TSXDrawArc( display, physDev->drawable, physDev->gc,
559                   dc->DCOrgX + left, dc->DCOrgY + top,
560                   right-left-1, bottom-top-1, 0, 360*64 );
561         update = TRUE;
562     }
563
564     /* Update the DIBSection from the pixmap */
565     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
566     
567     physDev->pen.width = oldwidth;
568     return TRUE;
569 }
570
571
572 /***********************************************************************
573  *           X11DRV_Rectangle
574  */
575 BOOL
576 X11DRV_Rectangle(DC *dc, INT left, INT top, INT right, INT bottom)
577 {
578     INT width, oldwidth, oldjoinstyle;
579     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
580     BOOL update = FALSE;
581
582     TRACE("(%d %d %d %d)\n", 
583         left, top, right, bottom);
584
585     left   = XLPTODP( dc, left );
586     top    = YLPTODP( dc, top );
587     right  = XLPTODP( dc, right );
588     bottom = YLPTODP( dc, bottom );
589
590     if ((left == right) || (top == bottom)) return TRUE;
591
592     if (right < left) { INT tmp = right; right = left; left = tmp; }
593     if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
594
595     oldwidth = width = physDev->pen.width;
596     if (!width) width = 1;
597     if(physDev->pen.style == PS_NULL) width = 0;
598
599     if ((physDev->pen.style == PS_INSIDEFRAME))
600     {
601         if (2*width > (right-left)) width=(right-left + 1)/2;
602         if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
603         left   += width / 2;
604         right  -= (width - 1) / 2;
605         top    += width / 2;
606         bottom -= (width - 1) / 2;
607     }
608     if(width == 1) width = 0;
609     physDev->pen.width = width;
610     oldjoinstyle = physDev->pen.linejoin;
611     if(physDev->pen.type != PS_GEOMETRIC)
612         physDev->pen.linejoin = PS_JOIN_MITER;
613
614     /* Update the pixmap from the DIB section */
615     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
616     
617     if ((right > left + width) && (bottom > top + width))
618         if (X11DRV_SetupGCForBrush( dc ))
619         {
620             TSXFillRectangle( display, physDev->drawable, physDev->gc,
621                             dc->DCOrgX + left + (width + 1) / 2,
622                             dc->DCOrgY + top + (width + 1) / 2,
623                             right-left-width-1, bottom-top-width-1);
624             update = TRUE;
625         }
626     if (X11DRV_SetupGCForPen( dc ))
627     {
628         TSXDrawRectangle( display, physDev->drawable, physDev->gc,
629                         dc->DCOrgX + left, dc->DCOrgY + top,
630                         right-left-1, bottom-top-1 );
631         update = TRUE;
632     }
633
634     /* Update the DIBSection from the pixmap */
635     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
636    
637     physDev->pen.width = oldwidth;
638     physDev->pen.linejoin = oldjoinstyle;
639     return TRUE;
640 }
641
642 /***********************************************************************
643  *           X11DRV_RoundRect
644  */
645 BOOL
646 X11DRV_RoundRect( DC *dc, INT left, INT top, INT right,
647                   INT bottom, INT ell_width, INT ell_height )
648 {
649     INT width, oldwidth, oldendcap;
650     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
651     BOOL update = FALSE;
652
653     TRACE("(%d %d %d %d  %d %d\n", 
654         left, top, right, bottom, ell_width, ell_height);
655
656     left   = XLPTODP( dc, left );
657     top    = YLPTODP( dc, top );
658     right  = XLPTODP( dc, right );
659     bottom = YLPTODP( dc, bottom );
660
661     if ((left == right) || (top == bottom))
662         return TRUE;
663
664     /* Make sure ell_width and ell_height are >= 1 otherwise XDrawArc gets
665        called with width/height < 0 */
666     ell_width  = max(abs( ell_width * dc->vportExtX / dc->wndExtX ), 1);
667     ell_height = max(abs( ell_height * dc->vportExtY / dc->wndExtY ), 1);
668
669     /* Fix the coordinates */
670
671     if (right < left) { INT tmp = right; right = left; left = tmp; }
672     if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
673
674     oldwidth = width = physDev->pen.width;
675     oldendcap = physDev->pen.endcap;
676     if (!width) width = 1;
677     if(physDev->pen.style == PS_NULL) width = 0;
678
679     if ((physDev->pen.style == PS_INSIDEFRAME))
680     {
681         if (2*width > (right-left)) width=(right-left + 1)/2;
682         if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
683         left   += width / 2;
684         right  -= (width - 1) / 2;
685         top    += width / 2;
686         bottom -= (width - 1) / 2;
687     }
688     if(width == 0) width = 1;
689     physDev->pen.width = width;
690     physDev->pen.endcap = PS_ENDCAP_SQUARE;
691
692     /* Update the pixmap from the DIB section */
693     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
694  
695     if (X11DRV_SetupGCForBrush( dc ))
696     {
697         if (ell_width > (right-left) )
698             if (ell_height > (bottom-top) )
699                     TSXFillArc( display, physDev->drawable, physDev->gc,
700                                 dc->DCOrgX + left, dc->DCOrgY + top,
701                                 right - left - 1, bottom - top - 1,
702                                 0, 360 * 64 );
703             else{
704                     TSXFillArc( display, physDev->drawable, physDev->gc,
705                                 dc->DCOrgX + left, dc->DCOrgY + top,
706                                 right - left - 1, ell_height, 0, 180 * 64 );
707                     TSXFillArc( display, physDev->drawable, physDev->gc,
708                                 dc->DCOrgX + left,
709                                 dc->DCOrgY + bottom - ell_height - 1,
710                                 right - left - 1, ell_height, 180 * 64,
711                                 180 * 64 );
712            }
713         else if (ell_height > (bottom-top) ){
714                 TSXFillArc( display, physDev->drawable, physDev->gc,
715                       dc->DCOrgX + left, dc->DCOrgY + top,
716                       ell_width, bottom - top - 1, 90 * 64, 180 * 64 );
717                 TSXFillArc( display, physDev->drawable, physDev->gc,
718                       dc->DCOrgX + right - ell_width -1, dc->DCOrgY + top,
719                       ell_width, bottom - top - 1, 270 * 64, 180 * 64 );
720         }else{
721                 TSXFillArc( display, physDev->drawable, physDev->gc,
722                       dc->DCOrgX + left, dc->DCOrgY + top,
723                       ell_width, ell_height, 90 * 64, 90 * 64 );
724                 TSXFillArc( display, physDev->drawable, physDev->gc,
725                       dc->DCOrgX + left,
726                       dc->DCOrgY + bottom - ell_height - 1,
727                       ell_width, ell_height, 180 * 64, 90 * 64 );
728                 TSXFillArc( display, physDev->drawable, physDev->gc,
729                       dc->DCOrgX + right - ell_width - 1,
730                       dc->DCOrgY + bottom - ell_height - 1,
731                       ell_width, ell_height, 270 * 64, 90 * 64 );
732                 TSXFillArc( display, physDev->drawable, physDev->gc,
733                       dc->DCOrgX + right - ell_width - 1,
734                       dc->DCOrgY + top,
735                       ell_width, ell_height, 0, 90 * 64 );
736         }
737         if (ell_width < right - left)
738         {
739             TSXFillRectangle( display, physDev->drawable, physDev->gc,
740                             dc->DCOrgX + left + (ell_width + 1) / 2,
741                             dc->DCOrgY + top + 1,
742                             right - left - ell_width - 1,
743                             (ell_height + 1) / 2 - 1);
744             TSXFillRectangle( display, physDev->drawable, physDev->gc,
745                             dc->DCOrgX + left + (ell_width + 1) / 2,
746                             dc->DCOrgY + bottom - (ell_height) / 2 - 1,
747                             right - left - ell_width - 1,
748                             (ell_height) / 2 );
749         }
750         if  (ell_height < bottom - top)
751         {
752             TSXFillRectangle( display, physDev->drawable, physDev->gc,
753                             dc->DCOrgX + left + 1,
754                             dc->DCOrgY + top + (ell_height + 1) / 2,
755                             right - left - 2,
756                             bottom - top - ell_height - 1);
757         }
758         update = TRUE;
759     }
760     /* FIXME: this could be done with on X call
761      * more efficient and probably more correct
762      * on any X server: XDrawArcs will draw
763      * straight horizontal and vertical lines
764      * if width or height are zero.
765      *
766      * BTW this stuff is optimized for an Xfree86 server
767      * read the comments inside the X11DRV_DrawArc function
768      */
769     if (X11DRV_SetupGCForPen(dc)) {
770         if (ell_width > (right-left) )
771             if (ell_height > (bottom-top) )
772                 TSXDrawArc( display, physDev->drawable, physDev->gc,
773                       dc->DCOrgX + left, dc->DCOrgY + top,
774                       right - left - 1, bottom -top - 1, 0 , 360 * 64 );
775             else{
776                 TSXDrawArc( display, physDev->drawable, physDev->gc,
777                       dc->DCOrgX + left, dc->DCOrgY + top,
778                       right - left - 1, ell_height - 1, 0 , 180 * 64 );
779                 TSXDrawArc( display, physDev->drawable, physDev->gc,
780                       dc->DCOrgX + left, 
781                       dc->DCOrgY + bottom - ell_height,
782                       right - left - 1, ell_height - 1, 180 * 64 , 180 * 64 );
783             }
784         else if (ell_height > (bottom-top) ){
785                 TSXDrawArc( display, physDev->drawable, physDev->gc,
786                       dc->DCOrgX + left, dc->DCOrgY + top,
787                       ell_width - 1 , bottom - top - 1, 90 * 64 , 180 * 64 );
788                 TSXDrawArc( display, physDev->drawable, physDev->gc,
789                       dc->DCOrgX + right - ell_width, 
790                       dc->DCOrgY + top,
791                       ell_width - 1 , bottom - top - 1, 270 * 64 , 180 * 64 );
792         }else{
793             TSXDrawArc( display, physDev->drawable, physDev->gc,
794                       dc->DCOrgX + left, dc->DCOrgY + top,
795                       ell_width - 1, ell_height - 1, 90 * 64, 90 * 64 );
796             TSXDrawArc( display, physDev->drawable, physDev->gc,
797                       dc->DCOrgX + left, dc->DCOrgY + bottom - ell_height,
798                       ell_width - 1, ell_height - 1, 180 * 64, 90 * 64 );
799             TSXDrawArc( display, physDev->drawable, physDev->gc,
800                       dc->DCOrgX + right - ell_width,
801                       dc->DCOrgY + bottom - ell_height,
802                       ell_width - 1, ell_height - 1, 270 * 64, 90 * 64 );
803             TSXDrawArc( display, physDev->drawable, physDev->gc,
804                       dc->DCOrgX + right - ell_width, dc->DCOrgY + top,
805                       ell_width - 1, ell_height - 1, 0, 90 * 64 );
806         }
807         if (ell_width < right - left)
808         {
809             TSXDrawLine( display, physDev->drawable, physDev->gc, 
810                dc->DCOrgX + left + ell_width / 2,
811                        dc->DCOrgY + top,
812                dc->DCOrgX + right - (ell_width+1) / 2,
813                        dc->DCOrgY + top);
814             TSXDrawLine( display, physDev->drawable, physDev->gc, 
815                dc->DCOrgX + left + ell_width / 2 ,
816                        dc->DCOrgY + bottom - 1,
817                dc->DCOrgX + right - (ell_width+1)/ 2,
818                        dc->DCOrgY + bottom - 1);
819         }
820         if (ell_height < bottom - top)
821         {
822             TSXDrawLine( display, physDev->drawable, physDev->gc, 
823                        dc->DCOrgX + right - 1,
824                dc->DCOrgY + top + ell_height / 2,
825                        dc->DCOrgX + right - 1,
826                dc->DCOrgY + bottom - (ell_height+1) / 2);
827             TSXDrawLine( display, physDev->drawable, physDev->gc, 
828                        dc->DCOrgX + left,
829                dc->DCOrgY + top + ell_height / 2,
830                        dc->DCOrgX + left,
831                dc->DCOrgY + bottom - (ell_height+1) / 2);
832         }
833         update = TRUE;
834     }
835     
836     /* Update the DIBSection from the pixmap */
837     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
838
839     physDev->pen.width = oldwidth;
840     physDev->pen.endcap = oldendcap;
841     return TRUE;
842 }
843
844
845 /***********************************************************************
846  *           X11DRV_SetPixel
847  */
848 COLORREF
849 X11DRV_SetPixel( DC *dc, INT x, INT y, COLORREF color )
850 {
851     Pixel pixel;
852     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
853     
854     x = dc->DCOrgX + XLPTODP( dc, x );
855     y = dc->DCOrgY + YLPTODP( dc, y );
856     pixel = X11DRV_PALETTE_ToPhysical( dc, color );
857     
858     TSXSetForeground( display, physDev->gc, pixel );
859     TSXSetFunction( display, physDev->gc, GXcopy );
860     TSXDrawPoint( display, physDev->drawable, physDev->gc, x, y );
861
862     /* inefficient but simple... */
863
864     /* FIXME: the DIBSection pixel should be updated too */
865     
866     return X11DRV_PALETTE_ToLogical(pixel);
867 }
868
869
870 /***********************************************************************
871  *           X11DRV_GetPixel
872  */
873 COLORREF
874 X11DRV_GetPixel( DC *dc, INT x, INT y )
875 {
876     static Pixmap pixmap = 0;
877     XImage * image;
878     int pixel;
879     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
880
881     x = dc->DCOrgX + XLPTODP( dc, x );
882     y = dc->DCOrgY + YLPTODP( dc, y );
883     EnterCriticalSection( &X11DRV_CritSection );
884     if (dc->flags & DC_MEMORY)
885     {
886         image = XGetImage( display, physDev->drawable, x, y, 1, 1,
887                            AllPlanes, ZPixmap );
888     }
889     else
890     {
891         /* If we are reading from the screen, use a temporary copy */
892         /* to avoid a BadMatch error */
893         if (!pixmap) pixmap = XCreatePixmap( display, X11DRV_GetXRootWindow(),
894                                              1, 1, dc->bitsPerPixel );
895         XCopyArea( display, physDev->drawable, pixmap, BITMAP_colorGC,
896                    x, y, 1, 1, 0, 0 );
897         image = XGetImage( display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
898     }
899     pixel = XGetPixel( image, 0, 0 );
900     XDestroyImage( image );
901     LeaveCriticalSection( &X11DRV_CritSection );
902     
903     return X11DRV_PALETTE_ToLogical(pixel);
904 }
905
906
907 /***********************************************************************
908  *           X11DRV_PaintRgn
909  */
910 BOOL
911 X11DRV_PaintRgn( DC *dc, HRGN hrgn )
912 {
913     RECT box;
914     HRGN tmpVisRgn, prevVisRgn;
915     HDC  hdc = dc->hSelf; /* FIXME: should not mix dc/hdc this way */
916     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
917
918     if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
919
920       /* Transform region into device co-ords */
921     if (  !REGION_LPTODP( hdc, tmpVisRgn, hrgn )
922         || OffsetRgn( tmpVisRgn, dc->DCOrgX, dc->DCOrgY ) == ERROR) {
923         DeleteObject( tmpVisRgn );
924         return FALSE;
925     }
926
927       /* Modify visible region */
928     if (!(prevVisRgn = SaveVisRgn16( hdc ))) {
929         DeleteObject( tmpVisRgn );
930         return FALSE;
931     }
932     CombineRgn( tmpVisRgn, prevVisRgn, tmpVisRgn, RGN_AND );
933     SelectVisRgn16( hdc, tmpVisRgn );
934     DeleteObject( tmpVisRgn );
935
936       /* Fill the region */
937
938     GetRgnBox( dc->hGCClipRgn, &box );
939     if (X11DRV_SetupGCForBrush( dc ))
940     {
941         /* Update the pixmap from the DIB section */
942         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
943
944         TSXFillRectangle( display, physDev->drawable, physDev->gc,
945                           box.left, box.top,
946                           box.right-box.left, box.bottom-box.top );
947     
948         /* Update the DIBSection from the pixmap */
949         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
950     }
951
952       /* Restore the visible region */
953
954     RestoreVisRgn16( hdc );
955     return TRUE;
956 }
957
958 /**********************************************************************
959  *          X11DRV_Polyline
960  */
961 BOOL
962 X11DRV_Polyline( DC *dc, const POINT* pt, INT count )
963 {
964     INT oldwidth;
965     register int i;
966     XPoint *points;
967     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
968
969     if((oldwidth = physDev->pen.width) == 0) physDev->pen.width = 1;
970
971     if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * count )))
972     {
973         WARN("No memory to convert POINTs to XPoints!\n");
974         return FALSE;
975     }
976     for (i = 0; i < count; i++)
977     {
978         points[i].x = dc->DCOrgX + XLPTODP( dc, pt[i].x );
979         points[i].y = dc->DCOrgY + YLPTODP( dc, pt[i].y );
980     }
981
982     if (X11DRV_SetupGCForPen ( dc ))
983     {
984         /* Update the pixmap from the DIB section */
985         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
986  
987         TSXDrawLines( display, physDev->drawable, physDev->gc,
988            points, count, CoordModeOrigin );
989
990         /* Update the DIBSection from the pixmap */
991         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
992     }
993
994     HeapFree( GetProcessHeap(), 0, points );
995     physDev->pen.width = oldwidth;
996     return TRUE;
997 }
998
999
1000 /**********************************************************************
1001  *          X11DRV_Polygon
1002  */
1003 BOOL
1004 X11DRV_Polygon( DC *dc, const POINT* pt, INT count )
1005 {
1006     register int i;
1007     XPoint *points;
1008     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1009     BOOL update = FALSE;
1010
1011     if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (count+1) )))
1012     {
1013         WARN("No memory to convert POINTs to XPoints!\n");
1014         return FALSE;
1015     }
1016     for (i = 0; i < count; i++)
1017     {
1018         points[i].x = dc->DCOrgX + XLPTODP( dc, pt[i].x );
1019         points[i].y = dc->DCOrgY + YLPTODP( dc, pt[i].y );
1020     }
1021     points[count] = points[0];
1022
1023     /* Update the pixmap from the DIB section */
1024     X11DRV_DIB_UpdateDIBSection(dc, FALSE);
1025  
1026     if (X11DRV_SetupGCForBrush( dc ))
1027     {
1028         TSXFillPolygon( display, physDev->drawable, physDev->gc,
1029                      points, count+1, Complex, CoordModeOrigin);
1030         update = TRUE;
1031     }
1032     if (X11DRV_SetupGCForPen ( dc ))
1033     {
1034         TSXDrawLines( display, physDev->drawable, physDev->gc,
1035                    points, count+1, CoordModeOrigin );
1036         update = TRUE;
1037     }
1038    
1039     /* Update the DIBSection from the pixmap */
1040     if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE);
1041
1042     HeapFree( GetProcessHeap(), 0, points );
1043     return TRUE;
1044 }
1045
1046
1047 /**********************************************************************
1048  *          X11DRV_PolyPolygon
1049  */
1050 BOOL 
1051 X11DRV_PolyPolygon( DC *dc, const POINT* pt, const INT* counts, UINT polygons)
1052 {
1053     HRGN hrgn;
1054     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1055
1056     /* FIXME: The points should be converted to device coords before */
1057     /* creating the region. */
1058
1059     hrgn = CreatePolyPolygonRgn( pt, counts, polygons, dc->polyFillMode );
1060     X11DRV_PaintRgn( dc, hrgn );
1061     DeleteObject( hrgn );
1062
1063       /* Draw the outline of the polygons */
1064
1065     if (X11DRV_SetupGCForPen ( dc ))
1066     {
1067         int i, j, max = 0;
1068         XPoint *points;
1069
1070         /* Update the pixmap from the DIB section */
1071         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
1072  
1073         for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
1074         if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (max+1) )))
1075         {
1076             WARN("No memory to convert POINTs to XPoints!\n");
1077             return FALSE;
1078         }
1079         for (i = 0; i < polygons; i++)
1080         {
1081             for (j = 0; j < counts[i]; j++)
1082             {
1083                 points[j].x = dc->DCOrgX + XLPTODP( dc, pt->x );
1084                 points[j].y = dc->DCOrgY + YLPTODP( dc, pt->y );
1085                 pt++;
1086             }
1087             points[j] = points[0];
1088             TSXDrawLines( display, physDev->drawable, physDev->gc,
1089                         points, j + 1, CoordModeOrigin );
1090         }
1091         
1092         /* Update the DIBSection of the dc's bitmap */
1093         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
1094
1095         HeapFree( GetProcessHeap(), 0, points );
1096     }
1097     return TRUE;
1098 }
1099
1100
1101 /**********************************************************************
1102  *          X11DRV_PolyPolyline
1103  */
1104 BOOL 
1105 X11DRV_PolyPolyline( DC *dc, const POINT* pt, const DWORD* counts, DWORD polylines )
1106 {
1107     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1108     
1109     if (X11DRV_SetupGCForPen ( dc ))
1110     {
1111         int i, j, max = 0;
1112         XPoint *points;
1113
1114         /* Update the pixmap from the DIB section */
1115         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
1116  
1117         for (i = 0; i < polylines; i++) if (counts[i] > max) max = counts[i];
1118         if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * max )))
1119         {
1120             WARN("No memory to convert POINTs to XPoints!\n");
1121             return FALSE;
1122         }
1123         for (i = 0; i < polylines; i++)
1124         {
1125             for (j = 0; j < counts[i]; j++)
1126             {
1127                 points[j].x = dc->DCOrgX + XLPTODP( dc, pt->x );
1128                 points[j].y = dc->DCOrgY + YLPTODP( dc, pt->y );
1129                 pt++;
1130             }
1131             TSXDrawLines( display, physDev->drawable, physDev->gc,
1132                           points, j, CoordModeOrigin );
1133         }
1134         
1135         /* Update the DIBSection of the dc's bitmap */
1136         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
1137
1138         HeapFree( GetProcessHeap(), 0, points );
1139     }
1140     return TRUE;
1141 }
1142
1143
1144 /**********************************************************************
1145  *          X11DRV_InternalFloodFill
1146  *
1147  * Internal helper function for flood fill.
1148  * (xorg,yorg) is the origin of the X image relative to the drawable.
1149  * (x,y) is relative to the origin of the X image.
1150  */
1151 static void X11DRV_InternalFloodFill(XImage *image, DC *dc,
1152                                      int x, int y,
1153                                      int xOrg, int yOrg,
1154                                      Pixel pixel, WORD fillType )
1155 {
1156     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1157     int left, right;
1158
1159 #define TO_FLOOD(x,y)  ((fillType == FLOODFILLBORDER) ? \
1160                         (XGetPixel(image,x,y) != pixel) : \
1161                         (XGetPixel(image,x,y) == pixel))
1162
1163     if (!TO_FLOOD(x,y)) return;
1164
1165       /* Find left and right boundaries */
1166
1167     left = right = x;
1168     while ((left > 0) && TO_FLOOD( left-1, y )) left--;
1169     while ((right < image->width) && TO_FLOOD( right, y )) right++;
1170     XFillRectangle( display, physDev->drawable, physDev->gc,
1171                     xOrg + left, yOrg + y, right-left, 1 );
1172
1173       /* Set the pixels of this line so we don't fill it again */
1174
1175     for (x = left; x < right; x++)
1176     {
1177         if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
1178         else XPutPixel( image, x, y, ~pixel );
1179     }
1180
1181       /* Fill the line above */
1182
1183     if (--y >= 0)
1184     {
1185         x = left;
1186         while (x < right)
1187         {
1188             while ((x < right) && !TO_FLOOD(x,y)) x++;
1189             if (x >= right) break;
1190             while ((x < right) && TO_FLOOD(x,y)) x++;
1191             X11DRV_InternalFloodFill(image, dc, x-1, y,
1192                                      xOrg, yOrg, pixel, fillType );
1193         }
1194     }
1195
1196       /* Fill the line below */
1197
1198     if ((y += 2) < image->height)
1199     {
1200         x = left;
1201         while (x < right)
1202         {
1203             while ((x < right) && !TO_FLOOD(x,y)) x++;
1204             if (x >= right) break;
1205             while ((x < right) && TO_FLOOD(x,y)) x++;
1206             X11DRV_InternalFloodFill(image, dc, x-1, y,
1207                                      xOrg, yOrg, pixel, fillType );
1208         }
1209     }
1210 #undef TO_FLOOD    
1211 }
1212
1213
1214 /**********************************************************************
1215  *          X11DRV_DoFloodFill
1216  *
1217  * Main flood-fill routine.
1218  *
1219  * The Xlib critical section must be entered before calling this function.
1220  */
1221
1222 struct FloodFill_params
1223 {
1224     DC      *dc;
1225     INT    x;
1226     INT    y;
1227     COLORREF color;
1228     UINT   fillType;
1229 };
1230
1231 static BOOL X11DRV_DoFloodFill( const struct FloodFill_params *params )
1232 {
1233     XImage *image;
1234     RECT rect;
1235     DC *dc = params->dc;
1236     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1237
1238     if (GetRgnBox( dc->hGCClipRgn, &rect ) == ERROR) return FALSE;
1239
1240     if (!(image = XGetImage( display, physDev->drawable,
1241                              rect.left,
1242                              rect.top,
1243                              rect.right - rect.left,
1244                              rect.bottom - rect.top,
1245                              AllPlanes, ZPixmap ))) return FALSE;
1246
1247     if (X11DRV_SetupGCForBrush( dc ))
1248     {
1249         /* Update the pixmap from the DIB section */
1250         X11DRV_DIB_UpdateDIBSection(dc, FALSE);
1251  
1252           /* ROP mode is always GXcopy for flood-fill */
1253         XSetFunction( display, physDev->gc, GXcopy );
1254         X11DRV_InternalFloodFill(image, dc,
1255                                  XLPTODP(dc,params->x) + dc->DCOrgX - rect.left,
1256                                  YLPTODP(dc,params->y) + dc->DCOrgY - rect.top,
1257                                  rect.left,
1258                                  rect.top,
1259                                  X11DRV_PALETTE_ToPhysical( dc, params->color ),
1260                                  params->fillType );
1261         
1262         /* Update the DIBSection of the dc's bitmap */
1263         X11DRV_DIB_UpdateDIBSection(dc, TRUE);
1264     }
1265
1266     XDestroyImage( image );
1267     return TRUE;
1268 }
1269
1270
1271 /**********************************************************************
1272  *          X11DRV_ExtFloodFill
1273  */
1274 BOOL
1275 X11DRV_ExtFloodFill( DC *dc, INT x, INT y, COLORREF color,
1276                      UINT fillType )
1277 {
1278     BOOL result;
1279     struct FloodFill_params params;
1280
1281     TRACE("X11DRV_ExtFloodFill %d,%d %06lx %d\n",
1282                       x, y, color, fillType );
1283
1284     params.dc = dc;
1285     params.x = x;
1286     params.y = y;
1287     params.color = color;
1288     params.fillType = fillType;
1289
1290     if (!PtVisible( dc->hSelf, x, y )) return FALSE;
1291     EnterCriticalSection( &X11DRV_CritSection );
1292     result = CALL_LARGE_STACK( X11DRV_DoFloodFill, &params );
1293     LeaveCriticalSection( &X11DRV_CritSection );
1294     return result;
1295 }
1296
1297 /**********************************************************************
1298  *          X11DRV_SetBkColor
1299  */
1300 COLORREF
1301 X11DRV_SetBkColor( DC *dc, COLORREF color )
1302 {
1303     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1304     COLORREF oldColor;
1305
1306     oldColor = dc->backgroundColor;
1307     dc->backgroundColor = color;
1308
1309     physDev->backgroundPixel = X11DRV_PALETTE_ToPhysical( dc, color );
1310
1311     return oldColor;
1312 }
1313
1314 /**********************************************************************
1315  *          X11DRV_SetTextColor
1316  */
1317 COLORREF
1318 X11DRV_SetTextColor( DC *dc, COLORREF color )
1319 {
1320     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1321     COLORREF oldColor;
1322
1323     oldColor = dc->textColor;
1324     dc->textColor = color;
1325
1326     physDev->textPixel = X11DRV_PALETTE_ToPhysical( dc, color );
1327
1328     return oldColor;
1329 }
1330
1331 /***********************************************************************
1332  *           X11DRV_GetDCOrgEx
1333  */
1334 BOOL X11DRV_GetDCOrgEx( DC *dc, LPPOINT lpp )
1335 {
1336     if (!(dc->flags & DC_MEMORY))
1337     {
1338        X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *) dc->physDev;
1339        Window root;
1340        int w, h, border, depth;
1341
1342        /* FIXME: this is not correct for managed windows */
1343        TSXGetGeometry( display, physDev->drawable, &root,
1344                        (int*)&lpp->x, (int*)&lpp->y, &w, &h, &border, &depth );
1345     }
1346     else lpp->x = lpp->y = 0;
1347     return TRUE;
1348 }
1349