Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DRessedAlarm184/LWXGL/llms.txt

Use this file to discover all available pages before exploring further.

Image elements are pixel-addressable XImage canvases embedded as regular LWXGL elements. Each pixel stores a palette index (0–15) rather than a raw color value, so the entire canvas recolors automatically when you modify the palette. After writing to the pixel buffer, call GUpdateImage to push changes to the X11 display.
GUpdateImage uses dirty tracking — it compares each byte in the pixel buffer against an internal shadow copy and only calls XPutPixel on changed pixels. This makes it efficient to call on every frame even for large canvases with few changes.

Creating an Image

void           GCreateImage(int id, int x, int y, int w, int h);
unsigned char* GGetImageData(int id);
void           GUpdateImage(int id);
void           GClearImage(int id, int c);
FunctionDescription
GCreateImageCreates an image element of size w × h pixels at position (x, y). The pixel buffer is zero-initialized (all pixels set to palette index 0).
GGetImageDataReturns a pointer to the w * h byte pixel buffer. Each byte holds a palette index 0–15. Data is stored row-major: pixel at (px, py) is at data[py * w + px].
GUpdateImagePushes dirty pixels from the buffer to the backing XImage, which is composited on the next GRenderWindow call.
GClearImageFills the entire pixel buffer with palette index c using memset. Call GUpdateImage afterward to see the change.
#define CANVAS_ID 10
#define CANVAS_W  200
#define CANVAS_H  200

/* Create a 200×200 canvas */
GCreateImage(CANVAS_ID, 50, 50, CANVAS_W, CANVAS_H);

/* Fill with palette index 1 (dark blue) */
GClearImage(CANVAS_ID, 1);

/* Write a single red pixel at (100, 100): palette index 4 (dark red) */
unsigned char* pixels = GGetImageData(CANVAS_ID);
pixels[100 * CANVAS_W + 100] = 4;

/* Push changes to the display */
GUpdateImage(CANVAS_ID);

Drawing Primitives

All primitive functions operate on a specific image element by id and write palette indices directly into the pixel buffer. Call GUpdateImage(id) after any set of primitives to commit the changes.

Rectangles

void GPrimitiveRect(int id, int x, int y, int w, int h, int fg, int bg);
Draws a filled rectangle with an outline. fg is the border/outline color index; bg is the fill color index. Pass -1 for either to skip drawing that layer.

Circles

void GPrimitiveCircle(int id, int cx, int cy, int r, int fg, int bg);
Draws a circle centered at (cx, cy) with radius r. fg is drawn on border pixels (the annular ring one pixel wide at the edge); bg fills the interior. Pass -1 to skip either.

Lines

void GPrimitiveLine(int id, int x1, int y1, int x2, int y2, int color);
Draws a straight line from (x1, y1) to (x2, y2) using palette index color. The implementation uses a floating-point incremental algorithm equivalent to Bresenham’s — pixels are placed at each step by rounding the sub-pixel position.

Combined Example

#define CANVAS_ID 10

/* White background */
GClearImage(CANVAS_ID, 15);

/* Dark gray filled rectangle with light gray border */
GPrimitiveRect(CANVAS_ID, 10, 10, 80, 60, 7, 8);

/* Blue filled circle with white border, centered at (150, 80), radius 40 */
GPrimitiveCircle(CANVAS_ID, 150, 80, 40, 15, 1);

/* Red diagonal line */
GPrimitiveLine(CANVAS_ID, 0, 0, 199, 199, 4);

/* Commit all changes */
GUpdateImage(CANVAS_ID);

Sprite Rendering

void GPrimitiveSprite(int id, int sx, int sy, int color,
                      const char* sprite, int scale);
ParameterDescription
idTarget image element.
sx, syTop-left origin of the sprite in image-local coordinates.
colorPalette index used for filled (#) pixels.
spriteRLE-encoded sprite string (see format below).
scaleInteger scale factor. Each logical pixel is rendered as a scale × scale block.

Sprite String Format

The sprite string is a compact run-length encoding:
TokenMeaning
#Draw one filled pixel (using color).
.Draw one transparent pixel (palette index 0).
$Newline — reset X to sx, advance Y by scale.
N>Skip N pixels horizontally (transparent).
N#Repeat # N times.
N.Repeat . N times.
N[...]Repeat the group [...] N times.
Groups can be nested. Counts are decimal integers immediately preceding the token.
/* A 5×5 cross shape:
       ..#..
       .###.
       #####
       .###.
       ..#..
*/
const char* cross = "..#..$"
                    ".###.$"
                    "5#$"
                    ".###.$"
                    "..#..";

/* Draw the cross at (10, 10) with color 4 (dark red), scale 2 */
GPrimitiveSprite(CANVAS_ID, 10, 10, 4, cross, 2);
GUpdateImage(CANVAS_ID);
The $ newline token uses any preceding count as a row-repeat multiplier (y += count * scale), not as a pixel-column advance.

Custom Bitmap Fonts

Image elements support loading a custom bitmap font for rendering text directly onto the canvas:
void GImageSetFont(int id, unsigned char* font, int h);
void GDrawString(int id, int x, int y, const char* txt, int color);

Font Format

The font buffer must contain exactly 256 * h bytes — one entry per ASCII character (all 256 values), each h bytes tall. Each byte encodes one row of 8 pixels, MSB first (bit 7 = leftmost pixel). Characters are rendered 9 pixels wide (8 data pixels + 1 pixel gap between characters).
font[(unsigned char)ch * h + row] = 8-bit pixel row bitmap for character ch, row index row

Rendering Text

GDrawString renders the string txt starting at (x, y) using the loaded font and palette index color. Newline (\n) advances the Y position by h pixels and resets X. Pixels outside the image bounds are clipped silently.
/* Assume `my_font_8x8` is a 256*8 byte bitmap font buffer */
extern unsigned char my_font_8x8[256 * 8];

GCreateImage(CANVAS_ID, 0, 0, 320, 240);
GImageSetFont(CANVAS_ID, my_font_8x8, 8);

GClearImage(CANVAS_ID, 0); /* black background */
GDrawString(CANVAS_ID, 10, 10, "Hello, canvas!", 15); /* white text */
GDrawString(CANVAS_ID, 10, 30, "Line two", 14);       /* yellow text */
GUpdateImage(CANVAS_ID);
GImageSetFont copies the font data into a heap buffer owned by the image element. The original font pointer does not need to remain valid after the call. The buffer is freed when the element is deleted.

Redrawing

void GRedrawAllImages(void);
GRedrawAllImages invalidates the shadow copy of every image element and calls GUpdateImage on each, forcing a full re-push of all pixel data to the X11 display. Call this after modifying the palette with GPaletteModify (with redraw=1) or GPaletteReset — both call it automatically. You can also call it manually if you need to force a full repaint.

Build docs developers (and LLMs) love