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