Application needs to call both XDrawArc and XFillArc to get symmetrical filled circle.
Submitted by Stef Van Vlierberghe
Assigned to Xorg Project Team
Description
Created attachment 37519 Rendering of drawn and filled circles using code in description.
There seems to be a bug/feature/limitation (not sure which one applies) with XFillArc, the small bit of code below illustrates the problem by using 5 different techniques to show a circle :
1- fill 2- draw 3- draw+fill 4- drap polygon approximated 5- fill polygon approximated
The attachment shows an xmag blow-up of the result, and this clearly shows that only 2..4 create a result that is both symmetrical around x and y axis, as one would expect for all "good" renderings of a circle.
The reason why 1 and 5 lack this symmetry has probably to do with the pixel coordinate system : drawing a line from (0,0) to (l,0) is in fact equivalent to filling a rectange (0,0), (l+1,0), (l+1,1), (0,1), so the drawings always show an "offset" toward bottom-right of the drawing one would get if one could draw infinitely thin lines. [ See Volume 1, Xlib Programming Manual, 6.1.4 "Filling", which only explains this effect when drawing and filling rectangles ]
Somehow this offset creates an asymmetry in the filled polygons that is not visible in the drawn polygons, but I can't see where this effect is documented.
What it a least a bit bizarre is that somebody who wants symmetrically filled circles (i.e. technique 3- draw+fill) needs to send 2 instructions to the server, one to draw and one to fill, while an extra option (e.g. a parameter fill_quality, similar to the Convex option of XFillPolygon) would obviously suffice to reduce this overhead. So in case this is not a bug, it is at least a source of unnecessary runtime overheap due to limitations of the API, and a lack of clarity in the documentation.
static void draw_graphics (void) { GC mygc; int i,j,x; XGCValues values;
XMapRaised (display, win);
values.line_width=0;
values.line_style=LineSolid;
values.cap_style=CapRound;
values.join_style=JoinRound;
mygc = XCreateGC (display, win, (GCLineWidth|GCLineStyle|GCCapStyle| GCJoinStyle), &values); XSetForeground (display, mygc, BlackPixel (display, screen)); XSetBackground (display, mygc, WhitePixel (display, screen)); XClearWindow (display, win);
x=10;
for (i=1;i <= 20; i++) { int diam = i; int space = 3; int y = 50; XPoint points[33]; int pt; int inner;
/* 1- fill circle */
XFillArc (display, win, mygc, x, y, diam, diam, 0, 360 * 64);
XFlush (display);
y=y+diam+space;
/* 2- draw circle */
XDrawArc (display, win, mygc, x, y, diam, diam, 0, 360 * 64);
XFlush (display);
y=y+diam+space;
/* 3- draw circle with inner fill */
XDrawArc (display, win, mygc, x, y, diam, diam, 0, 360 * 64);
XFillArc (display, win, mygc, x, y, diam, diam, 0, 360 * 64);
XFlush (display);
y=y+diam+space;
/* 4- draw approx circle by 32 sided polygon */
for (pt=0;pt<33;pt++)
{
points[pt].x=x+diam
+lround(diam/2.0cos(23.14159265358979323844pt/32.0)); points[pt].y=y+diam +lround(diam/2.0sin(23.14159265358979323844pt/32.0)); } XDrawLines (display, win, mygc, points, 33, CoordModeOrigin); XFlush (display); y=y+diam+space;
/* 5- fill approx circle by 32 sided polygon */
for (pt=0;pt<33;pt++)
{
points[pt].x=x+diam
+lround(diam/2.0cos(-23.14159265358979323844pt/32.0)); points[pt].y=y+diam +lround(diam/2.0sin(-23.14159265358979323844pt/32.0)); } XFillPolygon (display, win, mygc, points, 33, Convex, CoordModeOrigin); XFlush (display); y=y+diam+space;
x=x+2*diam+5;
}
XFlush (display); XFreeGC (display, mygc); }
I've seen the effect both in Linux Redhat EL5 and Linux Fedora 11 and HP-UX, using 3 different graphics cards and a virtual frame buffer, so it looks like this problem is not specific to OS or graphics hardware.
for reference xdpyinfo shows : name of display: :0.0 version number: 11.0 vendor string: The X.Org Foundation vendor release number: 70101000 X.Org version: 7.1.1 maximum request size: 262140 bytes motion buffer size: 256 bitmap unit, bit order, padding: 32, LSBFirst, 32 image byte order: LSBFirst number of supported pixmap formats: 7 supported pixmap formats: depth 1, bits_per_pixel 1, scanline_pad 32 depth 4, bits_per_pixel 8, scanline_pad 32 depth 8, bits_per_pixel 8, scanline_pad 32 depth 15, bits_per_pixel 16, scanline_pad 32 depth 16, bits_per_pixel 16, scanline_pad 32 depth 24, bits_per_pixel 32, scanline_pad 32 depth 32, bits_per_pixel 32, scanline_pad 32 keycode range: minimum 8, maximum 255 focus: window 0x3201beb, revert to Parent number of extensions: 16 Composite DAMAGE GLX MIT-SHM NV-CONTROL NV-GLX RANDR RENDER SECURITY VNC-EXTENSION XC-APPGROUP XFIXES XFree86-Bigfont XInputExtension XKEYBOARD XTEST default screen number: 0 number of screens: 1
Attachment 37519, "Rendering of drawn and filled circles using code in description.":
Version: 7.1 (2006.05)