Understand X11 graphics context functions by samples





5.00/5 (4 votes)
This tip shall help to select the desired GCFunction for fill operations.
Introduction
I always have to think over which X11 graphics context GCFunction
is the right to coose and i almost every time choose the wrong one at the first try. This tip shall show the differences and help you to prevent wrong choose.
Background
The X11 graphics context supports 16 different functions to merge current drawing request (e. g. XFillRectangle()
) - called the src - with window (widgets) current display - called the dst. These functions apply logical operations to the bit level of the color values of src and dst.
Here is one sample:
src 01010101 01010101 01010101 55 55 55 gray
dst 11110000 00000000 11110000 F0 00 FO violet
OR operation result 11110101 01010101 11110101 F5 55 F5 light violet
See XGCValues structure description for details.
To demonstrate the different effects of the foreground color i have choosen a linear gradient rectangle and a 50% overlapping of a XFillRectangle()
with three different shades of gray.
![]() color="#141414" XGCFunction=GXor | ![]() color="#555555" XGCFunction=GXor | ![]() color="#BDBDBD" XGCFunction=GXor |
To demonstrate the different effects of the graphics context GCFunction
i have choosen the same linear gradient rectangle as above and the sam 50% overlapping of a XFillRectangle()
as above with always the same foreground color #555555
.
First the OR
graphics context GCFunction
s:
![]() XGCFunction=GXxor src XOR dst ID=06 | ![]() XGCFunction=GXor src OR dst ID=07 | ![]() XGCFunction=GXnor (NOT src) AND (NOT dst) ID=08 |
![]() XGCFunction=GXorReverse src OR (NOT dst) ID=0B | ![]() XGCFunction=GXorInverted (NOT src) OR dst ID=0D |
Second the AND
and COPY
graphics context GCFunction
s:
![]() XGCFunction=GXand src AND dst ID=01 | ![]() XGCFunction=GXandReverse src AND NOT dst ID=02 | ![]() XGCFunction=GXandInverted (NOT src) AND dst ID=04 |
![]() XGCFunction=GXnand (NOT src) OR (NOT dst) ID=0E | ![]() XGCFunction=GXcopy src ID=03 | ![]() XGCFunction=GXcopyInverted NOT src ID=0C |
Finally the remaining graphics context GCFunction
s:
![]() XGCFunction=GXclear 0 ID=00 | ![]() XGCFunction=GXnoop dst ID=05 | ![]() XGCFunction=GXequiv (NOT src) XOR dst ID=09 |
![]() XGCFunction=GXinvert NOT dst ID=0A | ![]() XGCFunction=GXset 1 ID=0F |
This is the code i used for my samples:
XSetForeground (display, gc, XAllocClosestNamedColor (display, colormap, "#555555"));
XSetFunction(display, gc, GXor);
XFillRectangle (display, drawable, gc, clipRectangle);
XSetFunction(display, gc, XGCFunction.GXcopy);
There is no way to brighten or to darken a dst with graphics context GCFunction
s. To achieve this, it would require something like:
darken: dst >> 1 or dst >> 2 or dst >> 3 or dst >> 4 brighten: (dst >> 2) OR #404040 or (dst >> 1) OR #808080 or (dst >> 2) OR #B0B0B0 or (dst >> 4) OR #F0F0F0
But shift operators are not avalable from graphics context GCFunction
s.
Instead there are 2 approaches to brighten or to darken:
- Grab the dst as a pixmap, execute the appropriate operation and write back the result. This approach is slow (two pixmap transfers, calculation at the client) but has a smooth result.
- Overlay the dst with a stippled pixmap. This approach is fast (calculation at the server) but grainy.
I will give a closer look at approach 2:
![]() | stipple bits=(byte)0x22, (byte)0x88 … brighten=25% |
![]() | stipple bits= (byte)0x55, (byte)0xAA … brighten=50% |
![]() | stipple bits= (byte)0x5A, (byte)0xA5 … brighten=50% |
![]() | stipple bits= (byte)0xEE, (byte)0xBB … brighten=75% |
This is the code i used for my samples:
// 25%
//static byte[] stippleBits = {(byte)0x22, (byte)0x88, (byte)0x22, (byte)0x88,
// (byte)0x22, (byte)0x88, (byte)0x22, (byte)0x88};
// 50%
// static byte[] stippleBits = {(byte)0x55, (byte)0xAA, (byte)0x55, (byte)0xAA,
// (byte)0x55, (byte)0xAA, (byte)0x55, (byte)0xAA};
// 75%
static byte[] stippleBits = {(byte)0xEE, (byte)0xBB, (byte)0xEE, (byte)0xBB,
(byte)0xEE, (byte)0xBB, (byte)0xEE, (byte)0xBB};
static System.IntPtr opacityTile = System.IntPtr.Zero;
...
if (opacityTile == System.IntPtr.Zero)
{
opacityTile = XCreatePixmapFromBitmapData (display, drawable, stippleBits,
8, 8, XAllocClosestNamedColor (display, colormap, "#FFFFFF"),
XAllocClosestNamedColor (display, colormap, "#000000"), depth);
}
...
if (opacityTile != System.IntPtr.Zero)
{
XSetFunction(display, gc, XGCFunction.GXor);
XSetFillStyle (display, gc, XGCFillStyle.FillTiled);
XSetTile (display, gc, opacityTile);
XFillRectangle (display, drawable, gc, clipRectangle);
XSetFunction(display, gc, XGCFunction.GXcopy);
}
The stipple bits (byte)0x55, (byte)0x55
... produce a very flickering display. The next best choice is (byte)0x5A, (byte)0xA5
...
Points of Interest
I have always been bothered by the fact that there is no illustrated description of the X11 graphics context GCFunction
on the web. Now there is one...
History
The first version of this article is from 23. September 2016.