asvisual(3x)
β¨ asvisual(3x) β AfterStep X11 window manager β¨
okay bestie, sit down, hydrate, and let's talk about asvisual β the libAfterImage header libAfterImage/asvisual.h that gives us an abstraction layer sitting right on top of X Visuals and zeroes in on color handling. it's giving foundational, it's giving under-appreciated, and you're gonna love it. π«Ά
πΈ NAME πΈ
asvisual β defines an abstraction layer on top of X Visuals, as well as several fundamental color datatypes. π
π¦ SEE ALSO π¦
Structures π
ColorPairASVisual
Functions π
ASVisual initialization :
query_screen_visual(),setup_truecolor_visual(),setup_pseudo_visual(),setup_as_colormap(),create_asvisual(),destroy_asvisual()
ASVisual encoding/decoding :
visual2visual_prop(),visual_prop2visual()
ASVisual convenience functions :
create_visual_window(),create_visual_pixmap(),create_visual_ximage()
Other libAfterImage modules π
ascmap.h asfont.h asimage.h asvisual.h blender.h export.h import.h transform.h ximage.h
π AUTHOR π
Sasha Vasko <sasha at aftercode dot net>
libAfterImage/alpha
π FUNCTION π
the Alpha channel is literally just a visibility parameter bolted onto your color value. an Alpha channel value of 0xFF means completely visible (iconic, seen, unmasked), and 0 makes that pixel completely transparent β like, gone, invisible, not the main character. π
π SOURCE π
#define ALPHA_TRANSPARENT 0x00
#define ALPHA_SEMI_TRANSPARENT 0x7F
#define ALPHA_SOLID 0xFF
β libAfterImage/ARGB32 β
π NAME π
ARGB32 β the main color datatype. periodt.
π FUNCTION π
ARGB32 is the fundamental datatype, holding a 32bit value that corresponds to a pixel's color and its transparency value (the alpha channel) in the ARGB colorspace. it's encoded like this, no cap:
- lowermost 8 bits β Blue channel
- bits 8 to 15 β Green channel
- bits 16 to 23 β Red channel
- bits 24 to 31 β Alpha channel
π¦ EXAMPLE π¦
ASTile.1
β¨ SOURCE β¨
typedef CARD32 ARGB32;
#define ARGB32_White 0xFFFFFFFF
#define ARGB32_Black 0xFF000000
/* default background color is #FF000000 : */
#define ARGB32_DEFAULT_BACK_COLOR ARGB32_Black
#define ARGB32_ALPHA_CHAN 3
#define ARGB32_RED_CHAN 2
#define ARGB32_GREEN_CHAN 1
#define ARGB32_BLUE_CHAN 0
#define ARGB32_CHANNELS 4
#define MAKE_ARGB32(a,r,g,b) ((( (CARD32)a) <<24)| \
((((CARD32)r)&0x00FF)<<16)| \
((((CARD32)g)&0x00FF)<<8 )| \
(( (CARD32)b)&0x00FF))
#define MAKE_ARGB32_GREY8(a,l) (((a)<<24)|(((l)&0x00FF)<<16)| \
(((l)&0x00FF)<<8)|((l)&0x00FF))
#define ARGB32_ALPHA8(c) (((c)>>24)&0x00FF)
#define ARGB32_RED8(c) (((c)>>16)&0x00FF)
#define ARGB32_GREEN8(c) (((c)>>8 )&0x00FF)
#define ARGB32_BLUE8(c) ( (c) &0x00FF)
#define ARGB32_CHAN8(c,i) (((c)>>((i)<<3))&0x00FF)
#define MAKE_ARGB32_CHAN8(v,i) (((v)&0x0000FF)<<((i)<<3))
#ifdef __GNUC__
#define ARGB32_ALPHA16(c) ({ CARD32 __c = ARGB32_ALPHA8(c); __c | (__c<<8);})
#define ARGB32_RED16(c) ({ CARD32 __c = ARGB32_RED8(c); __c | (__c<<8);})
#define ARGB32_GREEN16(c) ({ CARD32 __c = ARGB32_GREEN8(c); __c | (__c<<8);})
#define ARGB32_BLUE16(c) ({ CARD32 __c = ARGB32_BLUE8(c); __c | (__c<<8);})
#define ARGB32_CHAN16(c,i) ({ CARD32 __c = ARGB32_CHAN8(c,i); __c | (__c<<8);})
#else
#define ARGB32_ALPHA16(c) ((((c)>>16)&0x00FF00)|(((c)>>24)&0x0000FF))
#define ARGB32_RED16(c) ((((c)>>8 )&0x00FF00)|(((c)>>16)&0x0000FF))
#define ARGB32_GREEN16(c) ((((c) &0x00FF00)|(((c)>>8 )&0x0000FF))
#define ARGB32_BLUE16(c) ((((c)<<8) &0x00FF00)|(((c) )&0x0000FF))
#define ARGB32_CHAN16(c,i) ((ARGB32_CHAN8(c,i)<<8)|ARGB32_CHAN8(c,i))
#endif
#define MAKE_ARGB32_CHAN16(v,i) ((((v)&0x00FF00)>>8)<<((i)<<3))
π§ libAfterImage/ARGB32_manhattan_distance() π§
π NAME π
ARGB32_manhattan_distance() β this function can be used to evaluate the closeness of two colors. vibe check for colors fr fr.
β SYNOPSIS β
long ARGB32_manhattan_distance (long a, long b);
πΈ INPUTS πΈ
a,bβARGB32color values to calculate Manhattan distance in between
π RETURN VALUE π
returns the calculated Manhattan distance. π
π libAfterImage/ColorPart π
π NAME π
IC_REDβ red channelIC_GREENβ green channelIC_BLUEβ blue channelIC_ALPHAβ alpha channelIC_NUM_CHANNELSβ number of supported channels
π FUNCTION π
these are the Ids of the channels. they're basically synonyms to the related ARGB32 channel numbers β same energy, different name, iykyk. β¨
π¦ SOURCE π¦
typedef enum {
IC_BLUE = ARGB32_BLUE_CHAN ,
IC_GREEN = ARGB32_GREEN_CHAN,
IC_RED = ARGB32_RED_CHAN ,
IC_ALPHA = ARGB32_ALPHA_CHAN,
IC_NUM_CHANNELS = ARGB32_CHANNELS } ColorPart;
π libAfterImage/ColorPair π
π NAME π
ColorPair β a convenient structure to hold a pair of colors. two colors, one struct, adorable. π₯Ί
β SOURCE β
typedef struct ColorPair {
ARGB32 fore;
ARGB32 back; }ColorPair;
π libAfterImage/ASVisual π
π NAME π
ASVisual β an abstraction layer on top of X Server Visual.
β¨ DESCRIPTION β¨
so this structure exists to compensate for the fact that X may have, like, so many different types of Visuals. bestie, it's a lot. ASVisual provides shortcuts to most Visual data, compensated for differences in Visuals. π₯
for PseudoColor visual it also contains a preallocated set of colors. this colormap lets us write XImages very fast and without exhausting the available X colors. this colormap consists of 8, 64, or 4096 colors and constitutes a fraction of the colors available in a particular colordepth. these colors are allocated to be evenly spread around the RGB spectrum. so when converting from internal presentation β all we need to do is discard unused bits, and use the rest of those bits as an index in our colormap. the opposite conversion is much trickier and we engage in the nasty business of having a hash table mapping pixel values into colors, or a straight table doing the same in lower colordepths. the idea is that we do all internal processing in 32bit colordepth, and ASVisual provides us with the means to convert it to actual X display format. respectively, ASVisual has methods to write out XImage lines and read XImage lines.
ASVisual creation is a tricky process. basically first we have to go through the list of available Visuals and choose the best suitable one. then, based on the type of this Visual, we have to set up our data members and method hooks. several functions are provided for that:
query_screen_visual()β will lookup best suitable visualsetup_truecolor_visual()β will setup hooks if visual is TrueColorsetup_pseudo_visual()β will setup hooks and data if Visual is PseudoColor.setup_as_colormap()β will preallocate colors for PseudoColor.
an alternative to the above is:
create_asvisual()β it encapsulates all of the above functionality, and returns a completely set upASVisualobject.
since the Visual selected for ASVisual may differ from the default (we choose the best suitable one), all the window creation functions must provide a colormap and some other parameters, like border color for example. so we created some convenience functions. these should be used instead of standard Xlib calls:
create_visual_window()β to create windowcreate_visual_pixmap()β to create pixmapcreate_visual_ximage()β to create XImage
ASVisual could be deallocated and its resources freed with:
destroy_asvisual()
π seriously, when it's giving manual resource management, use the helpers. don't raw-dog the Xlib calls and then act surprised.
πΈ EXAMPLE πΈ
asview.c: ASView
β¨ SOURCE β¨
okay bestie, here's the literal ASVisual struct definition β it's the blueprint, the whole vibe. Don't skim this, it's lowkey important. π
typedef struct ASVisual {
Display *dpy;
/* This envvar will be used to determine what X Visual
* (in hex) to use. If unset then best possible will
* be selected automagically : */ #define ASVISUAL_ID_ENVVAR
"AFTERIMAGE_VISUAL_ID"
XVisualInfo visual_info;
/* this things are calculated based on Visual : */
unsigned long rshift, gshift, bshift;
unsigned long rbits, gbits, bbits;
unsigned long true_depth; /* could be 15 when X reports 16 */
Bool BGR_mode;
Bool msb_first;
/* we must have colormap so that we can safely create windows
* with different visuals even if we are in TrueColor mode : */
Colormap colormap;
Bool own_colormap; /* tells us to free colormap when we
* done */
unsigned long black_pixel, white_pixel;
/* for PseudoColor mode we need some more stuff : */
enum {
ACM_None = 0,
ACM_3BPP,
ACM_6BPP,
ACM_12BPP
} as_colormap_type ; /* there can only be 64 or 4096 entries
* so far ( 6 or 12 bpp) */
unsigned long *as_colormap; /* array of preallocated colors for
* PseudoColor mode */
union /* reverse color lookup tables : */
{
ARGB32 *xref;
struct ASHashTable *hash;
}as_colormap_reverse ;
/* different useful callbacks : */
CARD32 (*color2pixel_func) ( struct ASVisual *asv,
CARD32 encoded_color,
unsigned long *pixel);
void (*pixel2color_func) ( struct ASVisual *asv,
unsigned long pixel,
CARD32 *red, CARD32 *green,
CARD32 *blue);
void (*ximage2scanline_func)( struct ASVisual *asv,
XImage *xim,
struct ASScanline *sl, int y,
unsigned char *xim_data );
void (*scanline2ximage_func)( struct ASVisual *asv,
XImage *xim,
struct ASScanline *sl, int y,
unsigned char *xim_data );
#define ASGLX_Unavailable 0 #define ASGLX_Available
(0x01<<0) #define ASGLX_DoubleBuffer (0x01<<1) #define
ASGLX_RGBA (0x01<<2) #define ASGLX_UseForImageTx
(0x01<<3)
ASFlagType glx_support ; /* one of the above flags */
void *glx_scratch_gc_indirect ; /* (GLXContext) */
void *glx_scratch_gc_direct ; /* (GLXContext) */
Window scratch_window;
#ifndef X_DISPLAY_MISSING #define ARGB2PIXEL(asv,argb,pixel)
\
(asv)->color2pixel_func((asv),(argb),(pixel)) #define
GET_SCANLINE(asv,xim,sl,y,xim_data) \
(asv)->ximage2scanline_func((asv),(xim),(sl),(y),(xim_data))
#define PUT_SCANLINE(asv,xim,sl,y,xim_data) \
(asv)->scanline2ximage_func((asv),(xim),(sl),(y),(xim_data))
#else #define ARGB2PIXEL(asv,argb,pixel) \
do{ break; }while(0) #define GET_SCANLINE(asv,xim,sl,y,xim_data)
\
do{ break; }while(0) #define PUT_SCANLINE(asv,xim,sl,y,xim_data)
\
do{ break; }while(0) #endif }ASVisual;
the way that AFTERIMAGE_VISUAL_ID env var determines what X Visual (in hex) to use, and if it's unset, best possible is selected automagically β¨. No cap.
and this whole struct lives in libAfterImage/query_screen_visual().
now let's talk about the functions that actually do stuff with it. first up:
β¨ NAME β¨
query_screen_visual_id() query_screen_visual()
β¨ SYNOPSIS β¨
Bool query_screen_visual_id( ASVisual *asv, Display *dpy, int screen,
Window root, int default_depth,
VisualID visual_id, Colormap cmap ); Bool
query_screen_visual( ASVisual *asv, Display *dpy, int screen,
Window root, int default_depth );
β¨ INPUTS β¨
asvβ preallocatedASVisualstructure.dpyβ valid pointer to opened X display.screenβ screen number on which to query visuals.rootβ root window on that screen.default_depthβ default colordepth of the screen.visual_idβ optional ID of preferred Visual.cmapβ optional colormap to be used.
β¨ RETURN VALUE β¨
True on success, False on failure. The ASVisual structure pointed by asv will have the following data members set on success: dpy, visual_info, colormap, own_colormap, black_pixel, white_pixel.
β¨ DESCRIPTION β¨
query_screen_visual_id() will go through a prioritized list of possible Visuals and attempt to match those to what is available on the specified screen. If all items from the list fail, then it goes about querying the default visual. query_screen_visual is identical to query_screen_visual_id with visual_id and cmap set to 0. Once X Visual has been identified, we create an X colormap and allocate white and black pixels from it. π
source: libAfterImage/setup_truecolor_visual()
β¨ NAME β¨
setup_truecolor_visual()
β¨ SYNOPSIS β¨
Bool setup_truecolor_visual( ASVisual *asv );
β¨ INPUTS β¨
asvβ preallocatedASVisualstructure.
β¨ RETURN VALUE β¨
True on success, False if visual is not TrueColor.
β¨ DESCRIPTION β¨
setup_truecolor_visual() checks if the Visual is indeed TrueColor and if so it goes about querying color masks, deducing real XImage colordepth, and whether we work in BGR mode. It then goes about setting up correct hooks to X IO functions. π¨
source: libAfterImage/setup_pseudo_visual()
β¨ NAME β¨
setup_pseudo_visual()
β¨ SYNOPSIS β¨
void setup_pseudo_visual( ASVisual *asv );
β¨ INPUTS β¨
asvβ preallocatedASVisualstructure.
β¨ DESCRIPTION β¨
setup_pseudo_visual() assumes that Visual is PseudoColor. It then tries to decide as to how many colors preallocate, and goes about setting up correct X IO hooks and possibly initialization of reverse colormap in case ASVisual already has colormap preallocated. π
source: libAfterImage/setup_as_colormap()
β¨ NAME β¨
setup_as_colormap()
β¨ SYNOPSIS β¨
void setup_as_colormap( ASVisual *asv );
β¨ INPUTS β¨
asvβ preallocatedASVisualstructure.
β¨ DESCRIPTION β¨
That has to be called in order to pre-allocate a sufficient number of colors. It uses colormap size identification supplied in ASVisual structure. If colors where preallocated successfully β it will also create reverse lookup colormap. π
source: libAfterImage/create_asvisual_for_id()
β¨ NAME β¨
create_asvisual_for_id()
β¨ SYNOPSIS β¨
ASVisual *create_asvisual_for_id( Display *dpy, int screen,
int default_depth,
VisualID visual_id, Colormap cmap,
ASVisual *reusable_memory );
β¨ INPUTS β¨
dpyβ valid pointer to opened X display.screenβ screen number on which to query visuals.rootβ root window on that screen.default_depthβ default colordepth of the screen.visual_idβ ID of X visual to use.cmapβ optional ID of the colormap to be used.reusable_memoryβ pointer to preallocatedASVisualstructure.
β¨ RETURN VALUE β¨
Pointer to ASVisual structure initialized with enough information to be able to deal with current X Visual.
β¨ DESCRIPTION β¨
This function calls all the needed functions in order to setup a new ASVisual structure for the specified screen and visual. If reusable_memory is not null β it will not allocate a new ASVisual structure, but instead will use the supplied one. Useful for allocating ASVisual on stack. This particular function will not do any autodetection and will use the Visual ID supplied. That is useful when libAfterImage is used with an app that has its own approach to Visual handling, and since Visuals on all Windows, Pixmaps and colormaps must match, there is a need to synchronise visuals used by an app and libAfterImage. π
source: libAfterImage/create_asvisual()
β¨ NAME β¨
create_asvisual()
β¨ SYNOPSIS β¨
ASVisual *create_asvisual( Display *dpy, int screen,
int default_depth,
ASVisual *reusable_memory );
β¨ INPUTS β¨
dpyβ valid pointer to opened X display.screenβ screen number on which to query visuals.rootβ root window on that screen.default_depthβ default colordepth of the screen.reusable_memoryβ pointer to preallocatedASVisualstructure.
β¨ RETURN VALUE β¨
Pointer to ASVisual structure initialized with enough information to be able to deal with current X Visual.
β¨ DESCRIPTION β¨
This function calls all the needed functions in order to setup a new ASVisual structure for the specified screen. If reusable_memory is not null β it will not allocate a new ASVisual structure, but instead will use the supplied one. Useful for allocating ASVisual on stack. It is different from create_asvisualfor_id() in that it will attempt to autodetect the best possible visual for the screen. For example on some SUN Solaris X servers there will be both 8bpp pseudocolor and 24bpp truecolor, and default will be 8bpp. In this scenario libAfterImage will detect and use 24bpp true color visual, thus producing much better results. π
source: libAfterImage/destroy_asvisual()
β¨ NAME β¨
destroy_asvisual()
β¨ SYNOPSIS β¨
void destroy_asvisual( ASVisual *asv, Bool reusable );
β¨ INPUTS β¨
asvβ validASVisualstructure.reusableβ ifTrueit will cause function to not free object itself.
β¨ DESCRIPTION β¨
Cleanup function. Frees all the memory and deallocates all the resources. If reusable is False it will also free the object, pointed to by asv. π
β¨ EXAMPLE β¨
asview.c: ASView.2
source: libAfterImage/visual2visual_prop()
β¨ NAME β¨
visual2visual_prop()
β¨ SYNOPSIS β¨
Bool visual2visual_prop( ASVisual *asv, size_t *size,
unsigned long *version, unsigned long **data );
β¨ INPUTS β¨
asvβ validASVisualstructure.
β¨ RETURN VALUE β¨
sizeβ size of the encoded memory block.versionβ version of the encoding.dataβ actual encoded memory block.Trueon success,Falseon failure.
β¨ DESCRIPTION β¨
This function will encode ASVisual structure into a memory block of 32 bit values, suitable for storing in X property. π¦
source: libAfterImage/visual_prop2visual()
β¨ NAME β¨
visual_prop2visual()
β¨ SYNOPSIS β¨
Bool visual_prop2visual( ASVisual *asv, Display *dpy, int screen,
size_t size,
unsigned long version, unsigned long *data );
β¨ INPUTS β¨
asvβ validASVisualstructure.dpyβ valid pointer to open X display.screenβ screen number.sizeβ encoded memory block's size.versionβ version of encoding.dataβ actual encoded memory block.
β¨ RETURN VALUE β¨
True on success, False on failure.
bestie, so visual_prop2visual() reads ASVisual data right back out of that memory block that visual2visual_prop() encoded for you π. It's the whole point of the round trip: yank data out of an X property and turn it into stuff you can actually use β colormap, visual info, all of it β¨. Just know that setup_truecolor_visual() or setup_pseudo_visual() has to be invoked, otherwise your ASVisual setup is literally unfinished, no cap π«Ά.
libAfterImage/create_visual_window()
π NAME β create_visual_window()
π¦ SYNOPSIS
Window create_visual_window( ASVisual *asv, Window parent,
int x, int y,
unsigned int width, unsigned int height,
unsigned int border_width,
unsigned int wclass,
unsigned long mask,
XSetWindowAttributes *attributes );
β¨ INPUTS
asvβ pointer to the validASVisualstructure, bestie. Gotta be valid, okay?parentβ Window ID of the parent the window π.x,yβ where the new window first spawns, its initial position π.width,heightβ the new window's initial size π.border_widthβ initial border width of the new window π.wclassβ Window class, and the only two vibes allowed areInputOnlyorInputOutputπ .maskβ defines what attributes are set πΈ.attributesβ the different window attributes, all the little extras π¦.
π RETURN VALUE
The ID of the newly created window when it works out, bestie π₯³. None when it does not π.
π DESCRIPTION
create_visual_window() does sanity checks on the parameters you passed in β vibe check first, always β then it adds the mandatory attributes if they're needed, and after that it attempts to create a window for the specified ASVisual β¨.
libAfterImage/create_visual_gc()
π NAME β create_visual_gc()
π¦ SYNOPSIS
GC create_visual_gc( ASVisual *asv, Window root,
unsigned long mask, XGCValues *gcvalues );
β¨ INPUTS
asvβ pointer to the validASVisualstructure π.rootβ Window ID of the root window of destination screen π.mask,gcvaluesβ values for creation of the new GC β go look atXCreateGC()for the deets, iykyk π.
π RETURN VALUE
A new GC created for a regular window on success π. NULL on failure π.
π DESCRIPTION
create_visual_gc() makes a temporary window for the depth and Visual that's specific to the ASVisual, and then it creates a GC for that window π¨. The GC you get back is good to be used for manipulation of windows and Pixmaps created for that same ASVisual β same ASVisual, same energy, periodt π.
libAfterImage/create_visual_pixmap()
π NAME β create_visual_pixmap()
π¦ SYNOPSIS
Pixmap create_visual_pixmap( ASVisual *asv, Window root,
unsigned int width, unsigned int height,
unsigned int depth );
β¨ INPUTS
asvβ pointer to the validASVisualstructure π«Ά.rootβ Window ID of the root window of destination screen π.width,heightβ size of the pixmap to create π.depthβ depth of the pixmap to create. If it's0, thenasv->true_depthgets used instead π.
π RETURN VALUE
The ID of the newly created pixmap on success β¨. None on failure π.
π DESCRIPTION
create_visual_pixmap() performs sanity checks on the parameters you passed, and then it attempts to create a pixmap for the specified ASVisual, root and depth β three-for-three, slay π.
libAfterImage/create_visual_ximage()
π NAME β create_visual_ximage()
π¦ SYNOPSIS
XImage* create_visual_ximage( ASVisual *asv,
unsigned int width, unsigned int height,
unsigned int depth );
β¨ INPUTS
asvβ pointer to the validASVisualstructure π.width,heightβ size of theXImageto create π.depthβ depth of theXImageto create. If it's0, thenasv->true_depthgets used instead π.
π RETURN VALUE
A pointer to the newly created XImage on success π. NULL on failure π.
π DESCRIPTION
create_visual_ximage() performs sanity checks on the parameters you passed, and it will attempt to create an XImage of sufficient size, at the colordepth you specified πΌοΈ. It also sets up hooks so that XImage deallocation gets handled by a custom function β cleanup is handled, we love to see it π«Άβ¨.
okay that's genuinely the whole page, bestie π₯Ήπ we did it. no skipped options, no skipped nothin'.
Source: the 3rd Berkeley Distribution π, and this is AfterStep v.2.2.12 π
, living in section asvisual(3x) of the manual. Footer didn't hand me a date, so that's all she wrote β mwah ππ¦
π¦ where this page comes from
- ubuntu resolute: libafterimage-dev 2.2.12-19 Β· GPL-2.0-or-later
- ubuntu stonking: libafterimage-dev 2.2.12-19 Β· GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms