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 violetColourised in 1ms
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);Colourised in 7ms
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 #F0F0F0Colourised in 7ms
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:
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);
}Colourised in 29ms
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.