2 * X11 graphics driver graphics functions
4 * Copyright 1993,1994 Alexandre Julliard
9 * FIXME: none of these functions obey the GM_ADVANCED
20 #include <X11/Intrinsic.h>
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 BOOL32
X11DRV_SetupGCForPatBlt( DC
* dc
, GC gc
, BOOL32 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
&& COLOR_PixelToPalette
)
96 val
.foreground
= COLOR_PixelToPalette
[val
.foreground
];
97 val
.background
= COLOR_PixelToPalette
[val
.background
];
100 if (dc
->w
.flags
& DC_DIRTY
) CLIPPING_UpdateGCRegion(dc
);
102 val
.function
= X11DRV_XROPfunction
[dc
->w
.ROPmode
-1];
104 ** Let's replace GXinvert by GXxor with (black xor white)
105 ** This solves the selection color and leak problems in excel
106 ** FIXME : Let's do that only if we work with X-pixels, not with Win-pixels
108 if (val
.function
== GXinvert
)
110 val
.foreground
= BlackPixelOfScreen(screen
) ^ WhitePixelOfScreen(screen
);
111 val
.function
= GXxor
;
113 val
.fill_style
= physDev
->brush
.fillStyle
;
114 switch(val
.fill_style
)
117 case FillOpaqueStippled
:
118 if (dc
->w
.backgroundMode
==OPAQUE
) val
.fill_style
= FillOpaqueStippled
;
119 val
.stipple
= physDev
->brush
.pixmap
;
124 if (fMapColors
&& COLOR_PixelToPalette
)
128 EnterCriticalSection( &X11DRV_CritSection
);
129 pixmap
= XCreatePixmap( display
, rootWindow
, 8, 8, screenDepth
);
130 image
= XGetImage( display
, physDev
->brush
.pixmap
, 0, 0, 8, 8,
131 AllPlanes
, ZPixmap
);
132 for (y
= 0; y
< 8; y
++)
133 for (x
= 0; x
< 8; x
++)
134 XPutPixel( image
, x
, y
,
135 COLOR_PixelToPalette
[XGetPixel( image
, x
, y
)] );
136 XPutImage( display
, pixmap
, gc
, image
, 0, 0, 0, 0, 8, 8 );
137 XDestroyImage( image
);
138 LeaveCriticalSection( &X11DRV_CritSection
);
141 else val
.tile
= physDev
->brush
.pixmap
;
149 val
.ts_x_origin
= dc
->w
.DCOrgX
+ dc
->w
.brushOrgX
;
150 val
.ts_y_origin
= dc
->w
.DCOrgY
+ dc
->w
.brushOrgY
;
151 val
.fill_rule
= (dc
->w
.polyFillMode
==WINDING
) ? WindingRule
: EvenOddRule
;
152 TSXChangeGC( display
, gc
,
153 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
154 GCFillRule
| GCTileStipXOrigin
| GCTileStipYOrigin
| mask
,
156 if (pixmap
) TSXFreePixmap( display
, pixmap
);
161 /***********************************************************************
162 * X11DRV_SetupGCForBrush
164 * Setup physDev->gc for drawing operations using current brush.
165 * Return FALSE if brush is BS_NULL, TRUE otherwise.
167 BOOL32
X11DRV_SetupGCForBrush( DC
* dc
)
169 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
170 return X11DRV_SetupGCForPatBlt( dc
, physDev
->gc
, FALSE
);
174 /***********************************************************************
175 * X11DRV_SetupGCForPen
177 * Setup physDev->gc for drawing operations using current pen.
178 * Return FALSE if pen is PS_NULL, TRUE otherwise.
180 BOOL32
X11DRV_SetupGCForPen( DC
* dc
)
183 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
185 if (physDev
->pen
.style
== PS_NULL
) return FALSE
;
187 if (dc
->w
.flags
& DC_DIRTY
) CLIPPING_UpdateGCRegion(dc
);
189 switch (dc
->w
.ROPmode
)
192 val
.foreground
= BlackPixelOfScreen( screen
);
193 val
.function
= GXcopy
;
196 val
.foreground
= WhitePixelOfScreen( screen
);
197 val
.function
= GXcopy
;
200 val
.foreground
= physDev
->pen
.pixel
;
201 /* It is very unlikely someone wants to XOR with 0 */
202 /* This fixes the rubber-drawings in paintbrush */
203 if (val
.foreground
== 0)
204 val
.foreground
= BlackPixelOfScreen( screen
)
205 ^ WhitePixelOfScreen( screen
);
206 val
.function
= GXxor
;
209 val
.foreground
= physDev
->pen
.pixel
;
210 val
.function
= X11DRV_XROPfunction
[dc
->w
.ROPmode
-1];
212 val
.background
= physDev
->backgroundPixel
;
213 val
.fill_style
= FillSolid
;
214 if ((physDev
->pen
.style
!=PS_SOLID
) && (physDev
->pen
.style
!=PS_INSIDEFRAME
))
216 TSXSetDashes( display
, physDev
->gc
, 0, physDev
->pen
.dashes
,
217 physDev
->pen
.dash_len
);
218 val
.line_style
= (dc
->w
.backgroundMode
== OPAQUE
) ?
219 LineDoubleDash
: LineOnOffDash
;
221 else val
.line_style
= LineSolid
;
222 val
.line_width
= physDev
->pen
.width
;
223 if (val
.line_width
<= 1) {
224 val
.cap_style
= CapNotLast
;
226 switch (physDev
->pen
.endcap
)
228 case PS_ENDCAP_SQUARE
:
229 val
.cap_style
= CapProjecting
;
232 val
.cap_style
= CapButt
;
234 case PS_ENDCAP_ROUND
:
236 val
.cap_style
= CapRound
;
239 switch (physDev
->pen
.linejoin
)
242 val
.join_style
= JoinBevel
;
245 val
.join_style
= JoinMiter
;
249 val
.join_style
= JoinRound
;
251 TSXChangeGC( display
, physDev
->gc
,
252 GCFunction
| GCForeground
| GCBackground
| GCLineWidth
|
253 GCLineStyle
| GCCapStyle
| GCJoinStyle
| GCFillStyle
, &val
);
258 /***********************************************************************
259 * X11DRV_SetupGCForText
261 * Setup physDev->gc for text drawing operations.
262 * Return FALSE if the font is null, TRUE otherwise.
264 BOOL32
X11DRV_SetupGCForText( DC
* dc
)
266 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
267 XFontStruct
* xfs
= XFONT_GetFontStruct( physDev
->font
);
273 if (dc
->w
.flags
& DC_DIRTY
) CLIPPING_UpdateGCRegion(dc
);
275 val
.function
= GXcopy
; /* Text is always GXcopy */
276 val
.foreground
= physDev
->textPixel
;
277 val
.background
= physDev
->backgroundPixel
;
278 val
.fill_style
= FillSolid
;
281 TSXChangeGC( display
, physDev
->gc
,
282 GCFunction
| GCForeground
| GCBackground
| GCFillStyle
|
286 WARN(dc
, "Physical font failure\n" );
291 /**********************************************************************
295 X11DRV_MoveToEx(DC
*dc
,INT32 x
,INT32 y
,LPPOINT32 pt
) {
298 pt
->x
= dc
->w
.CursPosX
;
299 pt
->y
= dc
->w
.CursPosY
;
306 /***********************************************************************
310 X11DRV_LineTo( DC
*dc
, INT32 x
, INT32 y
)
312 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
314 if (X11DRV_SetupGCForPen( dc
))
315 TSXDrawLine(display
, physDev
->drawable
, physDev
->gc
,
316 dc
->w
.DCOrgX
+ XLPTODP( dc
, dc
->w
.CursPosX
),
317 dc
->w
.DCOrgY
+ YLPTODP( dc
, dc
->w
.CursPosY
),
318 dc
->w
.DCOrgX
+ XLPTODP( dc
, x
),
319 dc
->w
.DCOrgY
+ YLPTODP( dc
, y
) );
327 /***********************************************************************
330 * Helper functions for Arc(), Chord() and Pie().
331 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
335 X11DRV_DrawArc( DC
*dc
, INT32 left
, INT32 top
, INT32 right
,
336 INT32 bottom
, INT32 xstart
, INT32 ystart
,
337 INT32 xend
, INT32 yend
, INT32 lines
)
339 INT32 xcenter
, ycenter
, istart_angle
, idiff_angle
;
340 INT32 width
, oldwidth
, oldendcap
;
341 double start_angle
, end_angle
;
343 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
345 left
= XLPTODP( dc
, left
);
346 top
= YLPTODP( dc
, top
);
347 right
= XLPTODP( dc
, right
);
348 bottom
= YLPTODP( dc
, bottom
);
349 xstart
= XLPTODP( dc
, xstart
);
350 ystart
= YLPTODP( dc
, ystart
);
351 xend
= XLPTODP( dc
, xend
);
352 yend
= YLPTODP( dc
, yend
);
354 if (right
< left
) { INT32 tmp
= right
; right
= left
; left
= tmp
; }
355 if (bottom
< top
) { INT32 tmp
= bottom
; bottom
= top
; top
= tmp
; }
356 if ((left
== right
) || (top
== bottom
)
357 ||(lines
&& ((right
-left
==1)||(bottom
-top
==1)))) return TRUE
;
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
= (INT32
)(start_angle
* 180 * 64 / PI
+ 0.5);
395 idiff_angle
= (INT32
)((end_angle
- start_angle
) * 180 * 64 / PI
+ 0.5);
396 if (idiff_angle
<= 0) idiff_angle
+= 360 * 64;
398 /* Fill arc with brush if Chord() or Pie() */
400 if ((lines
> 0) && X11DRV_SetupGCForBrush( dc
)) {
401 TSXSetArcMode( display
, physDev
->gc
,
402 (lines
==1) ? ArcChord
: ArcPieSlice
);
403 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
404 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
405 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
408 /* Draw arc and lines */
410 if (X11DRV_SetupGCForPen( dc
)){
411 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
412 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
413 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
415 /* use the truncated values */
416 start_angle
=(double)istart_angle
*PI
/64./180.;
417 end_angle
=(double)(istart_angle
+idiff_angle
)*PI
/64./180.;
418 /* calculate the endpoints and round correctly */
419 points
[0].x
= (int) floor(dc
->w
.DCOrgX
+ (right
+left
)/2.0 +
420 cos(start_angle
) * (right
-left
-width
*2+2) / 2. + 0.5);
421 points
[0].y
= (int) floor(dc
->w
.DCOrgY
+ (top
+bottom
)/2.0 -
422 sin(start_angle
) * (bottom
-top
-width
*2+2) / 2. + 0.5);
423 points
[1].x
= (int) floor(dc
->w
.DCOrgX
+ (right
+left
)/2.0 +
424 cos(end_angle
) * (right
-left
-width
*2+2) / 2. + 0.5);
425 points
[1].y
= (int) floor(dc
->w
.DCOrgY
+ (top
+bottom
)/2.0 -
426 sin(end_angle
) * (bottom
-top
-width
*2+2) / 2. + 0.5);
428 /* OK this stuff is optimized for Xfree86
429 * which is probably the most used server by
430 * wine users. Other X servers will not
431 * display correctly. (eXceed for instance)
432 * so if you feel you must change make sure that
433 * you either use Xfree86 or seperate your changes
434 * from these (compile switch or whatever)
438 points
[3] = points
[1];
439 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
;
440 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
;
441 points
[2] = points
[1];
442 dx1
=points
[1].x
-points
[0].x
;
443 dy1
=points
[1].y
-points
[0].y
;
444 if(((top
-bottom
) | -2) == -2)
445 if(dy1
>0) points
[1].y
--;
447 if (((-dx1
)*64)<=ABS(dy1
)*37) points
[0].x
--;
448 if(((-dx1
*9))<(dy1
*16)) points
[0].y
--;
449 if( dy1
<0 && ((dx1
*9)) < (dy1
*16)) points
[0].y
--;
451 if(dy1
< 0) points
[0].y
--;
452 if(((right
-left
) | -2) == -2) points
[1].x
--;
454 dx1
=points
[3].x
-points
[2].x
;
455 dy1
=points
[3].y
-points
[2].y
;
456 if(((top
-bottom
) | -2 ) == -2)
457 if(dy1
< 0) points
[2].y
--;
459 if( dy1
>0) points
[3].y
--;
460 if(((right
-left
) | -2) == -2 ) points
[2].x
--;
463 if( dx1
* 64 < dy1
* -37 ) points
[3].x
--;
467 TSXDrawLines( display
, physDev
->drawable
, physDev
->gc
,
468 points
, lines
+1, CoordModeOrigin
);
471 physDev
->pen
.width
= oldwidth
;
472 physDev
->pen
.endcap
= oldendcap
;
477 /***********************************************************************
481 X11DRV_Arc( DC
*dc
, INT32 left
, INT32 top
, INT32 right
, INT32 bottom
,
482 INT32 xstart
, INT32 ystart
, INT32 xend
, INT32 yend
)
484 return X11DRV_DrawArc( dc
, left
, top
, right
, bottom
,
485 xstart
, ystart
, xend
, yend
, 0 );
489 /***********************************************************************
493 X11DRV_Pie( DC
*dc
, INT32 left
, INT32 top
, INT32 right
, INT32 bottom
,
494 INT32 xstart
, INT32 ystart
, INT32 xend
, INT32 yend
)
496 return X11DRV_DrawArc( dc
, left
, top
, right
, bottom
,
497 xstart
, ystart
, xend
, yend
, 2 );
500 /***********************************************************************
504 X11DRV_Chord( DC
*dc
, INT32 left
, INT32 top
, INT32 right
, INT32 bottom
,
505 INT32 xstart
, INT32 ystart
, INT32 xend
, INT32 yend
)
507 return X11DRV_DrawArc( dc
, left
, top
, right
, bottom
,
508 xstart
, ystart
, xend
, yend
, 1 );
512 /***********************************************************************
516 X11DRV_Ellipse( DC
*dc
, INT32 left
, INT32 top
, INT32 right
, INT32 bottom
)
518 INT32 width
, oldwidth
;
519 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
521 left
= XLPTODP( dc
, left
);
522 top
= YLPTODP( dc
, top
);
523 right
= XLPTODP( dc
, right
);
524 bottom
= YLPTODP( dc
, bottom
);
525 if ((left
== right
) || (top
== bottom
)) return TRUE
;
527 if (right
< left
) { INT32 tmp
= right
; right
= left
; left
= tmp
; }
528 if (bottom
< top
) { INT32 tmp
= bottom
; bottom
= top
; top
= tmp
; }
530 oldwidth
= width
= physDev
->pen
.width
;
531 if (!width
) width
= 1;
532 if(physDev
->pen
.style
== PS_NULL
) width
= 0;
534 if ((physDev
->pen
.style
== PS_INSIDEFRAME
))
536 if (2*width
> (right
-left
)) width
=(right
-left
+ 1)/2;
537 if (2*width
> (bottom
-top
)) width
=(bottom
-top
+ 1)/2;
539 right
-= (width
- 1) / 2;
541 bottom
-= (width
- 1) / 2;
543 if(width
== 0) width
= 1; /* more accurate */
544 physDev
->pen
.width
= width
;
546 if (X11DRV_SetupGCForBrush( dc
))
547 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
548 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
549 right
-left
-1, bottom
-top
-1, 0, 360*64 );
550 if (X11DRV_SetupGCForPen( dc
))
551 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
552 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
553 right
-left
-1, bottom
-top
-1, 0, 360*64 );
554 physDev
->pen
.width
= oldwidth
;
559 /***********************************************************************
563 X11DRV_Rectangle(DC
*dc
, INT32 left
, INT32 top
, INT32 right
, INT32 bottom
)
565 INT32 width
, oldwidth
, oldjoinstyle
;
566 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
568 TRACE(graphics
, "(%d %d %d %d)\n",
569 left
, top
, right
, bottom
);
571 left
= XLPTODP( dc
, left
);
572 top
= YLPTODP( dc
, top
);
573 right
= XLPTODP( dc
, right
);
574 bottom
= YLPTODP( dc
, bottom
);
576 if ((left
== right
) || (top
== bottom
)) return TRUE
;
578 if (right
< left
) { INT32 tmp
= right
; right
= left
; left
= tmp
; }
579 if (bottom
< top
) { INT32 tmp
= bottom
; bottom
= top
; top
= tmp
; }
581 oldwidth
= width
= physDev
->pen
.width
;
582 if (!width
) width
= 1;
583 if(physDev
->pen
.style
== PS_NULL
) width
= 0;
585 if ((physDev
->pen
.style
== PS_INSIDEFRAME
))
587 if (2*width
> (right
-left
)) width
=(right
-left
+ 1)/2;
588 if (2*width
> (bottom
-top
)) width
=(bottom
-top
+ 1)/2;
590 right
-= (width
- 1) / 2;
592 bottom
-= (width
- 1) / 2;
594 if(width
== 1) width
= 0;
595 physDev
->pen
.width
= width
;
596 oldjoinstyle
= physDev
->pen
.linejoin
;
597 if(physDev
->pen
.type
!= PS_GEOMETRIC
)
598 physDev
->pen
.linejoin
= PS_JOIN_MITER
;
600 if ((right
> left
+ width
) && (bottom
> top
+ width
))
602 if (X11DRV_SetupGCForBrush( dc
))
603 TSXFillRectangle( display
, physDev
->drawable
, physDev
->gc
,
604 dc
->w
.DCOrgX
+ left
+ (width
+ 1) / 2,
605 dc
->w
.DCOrgY
+ top
+ (width
+ 1) / 2,
606 right
-left
-width
-1, bottom
-top
-width
-1);
608 if (X11DRV_SetupGCForPen( dc
))
609 TSXDrawRectangle( display
, physDev
->drawable
, physDev
->gc
,
610 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
611 right
-left
-1, bottom
-top
-1 );
613 physDev
->pen
.width
= oldwidth
;
614 physDev
->pen
.linejoin
= oldjoinstyle
;
618 /***********************************************************************
622 X11DRV_RoundRect( DC
*dc
, INT32 left
, INT32 top
, INT32 right
,
623 INT32 bottom
, INT32 ell_width
, INT32 ell_height
)
625 INT32 width
, oldwidth
, oldendcap
;
626 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
628 TRACE(graphics
, "(%d %d %d %d %d %d\n",
629 left
, top
, right
, bottom
, ell_width
, ell_height
);
631 left
= XLPTODP( dc
, left
);
632 top
= YLPTODP( dc
, top
);
633 right
= XLPTODP( dc
, right
);
634 bottom
= YLPTODP( dc
, bottom
);
636 if ((left
== right
) || (top
== bottom
))
639 /* Make sure ell_width and ell_height are >= 1 otherwise XDrawArc gets
640 called with width/height < 0 */
641 ell_width
= MAX(abs( ell_width
* dc
->vportExtX
/ dc
->wndExtX
), 1);
642 ell_height
= MAX(abs( ell_height
* dc
->vportExtY
/ dc
->wndExtY
), 1);
644 /* Fix the coordinates */
646 if (right
< left
) { INT32 tmp
= right
; right
= left
; left
= tmp
; }
647 if (bottom
< top
) { INT32 tmp
= bottom
; bottom
= top
; top
= tmp
; }
649 oldwidth
= width
= physDev
->pen
.width
;
650 oldendcap
= physDev
->pen
.endcap
;
651 if (!width
) width
= 1;
652 if(physDev
->pen
.style
== PS_NULL
) width
= 0;
654 if ((physDev
->pen
.style
== PS_INSIDEFRAME
))
656 if (2*width
> (right
-left
)) width
=(right
-left
+ 1)/2;
657 if (2*width
> (bottom
-top
)) width
=(bottom
-top
+ 1)/2;
659 right
-= (width
- 1) / 2;
661 bottom
-= (width
- 1) / 2;
663 if(width
== 0) width
= 1;
664 physDev
->pen
.width
= width
;
665 physDev
->pen
.endcap
= PS_ENDCAP_SQUARE
;
667 if (X11DRV_SetupGCForBrush( dc
))
669 if (ell_width
> (right
-left
) )
670 if (ell_height
> (bottom
-top
) )
671 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
672 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
673 right
- left
- 1, bottom
- top
- 1,
676 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
677 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
678 right
- left
- 1, ell_height
, 0, 180 * 64 );
679 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
681 dc
->w
.DCOrgY
+ bottom
- ell_height
- 1,
682 right
- left
- 1, ell_height
, 180 * 64,
685 else if (ell_height
> (bottom
-top
) ){
686 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
687 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
688 ell_width
, bottom
- top
- 1, 90 * 64, 180 * 64 );
689 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
690 dc
->w
.DCOrgX
+ right
- ell_width
-1, dc
->w
.DCOrgY
+ top
,
691 ell_width
, bottom
- top
- 1, 270 * 64, 180 * 64 );
693 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
694 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
695 ell_width
, ell_height
, 90 * 64, 90 * 64 );
696 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
698 dc
->w
.DCOrgY
+ bottom
- ell_height
- 1,
699 ell_width
, ell_height
, 180 * 64, 90 * 64 );
700 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
701 dc
->w
.DCOrgX
+ right
- ell_width
- 1,
702 dc
->w
.DCOrgY
+ bottom
- ell_height
- 1,
703 ell_width
, ell_height
, 270 * 64, 90 * 64 );
704 TSXFillArc( display
, physDev
->drawable
, physDev
->gc
,
705 dc
->w
.DCOrgX
+ right
- ell_width
- 1,
707 ell_width
, ell_height
, 0, 90 * 64 );
709 if (ell_width
< right
- left
)
711 TSXFillRectangle( display
, physDev
->drawable
, physDev
->gc
,
712 dc
->w
.DCOrgX
+ left
+ (ell_width
+ 1) / 2,
713 dc
->w
.DCOrgY
+ top
+ 1,
714 right
- left
- ell_width
- 1,
715 (ell_height
+ 1) / 2 - 1);
716 TSXFillRectangle( display
, physDev
->drawable
, physDev
->gc
,
717 dc
->w
.DCOrgX
+ left
+ (ell_width
+ 1) / 2,
718 dc
->w
.DCOrgY
+ bottom
- (ell_height
) / 2 - 1,
719 right
- left
- ell_width
- 1,
722 if (ell_height
< bottom
- top
)
724 TSXFillRectangle( display
, physDev
->drawable
, physDev
->gc
,
725 dc
->w
.DCOrgX
+ left
+ 1,
726 dc
->w
.DCOrgY
+ top
+ (ell_height
+ 1) / 2,
728 bottom
- top
- ell_height
- 1);
731 /* FIXME: this could be done with on X call
732 * more efficient and probably more correct
733 * on any X server: XDrawArcs will draw
734 * straight horizontal and vertical lines
735 * if width or height are zero.
737 * BTW this stuff is optimized for an Xfree86 server
738 * read the comments inside the X11DRV_DrawArc function
740 if (X11DRV_SetupGCForPen(dc
)) {
741 if (ell_width
> (right
-left
) )
742 if (ell_height
> (bottom
-top
) )
743 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
744 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
745 right
- left
- 1, bottom
-top
- 1, 0 , 360 * 64 );
747 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
748 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
749 right
- left
- 1, ell_height
- 1, 0 , 180 * 64 );
750 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
752 dc
->w
.DCOrgY
+ bottom
- ell_height
,
753 right
- left
- 1, ell_height
- 1, 180 * 64 , 180 * 64 );
755 else if (ell_height
> (bottom
-top
) ){
756 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
757 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
758 ell_width
- 1 , bottom
- top
- 1, 90 * 64 , 180 * 64 );
759 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
760 dc
->w
.DCOrgX
+ right
- ell_width
,
762 ell_width
- 1 , bottom
- top
- 1, 270 * 64 , 180 * 64 );
764 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
765 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
766 ell_width
- 1, ell_height
- 1, 90 * 64, 90 * 64 );
767 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
768 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
769 ell_width
- 1, ell_height
- 1, 180 * 64, 90 * 64 );
770 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
771 dc
->w
.DCOrgX
+ right
- ell_width
,
772 dc
->w
.DCOrgY
+ bottom
- ell_height
,
773 ell_width
- 1, ell_height
- 1, 270 * 64, 90 * 64 );
774 TSXDrawArc( display
, physDev
->drawable
, physDev
->gc
,
775 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
776 ell_width
- 1, ell_height
- 1, 0, 90 * 64 );
778 if (ell_width
< right
- left
)
780 TSXDrawLine( display
, physDev
->drawable
, physDev
->gc
,
781 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
783 dc
->w
.DCOrgX
+ right
- (ell_width
+1) / 2,
785 TSXDrawLine( display
, physDev
->drawable
, physDev
->gc
,
786 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2 ,
787 dc
->w
.DCOrgY
+ bottom
- 1,
788 dc
->w
.DCOrgX
+ right
- (ell_width
+1)/ 2,
789 dc
->w
.DCOrgY
+ bottom
- 1);
791 if (ell_height
< bottom
- top
)
793 TSXDrawLine( display
, physDev
->drawable
, physDev
->gc
,
794 dc
->w
.DCOrgX
+ right
- 1,
795 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
796 dc
->w
.DCOrgX
+ right
- 1,
797 dc
->w
.DCOrgY
+ bottom
- (ell_height
+1) / 2);
798 TSXDrawLine( display
, physDev
->drawable
, physDev
->gc
,
800 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
802 dc
->w
.DCOrgY
+ bottom
- (ell_height
+1) / 2);
805 physDev
->pen
.width
= oldwidth
;
806 physDev
->pen
.endcap
= oldendcap
;
811 /***********************************************************************
815 X11DRV_SetPixel( DC
*dc
, INT32 x
, INT32 y
, COLORREF color
)
818 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
820 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
821 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
822 pixel
= COLOR_ToPhysical( dc
, color
);
824 TSXSetForeground( display
, physDev
->gc
, pixel
);
825 TSXSetFunction( display
, physDev
->gc
, GXcopy
);
826 TSXDrawPoint( display
, physDev
->drawable
, physDev
->gc
, x
, y
);
828 /* inefficient but simple... */
830 return COLOR_ToLogical(pixel
);
834 /***********************************************************************
838 X11DRV_GetPixel( DC
*dc
, INT32 x
, INT32 y
)
840 static Pixmap pixmap
= 0;
843 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
845 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
846 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
847 EnterCriticalSection( &X11DRV_CritSection
);
848 if (dc
->w
.flags
& DC_MEMORY
)
850 image
= XGetImage( display
, physDev
->drawable
, x
, y
, 1, 1,
851 AllPlanes
, ZPixmap
);
855 /* If we are reading from the screen, use a temporary copy */
856 /* to avoid a BadMatch error */
857 if (!pixmap
) pixmap
= XCreatePixmap( display
, rootWindow
,
858 1, 1, dc
->w
.bitsPerPixel
);
859 XCopyArea( display
, physDev
->drawable
, pixmap
, BITMAP_colorGC
,
861 image
= XGetImage( display
, pixmap
, 0, 0, 1, 1, AllPlanes
, ZPixmap
);
863 pixel
= XGetPixel( image
, 0, 0 );
864 XDestroyImage( image
);
865 LeaveCriticalSection( &X11DRV_CritSection
);
867 return COLOR_ToLogical(pixel
);
871 /***********************************************************************
875 X11DRV_PaintRgn( DC
*dc
, HRGN32 hrgn
)
878 HRGN32 tmpVisRgn
, prevVisRgn
;
879 HDC32 hdc
= dc
->hSelf
; /* FIXME: should not mix dc/hdc this way */
880 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
882 if (!(tmpVisRgn
= CreateRectRgn32( 0, 0, 0, 0 ))) return FALSE
;
884 /* Transform region into device co-ords */
885 if ( !REGION_LPTODP( hdc
, tmpVisRgn
, hrgn
)
886 || OffsetRgn32( tmpVisRgn
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
) == ERROR
) {
887 DeleteObject32( tmpVisRgn
);
891 /* Modify visible region */
892 if (!(prevVisRgn
= SaveVisRgn( hdc
))) {
893 DeleteObject32( tmpVisRgn
);
896 CombineRgn32( tmpVisRgn
, prevVisRgn
, tmpVisRgn
, RGN_AND
);
897 SelectVisRgn( hdc
, tmpVisRgn
);
898 DeleteObject32( tmpVisRgn
);
900 /* Fill the region */
902 GetRgnBox32( dc
->w
.hGCClipRgn
, &box
);
903 if (X11DRV_SetupGCForBrush( dc
))
904 TSXFillRectangle( display
, physDev
->drawable
, physDev
->gc
,
906 box
.right
-box
.left
, box
.bottom
-box
.top
);
908 /* Restore the visible region */
910 RestoreVisRgn( hdc
);
914 /**********************************************************************
918 X11DRV_Polyline( DC
*dc
, const POINT32
* pt
, INT32 count
)
923 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
925 if((oldwidth
= physDev
->pen
.width
) == 0) physDev
->pen
.width
= 1;
927 points
= (XPoint
*) xmalloc (sizeof (XPoint
) * (count
));
928 for (i
= 0; i
< count
; i
++)
930 points
[i
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
[i
].x
);
931 points
[i
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
[i
].y
);
934 if (X11DRV_SetupGCForPen ( dc
))
935 TSXDrawLines( display
, physDev
->drawable
, physDev
->gc
,
936 points
, count
, CoordModeOrigin
);
939 physDev
->pen
.width
= oldwidth
;
944 /**********************************************************************
948 X11DRV_Polygon( DC
*dc
, const POINT32
* pt
, INT32 count
)
952 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
954 points
= (XPoint
*) xmalloc (sizeof (XPoint
) * (count
+1));
955 for (i
= 0; i
< count
; i
++)
957 points
[i
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
[i
].x
);
958 points
[i
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
[i
].y
);
960 points
[count
] = points
[0];
962 if (X11DRV_SetupGCForBrush( dc
))
963 TSXFillPolygon( display
, physDev
->drawable
, physDev
->gc
,
964 points
, count
+1, Complex
, CoordModeOrigin
);
966 if (X11DRV_SetupGCForPen ( dc
))
967 TSXDrawLines( display
, physDev
->drawable
, physDev
->gc
,
968 points
, count
+1, CoordModeOrigin
);
975 /**********************************************************************
979 X11DRV_PolyPolygon( DC
*dc
, const POINT32
* pt
, const INT32
* counts
, UINT32 polygons
)
982 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
984 /* FIXME: The points should be converted to device coords before */
985 /* creating the region. */
987 hrgn
= CreatePolyPolygonRgn32( pt
, counts
, polygons
, dc
->w
.polyFillMode
);
988 X11DRV_PaintRgn( dc
, hrgn
);
989 DeleteObject32( hrgn
);
991 /* Draw the outline of the polygons */
993 if (X11DRV_SetupGCForPen ( dc
))
998 for (i
= 0; i
< polygons
; i
++) if (counts
[i
] > max
) max
= counts
[i
];
999 points
= (XPoint
*) xmalloc( sizeof(XPoint
) * (max
+1) );
1001 for (i
= 0; i
< polygons
; i
++)
1003 for (j
= 0; j
< counts
[i
]; j
++)
1005 points
[j
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
->x
);
1006 points
[j
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
->y
);
1009 points
[j
] = points
[0];
1010 TSXDrawLines( display
, physDev
->drawable
, physDev
->gc
,
1011 points
, j
+ 1, CoordModeOrigin
);
1019 /**********************************************************************
1020 * X11DRV_PolyPolyline
1023 X11DRV_PolyPolyline( DC
*dc
, const POINT32
* pt
, const DWORD
* counts
, DWORD polylines
)
1025 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
1026 if (X11DRV_SetupGCForPen ( dc
))
1031 for (i
= 0; i
< polylines
; i
++) if (counts
[i
] > max
) max
= counts
[i
];
1032 points
= (XPoint
*) xmalloc( sizeof(XPoint
) * (max
+1) );
1034 for (i
= 0; i
< polylines
; i
++)
1036 for (j
= 0; j
< counts
[i
]; j
++)
1038 points
[j
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
->x
);
1039 points
[j
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
->y
);
1042 points
[j
] = points
[0];
1043 TSXDrawLines( display
, physDev
->drawable
, physDev
->gc
,
1044 points
, j
+ 1, CoordModeOrigin
);
1052 /**********************************************************************
1053 * X11DRV_InternalFloodFill
1055 * Internal helper function for flood fill.
1056 * (xorg,yorg) is the origin of the X image relative to the drawable.
1057 * (x,y) is relative to the origin of the X image.
1059 static void X11DRV_InternalFloodFill(XImage
*image
, DC
*dc
,
1062 Pixel pixel
, WORD fillType
)
1064 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
1067 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
1068 (XGetPixel(image,x,y) != pixel) : \
1069 (XGetPixel(image,x,y) == pixel))
1071 if (!TO_FLOOD(x
,y
)) return;
1073 /* Find left and right boundaries */
1076 while ((left
> 0) && TO_FLOOD( left
-1, y
)) left
--;
1077 while ((right
< image
->width
) && TO_FLOOD( right
, y
)) right
++;
1078 XFillRectangle( display
, physDev
->drawable
, physDev
->gc
,
1079 xOrg
+ left
, yOrg
+ y
, right
-left
, 1 );
1081 /* Set the pixels of this line so we don't fill it again */
1083 for (x
= left
; x
< right
; x
++)
1085 if (fillType
== FLOODFILLBORDER
) XPutPixel( image
, x
, y
, pixel
);
1086 else XPutPixel( image
, x
, y
, ~pixel
);
1089 /* Fill the line above */
1096 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
1097 if (x
>= right
) break;
1098 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
1099 X11DRV_InternalFloodFill(image
, dc
, x
-1, y
,
1100 xOrg
, yOrg
, pixel
, fillType
);
1104 /* Fill the line below */
1106 if ((y
+= 2) < image
->height
)
1111 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
1112 if (x
>= right
) break;
1113 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
1114 X11DRV_InternalFloodFill(image
, dc
, x
-1, y
,
1115 xOrg
, yOrg
, pixel
, fillType
);
1122 /**********************************************************************
1123 * X11DRV_DoFloodFill
1125 * Main flood-fill routine.
1127 * The Xlib critical section must be entered before calling this function.
1130 struct FloodFill_params
1139 static BOOL32
X11DRV_DoFloodFill( const struct FloodFill_params
*params
)
1143 DC
*dc
= params
->dc
;
1144 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
1146 if (GetRgnBox32( dc
->w
.hGCClipRgn
, &rect
) == ERROR
) return FALSE
;
1148 if (!(image
= XGetImage( display
, physDev
->drawable
,
1151 rect
.right
- rect
.left
,
1152 rect
.bottom
- rect
.top
,
1153 AllPlanes
, ZPixmap
))) return FALSE
;
1155 if (X11DRV_SetupGCForBrush( dc
))
1157 /* ROP mode is always GXcopy for flood-fill */
1158 XSetFunction( display
, physDev
->gc
, GXcopy
);
1159 X11DRV_InternalFloodFill(image
, dc
,
1160 XLPTODP(dc
,params
->x
) + dc
->w
.DCOrgX
- rect
.left
,
1161 YLPTODP(dc
,params
->y
) + dc
->w
.DCOrgY
- rect
.top
,
1164 COLOR_ToPhysical( dc
, params
->color
),
1168 XDestroyImage( image
);
1173 /**********************************************************************
1174 * X11DRV_ExtFloodFill
1177 X11DRV_ExtFloodFill( DC
*dc
, INT32 x
, INT32 y
, COLORREF color
,
1181 struct FloodFill_params params
= { dc
, x
, y
, color
, fillType
};
1183 TRACE(graphics
, "X11DRV_ExtFloodFill %d,%d %06lx %d\n",
1184 x
, y
, color
, fillType
);
1186 if (!PtVisible32( dc
->hSelf
, x
, y
)) return FALSE
;
1187 EnterCriticalSection( &X11DRV_CritSection
);
1188 result
= CALL_LARGE_STACK( X11DRV_DoFloodFill
, ¶ms
);
1189 LeaveCriticalSection( &X11DRV_CritSection
);
1193 /******************************************************************
1195 * *Very* simple bezier drawing code,
1197 * It uses a recursive algorithm to divide the curve in a series
1198 * of straight line segements. Not ideal but for me sufficient.
1199 * If you are in need for something better look for some incremental
1202 * 7 July 1998 Rein Klazes
1206 * some macro definitions for bezier drawing
1208 * to avoid trucation errors the coordinates are
1209 * shifted upwards. When used in drawing they are
1210 * shifted down again, including correct rounding
1211 * and avoiding floating point arithmatic
1212 * 4 bits should allow 27 bits coordinates which I saw
1213 * somewere in the win32 doc's
1217 #define BEZIERSHIFTBITS 4
1218 #define BEZIERSHIFTUP(x) ((x)<<BEZIERSHIFTBITS)
1219 #define BEZIERPIXEL BEZIERSHIFTUP(1)
1220 #define BEZIERSHIFTDOWN(x) (((x)+(1<<(BEZIERSHIFTBITS-1)))>>BEZIERSHIFTBITS)
1221 /* maximum depth of recursion */
1222 #define BEZIERMAXDEPTH 8
1224 /* size of array to store points on */
1225 /* enough for one curve */
1226 #define BEZMAXPOINTS (150)
1228 /* calculate Bezier average, in this case the middle
1229 * correctly rounded...
1232 #define BEZIERMIDDLE(Mid, P1, P2) \
1233 (Mid).x=((P1).x+(P2).x + 1)/2;\
1234 (Mid).y=((P1).y+(P2).y + 1)/2;
1236 /**********************************************************
1237 * BezierCheck helper function to check
1238 * that recursion can be terminated
1239 * Points[0] and Points[3] are begin and endpoint
1240 * Points[1] and Points[2] are control points
1241 * level is the recursion depth
1242 * returns true if the recusion can be terminated
1244 static BOOL32
BezierCheck( int level
, POINT32
*Points
)
1247 dx
=Points
[3].x
-Points
[0].x
;
1248 dy
=Points
[3].y
-Points
[0].y
;
1249 if(ABS(dy
)<=ABS(dx
)){/* shallow line */
1250 /* check that control points are between begin and end */
1251 if(Points
[1].x
< Points
[0].x
){
1252 if(Points
[1].x
< Points
[3].x
)
1255 if(Points
[1].x
> Points
[3].x
)
1257 if(Points
[2].x
< Points
[0].x
){
1258 if(Points
[2].x
< Points
[3].x
)
1261 if(Points
[2].x
> Points
[3].x
)
1263 dx
=BEZIERSHIFTDOWN(dx
);
1264 if(!dx
) return TRUE
;
1265 if(abs(Points
[1].y
-Points
[0].y
-(dy
/dx
)*
1266 BEZIERSHIFTDOWN(Points
[1].x
-Points
[0].x
)) > BEZIERPIXEL
||
1267 abs(Points
[2].y
-Points
[0].y
-(dy
/dx
)*
1268 BEZIERSHIFTDOWN(Points
[2].x
-Points
[0].x
)) > BEZIERPIXEL
)
1272 }else{ /* steep line */
1273 /* check that control points are between begin and end */
1274 if(Points
[1].y
< Points
[0].y
){
1275 if(Points
[1].y
< Points
[3].y
)
1278 if(Points
[1].y
> Points
[3].y
)
1280 if(Points
[2].y
< Points
[0].y
){
1281 if(Points
[2].y
< Points
[3].y
)
1284 if(Points
[2].y
> Points
[3].y
)
1286 dy
=BEZIERSHIFTDOWN(dy
);
1287 if(!dy
) return TRUE
;
1288 if(abs(Points
[1].x
-Points
[0].x
-(dx
/dy
)*
1289 BEZIERSHIFTDOWN(Points
[1].y
-Points
[0].y
)) > BEZIERPIXEL
||
1290 abs(Points
[2].x
-Points
[0].x
-(dx
/dy
)*
1291 BEZIERSHIFTDOWN(Points
[2].y
-Points
[0].y
)) > BEZIERPIXEL
)
1298 /***********************************************************************
1300 * Draw a -what microsoft calls- bezier curve
1301 * The routine recursively devides the curve
1302 * in two parts until a straight line can be drawn
1304 * level recusion depth counted backwards
1306 * Points array of begin(0), end(3) and control points(1 and 2)
1307 * XPoints array with points calculated sofar
1308 * *pIx nr points calculated sofar
1311 static void X11DRV_Bezier(int level
, DC
* dc
, POINT32
*Points
,
1312 XPoint
* xpoints
, unsigned int* pIx
)
1314 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
1316 if(*pIx
== BEZMAXPOINTS
){
1317 TSXDrawLines( display
, physDev
->drawable
, physDev
->gc
,
1318 xpoints
, *pIx
, CoordModeOrigin
);
1321 if(!level
|| BezierCheck(level
, Points
)) {
1323 xpoints
[*pIx
].x
= dc
->w
.DCOrgX
+ BEZIERSHIFTDOWN(Points
[0].x
);
1324 xpoints
[*pIx
].y
= dc
->w
.DCOrgY
+ BEZIERSHIFTDOWN(Points
[0].y
);
1327 xpoints
[*pIx
].x
= dc
->w
.DCOrgX
+ BEZIERSHIFTDOWN(Points
[3].x
);
1328 xpoints
[*pIx
].y
= dc
->w
.DCOrgY
+ BEZIERSHIFTDOWN(Points
[3].y
);
1331 POINT32 Points2
[4]; /* for the second recursive call */
1332 Points2
[3]=Points
[3];
1333 BEZIERMIDDLE(Points2
[2], Points
[2], Points
[3]);
1334 BEZIERMIDDLE(Points2
[0], Points
[1], Points
[2]);
1335 BEZIERMIDDLE(Points2
[1],Points2
[0],Points2
[2]);
1337 BEZIERMIDDLE(Points
[1], Points
[0], Points
[1]);
1338 BEZIERMIDDLE(Points
[2], Points
[1], Points2
[0]);
1339 BEZIERMIDDLE(Points
[3], Points
[2], Points2
[1]);
1341 Points2
[0]=Points
[3];
1343 /* do the two halves */
1344 X11DRV_Bezier(level
-1, dc
, Points
, xpoints
, pIx
);
1345 X11DRV_Bezier(level
-1, dc
, Points2
, xpoints
, pIx
);
1349 /***********************************************************************
1351 * Implement functionality for PolyBezier and PolyBezierTo
1353 * [i] dc pointer to device context
1354 * [i] start, first point in curve
1355 * [i] BezierPoints , array of point filled with rest of the points
1356 * [i] count, number of points in BezierPoints, must be a
1360 X11DRV_PolyBezier(DC
*dc
, POINT32 start
, const POINT32
* BezierPoints
, DWORD count
)
1366 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
1368 TRACE(graphics
, "dc=%04x count=%ld %d,%d - %d,%d - %d,%d -%d,%d \n",
1371 (Points
+0)->x
, (Points
+0)->y
,
1372 (Points
+1)->x
, (Points
+1)->y
,
1373 (Points
+2)->x
, (Points
+2)->y
);
1374 if(!count
|| count
% 3){/* paranoid */
1375 WARN(graphics
," bad value for count : %ld\n", count
);
1378 xpoints
=(XPoint
*) xmalloc( sizeof(XPoint
)*BEZMAXPOINTS
);
1379 Points
[3].x
=BEZIERSHIFTUP(XLPTODP(dc
,start
.x
));
1380 Points
[3].y
=BEZIERSHIFTUP(YLPTODP(dc
,start
.y
));
1382 Points
[0]=Points
[3];
1384 Points
[i
].x
= BEZIERSHIFTUP(XLPTODP(dc
,BezierPoints
->x
));
1385 Points
[i
].y
= BEZIERSHIFTUP(YLPTODP(dc
,BezierPoints
->y
));
1388 X11DRV_Bezier(BEZIERMAXDEPTH
, dc
, Points
, xpoints
, &ix
);
1391 if( ix
) TSXDrawLines( display
, physDev
->drawable
, physDev
->gc
,
1392 xpoints
, ix
, CoordModeOrigin
);
1397 /**********************************************************************
1401 X11DRV_SetBkColor( DC
*dc
, COLORREF color
)
1403 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
1406 oldColor
= dc
->w
.backgroundColor
;
1407 dc
->w
.backgroundColor
= color
;
1409 physDev
->backgroundPixel
= COLOR_ToPhysical( dc
, color
);
1414 /**********************************************************************
1415 * X11DRV_SetTextColor
1418 X11DRV_SetTextColor( DC
*dc
, COLORREF color
)
1420 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
1423 oldColor
= dc
->w
.textColor
;
1424 dc
->w
.textColor
= color
;
1426 physDev
->textPixel
= COLOR_ToPhysical( dc
, color
);