2 * X11 graphics driver graphics functions
4 * Copyright 1993,1994 Alexandre Julliard
8 * FIXME: only some of these functions obey the GM_ADVANCED
14 #include <X11/Intrinsic.h>
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(graphics);
41 #define ABS(x) ((x)<0?(-(x)):(x))
43 /* ROP code to GC function conversion */
44 const int X11DRV_XROPfunction[16] =
46 GXclear, /* R2_BLACK */
47 GXnor, /* R2_NOTMERGEPEN */
48 GXandInverted, /* R2_MASKNOTPEN */
49 GXcopyInverted, /* R2_NOTCOPYPEN */
50 GXandReverse, /* R2_MASKPENNOT */
51 GXinvert, /* R2_NOT */
52 GXxor, /* R2_XORPEN */
53 GXnand, /* R2_NOTMASKPEN */
54 GXand, /* R2_MASKPEN */
55 GXequiv, /* R2_NOTXORPEN */
57 GXorInverted, /* R2_MERGENOTPEN */
58 GXcopy, /* R2_COPYPEN */
59 GXorReverse, /* R2_MERGEPENNOT */
60 GXor, /* R2_MERGEPEN */
65 /***********************************************************************
66 * X11DRV_SetupGCForPatBlt
68 * Setup the GC for a PatBlt operation using current brush.
69 * If fMapColors is TRUE, X pixels are mapped to Windows colors.
70 * Return FALSE if brush is BS_NULL, TRUE otherwise.
72 BOOL X11DRV_SetupGCForPatBlt( DC * dc, GC gc, BOOL fMapColors )
77 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
79 if (physDev->brush.style == BS_NULL) return FALSE;
80 if (physDev->brush.pixel == -1)
82 /* Special case used for monochrome pattern brushes.
83 * We need to swap foreground and background because
84 * Windows does it the wrong way...
86 val.foreground = physDev->backgroundPixel;
87 val.background = physDev->textPixel;
91 val.foreground = physDev->brush.pixel;
92 val.background = physDev->backgroundPixel;
94 if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
96 val.foreground = X11DRV_PALETTE_XPixelToPalette[val.foreground];
97 val.background = X11DRV_PALETTE_XPixelToPalette[val.background];
100 val.function = X11DRV_XROPfunction[dc->ROPmode-1];
102 ** Let's replace GXinvert by GXxor with (black xor white)
103 ** This solves the selection color and leak problems in excel
104 ** FIXME : Let's do that only if we work with X-pixels, not with Win-pixels
106 if (val.function == GXinvert)
108 val.foreground = BlackPixelOfScreen(X11DRV_GetXScreen()) ^ WhitePixelOfScreen(X11DRV_GetXScreen());
109 val.function = GXxor;
111 val.fill_style = physDev->brush.fillStyle;
112 switch(val.fill_style)
115 case FillOpaqueStippled:
116 if (dc->backgroundMode==OPAQUE) val.fill_style = FillOpaqueStippled;
117 val.stipple = physDev->brush.pixmap;
122 if (fMapColors && X11DRV_PALETTE_XPixelToPalette)
127 pixmap = XCreatePixmap( display, X11DRV_GetXRootWindow(),
128 8, 8, X11DRV_GetDepth() );
129 image = XGetImage( display, physDev->brush.pixmap, 0, 0, 8, 8,
130 AllPlanes, ZPixmap );
131 for (y = 0; y < 8; y++)
132 for (x = 0; x < 8; x++)
133 XPutPixel( image, x, y,
134 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y)] );
135 XPutImage( display, pixmap, gc, image, 0, 0, 0, 0, 8, 8 );
136 XDestroyImage( image );
140 else val.tile = physDev->brush.pixmap;
148 val.ts_x_origin = dc->DCOrgX + dc->brushOrgX;
149 val.ts_y_origin = dc->DCOrgY + dc->brushOrgY;
150 val.fill_rule = (dc->polyFillMode==WINDING) ? WindingRule : EvenOddRule;
151 TSXChangeGC( display, gc,
152 GCFunction | GCForeground | GCBackground | GCFillStyle |
153 GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
155 if (pixmap) TSXFreePixmap( display, pixmap );
160 /***********************************************************************
161 * X11DRV_SetupGCForBrush
163 * Setup physDev->gc for drawing operations using current brush.
164 * Return FALSE if brush is BS_NULL, TRUE otherwise.
166 BOOL X11DRV_SetupGCForBrush( DC * dc )
168 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
169 return X11DRV_SetupGCForPatBlt( dc, physDev->gc, FALSE );
173 /***********************************************************************
174 * X11DRV_SetupGCForPen
176 * Setup physDev->gc for drawing operations using current pen.
177 * Return FALSE if pen is PS_NULL, TRUE otherwise.
179 BOOL X11DRV_SetupGCForPen( DC * dc )
182 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
184 if (physDev->pen.style == PS_NULL) return FALSE;
189 val.foreground = BlackPixelOfScreen( X11DRV_GetXScreen() );
190 val.function = GXcopy;
193 val.foreground = WhitePixelOfScreen( X11DRV_GetXScreen() );
194 val.function = GXcopy;
197 val.foreground = physDev->pen.pixel;
198 /* It is very unlikely someone wants to XOR with 0 */
199 /* This fixes the rubber-drawings in paintbrush */
200 if (val.foreground == 0)
201 val.foreground = BlackPixelOfScreen( X11DRV_GetXScreen() )
202 ^ WhitePixelOfScreen( X11DRV_GetXScreen() );
203 val.function = GXxor;
206 val.foreground = physDev->pen.pixel;
207 val.function = X11DRV_XROPfunction[dc->ROPmode-1];
209 val.background = physDev->backgroundPixel;
210 val.fill_style = FillSolid;
211 if ((physDev->pen.width <= 1) &&
212 (physDev->pen.style != PS_SOLID) &&
213 (physDev->pen.style != PS_INSIDEFRAME))
215 TSXSetDashes( display, physDev->gc, 0, physDev->pen.dashes,
216 physDev->pen.dash_len );
217 val.line_style = (dc->backgroundMode == OPAQUE) ?
218 LineDoubleDash : LineOnOffDash;
220 else val.line_style = LineSolid;
221 val.line_width = physDev->pen.width;
222 if (val.line_width <= 1) {
223 val.cap_style = CapNotLast;
225 switch (physDev->pen.endcap)
227 case PS_ENDCAP_SQUARE:
228 val.cap_style = CapProjecting;
231 val.cap_style = CapButt;
233 case PS_ENDCAP_ROUND:
235 val.cap_style = CapRound;
238 switch (physDev->pen.linejoin)
241 val.join_style = JoinBevel;
244 val.join_style = JoinMiter;
248 val.join_style = JoinRound;
250 TSXChangeGC( display, physDev->gc,
251 GCFunction | GCForeground | GCBackground | GCLineWidth |
252 GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
257 /***********************************************************************
258 * X11DRV_SetupGCForText
260 * Setup physDev->gc for text drawing operations.
261 * Return FALSE if the font is null, TRUE otherwise.
263 BOOL X11DRV_SetupGCForText( DC * dc )
265 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
266 XFontStruct* xfs = XFONT_GetFontStruct( physDev->font );
272 val.function = GXcopy; /* Text is always GXcopy */
273 val.foreground = physDev->textPixel;
274 val.background = physDev->backgroundPixel;
275 val.fill_style = FillSolid;
278 TSXChangeGC( display, physDev->gc,
279 GCFunction | GCForeground | GCBackground | GCFillStyle |
283 WARN("Physical font failure\n" );
287 /***********************************************************************
291 X11DRV_LineTo( DC *dc, INT x, INT y )
293 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
297 if (X11DRV_SetupGCForPen( dc )) {
298 /* Update the pixmap from the DIB section */
299 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
301 start.x = dc->CursPosX;
302 start.y = dc->CursPosY;
305 INTERNAL_LPTODP(dc,&start);
306 INTERNAL_LPTODP(dc,&end);
308 TSXDrawLine(display, physDev->drawable, physDev->gc,
309 dc->DCOrgX + start.x,
310 dc->DCOrgY + start.y,
314 /* Update the DIBSection from the pixmap */
315 X11DRV_UnlockDIBSection(dc, TRUE);
322 /***********************************************************************
325 * Helper functions for Arc(), Chord() and Pie().
326 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
330 X11DRV_DrawArc( DC *dc, INT left, INT top, INT right,
331 INT bottom, INT xstart, INT ystart,
332 INT xend, INT yend, INT lines )
334 INT xcenter, ycenter, istart_angle, idiff_angle;
335 INT width, oldwidth, oldendcap;
336 double start_angle, end_angle;
338 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
341 left = XLPTODP( dc, left );
342 top = YLPTODP( dc, top );
343 right = XLPTODP( dc, right );
344 bottom = YLPTODP( dc, bottom );
345 xstart = XLPTODP( dc, xstart );
346 ystart = YLPTODP( dc, ystart );
347 xend = XLPTODP( dc, xend );
348 yend = YLPTODP( dc, yend );
350 if (right < left) { INT tmp = right; right = left; left = tmp; }
351 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
352 if ((left == right) || (top == bottom)
353 ||(lines && ((right-left==1)||(bottom-top==1)))) return TRUE;
355 if( dc->ArcDirection == AD_CLOCKWISE )
356 { INT tmp = xstart; xstart = xend; xend = tmp;
357 tmp = ystart; ystart = yend; yend = tmp; }
359 oldwidth = width = physDev->pen.width;
360 oldendcap = physDev->pen.endcap;
361 if (!width) width = 1;
362 if(physDev->pen.style == PS_NULL) width = 0;
364 if ((physDev->pen.style == PS_INSIDEFRAME))
366 if (2*width > (right-left)) width=(right-left + 1)/2;
367 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
369 right -= (width - 1) / 2;
371 bottom -= (width - 1) / 2;
373 if(width == 0) width = 1; /* more accurate */
374 physDev->pen.width = width;
375 physDev->pen.endcap = PS_ENDCAP_SQUARE;
377 xcenter = (right + left) / 2;
378 ycenter = (bottom + top) / 2;
379 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
380 (double)(xstart-xcenter)*(bottom-top) );
381 end_angle = atan2( (double)(ycenter-yend)*(right-left),
382 (double)(xend-xcenter)*(bottom-top) );
383 if ((xstart==xend)&&(ystart==yend))
384 { /* A lazy program delivers xstart=xend=ystart=yend=0) */
388 else /* notorious cases */
389 if ((start_angle == PI)&&( end_angle <0))
392 if ((end_angle == PI)&&( start_angle <0))
394 istart_angle = (INT)(start_angle * 180 * 64 / PI + 0.5);
395 idiff_angle = (INT)((end_angle - start_angle) * 180 * 64 / PI + 0.5);
396 if (idiff_angle <= 0) idiff_angle += 360 * 64;
398 /* Update the pixmap from the DIB section */
399 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
401 /* Fill arc with brush if Chord() or Pie() */
403 if ((lines > 0) && X11DRV_SetupGCForBrush( dc )) {
404 TSXSetArcMode( display, physDev->gc,
405 (lines==1) ? ArcChord : ArcPieSlice);
406 TSXFillArc( display, physDev->drawable, physDev->gc,
407 dc->DCOrgX + left, dc->DCOrgY + top,
408 right-left-1, bottom-top-1, istart_angle, idiff_angle );
412 /* Draw arc and lines */
414 if (X11DRV_SetupGCForPen( dc )){
415 TSXDrawArc( display, physDev->drawable, physDev->gc,
416 dc->DCOrgX + left, dc->DCOrgY + top,
417 right-left-1, bottom-top-1, istart_angle, idiff_angle );
419 /* use the truncated values */
420 start_angle=(double)istart_angle*PI/64./180.;
421 end_angle=(double)(istart_angle+idiff_angle)*PI/64./180.;
422 /* calculate the endpoints and round correctly */
423 points[0].x = (int) floor(dc->DCOrgX + (right+left)/2.0 +
424 cos(start_angle) * (right-left-width*2+2) / 2. + 0.5);
425 points[0].y = (int) floor(dc->DCOrgY + (top+bottom)/2.0 -
426 sin(start_angle) * (bottom-top-width*2+2) / 2. + 0.5);
427 points[1].x = (int) floor(dc->DCOrgX + (right+left)/2.0 +
428 cos(end_angle) * (right-left-width*2+2) / 2. + 0.5);
429 points[1].y = (int) floor(dc->DCOrgY + (top+bottom)/2.0 -
430 sin(end_angle) * (bottom-top-width*2+2) / 2. + 0.5);
432 /* OK, this stuff is optimized for Xfree86
433 * which is probably the server most used by
434 * wine users. Other X servers will not
435 * display correctly. (eXceed for instance)
436 * so if you feel you must make changes, make sure that
437 * you either use Xfree86 or separate your changes
438 * from these (compile switch or whatever)
442 points[3] = points[1];
443 points[1].x = dc->DCOrgX + xcenter;
444 points[1].y = dc->DCOrgY + ycenter;
445 points[2] = points[1];
446 dx1=points[1].x-points[0].x;
447 dy1=points[1].y-points[0].y;
448 if(((top-bottom) | -2) == -2)
449 if(dy1>0) points[1].y--;
451 if (((-dx1)*64)<=ABS(dy1)*37) points[0].x--;
452 if(((-dx1*9))<(dy1*16)) points[0].y--;
453 if( dy1<0 && ((dx1*9)) < (dy1*16)) points[0].y--;
455 if(dy1 < 0) points[0].y--;
456 if(((right-left) | -2) == -2) points[1].x--;
458 dx1=points[3].x-points[2].x;
459 dy1=points[3].y-points[2].y;
460 if(((top-bottom) | -2 ) == -2)
461 if(dy1 < 0) points[2].y--;
463 if( dy1>0) points[3].y--;
464 if(((right-left) | -2) == -2 ) points[2].x--;
467 if( dx1 * 64 < dy1 * -37 ) points[3].x--;
471 TSXDrawLines( display, physDev->drawable, physDev->gc,
472 points, lines+1, CoordModeOrigin );
477 /* Update the DIBSection of the pixmap */
478 X11DRV_UnlockDIBSection(dc, update);
480 physDev->pen.width = oldwidth;
481 physDev->pen.endcap = oldendcap;
486 /***********************************************************************
490 X11DRV_Arc( DC *dc, INT left, INT top, INT right, INT bottom,
491 INT xstart, INT ystart, INT xend, INT yend )
493 return X11DRV_DrawArc( dc, left, top, right, bottom,
494 xstart, ystart, xend, yend, 0 );
498 /***********************************************************************
502 X11DRV_Pie( DC *dc, INT left, INT top, INT right, INT bottom,
503 INT xstart, INT ystart, INT xend, INT yend )
505 return X11DRV_DrawArc( dc, left, top, right, bottom,
506 xstart, ystart, xend, yend, 2 );
509 /***********************************************************************
513 X11DRV_Chord( DC *dc, INT left, INT top, INT right, INT bottom,
514 INT xstart, INT ystart, INT xend, INT yend )
516 return X11DRV_DrawArc( dc, left, top, right, bottom,
517 xstart, ystart, xend, yend, 1 );
521 /***********************************************************************
525 X11DRV_Ellipse( DC *dc, INT left, INT top, INT right, INT bottom )
528 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
531 left = XLPTODP( dc, left );
532 top = YLPTODP( dc, top );
533 right = XLPTODP( dc, right );
534 bottom = YLPTODP( dc, bottom );
535 if ((left == right) || (top == bottom)) return TRUE;
537 if (right < left) { INT tmp = right; right = left; left = tmp; }
538 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
540 oldwidth = width = physDev->pen.width;
541 if (!width) width = 1;
542 if(physDev->pen.style == PS_NULL) width = 0;
544 if ((physDev->pen.style == PS_INSIDEFRAME))
546 if (2*width > (right-left)) width=(right-left + 1)/2;
547 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
549 right -= (width - 1) / 2;
551 bottom -= (width - 1) / 2;
553 if(width == 0) width = 1; /* more accurate */
554 physDev->pen.width = width;
556 /* Update the pixmap from the DIB section */
557 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
559 if (X11DRV_SetupGCForBrush( dc ))
561 TSXFillArc( display, physDev->drawable, physDev->gc,
562 dc->DCOrgX + left, dc->DCOrgY + top,
563 right-left-1, bottom-top-1, 0, 360*64 );
566 if (X11DRV_SetupGCForPen( dc ))
568 TSXDrawArc( display, physDev->drawable, physDev->gc,
569 dc->DCOrgX + left, dc->DCOrgY + top,
570 right-left-1, bottom-top-1, 0, 360*64 );
574 /* Update the DIBSection from the pixmap */
575 X11DRV_UnlockDIBSection(dc, update);
577 physDev->pen.width = oldwidth;
582 /***********************************************************************
586 X11DRV_Rectangle(DC *dc, INT left, INT top, INT right, INT bottom)
588 INT width, oldwidth, oldjoinstyle;
589 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
592 TRACE("(%d %d %d %d)\n",
593 left, top, right, bottom);
595 left = INTERNAL_XWPTODP( dc, left, top );
596 top = INTERNAL_YWPTODP( dc, left, top );
597 right = INTERNAL_XWPTODP( dc, right, bottom );
598 bottom = INTERNAL_YWPTODP( dc, right, bottom );
600 if ((left == right) || (top == bottom)) return TRUE;
602 if (right < left) { INT tmp = right; right = left; left = tmp; }
603 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
605 oldwidth = width = physDev->pen.width;
606 if (!width) width = 1;
607 if(physDev->pen.style == PS_NULL) width = 0;
609 if ((physDev->pen.style == PS_INSIDEFRAME))
611 if (2*width > (right-left)) width=(right-left + 1)/2;
612 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
614 right -= (width - 1) / 2;
616 bottom -= (width - 1) / 2;
618 if(width == 1) width = 0;
619 physDev->pen.width = width;
620 oldjoinstyle = physDev->pen.linejoin;
621 if(physDev->pen.type != PS_GEOMETRIC)
622 physDev->pen.linejoin = PS_JOIN_MITER;
624 /* Update the pixmap from the DIB section */
625 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
627 if ((right > left + width) && (bottom > top + width))
628 if (X11DRV_SetupGCForBrush( dc ))
630 TSXFillRectangle( display, physDev->drawable, physDev->gc,
631 dc->DCOrgX + left + (width + 1) / 2,
632 dc->DCOrgY + top + (width + 1) / 2,
633 right-left-width-1, bottom-top-width-1);
636 if (X11DRV_SetupGCForPen( dc ))
638 TSXDrawRectangle( display, physDev->drawable, physDev->gc,
639 dc->DCOrgX + left, dc->DCOrgY + top,
640 right-left-1, bottom-top-1 );
644 /* Update the DIBSection from the pixmap */
645 X11DRV_UnlockDIBSection(dc, update);
647 physDev->pen.width = oldwidth;
648 physDev->pen.linejoin = oldjoinstyle;
652 /***********************************************************************
656 X11DRV_RoundRect( DC *dc, INT left, INT top, INT right,
657 INT bottom, INT ell_width, INT ell_height )
659 INT width, oldwidth, oldendcap;
660 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
663 TRACE("(%d %d %d %d %d %d\n",
664 left, top, right, bottom, ell_width, ell_height);
666 left = XLPTODP( dc, left );
667 top = YLPTODP( dc, top );
668 right = XLPTODP( dc, right );
669 bottom = YLPTODP( dc, bottom );
671 if ((left == right) || (top == bottom))
674 /* Make sure ell_width and ell_height are >= 1 otherwise XDrawArc gets
675 called with width/height < 0 */
676 ell_width = max(abs( ell_width * dc->vportExtX / dc->wndExtX ), 1);
677 ell_height = max(abs( ell_height * dc->vportExtY / dc->wndExtY ), 1);
679 /* Fix the coordinates */
681 if (right < left) { INT tmp = right; right = left; left = tmp; }
682 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
684 oldwidth = width = physDev->pen.width;
685 oldendcap = physDev->pen.endcap;
686 if (!width) width = 1;
687 if(physDev->pen.style == PS_NULL) width = 0;
689 if ((physDev->pen.style == PS_INSIDEFRAME))
691 if (2*width > (right-left)) width=(right-left + 1)/2;
692 if (2*width > (bottom-top)) width=(bottom-top + 1)/2;
694 right -= (width - 1) / 2;
696 bottom -= (width - 1) / 2;
698 if(width == 0) width = 1;
699 physDev->pen.width = width;
700 physDev->pen.endcap = PS_ENDCAP_SQUARE;
702 /* Update the pixmap from the DIB section */
703 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
705 if (X11DRV_SetupGCForBrush( dc ))
707 if (ell_width > (right-left) )
708 if (ell_height > (bottom-top) )
709 TSXFillArc( display, physDev->drawable, physDev->gc,
710 dc->DCOrgX + left, dc->DCOrgY + top,
711 right - left - 1, bottom - top - 1,
714 TSXFillArc( display, physDev->drawable, physDev->gc,
715 dc->DCOrgX + left, dc->DCOrgY + top,
716 right - left - 1, ell_height, 0, 180 * 64 );
717 TSXFillArc( display, physDev->drawable, physDev->gc,
719 dc->DCOrgY + bottom - ell_height - 1,
720 right - left - 1, ell_height, 180 * 64,
723 else if (ell_height > (bottom-top) ){
724 TSXFillArc( display, physDev->drawable, physDev->gc,
725 dc->DCOrgX + left, dc->DCOrgY + top,
726 ell_width, bottom - top - 1, 90 * 64, 180 * 64 );
727 TSXFillArc( display, physDev->drawable, physDev->gc,
728 dc->DCOrgX + right - ell_width -1, dc->DCOrgY + top,
729 ell_width, bottom - top - 1, 270 * 64, 180 * 64 );
731 TSXFillArc( display, physDev->drawable, physDev->gc,
732 dc->DCOrgX + left, dc->DCOrgY + top,
733 ell_width, ell_height, 90 * 64, 90 * 64 );
734 TSXFillArc( display, physDev->drawable, physDev->gc,
736 dc->DCOrgY + bottom - ell_height - 1,
737 ell_width, ell_height, 180 * 64, 90 * 64 );
738 TSXFillArc( display, physDev->drawable, physDev->gc,
739 dc->DCOrgX + right - ell_width - 1,
740 dc->DCOrgY + bottom - ell_height - 1,
741 ell_width, ell_height, 270 * 64, 90 * 64 );
742 TSXFillArc( display, physDev->drawable, physDev->gc,
743 dc->DCOrgX + right - ell_width - 1,
745 ell_width, ell_height, 0, 90 * 64 );
747 if (ell_width < right - left)
749 TSXFillRectangle( display, physDev->drawable, physDev->gc,
750 dc->DCOrgX + left + (ell_width + 1) / 2,
751 dc->DCOrgY + top + 1,
752 right - left - ell_width - 1,
753 (ell_height + 1) / 2 - 1);
754 TSXFillRectangle( display, physDev->drawable, physDev->gc,
755 dc->DCOrgX + left + (ell_width + 1) / 2,
756 dc->DCOrgY + bottom - (ell_height) / 2 - 1,
757 right - left - ell_width - 1,
760 if (ell_height < bottom - top)
762 TSXFillRectangle( display, physDev->drawable, physDev->gc,
763 dc->DCOrgX + left + 1,
764 dc->DCOrgY + top + (ell_height + 1) / 2,
766 bottom - top - ell_height - 1);
770 /* FIXME: this could be done with on X call
771 * more efficient and probably more correct
772 * on any X server: XDrawArcs will draw
773 * straight horizontal and vertical lines
774 * if width or height are zero.
776 * BTW this stuff is optimized for an Xfree86 server
777 * read the comments inside the X11DRV_DrawArc function
779 if (X11DRV_SetupGCForPen(dc)) {
780 if (ell_width > (right-left) )
781 if (ell_height > (bottom-top) )
782 TSXDrawArc( display, physDev->drawable, physDev->gc,
783 dc->DCOrgX + left, dc->DCOrgY + top,
784 right - left - 1, bottom -top - 1, 0 , 360 * 64 );
786 TSXDrawArc( display, physDev->drawable, physDev->gc,
787 dc->DCOrgX + left, dc->DCOrgY + top,
788 right - left - 1, ell_height - 1, 0 , 180 * 64 );
789 TSXDrawArc( display, physDev->drawable, physDev->gc,
791 dc->DCOrgY + bottom - ell_height,
792 right - left - 1, ell_height - 1, 180 * 64 , 180 * 64 );
794 else if (ell_height > (bottom-top) ){
795 TSXDrawArc( display, physDev->drawable, physDev->gc,
796 dc->DCOrgX + left, dc->DCOrgY + top,
797 ell_width - 1 , bottom - top - 1, 90 * 64 , 180 * 64 );
798 TSXDrawArc( display, physDev->drawable, physDev->gc,
799 dc->DCOrgX + right - ell_width,
801 ell_width - 1 , bottom - top - 1, 270 * 64 , 180 * 64 );
803 TSXDrawArc( display, physDev->drawable, physDev->gc,
804 dc->DCOrgX + left, dc->DCOrgY + top,
805 ell_width - 1, ell_height - 1, 90 * 64, 90 * 64 );
806 TSXDrawArc( display, physDev->drawable, physDev->gc,
807 dc->DCOrgX + left, dc->DCOrgY + bottom - ell_height,
808 ell_width - 1, ell_height - 1, 180 * 64, 90 * 64 );
809 TSXDrawArc( display, physDev->drawable, physDev->gc,
810 dc->DCOrgX + right - ell_width,
811 dc->DCOrgY + bottom - ell_height,
812 ell_width - 1, ell_height - 1, 270 * 64, 90 * 64 );
813 TSXDrawArc( display, physDev->drawable, physDev->gc,
814 dc->DCOrgX + right - ell_width, dc->DCOrgY + top,
815 ell_width - 1, ell_height - 1, 0, 90 * 64 );
817 if (ell_width < right - left)
819 TSXDrawLine( display, physDev->drawable, physDev->gc,
820 dc->DCOrgX + left + ell_width / 2,
822 dc->DCOrgX + right - (ell_width+1) / 2,
824 TSXDrawLine( display, physDev->drawable, physDev->gc,
825 dc->DCOrgX + left + ell_width / 2 ,
826 dc->DCOrgY + bottom - 1,
827 dc->DCOrgX + right - (ell_width+1)/ 2,
828 dc->DCOrgY + bottom - 1);
830 if (ell_height < bottom - top)
832 TSXDrawLine( display, physDev->drawable, physDev->gc,
833 dc->DCOrgX + right - 1,
834 dc->DCOrgY + top + ell_height / 2,
835 dc->DCOrgX + right - 1,
836 dc->DCOrgY + bottom - (ell_height+1) / 2);
837 TSXDrawLine( display, physDev->drawable, physDev->gc,
839 dc->DCOrgY + top + ell_height / 2,
841 dc->DCOrgY + bottom - (ell_height+1) / 2);
846 /* Update the DIBSection from the pixmap */
847 X11DRV_UnlockDIBSection(dc, update);
849 physDev->pen.width = oldwidth;
850 physDev->pen.endcap = oldendcap;
855 /***********************************************************************
859 X11DRV_SetPixel( DC *dc, INT x, INT y, COLORREF color )
862 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
864 x = dc->DCOrgX + INTERNAL_XWPTODP( dc, x, y );
865 y = dc->DCOrgY + INTERNAL_YWPTODP( dc, x, y );
866 pixel = X11DRV_PALETTE_ToPhysical( dc, color );
868 /* Update the pixmap from the DIB section */
869 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
871 /* inefficient but simple... */
872 TSXSetForeground( display, physDev->gc, pixel );
873 TSXSetFunction( display, physDev->gc, GXcopy );
874 TSXDrawPoint( display, physDev->drawable, physDev->gc, x, y );
876 /* Update the DIBSection from the pixmap */
877 X11DRV_UnlockDIBSection(dc, TRUE);
879 return X11DRV_PALETTE_ToLogical(pixel);
883 /***********************************************************************
887 X11DRV_GetPixel( DC *dc, INT x, INT y )
889 static Pixmap pixmap = 0;
892 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
894 /* Update the pixmap from the DIB section */
895 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
897 x = dc->DCOrgX + INTERNAL_XWPTODP( dc, x, y );
898 y = dc->DCOrgY + INTERNAL_YWPTODP( dc, x, y );
900 if (dc->flags & DC_MEMORY)
902 image = XGetImage( display, physDev->drawable, x, y, 1, 1,
903 AllPlanes, ZPixmap );
907 /* If we are reading from the screen, use a temporary copy */
908 /* to avoid a BadMatch error */
909 if (!pixmap) pixmap = XCreatePixmap( display, X11DRV_GetXRootWindow(),
910 1, 1, dc->bitsPerPixel );
911 XCopyArea( display, physDev->drawable, pixmap, BITMAP_colorGC,
913 image = XGetImage( display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
915 pixel = XGetPixel( image, 0, 0 );
916 XDestroyImage( image );
919 /* Update the DIBSection from the pixmap */
920 X11DRV_UnlockDIBSection(dc, FALSE);
922 return X11DRV_PALETTE_ToLogical(pixel);
926 /***********************************************************************
930 X11DRV_PaintRgn( DC *dc, HRGN hrgn )
933 HRGN tmpVisRgn, prevVisRgn;
934 HDC hdc = dc->hSelf; /* FIXME: should not mix dc/hdc this way */
935 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
937 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
939 /* Transform region into device co-ords */
940 if ( !REGION_LPTODP( hdc, tmpVisRgn, hrgn )
941 || OffsetRgn( tmpVisRgn, dc->DCOrgX, dc->DCOrgY ) == ERROR) {
942 DeleteObject( tmpVisRgn );
946 /* Modify visible region */
947 if (!(prevVisRgn = SaveVisRgn16( hdc ))) {
948 DeleteObject( tmpVisRgn );
951 CombineRgn( tmpVisRgn, prevVisRgn, tmpVisRgn, RGN_AND );
952 SelectVisRgn16( hdc, tmpVisRgn );
953 DeleteObject( tmpVisRgn );
955 /* Fill the region */
957 GetRgnBox( dc->hGCClipRgn, &box );
958 if (X11DRV_SetupGCForBrush( dc ))
960 /* Update the pixmap from the DIB section */
961 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
963 TSXFillRectangle( display, physDev->drawable, physDev->gc,
965 box.right-box.left, box.bottom-box.top );
967 /* Update the DIBSection from the pixmap */
968 X11DRV_UnlockDIBSection(dc, TRUE);
971 /* Restore the visible region */
973 RestoreVisRgn16( hdc );
977 /**********************************************************************
981 X11DRV_Polyline( DC *dc, const POINT* pt, INT count )
986 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
988 if((oldwidth = physDev->pen.width) == 0) physDev->pen.width = 1;
990 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * count )))
992 WARN("No memory to convert POINTs to XPoints!\n");
995 for (i = 0; i < count; i++)
997 points[i].x = dc->DCOrgX + INTERNAL_XWPTODP( dc, pt[i].x, pt[i].y );
998 points[i].y = dc->DCOrgY + INTERNAL_YWPTODP( dc, pt[i].x, pt[i].y );
1001 if (X11DRV_SetupGCForPen ( dc ))
1003 /* Update the pixmap from the DIB section */
1004 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
1006 TSXDrawLines( display, physDev->drawable, physDev->gc,
1007 points, count, CoordModeOrigin );
1009 /* Update the DIBSection from the pixmap */
1010 X11DRV_UnlockDIBSection(dc, TRUE);
1013 HeapFree( GetProcessHeap(), 0, points );
1014 physDev->pen.width = oldwidth;
1019 /**********************************************************************
1023 X11DRV_Polygon( DC *dc, const POINT* pt, INT count )
1027 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1028 BOOL update = FALSE;
1030 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (count+1) )))
1032 WARN("No memory to convert POINTs to XPoints!\n");
1035 for (i = 0; i < count; i++)
1037 points[i].x = dc->DCOrgX + INTERNAL_XWPTODP( dc, pt[i].x, pt[i].y );
1038 points[i].y = dc->DCOrgY + INTERNAL_YWPTODP( dc, pt[i].x, pt[i].y );
1040 points[count] = points[0];
1042 /* Update the pixmap from the DIB section */
1043 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
1045 if (X11DRV_SetupGCForBrush( dc ))
1047 TSXFillPolygon( display, physDev->drawable, physDev->gc,
1048 points, count+1, Complex, CoordModeOrigin);
1051 if (X11DRV_SetupGCForPen ( dc ))
1053 TSXDrawLines( display, physDev->drawable, physDev->gc,
1054 points, count+1, CoordModeOrigin );
1058 /* Update the DIBSection from the pixmap */
1059 X11DRV_UnlockDIBSection(dc, update);
1061 HeapFree( GetProcessHeap(), 0, points );
1066 /**********************************************************************
1067 * X11DRV_PolyPolygon
1070 X11DRV_PolyPolygon( DC *dc, const POINT* pt, const INT* counts, UINT polygons)
1073 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1075 /* FIXME: The points should be converted to device coords before */
1076 /* creating the region. */
1078 hrgn = CreatePolyPolygonRgn( pt, counts, polygons, dc->polyFillMode );
1079 X11DRV_PaintRgn( dc, hrgn );
1080 DeleteObject( hrgn );
1082 /* Draw the outline of the polygons */
1084 if (X11DRV_SetupGCForPen ( dc ))
1089 /* Update the pixmap from the DIB section */
1090 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
1092 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
1093 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (max+1) )))
1095 WARN("No memory to convert POINTs to XPoints!\n");
1098 for (i = 0; i < polygons; i++)
1100 for (j = 0; j < counts[i]; j++)
1102 points[j].x = dc->DCOrgX + INTERNAL_XWPTODP( dc, pt->x, pt->y );
1103 points[j].y = dc->DCOrgY + INTERNAL_YWPTODP( dc, pt->x, pt->y );
1106 points[j] = points[0];
1107 TSXDrawLines( display, physDev->drawable, physDev->gc,
1108 points, j + 1, CoordModeOrigin );
1111 /* Update the DIBSection of the dc's bitmap */
1112 X11DRV_UnlockDIBSection(dc, TRUE);
1114 HeapFree( GetProcessHeap(), 0, points );
1120 /**********************************************************************
1121 * X11DRV_PolyPolyline
1124 X11DRV_PolyPolyline( DC *dc, const POINT* pt, const DWORD* counts, DWORD polylines )
1126 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1128 if (X11DRV_SetupGCForPen ( dc ))
1133 /* Update the pixmap from the DIB section */
1134 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
1136 for (i = 0; i < polylines; i++) if (counts[i] > max) max = counts[i];
1137 if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * max )))
1139 WARN("No memory to convert POINTs to XPoints!\n");
1142 for (i = 0; i < polylines; i++)
1144 for (j = 0; j < counts[i]; j++)
1146 points[j].x = dc->DCOrgX + INTERNAL_XWPTODP( dc, pt->x, pt->y );
1147 points[j].y = dc->DCOrgY + INTERNAL_YWPTODP( dc, pt->x, pt->y );
1150 TSXDrawLines( display, physDev->drawable, physDev->gc,
1151 points, j, CoordModeOrigin );
1154 /* Update the DIBSection of the dc's bitmap */
1155 X11DRV_UnlockDIBSection(dc, TRUE);
1157 HeapFree( GetProcessHeap(), 0, points );
1163 /**********************************************************************
1164 * X11DRV_InternalFloodFill
1166 * Internal helper function for flood fill.
1167 * (xorg,yorg) is the origin of the X image relative to the drawable.
1168 * (x,y) is relative to the origin of the X image.
1170 static void X11DRV_InternalFloodFill(XImage *image, DC *dc,
1173 Pixel pixel, WORD fillType )
1175 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1178 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
1179 (XGetPixel(image,x,y) != pixel) : \
1180 (XGetPixel(image,x,y) == pixel))
1182 if (!TO_FLOOD(x,y)) return;
1184 /* Find left and right boundaries */
1187 while ((left > 0) && TO_FLOOD( left-1, y )) left--;
1188 while ((right < image->width) && TO_FLOOD( right, y )) right++;
1189 XFillRectangle( display, physDev->drawable, physDev->gc,
1190 xOrg + left, yOrg + y, right-left, 1 );
1192 /* Set the pixels of this line so we don't fill it again */
1194 for (x = left; x < right; x++)
1196 if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
1197 else XPutPixel( image, x, y, ~pixel );
1200 /* Fill the line above */
1207 while ((x < right) && !TO_FLOOD(x,y)) x++;
1208 if (x >= right) break;
1209 while ((x < right) && TO_FLOOD(x,y)) x++;
1210 X11DRV_InternalFloodFill(image, dc, x-1, y,
1211 xOrg, yOrg, pixel, fillType );
1215 /* Fill the line below */
1217 if ((y += 2) < image->height)
1222 while ((x < right) && !TO_FLOOD(x,y)) x++;
1223 if (x >= right) break;
1224 while ((x < right) && TO_FLOOD(x,y)) x++;
1225 X11DRV_InternalFloodFill(image, dc, x-1, y,
1226 xOrg, yOrg, pixel, fillType );
1233 /**********************************************************************
1234 * X11DRV_ExtFloodFill
1237 X11DRV_ExtFloodFill( DC *dc, INT x, INT y, COLORREF color,
1242 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1244 TRACE("X11DRV_ExtFloodFill %d,%d %06lx %d\n", x, y, color, fillType );
1246 if (!PtVisible( dc->hSelf, x, y )) return FALSE;
1247 if (GetRgnBox( dc->hGCClipRgn, &rect ) == ERROR) return FALSE;
1249 if (!(image = TSXGetImage( display, physDev->drawable,
1252 rect.right - rect.left,
1253 rect.bottom - rect.top,
1254 AllPlanes, ZPixmap ))) return FALSE;
1257 if (X11DRV_SetupGCForBrush( dc ))
1259 /* Update the pixmap from the DIB section */
1260 X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE);
1262 /* ROP mode is always GXcopy for flood-fill */
1263 XSetFunction( display, physDev->gc, GXcopy );
1264 X11DRV_InternalFloodFill(image, dc,
1265 XLPTODP(dc,x) + dc->DCOrgX - rect.left,
1266 YLPTODP(dc,y) + dc->DCOrgY - rect.top,
1267 rect.left, rect.top,
1268 X11DRV_PALETTE_ToPhysical( dc, color ),
1270 /* Update the DIBSection of the dc's bitmap */
1271 X11DRV_UnlockDIBSection(dc, TRUE);
1274 XDestroyImage( image );
1275 wine_tsx11_unlock();
1279 /**********************************************************************
1283 X11DRV_SetBkColor( DC *dc, COLORREF color )
1285 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1288 oldColor = dc->backgroundColor;
1289 dc->backgroundColor = color;
1291 physDev->backgroundPixel = X11DRV_PALETTE_ToPhysical( dc, color );
1296 /**********************************************************************
1297 * X11DRV_SetTextColor
1300 X11DRV_SetTextColor( DC *dc, COLORREF color )
1302 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1305 oldColor = dc->textColor;
1306 dc->textColor = color;
1308 physDev->textPixel = X11DRV_PALETTE_ToPhysical( dc, color );
1313 /***********************************************************************
1316 BOOL X11DRV_GetDCOrgEx( DC *dc, LPPOINT lpp )
1318 if (!(dc->flags & DC_MEMORY))
1320 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *) dc->physDev;
1322 int w, h, border, depth;
1324 /* FIXME: this is not correct for managed windows */
1325 TSXGetGeometry( display, physDev->drawable, &root,
1326 (int*)&lpp->x, (int*)&lpp->y, &w, &h, &border, &depth );
1328 else lpp->x = lpp->y = 0;