kernel32: Silence a fixme in GetNativeSystemInfo.
[wine/multimedia.git] / dlls / winex11.drv / graphics.c
blobe580fd6fa30c72c188e5417902d8bc9d68603f1b
1 /*
2 * X11 graphics driver graphics functions
4 * Copyright 1993,1994 Alexandre Julliard
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * FIXME: only some of these functions obey the GM_ADVANCED
23 * graphics mode
26 #include "config.h"
28 #include <math.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include <stdlib.h>
33 #ifndef PI
34 #define PI M_PI
35 #endif
36 #include <string.h>
38 #include "x11drv.h"
39 #include "x11font.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(graphics);
44 #define ABS(x) ((x)<0?(-(x)):(x))
46 /* ROP code to GC function conversion */
47 const int X11DRV_XROPfunction[16] =
49 GXclear, /* R2_BLACK */
50 GXnor, /* R2_NOTMERGEPEN */
51 GXandInverted, /* R2_MASKNOTPEN */
52 GXcopyInverted, /* R2_NOTCOPYPEN */
53 GXandReverse, /* R2_MASKPENNOT */
54 GXinvert, /* R2_NOT */
55 GXxor, /* R2_XORPEN */
56 GXnand, /* R2_NOTMASKPEN */
57 GXand, /* R2_MASKPEN */
58 GXequiv, /* R2_NOTXORPEN */
59 GXnoop, /* R2_NOP */
60 GXorInverted, /* R2_MERGENOTPEN */
61 GXcopy, /* R2_COPYPEN */
62 GXorReverse, /* R2_MERGEPENNOT */
63 GXor, /* R2_MERGEPEN */
64 GXset /* R2_WHITE */
68 /***********************************************************************
69 * X11DRV_SetupGCForPatBlt
71 * Setup the GC for a PatBlt operation using current brush.
72 * If fMapColors is TRUE, X pixels are mapped to Windows colors.
73 * Return FALSE if brush is BS_NULL, TRUE otherwise.
75 BOOL X11DRV_SetupGCForPatBlt( X11DRV_PDEVICE *physDev, GC gc, BOOL fMapColors )
77 XGCValues val;
78 unsigned long mask;
79 Pixmap pixmap = 0;
80 POINT pt;
82 if (physDev->brush.style == BS_NULL) return FALSE;
83 if (physDev->brush.pixel == -1)
85 /* Special case used for monochrome pattern brushes.
86 * We need to swap foreground and background because
87 * Windows does it the wrong way...
89 val.foreground = physDev->backgroundPixel;
90 val.background = physDev->textPixel;
92 else
94 val.foreground = physDev->brush.pixel;
95 val.background = physDev->backgroundPixel;
97 if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
99 val.foreground = X11DRV_PALETTE_XPixelToPalette[val.foreground];
100 val.background = X11DRV_PALETTE_XPixelToPalette[val.background];
103 val.function = X11DRV_XROPfunction[GetROP2(physDev->hdc)-1];
105 ** Let's replace GXinvert by GXxor with (black xor white)
106 ** This solves the selection color and leak problems in excel
107 ** FIXME : Let's do that only if we work with X-pixels, not with Win-pixels
109 if (val.function == GXinvert)
111 val.foreground = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
112 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
113 val.function = GXxor;
115 val.fill_style = physDev->brush.fillStyle;
116 switch(val.fill_style)
118 case FillStippled:
119 case FillOpaqueStippled:
120 if (GetBkMode(physDev->hdc)==OPAQUE) val.fill_style = FillOpaqueStippled;
121 val.stipple = physDev->brush.pixmap;
122 mask = GCStipple;
123 break;
125 case FillTiled:
126 if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
128 register int x, y;
129 XImage *image;
130 wine_tsx11_lock();
131 pixmap = XCreatePixmap( gdi_display, root_window, 8, 8, screen_depth );
132 image = XGetImage( gdi_display, physDev->brush.pixmap, 0, 0, 8, 8,
133 AllPlanes, ZPixmap );
134 for (y = 0; y < 8; y++)
135 for (x = 0; x < 8; x++)
136 XPutPixel( image, x, y,
137 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y)] );
138 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, 8, 8 );
139 XDestroyImage( image );
140 wine_tsx11_unlock();
141 val.tile = pixmap;
143 else val.tile = physDev->brush.pixmap;
144 mask = GCTile;
145 break;
147 default:
148 mask = 0;
149 break;
151 GetBrushOrgEx( physDev->hdc, &pt );
152 val.ts_x_origin = physDev->dc_rect.left + pt.x;
153 val.ts_y_origin = physDev->dc_rect.top + pt.y;
154 val.fill_rule = (GetPolyFillMode(physDev->hdc) == WINDING) ? WindingRule : EvenOddRule;
155 wine_tsx11_lock();
156 XChangeGC( gdi_display, gc,
157 GCFunction | GCForeground | GCBackground | GCFillStyle |
158 GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
159 &val );
160 if (pixmap) XFreePixmap( gdi_display, pixmap );
161 wine_tsx11_unlock();
162 return TRUE;
166 /***********************************************************************
167 * X11DRV_SetupGCForBrush
169 * Setup physDev->gc for drawing operations using current brush.
170 * Return FALSE if brush is BS_NULL, TRUE otherwise.
172 BOOL X11DRV_SetupGCForBrush( X11DRV_PDEVICE *physDev )
174 return X11DRV_SetupGCForPatBlt( physDev, physDev->gc, FALSE );
178 /***********************************************************************
179 * X11DRV_SetupGCForPen
181 * Setup physDev->gc for drawing operations using current pen.
182 * Return FALSE if pen is PS_NULL, TRUE otherwise.
184 BOOL X11DRV_SetupGCForPen( X11DRV_PDEVICE *physDev )
186 XGCValues val;
187 UINT rop2 = GetROP2(physDev->hdc);
189 if (physDev->pen.style == PS_NULL) return FALSE;
191 switch (rop2)
193 case R2_BLACK :
194 val.foreground = BlackPixel( gdi_display, DefaultScreen(gdi_display) );
195 val.function = GXcopy;
196 break;
197 case R2_WHITE :
198 val.foreground = WhitePixel( gdi_display, DefaultScreen(gdi_display) );
199 val.function = GXcopy;
200 break;
201 case R2_XORPEN :
202 val.foreground = physDev->pen.pixel;
203 /* It is very unlikely someone wants to XOR with 0 */
204 /* This fixes the rubber-drawings in paintbrush */
205 if (val.foreground == 0)
206 val.foreground = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
207 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
208 val.function = GXxor;
209 break;
210 default :
211 val.foreground = physDev->pen.pixel;
212 val.function = X11DRV_XROPfunction[rop2-1];
214 val.background = physDev->backgroundPixel;
215 val.fill_style = FillSolid;
216 val.line_width = physDev->pen.width;
217 if (val.line_width <= 1) {
218 val.cap_style = CapNotLast;
219 } else {
220 switch (physDev->pen.endcap)
222 case PS_ENDCAP_SQUARE:
223 val.cap_style = CapProjecting;
224 break;
225 case PS_ENDCAP_FLAT:
226 val.cap_style = CapButt;
227 break;
228 case PS_ENDCAP_ROUND:
229 default:
230 val.cap_style = CapRound;
233 switch (physDev->pen.linejoin)
235 case PS_JOIN_BEVEL:
236 val.join_style = JoinBevel;
237 break;
238 case PS_JOIN_MITER:
239 val.join_style = JoinMiter;
240 break;
241 case PS_JOIN_ROUND:
242 default:
243 val.join_style = JoinRound;
246 if (physDev->pen.dash_len)
247 val.line_style = ((GetBkMode(physDev->hdc) == OPAQUE) && (!physDev->pen.ext))
248 ? LineDoubleDash : LineOnOffDash;
249 else
250 val.line_style = LineSolid;
252 wine_tsx11_lock();
253 if (physDev->pen.dash_len)
254 XSetDashes( gdi_display, physDev->gc, 0, physDev->pen.dashes, physDev->pen.dash_len );
255 XChangeGC( gdi_display, physDev->gc,
256 GCFunction | GCForeground | GCBackground | GCLineWidth |
257 GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
258 wine_tsx11_unlock();
259 return TRUE;
263 /***********************************************************************
264 * X11DRV_SetupGCForText
266 * Setup physDev->gc for text drawing operations.
267 * Return FALSE if the font is null, TRUE otherwise.
269 BOOL X11DRV_SetupGCForText( X11DRV_PDEVICE *physDev )
271 XFontStruct* xfs = XFONT_GetFontStruct( physDev->font );
273 if( xfs )
275 XGCValues val;
277 val.function = GXcopy; /* Text is always GXcopy */
278 val.foreground = physDev->textPixel;
279 val.background = physDev->backgroundPixel;
280 val.fill_style = FillSolid;
281 val.font = xfs->fid;
283 wine_tsx11_lock();
284 XChangeGC( gdi_display, physDev->gc,
285 GCFunction | GCForeground | GCBackground | GCFillStyle |
286 GCFont, &val );
287 wine_tsx11_unlock();
288 return TRUE;
290 WARN("Physical font failure\n" );
291 return FALSE;
294 /***********************************************************************
295 * X11DRV_XWStoDS
297 * Performs a world-to-viewport transformation on the specified width.
299 INT X11DRV_XWStoDS( X11DRV_PDEVICE *physDev, INT width )
301 POINT pt[2];
303 pt[0].x = 0;
304 pt[0].y = 0;
305 pt[1].x = width;
306 pt[1].y = 0;
307 LPtoDP( physDev->hdc, pt, 2 );
308 return pt[1].x - pt[0].x;
311 /***********************************************************************
312 * X11DRV_YWStoDS
314 * Performs a world-to-viewport transformation on the specified height.
316 INT X11DRV_YWStoDS( X11DRV_PDEVICE *physDev, INT height )
318 POINT pt[2];
320 pt[0].x = 0;
321 pt[0].y = 0;
322 pt[1].x = 0;
323 pt[1].y = height;
324 LPtoDP( physDev->hdc, pt, 2 );
325 return pt[1].y - pt[0].y;
328 /***********************************************************************
329 * X11DRV_LineTo
331 BOOL
332 X11DRV_LineTo( X11DRV_PDEVICE *physDev, INT x, INT y )
334 POINT pt[2];
336 if (X11DRV_SetupGCForPen( physDev )) {
337 /* Update the pixmap from the DIB section */
338 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
340 GetCurrentPositionEx( physDev->hdc, &pt[0] );
341 pt[1].x = x;
342 pt[1].y = y;
343 LPtoDP( physDev->hdc, pt, 2 );
345 wine_tsx11_lock();
346 XDrawLine(gdi_display, physDev->drawable, physDev->gc,
347 physDev->dc_rect.left + pt[0].x, physDev->dc_rect.top + pt[0].y,
348 physDev->dc_rect.left + pt[1].x, physDev->dc_rect.top + pt[1].y );
349 wine_tsx11_unlock();
351 /* Update the DIBSection from the pixmap */
352 X11DRV_UnlockDIBSection(physDev, TRUE);
354 return TRUE;
359 /***********************************************************************
360 * X11DRV_DrawArc
362 * Helper functions for Arc(), Chord() and Pie().
363 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
366 static BOOL
367 X11DRV_DrawArc( X11DRV_PDEVICE *physDev, INT left, INT top, INT right,
368 INT bottom, INT xstart, INT ystart,
369 INT xend, INT yend, INT lines )
371 INT xcenter, ycenter, istart_angle, idiff_angle;
372 INT width, oldwidth;
373 double start_angle, end_angle;
374 XPoint points[4];
375 BOOL update = FALSE;
376 POINT start, end;
377 RECT rc;
379 SetRect(&rc, left, top, right, bottom);
380 start.x = xstart;
381 start.y = ystart;
382 end.x = xend;
383 end.y = yend;
384 LPtoDP(physDev->hdc, (POINT*)&rc, 2);
385 LPtoDP(physDev->hdc, &start, 1);
386 LPtoDP(physDev->hdc, &end, 1);
388 if (rc.right < rc.left) { INT tmp = rc.right; rc.right = rc.left; rc.left = tmp; }
389 if (rc.bottom < rc.top) { INT tmp = rc.bottom; rc.bottom = rc.top; rc.top = tmp; }
390 if ((rc.left == rc.right) || (rc.top == rc.bottom)
391 ||(lines && ((rc.right-rc.left==1)||(rc.bottom-rc.top==1)))) return TRUE;
393 if (GetArcDirection( physDev->hdc ) == AD_CLOCKWISE)
394 { POINT tmp = start; start = end; end = tmp; }
396 oldwidth = width = physDev->pen.width;
397 if (!width) width = 1;
398 if(physDev->pen.style == PS_NULL) width = 0;
400 if ((physDev->pen.style == PS_INSIDEFRAME))
402 if (2*width > (rc.right-rc.left)) width=(rc.right-rc.left + 1)/2;
403 if (2*width > (rc.bottom-rc.top)) width=(rc.bottom-rc.top + 1)/2;
404 rc.left += width / 2;
405 rc.right -= (width - 1) / 2;
406 rc.top += width / 2;
407 rc.bottom -= (width - 1) / 2;
409 if(width == 0) width = 1; /* more accurate */
410 physDev->pen.width = width;
412 xcenter = (rc.right + rc.left) / 2;
413 ycenter = (rc.bottom + rc.top) / 2;
414 start_angle = atan2( (double)(ycenter-start.y)*(rc.right-rc.left),
415 (double)(start.x-xcenter)*(rc.bottom-rc.top) );
416 end_angle = atan2( (double)(ycenter-end.y)*(rc.right-rc.left),
417 (double)(end.x-xcenter)*(rc.bottom-rc.top) );
418 if ((start.x==end.x)&&(start.y==end.y))
419 { /* A lazy program delivers xstart=xend=ystart=yend=0) */
420 start_angle = 0;
421 end_angle = 2* PI;
423 else /* notorious cases */
424 if ((start_angle == PI)&&( end_angle <0))
425 start_angle = - PI;
426 else
427 if ((end_angle == PI)&&( start_angle <0))
428 end_angle = - PI;
429 istart_angle = (INT)(start_angle * 180 * 64 / PI + 0.5);
430 idiff_angle = (INT)((end_angle - start_angle) * 180 * 64 / PI + 0.5);
431 if (idiff_angle <= 0) idiff_angle += 360 * 64;
433 /* Update the pixmap from the DIB section */
434 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
436 /* Fill arc with brush if Chord() or Pie() */
438 if ((lines > 0) && X11DRV_SetupGCForBrush( physDev )) {
439 wine_tsx11_lock();
440 XSetArcMode( gdi_display, physDev->gc, (lines==1) ? ArcChord : ArcPieSlice);
441 XFillArc( gdi_display, physDev->drawable, physDev->gc,
442 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
443 rc.right-rc.left-1, rc.bottom-rc.top-1, istart_angle, idiff_angle );
444 wine_tsx11_unlock();
445 update = TRUE;
448 /* Draw arc and lines */
450 if (X11DRV_SetupGCForPen( physDev ))
452 wine_tsx11_lock();
453 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
454 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
455 rc.right-rc.left-1, rc.bottom-rc.top-1, istart_angle, idiff_angle );
456 if (lines) {
457 /* use the truncated values */
458 start_angle=(double)istart_angle*PI/64./180.;
459 end_angle=(double)(istart_angle+idiff_angle)*PI/64./180.;
460 /* calculate the endpoints and round correctly */
461 points[0].x = (int) floor(physDev->dc_rect.left + (rc.right+rc.left)/2.0 +
462 cos(start_angle) * (rc.right-rc.left-width*2+2) / 2. + 0.5);
463 points[0].y = (int) floor(physDev->dc_rect.top + (rc.top+rc.bottom)/2.0 -
464 sin(start_angle) * (rc.bottom-rc.top-width*2+2) / 2. + 0.5);
465 points[1].x = (int) floor(physDev->dc_rect.left + (rc.right+rc.left)/2.0 +
466 cos(end_angle) * (rc.right-rc.left-width*2+2) / 2. + 0.5);
467 points[1].y = (int) floor(physDev->dc_rect.top + (rc.top+rc.bottom)/2.0 -
468 sin(end_angle) * (rc.bottom-rc.top-width*2+2) / 2. + 0.5);
470 /* OK, this stuff is optimized for Xfree86
471 * which is probably the server most used by
472 * wine users. Other X servers will not
473 * display correctly. (eXceed for instance)
474 * so if you feel you must make changes, make sure that
475 * you either use Xfree86 or separate your changes
476 * from these (compile switch or whatever)
478 if (lines == 2) {
479 INT dx1,dy1;
480 points[3] = points[1];
481 points[1].x = physDev->dc_rect.left + xcenter;
482 points[1].y = physDev->dc_rect.top + ycenter;
483 points[2] = points[1];
484 dx1=points[1].x-points[0].x;
485 dy1=points[1].y-points[0].y;
486 if(((rc.top-rc.bottom) | -2) == -2)
487 if(dy1>0) points[1].y--;
488 if(dx1<0) {
489 if (((-dx1)*64)<=ABS(dy1)*37) points[0].x--;
490 if(((-dx1*9))<(dy1*16)) points[0].y--;
491 if( dy1<0 && ((dx1*9)) < (dy1*16)) points[0].y--;
492 } else {
493 if(dy1 < 0) points[0].y--;
494 if(((rc.right-rc.left) | -2) == -2) points[1].x--;
496 dx1=points[3].x-points[2].x;
497 dy1=points[3].y-points[2].y;
498 if(((rc.top-rc.bottom) | -2 ) == -2)
499 if(dy1 < 0) points[2].y--;
500 if( dx1<0){
501 if( dy1>0) points[3].y--;
502 if(((rc.right-rc.left) | -2) == -2 ) points[2].x--;
503 }else {
504 points[3].y--;
505 if( dx1 * 64 < dy1 * -37 ) points[3].x--;
507 lines++;
509 XDrawLines( gdi_display, physDev->drawable, physDev->gc,
510 points, lines+1, CoordModeOrigin );
512 wine_tsx11_unlock();
513 update = TRUE;
516 /* Update the DIBSection of the pixmap */
517 X11DRV_UnlockDIBSection(physDev, update);
519 physDev->pen.width = oldwidth;
520 return TRUE;
524 /***********************************************************************
525 * X11DRV_Arc
527 BOOL
528 X11DRV_Arc( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
529 INT xstart, INT ystart, INT xend, INT yend )
531 return X11DRV_DrawArc( physDev, left, top, right, bottom,
532 xstart, ystart, xend, yend, 0 );
536 /***********************************************************************
537 * X11DRV_Pie
539 BOOL
540 X11DRV_Pie( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
541 INT xstart, INT ystart, INT xend, INT yend )
543 return X11DRV_DrawArc( physDev, left, top, right, bottom,
544 xstart, ystart, xend, yend, 2 );
547 /***********************************************************************
548 * X11DRV_Chord
550 BOOL
551 X11DRV_Chord( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
552 INT xstart, INT ystart, INT xend, INT yend )
554 return X11DRV_DrawArc( physDev, left, top, right, bottom,
555 xstart, ystart, xend, yend, 1 );
559 /***********************************************************************
560 * X11DRV_Ellipse
562 BOOL
563 X11DRV_Ellipse( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom )
565 INT width, oldwidth;
566 BOOL update = FALSE;
567 RECT rc;
569 SetRect(&rc, left, top, right, bottom);
570 LPtoDP(physDev->hdc, (POINT*)&rc, 2);
572 if ((rc.left == rc.right) || (rc.top == rc.bottom)) return TRUE;
574 if (rc.right < rc.left) { INT tmp = rc.right; rc.right = rc.left; rc.left = tmp; }
575 if (rc.bottom < rc.top) { INT tmp = rc.bottom; rc.bottom = rc.top; rc.top = tmp; }
577 oldwidth = width = physDev->pen.width;
578 if (!width) width = 1;
579 if(physDev->pen.style == PS_NULL) width = 0;
581 if ((physDev->pen.style == PS_INSIDEFRAME))
583 if (2*width > (rc.right-rc.left)) width=(rc.right-rc.left + 1)/2;
584 if (2*width > (rc.bottom-rc.top)) width=(rc.bottom-rc.top + 1)/2;
585 rc.left += width / 2;
586 rc.right -= (width - 1) / 2;
587 rc.top += width / 2;
588 rc.bottom -= (width - 1) / 2;
590 if(width == 0) width = 1; /* more accurate */
591 physDev->pen.width = width;
593 /* Update the pixmap from the DIB section */
594 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
596 if (X11DRV_SetupGCForBrush( physDev ))
598 wine_tsx11_lock();
599 XFillArc( gdi_display, physDev->drawable, physDev->gc,
600 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
601 rc.right-rc.left-1, rc.bottom-rc.top-1, 0, 360*64 );
602 wine_tsx11_unlock();
603 update = TRUE;
605 if (X11DRV_SetupGCForPen( physDev ))
607 wine_tsx11_lock();
608 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
609 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
610 rc.right-rc.left-1, rc.bottom-rc.top-1, 0, 360*64 );
611 wine_tsx11_unlock();
612 update = TRUE;
615 /* Update the DIBSection from the pixmap */
616 X11DRV_UnlockDIBSection(physDev, update);
618 physDev->pen.width = oldwidth;
619 return TRUE;
623 /***********************************************************************
624 * X11DRV_Rectangle
626 BOOL
627 X11DRV_Rectangle(X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom)
629 INT width, oldwidth, oldjoinstyle;
630 BOOL update = FALSE;
631 RECT rc;
633 TRACE("(%d %d %d %d)\n", left, top, right, bottom);
635 SetRect(&rc, left, top, right, bottom);
636 LPtoDP(physDev->hdc, (POINT*)&rc, 2);
638 if ((rc.left == rc.right) || (rc.top == rc.bottom)) return TRUE;
640 if (rc.right < rc.left) { INT tmp = rc.right; rc.right = rc.left; rc.left = tmp; }
641 if (rc.bottom < rc.top) { INT tmp = rc.bottom; rc.bottom = rc.top; rc.top = tmp; }
643 oldwidth = width = physDev->pen.width;
644 if (!width) width = 1;
645 if(physDev->pen.style == PS_NULL) width = 0;
647 if ((physDev->pen.style == PS_INSIDEFRAME))
649 if (2*width > (rc.right-rc.left)) width=(rc.right-rc.left + 1)/2;
650 if (2*width > (rc.bottom-rc.top)) width=(rc.bottom-rc.top + 1)/2;
651 rc.left += width / 2;
652 rc.right -= (width - 1) / 2;
653 rc.top += width / 2;
654 rc.bottom -= (width - 1) / 2;
656 if(width == 1) width = 0;
657 physDev->pen.width = width;
658 oldjoinstyle = physDev->pen.linejoin;
659 if(physDev->pen.type != PS_GEOMETRIC)
660 physDev->pen.linejoin = PS_JOIN_MITER;
662 /* Update the pixmap from the DIB section */
663 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
665 if ((rc.right > rc.left + width) && (rc.bottom > rc.top + width))
667 if (X11DRV_SetupGCForBrush( physDev ))
669 wine_tsx11_lock();
670 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
671 physDev->dc_rect.left + rc.left + (width + 1) / 2,
672 physDev->dc_rect.top + rc.top + (width + 1) / 2,
673 rc.right-rc.left-width-1, rc.bottom-rc.top-width-1);
674 wine_tsx11_unlock();
675 update = TRUE;
678 if (X11DRV_SetupGCForPen( physDev ))
680 wine_tsx11_lock();
681 XDrawRectangle( gdi_display, physDev->drawable, physDev->gc,
682 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
683 rc.right-rc.left-1, rc.bottom-rc.top-1 );
684 wine_tsx11_unlock();
685 update = TRUE;
688 /* Update the DIBSection from the pixmap */
689 X11DRV_UnlockDIBSection(physDev, update);
691 physDev->pen.width = oldwidth;
692 physDev->pen.linejoin = oldjoinstyle;
693 return TRUE;
696 /***********************************************************************
697 * X11DRV_RoundRect
699 BOOL
700 X11DRV_RoundRect( X11DRV_PDEVICE *physDev, INT left, INT top, INT right,
701 INT bottom, INT ell_width, INT ell_height )
703 INT width, oldwidth, oldendcap;
704 BOOL update = FALSE;
705 RECT rc;
706 POINT pts[2];
708 TRACE("(%d %d %d %d %d %d\n",
709 left, top, right, bottom, ell_width, ell_height);
711 SetRect(&rc, left, top, right, bottom);
712 LPtoDP(physDev->hdc, (POINT*)&rc, 2);
714 if ((rc.left == rc.right) || (rc.top == rc.bottom))
715 return TRUE;
717 /* Make sure ell_width and ell_height are >= 1 otherwise XDrawArc gets
718 called with width/height < 0 */
719 pts[0].x = pts[0].y = 0;
720 pts[1].x = ell_width;
721 pts[1].y = ell_height;
722 LPtoDP(physDev->hdc, pts, 2);
723 ell_width = max(abs( pts[1].x - pts[0].x ), 1);
724 ell_height = max(abs( pts[1].y - pts[0].y ), 1);
726 /* Fix the coordinates */
728 if (rc.right < rc.left) { INT tmp = rc.right; rc.right = rc.left; rc.left = tmp; }
729 if (rc.bottom < rc.top) { INT tmp = rc.bottom; rc.bottom = rc.top; rc.top = tmp; }
731 oldwidth = width = physDev->pen.width;
732 oldendcap = physDev->pen.endcap;
733 if (!width) width = 1;
734 if(physDev->pen.style == PS_NULL) width = 0;
736 if ((physDev->pen.style == PS_INSIDEFRAME))
738 if (2*width > (rc.right-rc.left)) width=(rc.right-rc.left + 1)/2;
739 if (2*width > (rc.bottom-rc.top)) width=(rc.bottom-rc.top + 1)/2;
740 rc.left += width / 2;
741 rc.right -= (width - 1) / 2;
742 rc.top += width / 2;
743 rc.bottom -= (width - 1) / 2;
745 if(width == 0) width = 1;
746 physDev->pen.width = width;
747 physDev->pen.endcap = PS_ENDCAP_SQUARE;
749 /* Update the pixmap from the DIB section */
750 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
752 if (X11DRV_SetupGCForBrush( physDev ))
754 wine_tsx11_lock();
755 if (ell_width > (rc.right-rc.left) )
756 if (ell_height > (rc.bottom-rc.top) )
757 XFillArc( gdi_display, physDev->drawable, physDev->gc,
758 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
759 rc.right - rc.left - 1, rc.bottom - rc.top - 1,
760 0, 360 * 64 );
761 else{
762 XFillArc( gdi_display, physDev->drawable, physDev->gc,
763 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
764 rc.right - rc.left - 1, ell_height, 0, 180 * 64 );
765 XFillArc( gdi_display, physDev->drawable, physDev->gc,
766 physDev->dc_rect.left + rc.left,
767 physDev->dc_rect.top + rc.bottom - ell_height - 1,
768 rc.right - rc.left - 1, ell_height, 180 * 64,
769 180 * 64 );
771 else if (ell_height > (rc.bottom-rc.top) ){
772 XFillArc( gdi_display, physDev->drawable, physDev->gc,
773 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
774 ell_width, rc.bottom - rc.top - 1, 90 * 64, 180 * 64 );
775 XFillArc( gdi_display, physDev->drawable, physDev->gc,
776 physDev->dc_rect.left + rc.right - ell_width - 1, physDev->dc_rect.top + rc.top,
777 ell_width, rc.bottom - rc.top - 1, 270 * 64, 180 * 64 );
778 }else{
779 XFillArc( gdi_display, physDev->drawable, physDev->gc,
780 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
781 ell_width, ell_height, 90 * 64, 90 * 64 );
782 XFillArc( gdi_display, physDev->drawable, physDev->gc,
783 physDev->dc_rect.left + rc.left,
784 physDev->dc_rect.top + rc.bottom - ell_height - 1,
785 ell_width, ell_height, 180 * 64, 90 * 64 );
786 XFillArc( gdi_display, physDev->drawable, physDev->gc,
787 physDev->dc_rect.left + rc.right - ell_width - 1,
788 physDev->dc_rect.top + rc.bottom - ell_height - 1,
789 ell_width, ell_height, 270 * 64, 90 * 64 );
790 XFillArc( gdi_display, physDev->drawable, physDev->gc,
791 physDev->dc_rect.left + rc.right - ell_width - 1,
792 physDev->dc_rect.top + rc.top,
793 ell_width, ell_height, 0, 90 * 64 );
795 if (ell_width < rc.right - rc.left)
797 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
798 physDev->dc_rect.left + rc.left + (ell_width + 1) / 2,
799 physDev->dc_rect.top + rc.top + 1,
800 rc.right - rc.left - ell_width - 1,
801 (ell_height + 1) / 2 - 1);
802 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
803 physDev->dc_rect.left + rc.left + (ell_width + 1) / 2,
804 physDev->dc_rect.top + rc.bottom - (ell_height) / 2 - 1,
805 rc.right - rc.left - ell_width - 1,
806 (ell_height) / 2 );
808 if (ell_height < rc.bottom - rc.top)
810 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
811 physDev->dc_rect.left + rc.left + 1,
812 physDev->dc_rect.top + rc.top + (ell_height + 1) / 2,
813 rc.right - rc.left - 2,
814 rc.bottom - rc.top - ell_height - 1);
816 wine_tsx11_unlock();
817 update = TRUE;
819 /* FIXME: this could be done with on X call
820 * more efficient and probably more correct
821 * on any X server: XDrawArcs will draw
822 * straight horizontal and vertical lines
823 * if width or height are zero.
825 * BTW this stuff is optimized for an Xfree86 server
826 * read the comments inside the X11DRV_DrawArc function
828 if (X11DRV_SetupGCForPen( physDev ))
830 wine_tsx11_lock();
831 if (ell_width > (rc.right-rc.left) )
832 if (ell_height > (rc.bottom-rc.top) )
833 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
834 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
835 rc.right - rc.left - 1, rc.bottom - rc.top - 1, 0 , 360 * 64 );
836 else{
837 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
838 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
839 rc.right - rc.left - 1, ell_height - 1, 0 , 180 * 64 );
840 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
841 physDev->dc_rect.left + rc.left,
842 physDev->dc_rect.top + rc.bottom - ell_height,
843 rc.right - rc.left - 1, ell_height - 1, 180 * 64 , 180 * 64 );
845 else if (ell_height > (rc.bottom-rc.top) ){
846 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
847 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
848 ell_width - 1 , rc.bottom - rc.top - 1, 90 * 64 , 180 * 64 );
849 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
850 physDev->dc_rect.left + rc.right - ell_width,
851 physDev->dc_rect.top + rc.top,
852 ell_width - 1 , rc.bottom - rc.top - 1, 270 * 64 , 180 * 64 );
853 }else{
854 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
855 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
856 ell_width - 1, ell_height - 1, 90 * 64, 90 * 64 );
857 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
858 physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.bottom - ell_height,
859 ell_width - 1, ell_height - 1, 180 * 64, 90 * 64 );
860 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
861 physDev->dc_rect.left + rc.right - ell_width,
862 physDev->dc_rect.top + rc.bottom - ell_height,
863 ell_width - 1, ell_height - 1, 270 * 64, 90 * 64 );
864 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
865 physDev->dc_rect.left + rc.right - ell_width, physDev->dc_rect.top + rc.top,
866 ell_width - 1, ell_height - 1, 0, 90 * 64 );
868 if (ell_width < rc.right - rc.left)
870 XDrawLine( gdi_display, physDev->drawable, physDev->gc,
871 physDev->dc_rect.left + rc.left + ell_width / 2,
872 physDev->dc_rect.top + rc.top,
873 physDev->dc_rect.left + rc.right - (ell_width+1) / 2,
874 physDev->dc_rect.top + rc.top);
875 XDrawLine( gdi_display, physDev->drawable, physDev->gc,
876 physDev->dc_rect.left + rc.left + ell_width / 2 ,
877 physDev->dc_rect.top + rc.bottom - 1,
878 physDev->dc_rect.left + rc.right - (ell_width+1)/ 2,
879 physDev->dc_rect.top + rc.bottom - 1);
881 if (ell_height < rc.bottom - rc.top)
883 XDrawLine( gdi_display, physDev->drawable, physDev->gc,
884 physDev->dc_rect.left + rc.right - 1,
885 physDev->dc_rect.top + rc.top + ell_height / 2,
886 physDev->dc_rect.left + rc.right - 1,
887 physDev->dc_rect.top + rc.bottom - (ell_height+1) / 2);
888 XDrawLine( gdi_display, physDev->drawable, physDev->gc,
889 physDev->dc_rect.left + rc.left,
890 physDev->dc_rect.top + rc.top + ell_height / 2,
891 physDev->dc_rect.left + rc.left,
892 physDev->dc_rect.top + rc.bottom - (ell_height+1) / 2);
894 wine_tsx11_unlock();
895 update = TRUE;
897 /* Update the DIBSection from the pixmap */
898 X11DRV_UnlockDIBSection(physDev, update);
900 physDev->pen.width = oldwidth;
901 physDev->pen.endcap = oldendcap;
902 return TRUE;
906 /***********************************************************************
907 * X11DRV_SetPixel
909 COLORREF
910 X11DRV_SetPixel( X11DRV_PDEVICE *physDev, INT x, INT y, COLORREF color )
912 unsigned long pixel;
913 POINT pt;
915 pt.x = x;
916 pt.y = y;
917 LPtoDP( physDev->hdc, &pt, 1 );
918 pixel = X11DRV_PALETTE_ToPhysical( physDev, color );
920 /* Update the pixmap from the DIB section */
921 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
923 /* inefficient but simple... */
924 wine_tsx11_lock();
925 XSetForeground( gdi_display, physDev->gc, pixel );
926 XSetFunction( gdi_display, physDev->gc, GXcopy );
927 XDrawPoint( gdi_display, physDev->drawable, physDev->gc,
928 physDev->dc_rect.left + pt.x, physDev->dc_rect.top + pt.y );
929 wine_tsx11_unlock();
931 /* Update the DIBSection from the pixmap */
932 X11DRV_UnlockDIBSection(physDev, TRUE);
934 return X11DRV_PALETTE_ToLogical(pixel);
938 /***********************************************************************
939 * X11DRV_GetPixel
941 COLORREF
942 X11DRV_GetPixel( X11DRV_PDEVICE *physDev, INT x, INT y )
944 static Pixmap pixmap = 0;
945 XImage * image;
946 int pixel;
947 POINT pt;
948 BOOL memdc = (GetObjectType(physDev->hdc) == OBJ_MEMDC);
950 pt.x = x;
951 pt.y = y;
952 LPtoDP( physDev->hdc, &pt, 1 );
954 /* Update the pixmap from the DIB section */
955 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
957 wine_tsx11_lock();
958 if (memdc)
960 image = XGetImage( gdi_display, physDev->drawable,
961 physDev->dc_rect.left + pt.x, physDev->dc_rect.top + pt.y,
962 1, 1, AllPlanes, ZPixmap );
964 else
966 /* If we are reading from the screen, use a temporary copy */
967 /* to avoid a BadMatch error */
968 if (!pixmap) pixmap = XCreatePixmap( gdi_display, root_window,
969 1, 1, physDev->depth );
970 XCopyArea( gdi_display, physDev->drawable, pixmap, BITMAP_colorGC,
971 physDev->dc_rect.left + pt.x, physDev->dc_rect.top + pt.y, 1, 1, 0, 0 );
972 image = XGetImage( gdi_display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
974 pixel = XGetPixel( image, 0, 0 );
975 XDestroyImage( image );
976 wine_tsx11_unlock();
978 /* Update the DIBSection from the pixmap */
979 X11DRV_UnlockDIBSection(physDev, FALSE);
981 return X11DRV_PALETTE_ToLogical(pixel);
985 /***********************************************************************
986 * X11DRV_PaintRgn
988 BOOL
989 X11DRV_PaintRgn( X11DRV_PDEVICE *physDev, HRGN hrgn )
991 if (X11DRV_SetupGCForBrush( physDev ))
993 unsigned int i;
994 XRectangle *rect;
995 RGNDATA *data = X11DRV_GetRegionData( hrgn, physDev->hdc );
997 if (!data) return FALSE;
998 rect = (XRectangle *)data->Buffer;
999 for (i = 0; i < data->rdh.nCount; i++)
1001 rect[i].x += physDev->dc_rect.left;
1002 rect[i].y += physDev->dc_rect.top;
1005 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
1006 wine_tsx11_lock();
1007 XFillRectangles( gdi_display, physDev->drawable, physDev->gc, rect, data->rdh.nCount );
1008 wine_tsx11_unlock();
1009 X11DRV_UnlockDIBSection(physDev, TRUE);
1010 HeapFree( GetProcessHeap(), 0, data );
1012 return TRUE;
1015 /**********************************************************************
1016 * X11DRV_Polyline
1018 BOOL
1019 X11DRV_Polyline( X11DRV_PDEVICE *physDev, const POINT* pt, INT count )
1021 int i;
1022 XPoint *points;
1024 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * count )))
1026 WARN("No memory to convert POINTs to XPoints!\n");
1027 return FALSE;
1029 for (i = 0; i < count; i++)
1031 POINT tmp = pt[i];
1032 LPtoDP(physDev->hdc, &tmp, 1);
1033 points[i].x = physDev->dc_rect.left + tmp.x;
1034 points[i].y = physDev->dc_rect.top + tmp.y;
1037 if (X11DRV_SetupGCForPen ( physDev ))
1039 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
1040 wine_tsx11_lock();
1041 XDrawLines( gdi_display, physDev->drawable, physDev->gc,
1042 points, count, CoordModeOrigin );
1043 wine_tsx11_unlock();
1044 X11DRV_UnlockDIBSection(physDev, TRUE);
1047 HeapFree( GetProcessHeap(), 0, points );
1048 return TRUE;
1052 /**********************************************************************
1053 * X11DRV_Polygon
1055 BOOL
1056 X11DRV_Polygon( X11DRV_PDEVICE *physDev, const POINT* pt, INT count )
1058 register int i;
1059 XPoint *points;
1060 BOOL update = FALSE;
1062 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (count+1) )))
1064 WARN("No memory to convert POINTs to XPoints!\n");
1065 return FALSE;
1067 for (i = 0; i < count; i++)
1069 POINT tmp = pt[i];
1070 LPtoDP(physDev->hdc, &tmp, 1);
1071 points[i].x = physDev->dc_rect.left + tmp.x;
1072 points[i].y = physDev->dc_rect.top + tmp.y;
1074 points[count] = points[0];
1076 /* Update the pixmap from the DIB section */
1077 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
1079 if (X11DRV_SetupGCForBrush( physDev ))
1081 wine_tsx11_lock();
1082 XFillPolygon( gdi_display, physDev->drawable, physDev->gc,
1083 points, count+1, Complex, CoordModeOrigin);
1084 wine_tsx11_unlock();
1085 update = TRUE;
1087 if (X11DRV_SetupGCForPen ( physDev ))
1089 wine_tsx11_lock();
1090 XDrawLines( gdi_display, physDev->drawable, physDev->gc,
1091 points, count+1, CoordModeOrigin );
1092 wine_tsx11_unlock();
1093 update = TRUE;
1096 /* Update the DIBSection from the pixmap */
1097 X11DRV_UnlockDIBSection(physDev, update);
1099 HeapFree( GetProcessHeap(), 0, points );
1100 return TRUE;
1104 /**********************************************************************
1105 * X11DRV_PolyPolygon
1107 BOOL
1108 X11DRV_PolyPolygon( X11DRV_PDEVICE *physDev, const POINT* pt, const INT* counts, UINT polygons)
1110 HRGN hrgn;
1112 /* FIXME: The points should be converted to device coords before */
1113 /* creating the region. */
1115 hrgn = CreatePolyPolygonRgn( pt, counts, polygons, GetPolyFillMode( physDev->hdc ) );
1116 X11DRV_PaintRgn( physDev, hrgn );
1117 DeleteObject( hrgn );
1119 /* Draw the outline of the polygons */
1121 if (X11DRV_SetupGCForPen ( physDev ))
1123 unsigned int i;
1124 int j, max = 0;
1125 XPoint *points;
1127 /* Update the pixmap from the DIB section */
1128 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
1130 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
1131 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (max+1) )))
1133 WARN("No memory to convert POINTs to XPoints!\n");
1134 return FALSE;
1136 for (i = 0; i < polygons; i++)
1138 for (j = 0; j < counts[i]; j++)
1140 POINT tmp = *pt;
1141 LPtoDP(physDev->hdc, &tmp, 1);
1142 points[j].x = physDev->dc_rect.left + tmp.x;
1143 points[j].y = physDev->dc_rect.top + tmp.y;
1144 pt++;
1146 points[j] = points[0];
1147 wine_tsx11_lock();
1148 XDrawLines( gdi_display, physDev->drawable, physDev->gc,
1149 points, j + 1, CoordModeOrigin );
1150 wine_tsx11_unlock();
1153 /* Update the DIBSection of the dc's bitmap */
1154 X11DRV_UnlockDIBSection(physDev, TRUE);
1156 HeapFree( GetProcessHeap(), 0, points );
1158 return TRUE;
1162 /**********************************************************************
1163 * X11DRV_PolyPolyline
1165 BOOL
1166 X11DRV_PolyPolyline( X11DRV_PDEVICE *physDev, const POINT* pt, const DWORD* counts, DWORD polylines )
1168 if (X11DRV_SetupGCForPen ( physDev ))
1170 unsigned int i, j, max = 0;
1171 XPoint *points;
1173 /* Update the pixmap from the DIB section */
1174 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
1176 for (i = 0; i < polylines; i++) if (counts[i] > max) max = counts[i];
1177 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * max )))
1179 WARN("No memory to convert POINTs to XPoints!\n");
1180 return FALSE;
1182 for (i = 0; i < polylines; i++)
1184 for (j = 0; j < counts[i]; j++)
1186 POINT tmp = *pt;
1187 LPtoDP(physDev->hdc, &tmp, 1);
1188 points[j].x = physDev->dc_rect.left + tmp.x;
1189 points[j].y = physDev->dc_rect.top + tmp.y;
1190 pt++;
1192 wine_tsx11_lock();
1193 XDrawLines( gdi_display, physDev->drawable, physDev->gc,
1194 points, j, CoordModeOrigin );
1195 wine_tsx11_unlock();
1198 /* Update the DIBSection of the dc's bitmap */
1199 X11DRV_UnlockDIBSection(physDev, TRUE);
1201 HeapFree( GetProcessHeap(), 0, points );
1203 return TRUE;
1207 /**********************************************************************
1208 * X11DRV_InternalFloodFill
1210 * Internal helper function for flood fill.
1211 * (xorg,yorg) is the origin of the X image relative to the drawable.
1212 * (x,y) is relative to the origin of the X image.
1214 static void X11DRV_InternalFloodFill(XImage *image, X11DRV_PDEVICE *physDev,
1215 int x, int y,
1216 int xOrg, int yOrg,
1217 unsigned long pixel, WORD fillType )
1219 int left, right;
1221 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
1222 (XGetPixel(image,x,y) != pixel) : \
1223 (XGetPixel(image,x,y) == pixel))
1225 if (!TO_FLOOD(x,y)) return;
1227 /* Find left and right boundaries */
1229 left = right = x;
1230 while ((left > 0) && TO_FLOOD( left-1, y )) left--;
1231 while ((right < image->width) && TO_FLOOD( right, y )) right++;
1232 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
1233 xOrg + left, yOrg + y, right-left, 1 );
1235 /* Set the pixels of this line so we don't fill it again */
1237 for (x = left; x < right; x++)
1239 if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
1240 else XPutPixel( image, x, y, ~pixel );
1243 /* Fill the line above */
1245 if (--y >= 0)
1247 x = left;
1248 while (x < right)
1250 while ((x < right) && !TO_FLOOD(x,y)) x++;
1251 if (x >= right) break;
1252 while ((x < right) && TO_FLOOD(x,y)) x++;
1253 X11DRV_InternalFloodFill(image, physDev, x-1, y,
1254 xOrg, yOrg, pixel, fillType );
1258 /* Fill the line below */
1260 if ((y += 2) < image->height)
1262 x = left;
1263 while (x < right)
1265 while ((x < right) && !TO_FLOOD(x,y)) x++;
1266 if (x >= right) break;
1267 while ((x < right) && TO_FLOOD(x,y)) x++;
1268 X11DRV_InternalFloodFill(image, physDev, x-1, y,
1269 xOrg, yOrg, pixel, fillType );
1272 #undef TO_FLOOD
1276 static int ExtFloodFillXGetImageErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
1278 return (event->request_code == X_GetImage && event->error_code == BadMatch);
1281 /**********************************************************************
1282 * X11DRV_ExtFloodFill
1284 BOOL
1285 X11DRV_ExtFloodFill( X11DRV_PDEVICE *physDev, INT x, INT y, COLORREF color,
1286 UINT fillType )
1288 XImage *image;
1289 RECT rect;
1290 POINT pt;
1292 TRACE("X11DRV_ExtFloodFill %d,%d %06x %d\n", x, y, color, fillType );
1294 pt.x = x;
1295 pt.y = y;
1296 LPtoDP( physDev->hdc, &pt, 1 );
1297 if (!PtInRegion( physDev->region, pt.x, pt.y )) return FALSE;
1298 GetRgnBox( physDev->region, &rect );
1300 X11DRV_expect_error( gdi_display, ExtFloodFillXGetImageErrorHandler, NULL );
1301 image = XGetImage( gdi_display, physDev->drawable,
1302 physDev->dc_rect.left + rect.left, physDev->dc_rect.top + rect.top,
1303 rect.right - rect.left, rect.bottom - rect.top,
1304 AllPlanes, ZPixmap );
1305 if(X11DRV_check_error()) image = NULL;
1306 if (!image) return FALSE;
1308 if (X11DRV_SetupGCForBrush( physDev ))
1310 unsigned long pixel = X11DRV_PALETTE_ToPhysical( physDev, color );
1312 /* Update the pixmap from the DIB section */
1313 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod);
1315 /* ROP mode is always GXcopy for flood-fill */
1316 wine_tsx11_lock();
1317 XSetFunction( gdi_display, physDev->gc, GXcopy );
1318 X11DRV_InternalFloodFill(image, physDev,
1319 pt.x - rect.left,
1320 pt.y - rect.top,
1321 physDev->dc_rect.left + rect.left,
1322 physDev->dc_rect.top + rect.top,
1323 pixel, fillType );
1324 wine_tsx11_unlock();
1325 /* Update the DIBSection of the dc's bitmap */
1326 X11DRV_UnlockDIBSection(physDev, TRUE);
1329 wine_tsx11_lock();
1330 XDestroyImage( image );
1331 wine_tsx11_unlock();
1332 return TRUE;
1335 /**********************************************************************
1336 * X11DRV_SetBkColor
1338 COLORREF
1339 X11DRV_SetBkColor( X11DRV_PDEVICE *physDev, COLORREF color )
1341 physDev->backgroundPixel = X11DRV_PALETTE_ToPhysical( physDev, color );
1342 return color;
1345 /**********************************************************************
1346 * X11DRV_SetTextColor
1348 COLORREF
1349 X11DRV_SetTextColor( X11DRV_PDEVICE *physDev, COLORREF color )
1351 physDev->textPixel = X11DRV_PALETTE_ToPhysical( physDev, color );
1352 return color;
1355 /***********************************************************************
1356 * GetDCOrgEx (X11DRV.@)
1358 BOOL X11DRV_GetDCOrgEx( X11DRV_PDEVICE *physDev, LPPOINT lpp )
1360 lpp->x = physDev->dc_rect.left + physDev->drawable_rect.left;
1361 lpp->y = physDev->dc_rect.top + physDev->drawable_rect.top;
1362 return TRUE;
1366 /***********************************************************************
1367 * SetDCOrg (X11DRV.@)
1369 DWORD X11DRV_SetDCOrg( X11DRV_PDEVICE *physDev, INT x, INT y )
1371 DWORD ret = MAKELONG( physDev->dc_rect.left + physDev->drawable_rect.left,
1372 physDev->dc_rect.top + physDev->drawable_rect.top );
1373 physDev->dc_rect.left = x - physDev->drawable_rect.left;
1374 physDev->dc_rect.top = y - physDev->drawable_rect.top;
1375 return ret;