Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Understand X11 graphics context functions by samples

0.00/5 (No votes)
22 Sep 2016 1  
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
Colourised 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 GCFunctions:


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 GCFunctions:


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 GCFunctions:


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 GCFunctions. 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
Colourised in 7ms

But shift operators are not avalable from graphics context GCFunctions.

Instead there are 2 approaches to brighten or to darken:

  1. 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.
  2. 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);
}
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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here