Add missing \n to output messages.
[wine/wine-gecko.git] / graphics / x11drv / graphics.c
blob7e34689a5e15334b6727d900e610ec53f2e8218b
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * FIXME: only some of these functions obey the GM_ADVANCED
23 * graphics mode
26 #include "config.h"
28 #include <X11/Intrinsic.h>
30 #include "ts_xlib.h"
31 #include "ts_xutil.h"
33 #include <math.h>
34 #ifdef HAVE_FLOAT_H
35 # include <float.h>
36 #endif
37 #include <stdlib.h>
38 #ifndef PI
39 #define PI M_PI
40 #endif
41 #include <string.h>
43 #include "x11drv.h"
44 #include "x11font.h"
45 #include "bitmap.h"
46 #include "gdi.h"
47 #include "palette.h"
48 #include "region.h"
49 #include "wine/debug.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(graphics);
53 #define ABS(x) ((x)<0?(-(x)):(x))
55 /* ROP code to GC function conversion */
56 const int X11DRV_XROPfunction[16] =
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 */
77 /***********************************************************************
78 * X11DRV_SetupGCForPatBlt
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.
84 BOOL X11DRV_SetupGCForPatBlt( X11DRV_PDEVICE *physDev, GC gc, BOOL fMapColors )
86 XGCValues val;
87 unsigned long mask;
88 Pixmap pixmap = 0;
89 DC *dc = physDev->dc;
91 if (physDev->brush.style == BS_NULL) return FALSE;
92 if (physDev->brush.pixel == -1)
94 /* Special case used for monochrome pattern brushes.
95 * We need to swap foreground and background because
96 * Windows does it the wrong way...
98 val.foreground = physDev->backgroundPixel;
99 val.background = physDev->textPixel;
101 else
103 val.foreground = physDev->brush.pixel;
104 val.background = physDev->backgroundPixel;
106 if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
108 val.foreground = X11DRV_PALETTE_XPixelToPalette[val.foreground];
109 val.background = X11DRV_PALETTE_XPixelToPalette[val.background];
112 val.function = X11DRV_XROPfunction[dc->ROPmode-1];
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
118 if (val.function == GXinvert)
120 val.foreground = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
121 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
122 val.function = GXxor;
124 val.fill_style = physDev->brush.fillStyle;
125 switch(val.fill_style)
127 case FillStippled:
128 case FillOpaqueStippled:
129 if (GetBkMode(dc->hSelf)==OPAQUE) val.fill_style = FillOpaqueStippled;
130 val.stipple = physDev->brush.pixmap;
131 mask = GCStipple;
132 break;
134 case FillTiled:
135 if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
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;
152 else val.tile = physDev->brush.pixmap;
153 mask = GCTile;
154 break;
156 default:
157 mask = 0;
158 break;
160 val.ts_x_origin = dc->DCOrgX + dc->brushOrgX;
161 val.ts_y_origin = dc->DCOrgY + dc->brushOrgY;
162 val.fill_rule = (GetPolyFillMode(physDev->hdc) == WINDING) ? WindingRule : EvenOddRule;
163 TSXChangeGC( gdi_display, gc,
164 GCFunction | GCForeground | GCBackground | GCFillStyle |
165 GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
166 &val );
167 if (pixmap) TSXFreePixmap( gdi_display, pixmap );
168 return TRUE;
172 /***********************************************************************
173 * X11DRV_SetupGCForBrush
175 * Setup physDev->gc for drawing operations using current brush.
176 * Return FALSE if brush is BS_NULL, TRUE otherwise.
178 BOOL X11DRV_SetupGCForBrush( X11DRV_PDEVICE *physDev )
180 return X11DRV_SetupGCForPatBlt( physDev, physDev->gc, FALSE );
184 /***********************************************************************
185 * X11DRV_SetupGCForPen
187 * Setup physDev->gc for drawing operations using current pen.
188 * Return FALSE if pen is PS_NULL, TRUE otherwise.
190 BOOL X11DRV_SetupGCForPen( X11DRV_PDEVICE *physDev )
192 XGCValues val;
193 DC *dc = physDev->dc;
195 if (physDev->pen.style == PS_NULL) return FALSE;
197 switch (dc->ROPmode)
199 case R2_BLACK :
200 val.foreground = BlackPixel( gdi_display, DefaultScreen(gdi_display) );
201 val.function = GXcopy;
202 break;
203 case R2_WHITE :
204 val.foreground = WhitePixel( gdi_display, DefaultScreen(gdi_display) );
205 val.function = GXcopy;
206 break;
207 case R2_XORPEN :
208 val.foreground = physDev->pen.pixel;
209 /* It is very unlikely someone wants to XOR with 0 */
210 /* This fixes the rubber-drawings in paintbrush */
211 if (val.foreground == 0)
212 val.foreground = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
213 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
214 val.function = GXxor;
215 break;
216 default :
217 val.foreground = physDev->pen.pixel;
218 val.function = X11DRV_XROPfunction[dc->ROPmode-1];
220 val.background = physDev->backgroundPixel;
221 val.fill_style = FillSolid;
222 if ((physDev->pen.width <= 1) &&
223 (physDev->pen.style != PS_SOLID) &&
224 (physDev->pen.style != PS_INSIDEFRAME))
226 TSXSetDashes( gdi_display, physDev->gc, 0, physDev->pen.dashes, physDev->pen.dash_len );
227 val.line_style = (GetBkMode(dc->hSelf) == OPAQUE) ? LineDoubleDash : LineOnOffDash;
229 else val.line_style = LineSolid;
230 val.line_width = physDev->pen.width;
231 if (val.line_width <= 1) {
232 val.cap_style = CapNotLast;
233 } else {
234 switch (physDev->pen.endcap)
236 case PS_ENDCAP_SQUARE:
237 val.cap_style = CapProjecting;
238 break;
239 case PS_ENDCAP_FLAT:
240 val.cap_style = CapButt;
241 break;
242 case PS_ENDCAP_ROUND:
243 default:
244 val.cap_style = CapRound;
247 switch (physDev->pen.linejoin)
249 case PS_JOIN_BEVEL:
250 val.join_style = JoinBevel;
251 break;
252 case PS_JOIN_MITER:
253 val.join_style = JoinMiter;
254 break;
255 case PS_JOIN_ROUND:
256 default:
257 val.join_style = JoinRound;
259 TSXChangeGC( gdi_display, physDev->gc,
260 GCFunction | GCForeground | GCBackground | GCLineWidth |
261 GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
262 return TRUE;
266 /***********************************************************************
267 * X11DRV_SetupGCForText
269 * Setup physDev->gc for text drawing operations.
270 * Return FALSE if the font is null, TRUE otherwise.
272 BOOL X11DRV_SetupGCForText( X11DRV_PDEVICE *physDev )
274 XFontStruct* xfs = XFONT_GetFontStruct( physDev->font );
276 if( xfs )
278 XGCValues val;
280 val.function = GXcopy; /* Text is always GXcopy */
281 val.foreground = physDev->textPixel;
282 val.background = physDev->backgroundPixel;
283 val.fill_style = FillSolid;
284 val.font = xfs->fid;
286 TSXChangeGC( gdi_display, physDev->gc,
287 GCFunction | GCForeground | GCBackground | GCFillStyle |
288 GCFont, &val );
289 return TRUE;
291 WARN("Physical font failure\n" );
292 return FALSE;
295 /***********************************************************************
296 * X11DRV_LineTo
298 BOOL
299 X11DRV_LineTo( X11DRV_PDEVICE *physDev, INT x, INT y )
301 DC *dc = physDev->dc;
302 POINT start;
303 POINT end;
305 if (X11DRV_SetupGCForPen( physDev )) {
306 /* Update the pixmap from the DIB section */
307 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
309 start.x = dc->CursPosX;
310 start.y = dc->CursPosY;
311 end.x = x;
312 end.y = y;
313 INTERNAL_LPTODP(dc,&start);
314 INTERNAL_LPTODP(dc,&end);
316 TSXDrawLine(gdi_display, physDev->drawable, physDev->gc,
317 dc->DCOrgX + start.x,
318 dc->DCOrgY + start.y,
319 dc->DCOrgX + end.x,
320 dc->DCOrgY + end.y);
322 /* Update the DIBSection from the pixmap */
323 X11DRV_UnlockDIBSection(physDev, TRUE);
325 return TRUE;
330 /***********************************************************************
331 * X11DRV_DrawArc
333 * Helper functions for Arc(), Chord() and Pie().
334 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
337 static BOOL
338 X11DRV_DrawArc( X11DRV_PDEVICE *physDev, INT left, INT top, INT right,
339 INT bottom, INT xstart, INT ystart,
340 INT xend, INT yend, INT lines )
342 INT xcenter, ycenter, istart_angle, idiff_angle;
343 INT width, oldwidth, oldendcap;
344 double start_angle, end_angle;
345 XPoint points[4];
346 DC *dc = physDev->dc;
347 BOOL update = FALSE;
349 left = XLPTODP( dc, left );
350 top = YLPTODP( dc, top );
351 right = XLPTODP( dc, right );
352 bottom = YLPTODP( dc, bottom );
353 xstart = XLPTODP( dc, xstart );
354 ystart = YLPTODP( dc, ystart );
355 xend = XLPTODP( dc, xend );
356 yend = YLPTODP( dc, yend );
358 if (right < left) { INT tmp = right; right = left; left = tmp; }
359 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
360 if ((left == right) || (top == bottom)
361 ||(lines && ((right-left==1)||(bottom-top==1)))) return TRUE;
363 if( dc->ArcDirection == AD_CLOCKWISE )
364 { INT tmp = xstart; xstart = xend; xend = tmp;
365 tmp = ystart; ystart = yend; yend = tmp; }
367 oldwidth = width = physDev->pen.width;
368 oldendcap = physDev->pen.endcap;
369 if (!width) width = 1;
370 if(physDev->pen.style == PS_NULL) width = 0;
372 if ((physDev->pen.style == PS_INSIDEFRAME))
374 if (2*width > (right-left)) width=(right-left + 1)/2;
375 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
376 left += width / 2;
377 right -= (width - 1) / 2;
378 top += width / 2;
379 bottom -= (width - 1) / 2;
381 if(width == 0) width = 1; /* more accurate */
382 physDev->pen.width = width;
383 physDev->pen.endcap = PS_ENDCAP_SQUARE;
385 xcenter = (right + left) / 2;
386 ycenter = (bottom + top) / 2;
387 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
388 (double)(xstart-xcenter)*(bottom-top) );
389 end_angle = atan2( (double)(ycenter-yend)*(right-left),
390 (double)(xend-xcenter)*(bottom-top) );
391 if ((xstart==xend)&&(ystart==yend))
392 { /* A lazy program delivers xstart=xend=ystart=yend=0) */
393 start_angle = 0;
394 end_angle = 2* PI;
396 else /* notorious cases */
397 if ((start_angle == PI)&&( end_angle <0))
398 start_angle = - PI;
399 else
400 if ((end_angle == PI)&&( start_angle <0))
401 end_angle = - PI;
402 istart_angle = (INT)(start_angle * 180 * 64 / PI + 0.5);
403 idiff_angle = (INT)((end_angle - start_angle) * 180 * 64 / PI + 0.5);
404 if (idiff_angle <= 0) idiff_angle += 360 * 64;
406 /* Update the pixmap from the DIB section */
407 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
409 /* Fill arc with brush if Chord() or Pie() */
411 if ((lines > 0) && X11DRV_SetupGCForBrush( physDev )) {
412 TSXSetArcMode( gdi_display, physDev->gc, (lines==1) ? ArcChord : ArcPieSlice);
413 TSXFillArc( gdi_display, physDev->drawable, physDev->gc,
414 dc->DCOrgX + left, dc->DCOrgY + top,
415 right-left-1, bottom-top-1, istart_angle, idiff_angle );
416 update = TRUE;
419 /* Draw arc and lines */
421 if (X11DRV_SetupGCForPen( physDev )){
422 TSXDrawArc( gdi_display, physDev->drawable, physDev->gc,
423 dc->DCOrgX + left, dc->DCOrgY + top,
424 right-left-1, bottom-top-1, istart_angle, idiff_angle );
425 if (lines) {
426 /* use the truncated values */
427 start_angle=(double)istart_angle*PI/64./180.;
428 end_angle=(double)(istart_angle+idiff_angle)*PI/64./180.;
429 /* calculate the endpoints and round correctly */
430 points[0].x = (int) floor(dc->DCOrgX + (right+left)/2.0 +
431 cos(start_angle) * (right-left-width*2+2) / 2. + 0.5);
432 points[0].y = (int) floor(dc->DCOrgY + (top+bottom)/2.0 -
433 sin(start_angle) * (bottom-top-width*2+2) / 2. + 0.5);
434 points[1].x = (int) floor(dc->DCOrgX + (right+left)/2.0 +
435 cos(end_angle) * (right-left-width*2+2) / 2. + 0.5);
436 points[1].y = (int) floor(dc->DCOrgY + (top+bottom)/2.0 -
437 sin(end_angle) * (bottom-top-width*2+2) / 2. + 0.5);
439 /* OK, this stuff is optimized for Xfree86
440 * which is probably the server most used by
441 * wine users. Other X servers will not
442 * display correctly. (eXceed for instance)
443 * so if you feel you must make changes, make sure that
444 * you either use Xfree86 or separate your changes
445 * from these (compile switch or whatever)
447 if (lines == 2) {
448 INT dx1,dy1;
449 points[3] = points[1];
450 points[1].x = dc->DCOrgX + xcenter;
451 points[1].y = dc->DCOrgY + ycenter;
452 points[2] = points[1];
453 dx1=points[1].x-points[0].x;
454 dy1=points[1].y-points[0].y;
455 if(((top-bottom) | -2) == -2)
456 if(dy1>0) points[1].y--;
457 if(dx1<0) {
458 if (((-dx1)*64)<=ABS(dy1)*37) points[0].x--;
459 if(((-dx1*9))<(dy1*16)) points[0].y--;
460 if( dy1<0 && ((dx1*9)) < (dy1*16)) points[0].y--;
461 } else {
462 if(dy1 < 0) points[0].y--;
463 if(((right-left) | -2) == -2) points[1].x--;
465 dx1=points[3].x-points[2].x;
466 dy1=points[3].y-points[2].y;
467 if(((top-bottom) | -2 ) == -2)
468 if(dy1 < 0) points[2].y--;
469 if( dx1<0){
470 if( dy1>0) points[3].y--;
471 if(((right-left) | -2) == -2 ) points[2].x--;
472 }else {
473 points[3].y--;
474 if( dx1 * 64 < dy1 * -37 ) points[3].x--;
476 lines++;
478 TSXDrawLines( gdi_display, physDev->drawable, physDev->gc,
479 points, lines+1, CoordModeOrigin );
481 update = TRUE;
484 /* Update the DIBSection of the pixmap */
485 X11DRV_UnlockDIBSection(physDev, update);
487 physDev->pen.width = oldwidth;
488 physDev->pen.endcap = oldendcap;
489 return TRUE;
493 /***********************************************************************
494 * X11DRV_Arc
496 BOOL
497 X11DRV_Arc( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
498 INT xstart, INT ystart, INT xend, INT yend )
500 return X11DRV_DrawArc( physDev, left, top, right, bottom,
501 xstart, ystart, xend, yend, 0 );
505 /***********************************************************************
506 * X11DRV_Pie
508 BOOL
509 X11DRV_Pie( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
510 INT xstart, INT ystart, INT xend, INT yend )
512 return X11DRV_DrawArc( physDev, left, top, right, bottom,
513 xstart, ystart, xend, yend, 2 );
516 /***********************************************************************
517 * X11DRV_Chord
519 BOOL
520 X11DRV_Chord( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
521 INT xstart, INT ystart, INT xend, INT yend )
523 return X11DRV_DrawArc( physDev, left, top, right, bottom,
524 xstart, ystart, xend, yend, 1 );
528 /***********************************************************************
529 * X11DRV_Ellipse
531 BOOL
532 X11DRV_Ellipse( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom )
534 INT width, oldwidth;
535 DC *dc = physDev->dc;
536 BOOL update = FALSE;
538 left = XLPTODP( dc, left );
539 top = YLPTODP( dc, top );
540 right = XLPTODP( dc, right );
541 bottom = YLPTODP( dc, bottom );
542 if ((left == right) || (top == bottom)) return TRUE;
544 if (right < left) { INT tmp = right; right = left; left = tmp; }
545 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
547 oldwidth = width = physDev->pen.width;
548 if (!width) width = 1;
549 if(physDev->pen.style == PS_NULL) width = 0;
551 if ((physDev->pen.style == PS_INSIDEFRAME))
553 if (2*width > (right-left)) width=(right-left + 1)/2;
554 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
555 left += width / 2;
556 right -= (width - 1) / 2;
557 top += width / 2;
558 bottom -= (width - 1) / 2;
560 if(width == 0) width = 1; /* more accurate */
561 physDev->pen.width = width;
563 /* Update the pixmap from the DIB section */
564 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
566 if (X11DRV_SetupGCForBrush( physDev ))
568 TSXFillArc( gdi_display, physDev->drawable, physDev->gc,
569 dc->DCOrgX + left, dc->DCOrgY + top,
570 right-left-1, bottom-top-1, 0, 360*64 );
571 update = TRUE;
573 if (X11DRV_SetupGCForPen( physDev ))
575 TSXDrawArc( gdi_display, physDev->drawable, physDev->gc,
576 dc->DCOrgX + left, dc->DCOrgY + top,
577 right-left-1, bottom-top-1, 0, 360*64 );
578 update = TRUE;
581 /* Update the DIBSection from the pixmap */
582 X11DRV_UnlockDIBSection(physDev, update);
584 physDev->pen.width = oldwidth;
585 return TRUE;
589 /***********************************************************************
590 * X11DRV_Rectangle
592 BOOL
593 X11DRV_Rectangle(X11DRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom)
595 INT width, oldwidth, oldjoinstyle;
596 DC *dc = physDev->dc;
597 BOOL update = FALSE;
599 TRACE("(%d %d %d %d)\n",
600 left, top, right, bottom);
602 left = INTERNAL_XWPTODP( dc, left, top );
603 top = INTERNAL_YWPTODP( dc, left, top );
604 right = INTERNAL_XWPTODP( dc, right, bottom );
605 bottom = INTERNAL_YWPTODP( dc, right, bottom );
607 if ((left == right) || (top == bottom)) return TRUE;
609 if (right < left) { INT tmp = right; right = left; left = tmp; }
610 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
612 oldwidth = width = physDev->pen.width;
613 if (!width) width = 1;
614 if(physDev->pen.style == PS_NULL) width = 0;
616 if ((physDev->pen.style == PS_INSIDEFRAME))
618 if (2*width > (right-left)) width=(right-left + 1)/2;
619 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
620 left += width / 2;
621 right -= (width - 1) / 2;
622 top += width / 2;
623 bottom -= (width - 1) / 2;
625 if(width == 1) width = 0;
626 physDev->pen.width = width;
627 oldjoinstyle = physDev->pen.linejoin;
628 if(physDev->pen.type != PS_GEOMETRIC)
629 physDev->pen.linejoin = PS_JOIN_MITER;
631 /* Update the pixmap from the DIB section */
632 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
634 if ((right > left + width) && (bottom > top + width))
635 if (X11DRV_SetupGCForBrush( physDev ))
637 TSXFillRectangle( gdi_display, physDev->drawable, physDev->gc,
638 dc->DCOrgX + left + (width + 1) / 2,
639 dc->DCOrgY + top + (width + 1) / 2,
640 right-left-width-1, bottom-top-width-1);
641 update = TRUE;
643 if (X11DRV_SetupGCForPen( physDev ))
645 TSXDrawRectangle( gdi_display, physDev->drawable, physDev->gc,
646 dc->DCOrgX + left, dc->DCOrgY + top,
647 right-left-1, bottom-top-1 );
648 update = TRUE;
651 /* Update the DIBSection from the pixmap */
652 X11DRV_UnlockDIBSection(physDev, update);
654 physDev->pen.width = oldwidth;
655 physDev->pen.linejoin = oldjoinstyle;
656 return TRUE;
659 /***********************************************************************
660 * X11DRV_RoundRect
662 BOOL
663 X11DRV_RoundRect( X11DRV_PDEVICE *physDev, INT left, INT top, INT right,
664 INT bottom, INT ell_width, INT ell_height )
666 INT width, oldwidth, oldendcap;
667 DC *dc = physDev->dc;
668 BOOL update = FALSE;
670 TRACE("(%d %d %d %d %d %d\n",
671 left, top, right, bottom, ell_width, ell_height);
673 left = XLPTODP( dc, left );
674 top = YLPTODP( dc, top );
675 right = XLPTODP( dc, right );
676 bottom = YLPTODP( dc, bottom );
678 if ((left == right) || (top == bottom))
679 return TRUE;
681 /* Make sure ell_width and ell_height are >= 1 otherwise XDrawArc gets
682 called with width/height < 0 */
683 ell_width = max(abs( ell_width * dc->vportExtX / dc->wndExtX ), 1);
684 ell_height = max(abs( ell_height * dc->vportExtY / dc->wndExtY ), 1);
686 /* Fix the coordinates */
688 if (right < left) { INT tmp = right; right = left; left = tmp; }
689 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
691 oldwidth = width = physDev->pen.width;
692 oldendcap = physDev->pen.endcap;
693 if (!width) width = 1;
694 if(physDev->pen.style == PS_NULL) width = 0;
696 if ((physDev->pen.style == PS_INSIDEFRAME))
698 if (2*width > (right-left)) width=(right-left + 1)/2;
699 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
700 left += width / 2;
701 right -= (width - 1) / 2;
702 top += width / 2;
703 bottom -= (width - 1) / 2;
705 if(width == 0) width = 1;
706 physDev->pen.width = width;
707 physDev->pen.endcap = PS_ENDCAP_SQUARE;
709 /* Update the pixmap from the DIB section */
710 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
712 wine_tsx11_lock();
713 if (X11DRV_SetupGCForBrush( physDev ))
715 if (ell_width > (right-left) )
716 if (ell_height > (bottom-top) )
717 XFillArc( gdi_display, physDev->drawable, physDev->gc,
718 dc->DCOrgX + left, dc->DCOrgY + top,
719 right - left - 1, bottom - top - 1,
720 0, 360 * 64 );
721 else{
722 XFillArc( gdi_display, physDev->drawable, physDev->gc,
723 dc->DCOrgX + left, dc->DCOrgY + top,
724 right - left - 1, ell_height, 0, 180 * 64 );
725 XFillArc( gdi_display, physDev->drawable, physDev->gc,
726 dc->DCOrgX + left,
727 dc->DCOrgY + bottom - ell_height - 1,
728 right - left - 1, ell_height, 180 * 64,
729 180 * 64 );
731 else if (ell_height > (bottom-top) ){
732 XFillArc( gdi_display, physDev->drawable, physDev->gc,
733 dc->DCOrgX + left, dc->DCOrgY + top,
734 ell_width, bottom - top - 1, 90 * 64, 180 * 64 );
735 XFillArc( gdi_display, physDev->drawable, physDev->gc,
736 dc->DCOrgX + right - ell_width -1, dc->DCOrgY + top,
737 ell_width, bottom - top - 1, 270 * 64, 180 * 64 );
738 }else{
739 XFillArc( gdi_display, physDev->drawable, physDev->gc,
740 dc->DCOrgX + left, dc->DCOrgY + top,
741 ell_width, ell_height, 90 * 64, 90 * 64 );
742 XFillArc( gdi_display, physDev->drawable, physDev->gc,
743 dc->DCOrgX + left,
744 dc->DCOrgY + bottom - ell_height - 1,
745 ell_width, ell_height, 180 * 64, 90 * 64 );
746 XFillArc( gdi_display, physDev->drawable, physDev->gc,
747 dc->DCOrgX + right - ell_width - 1,
748 dc->DCOrgY + bottom - ell_height - 1,
749 ell_width, ell_height, 270 * 64, 90 * 64 );
750 XFillArc( gdi_display, physDev->drawable, physDev->gc,
751 dc->DCOrgX + right - ell_width - 1,
752 dc->DCOrgY + top,
753 ell_width, ell_height, 0, 90 * 64 );
755 if (ell_width < right - left)
757 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
758 dc->DCOrgX + left + (ell_width + 1) / 2,
759 dc->DCOrgY + top + 1,
760 right - left - ell_width - 1,
761 (ell_height + 1) / 2 - 1);
762 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
763 dc->DCOrgX + left + (ell_width + 1) / 2,
764 dc->DCOrgY + bottom - (ell_height) / 2 - 1,
765 right - left - ell_width - 1,
766 (ell_height) / 2 );
768 if (ell_height < bottom - top)
770 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
771 dc->DCOrgX + left + 1,
772 dc->DCOrgY + top + (ell_height + 1) / 2,
773 right - left - 2,
774 bottom - top - ell_height - 1);
776 update = TRUE;
778 /* FIXME: this could be done with on X call
779 * more efficient and probably more correct
780 * on any X server: XDrawArcs will draw
781 * straight horizontal and vertical lines
782 * if width or height are zero.
784 * BTW this stuff is optimized for an Xfree86 server
785 * read the comments inside the X11DRV_DrawArc function
787 if (X11DRV_SetupGCForPen( physDev ))
789 if (ell_width > (right-left) )
790 if (ell_height > (bottom-top) )
791 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
792 dc->DCOrgX + left, dc->DCOrgY + top,
793 right - left - 1, bottom -top - 1, 0 , 360 * 64 );
794 else{
795 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
796 dc->DCOrgX + left, dc->DCOrgY + top,
797 right - left - 1, ell_height - 1, 0 , 180 * 64 );
798 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
799 dc->DCOrgX + left,
800 dc->DCOrgY + bottom - ell_height,
801 right - left - 1, ell_height - 1, 180 * 64 , 180 * 64 );
803 else if (ell_height > (bottom-top) ){
804 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
805 dc->DCOrgX + left, dc->DCOrgY + top,
806 ell_width - 1 , bottom - top - 1, 90 * 64 , 180 * 64 );
807 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
808 dc->DCOrgX + right - ell_width,
809 dc->DCOrgY + top,
810 ell_width - 1 , bottom - top - 1, 270 * 64 , 180 * 64 );
811 }else{
812 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
813 dc->DCOrgX + left, dc->DCOrgY + top,
814 ell_width - 1, ell_height - 1, 90 * 64, 90 * 64 );
815 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
816 dc->DCOrgX + left, dc->DCOrgY + bottom - ell_height,
817 ell_width - 1, ell_height - 1, 180 * 64, 90 * 64 );
818 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
819 dc->DCOrgX + right - ell_width,
820 dc->DCOrgY + bottom - ell_height,
821 ell_width - 1, ell_height - 1, 270 * 64, 90 * 64 );
822 XDrawArc( gdi_display, physDev->drawable, physDev->gc,
823 dc->DCOrgX + right - ell_width, dc->DCOrgY + top,
824 ell_width - 1, ell_height - 1, 0, 90 * 64 );
826 if (ell_width < right - left)
828 XDrawLine( gdi_display, physDev->drawable, physDev->gc,
829 dc->DCOrgX + left + ell_width / 2,
830 dc->DCOrgY + top,
831 dc->DCOrgX + right - (ell_width+1) / 2,
832 dc->DCOrgY + top);
833 XDrawLine( gdi_display, physDev->drawable, physDev->gc,
834 dc->DCOrgX + left + ell_width / 2 ,
835 dc->DCOrgY + bottom - 1,
836 dc->DCOrgX + right - (ell_width+1)/ 2,
837 dc->DCOrgY + bottom - 1);
839 if (ell_height < bottom - top)
841 XDrawLine( gdi_display, physDev->drawable, physDev->gc,
842 dc->DCOrgX + right - 1,
843 dc->DCOrgY + top + ell_height / 2,
844 dc->DCOrgX + right - 1,
845 dc->DCOrgY + bottom - (ell_height+1) / 2);
846 XDrawLine( gdi_display, physDev->drawable, physDev->gc,
847 dc->DCOrgX + left,
848 dc->DCOrgY + top + ell_height / 2,
849 dc->DCOrgX + left,
850 dc->DCOrgY + bottom - (ell_height+1) / 2);
852 update = TRUE;
854 wine_tsx11_unlock();
855 /* Update the DIBSection from the pixmap */
856 X11DRV_UnlockDIBSection(physDev, update);
858 physDev->pen.width = oldwidth;
859 physDev->pen.endcap = oldendcap;
860 return TRUE;
864 /***********************************************************************
865 * X11DRV_SetPixel
867 COLORREF
868 X11DRV_SetPixel( X11DRV_PDEVICE *physDev, INT x, INT y, COLORREF color )
870 Pixel pixel;
871 DC *dc = physDev->dc;
873 x = dc->DCOrgX + INTERNAL_XWPTODP( dc, x, y );
874 y = dc->DCOrgY + INTERNAL_YWPTODP( dc, x, y );
875 pixel = X11DRV_PALETTE_ToPhysical( physDev, color );
877 /* Update the pixmap from the DIB section */
878 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
880 /* inefficient but simple... */
881 wine_tsx11_lock();
882 XSetForeground( gdi_display, physDev->gc, pixel );
883 XSetFunction( gdi_display, physDev->gc, GXcopy );
884 XDrawPoint( gdi_display, physDev->drawable, physDev->gc, x, y );
885 wine_tsx11_unlock();
887 /* Update the DIBSection from the pixmap */
888 X11DRV_UnlockDIBSection(physDev, TRUE);
890 return X11DRV_PALETTE_ToLogical(pixel);
894 /***********************************************************************
895 * X11DRV_GetPixel
897 COLORREF
898 X11DRV_GetPixel( X11DRV_PDEVICE *physDev, INT x, INT y )
900 static Pixmap pixmap = 0;
901 XImage * image;
902 int pixel;
903 DC *dc = physDev->dc;
905 /* Update the pixmap from the DIB section */
906 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
908 x = dc->DCOrgX + INTERNAL_XWPTODP( dc, x, y );
909 y = dc->DCOrgY + INTERNAL_YWPTODP( dc, x, y );
910 wine_tsx11_lock();
911 if (dc->flags & DC_MEMORY)
913 image = XGetImage( gdi_display, physDev->drawable, x, y, 1, 1,
914 AllPlanes, ZPixmap );
916 else
918 /* If we are reading from the screen, use a temporary copy */
919 /* to avoid a BadMatch error */
920 if (!pixmap) pixmap = XCreatePixmap( gdi_display, root_window,
921 1, 1, dc->bitsPerPixel );
922 XCopyArea( gdi_display, physDev->drawable, pixmap, BITMAP_colorGC,
923 x, y, 1, 1, 0, 0 );
924 image = XGetImage( gdi_display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
926 pixel = XGetPixel( image, 0, 0 );
927 XDestroyImage( image );
928 wine_tsx11_unlock();
930 /* Update the DIBSection from the pixmap */
931 X11DRV_UnlockDIBSection(physDev, FALSE);
933 return X11DRV_PALETTE_ToLogical(pixel);
937 /***********************************************************************
938 * X11DRV_PaintRgn
940 BOOL
941 X11DRV_PaintRgn( X11DRV_PDEVICE *physDev, HRGN hrgn )
943 RECT box;
944 HRGN tmpVisRgn, prevVisRgn;
945 DC *dc = physDev->dc;
946 HDC hdc = physDev->hdc; /* FIXME: should not mix dc/hdc this way */
948 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
950 /* Transform region into device co-ords */
951 if ( !REGION_LPTODP( hdc, tmpVisRgn, hrgn )
952 || OffsetRgn( tmpVisRgn, dc->DCOrgX, dc->DCOrgY ) == ERROR) {
953 DeleteObject( tmpVisRgn );
954 return FALSE;
957 /* Modify visible region */
958 if (!(prevVisRgn = SaveVisRgn16( hdc ))) {
959 DeleteObject( tmpVisRgn );
960 return FALSE;
962 CombineRgn( tmpVisRgn, prevVisRgn, tmpVisRgn, RGN_AND );
963 SelectVisRgn16( hdc, tmpVisRgn );
964 DeleteObject( tmpVisRgn );
966 /* Fill the region */
968 GetRgnBox( dc->hGCClipRgn, &box );
969 if (X11DRV_SetupGCForBrush( physDev ))
971 /* Update the pixmap from the DIB section */
972 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
974 TSXFillRectangle( gdi_display, physDev->drawable, physDev->gc,
975 box.left, box.top,
976 box.right-box.left, box.bottom-box.top );
978 /* Update the DIBSection from the pixmap */
979 X11DRV_UnlockDIBSection(physDev, TRUE);
982 /* Restore the visible region */
984 RestoreVisRgn16( hdc );
985 return TRUE;
988 /**********************************************************************
989 * X11DRV_Polyline
991 BOOL
992 X11DRV_Polyline( X11DRV_PDEVICE *physDev, const POINT* pt, INT count )
994 INT oldwidth;
995 register int i;
996 XPoint *points;
997 DC *dc = physDev->dc;
999 if((oldwidth = physDev->pen.width) == 0) physDev->pen.width = 1;
1001 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * count )))
1003 WARN("No memory to convert POINTs to XPoints!\n");
1004 return FALSE;
1006 for (i = 0; i < count; i++)
1008 points[i].x = dc->DCOrgX + INTERNAL_XWPTODP( dc, pt[i].x, pt[i].y );
1009 points[i].y = dc->DCOrgY + INTERNAL_YWPTODP( dc, pt[i].x, pt[i].y );
1012 if (X11DRV_SetupGCForPen ( physDev ))
1014 /* Update the pixmap from the DIB section */
1015 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
1017 TSXDrawLines( gdi_display, physDev->drawable, physDev->gc,
1018 points, count, CoordModeOrigin );
1020 /* Update the DIBSection from the pixmap */
1021 X11DRV_UnlockDIBSection(physDev, TRUE);
1024 HeapFree( GetProcessHeap(), 0, points );
1025 physDev->pen.width = oldwidth;
1026 return TRUE;
1030 /**********************************************************************
1031 * X11DRV_Polygon
1033 BOOL
1034 X11DRV_Polygon( X11DRV_PDEVICE *physDev, const POINT* pt, INT count )
1036 register int i;
1037 XPoint *points;
1038 DC *dc = physDev->dc;
1039 BOOL update = FALSE;
1041 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (count+1) )))
1043 WARN("No memory to convert POINTs to XPoints!\n");
1044 return FALSE;
1046 for (i = 0; i < count; i++)
1048 points[i].x = dc->DCOrgX + INTERNAL_XWPTODP( dc, pt[i].x, pt[i].y );
1049 points[i].y = dc->DCOrgY + INTERNAL_YWPTODP( dc, pt[i].x, pt[i].y );
1051 points[count] = points[0];
1053 /* Update the pixmap from the DIB section */
1054 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
1056 if (X11DRV_SetupGCForBrush( physDev ))
1058 TSXFillPolygon( gdi_display, physDev->drawable, physDev->gc,
1059 points, count+1, Complex, CoordModeOrigin);
1060 update = TRUE;
1062 if (X11DRV_SetupGCForPen ( physDev ))
1064 TSXDrawLines( gdi_display, physDev->drawable, physDev->gc,
1065 points, count+1, CoordModeOrigin );
1066 update = TRUE;
1069 /* Update the DIBSection from the pixmap */
1070 X11DRV_UnlockDIBSection(physDev, update);
1072 HeapFree( GetProcessHeap(), 0, points );
1073 return TRUE;
1077 /**********************************************************************
1078 * X11DRV_PolyPolygon
1080 BOOL
1081 X11DRV_PolyPolygon( X11DRV_PDEVICE *physDev, const POINT* pt, const INT* counts, UINT polygons)
1083 HRGN hrgn;
1084 DC *dc = physDev->dc;
1086 /* FIXME: The points should be converted to device coords before */
1087 /* creating the region. */
1089 hrgn = CreatePolyPolygonRgn( pt, counts, polygons, GetPolyFillMode( physDev->hdc ) );
1090 X11DRV_PaintRgn( physDev, hrgn );
1091 DeleteObject( hrgn );
1093 /* Draw the outline of the polygons */
1095 if (X11DRV_SetupGCForPen ( physDev ))
1097 int i, j, max = 0;
1098 XPoint *points;
1100 /* Update the pixmap from the DIB section */
1101 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
1103 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
1104 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (max+1) )))
1106 WARN("No memory to convert POINTs to XPoints!\n");
1107 return FALSE;
1109 for (i = 0; i < polygons; i++)
1111 for (j = 0; j < counts[i]; j++)
1113 points[j].x = dc->DCOrgX + INTERNAL_XWPTODP( dc, pt->x, pt->y );
1114 points[j].y = dc->DCOrgY + INTERNAL_YWPTODP( dc, pt->x, pt->y );
1115 pt++;
1117 points[j] = points[0];
1118 TSXDrawLines( gdi_display, physDev->drawable, physDev->gc,
1119 points, j + 1, CoordModeOrigin );
1122 /* Update the DIBSection of the dc's bitmap */
1123 X11DRV_UnlockDIBSection(physDev, TRUE);
1125 HeapFree( GetProcessHeap(), 0, points );
1127 return TRUE;
1131 /**********************************************************************
1132 * X11DRV_PolyPolyline
1134 BOOL
1135 X11DRV_PolyPolyline( X11DRV_PDEVICE *physDev, const POINT* pt, const DWORD* counts, DWORD polylines )
1137 DC *dc = physDev->dc;
1139 if (X11DRV_SetupGCForPen ( physDev ))
1141 int i, j, max = 0;
1142 XPoint *points;
1144 /* Update the pixmap from the DIB section */
1145 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
1147 for (i = 0; i < polylines; i++) if (counts[i] > max) max = counts[i];
1148 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * max )))
1150 WARN("No memory to convert POINTs to XPoints!\n");
1151 return FALSE;
1153 for (i = 0; i < polylines; i++)
1155 for (j = 0; j < counts[i]; j++)
1157 points[j].x = dc->DCOrgX + INTERNAL_XWPTODP( dc, pt->x, pt->y );
1158 points[j].y = dc->DCOrgY + INTERNAL_YWPTODP( dc, pt->x, pt->y );
1159 pt++;
1161 TSXDrawLines( gdi_display, physDev->drawable, physDev->gc,
1162 points, j, CoordModeOrigin );
1165 /* Update the DIBSection of the dc's bitmap */
1166 X11DRV_UnlockDIBSection(physDev, TRUE);
1168 HeapFree( GetProcessHeap(), 0, points );
1170 return TRUE;
1174 /**********************************************************************
1175 * X11DRV_InternalFloodFill
1177 * Internal helper function for flood fill.
1178 * (xorg,yorg) is the origin of the X image relative to the drawable.
1179 * (x,y) is relative to the origin of the X image.
1181 static void X11DRV_InternalFloodFill(XImage *image, X11DRV_PDEVICE *physDev,
1182 int x, int y,
1183 int xOrg, int yOrg,
1184 Pixel pixel, WORD fillType )
1186 int left, right;
1188 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
1189 (XGetPixel(image,x,y) != pixel) : \
1190 (XGetPixel(image,x,y) == pixel))
1192 if (!TO_FLOOD(x,y)) return;
1194 /* Find left and right boundaries */
1196 left = right = x;
1197 while ((left > 0) && TO_FLOOD( left-1, y )) left--;
1198 while ((right < image->width) && TO_FLOOD( right, y )) right++;
1199 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
1200 xOrg + left, yOrg + y, right-left, 1 );
1202 /* Set the pixels of this line so we don't fill it again */
1204 for (x = left; x < right; x++)
1206 if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
1207 else XPutPixel( image, x, y, ~pixel );
1210 /* Fill the line above */
1212 if (--y >= 0)
1214 x = left;
1215 while (x < right)
1217 while ((x < right) && !TO_FLOOD(x,y)) x++;
1218 if (x >= right) break;
1219 while ((x < right) && TO_FLOOD(x,y)) x++;
1220 X11DRV_InternalFloodFill(image, physDev, x-1, y,
1221 xOrg, yOrg, pixel, fillType );
1225 /* Fill the line below */
1227 if ((y += 2) < image->height)
1229 x = left;
1230 while (x < right)
1232 while ((x < right) && !TO_FLOOD(x,y)) x++;
1233 if (x >= right) break;
1234 while ((x < right) && TO_FLOOD(x,y)) x++;
1235 X11DRV_InternalFloodFill(image, physDev, x-1, y,
1236 xOrg, yOrg, pixel, fillType );
1239 #undef TO_FLOOD
1243 /**********************************************************************
1244 * X11DRV_ExtFloodFill
1246 BOOL
1247 X11DRV_ExtFloodFill( X11DRV_PDEVICE *physDev, INT x, INT y, COLORREF color,
1248 UINT fillType )
1250 XImage *image;
1251 RECT rect;
1252 DC *dc = physDev->dc;
1254 TRACE("X11DRV_ExtFloodFill %d,%d %06lx %d\n", x, y, color, fillType );
1256 if (!PtVisible( dc->hSelf, x, y )) return FALSE;
1257 if (GetRgnBox( dc->hGCClipRgn, &rect ) == ERROR) return FALSE;
1259 if (!(image = TSXGetImage( gdi_display, physDev->drawable,
1260 rect.left,
1261 rect.top,
1262 rect.right - rect.left,
1263 rect.bottom - rect.top,
1264 AllPlanes, ZPixmap ))) return FALSE;
1266 if (X11DRV_SetupGCForBrush( physDev ))
1268 /* Update the pixmap from the DIB section */
1269 X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
1271 /* ROP mode is always GXcopy for flood-fill */
1272 wine_tsx11_lock();
1273 XSetFunction( gdi_display, physDev->gc, GXcopy );
1274 X11DRV_InternalFloodFill(image, physDev,
1275 XLPTODP(dc,x) + dc->DCOrgX - rect.left,
1276 YLPTODP(dc,y) + dc->DCOrgY - rect.top,
1277 rect.left, rect.top,
1278 X11DRV_PALETTE_ToPhysical( physDev, color ),
1279 fillType );
1280 wine_tsx11_unlock();
1281 /* Update the DIBSection of the dc's bitmap */
1282 X11DRV_UnlockDIBSection(physDev, TRUE);
1285 TSXDestroyImage( image );
1286 return TRUE;
1289 /**********************************************************************
1290 * X11DRV_SetBkColor
1292 COLORREF
1293 X11DRV_SetBkColor( X11DRV_PDEVICE *physDev, COLORREF color )
1295 physDev->backgroundPixel = X11DRV_PALETTE_ToPhysical( physDev, color );
1296 return color;
1299 /**********************************************************************
1300 * X11DRV_SetTextColor
1302 COLORREF
1303 X11DRV_SetTextColor( X11DRV_PDEVICE *physDev, COLORREF color )
1305 physDev->textPixel = X11DRV_PALETTE_ToPhysical( physDev, color );
1306 return color;
1309 /***********************************************************************
1310 * X11DRV_GetDCOrgEx
1312 BOOL X11DRV_GetDCOrgEx( X11DRV_PDEVICE *physDev, LPPOINT lpp )
1314 if (!(physDev->dc->flags & DC_MEMORY))
1316 Window root;
1317 int x, y, w, h, border, depth;
1319 FIXME("this is not correct for managed windows\n");
1320 TSXGetGeometry( gdi_display, physDev->drawable, &root,
1321 &x, &y, &w, &h, &border, &depth );
1322 lpp->x = x;
1323 lpp->y = y;
1325 else lpp->x = lpp->y = 0;
1326 return TRUE;