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.

LWXGL image canvases are pixel buffers indexed by the 16-color palette. You write palette indices into the buffer, call GUpdateImage to flush changes to the XImage, and the canvas is composited into the window each frame. Because canvases use the same 16-color system as the rest of LWXGL, modifying the palette with GPaletteModify instantly affects all pixels on every canvas.

Creating an image canvas

void GCreateImage(int id, int x, int y, int w, int h);
Creates a w × h pixel canvas element positioned at (x, y). The pixel buffer is zero-initialized (palette index 0, typically black).
GCreateImage(10, 0, 50, 320, 240); // 320×240 canvas at (0, 50)

Accessing the pixel buffer

unsigned char* GGetImageData(int id);
Returns a pointer to the flat w * h byte array that backs the canvas. Each byte is a palette index in the range 0–15. The pixel at canvas coordinate (x, y) lives at offset y * width + x. After modifying the buffer, you must call GUpdateImage to push the changes to the underlying XImage.
unsigned char* data = GGetImageData(10);
data[10 * 320 + 20] = 15; // Set pixel (20, 10) to White (palette 15)
GUpdateImage(10);          // Flush changes to screen

GUpdateImage

void GUpdateImage(int id);
Scans the pixel buffer for changes since the last call and updates only the modified pixels in the XImage. Because it diffs against a shadow copy, it is efficient for sparse per-frame updates — you can safely call it every frame even if few pixels changed.

GClearImage

void GClearImage(int id, int c);
Fills the entire pixel buffer with palette index c using a single memset. This is faster than manually zeroing the buffer. Remember to call GUpdateImage afterwards.
GClearImage(10, 0); // Fill entire canvas with Black (palette 0)
GUpdateImage(10);

Primitive drawing

LWXGL provides three functions that write directly into the canvas pixel buffer without requiring you to calculate pixel offsets yourself. Pixels outside the canvas bounds are silently clipped.

Filled rectangle

void GPrimitiveRect(int id, int x, int y, int w, int h, int fg, int bg);
Draws a filled rectangle with a border. fg is the border color and bg is the fill color (palette indices). Pass fg = -1 to draw a filled rectangle whose border is the same color as the fill (effectively borderless). Pass bg = -1 to draw an outline-only rectangle (the interior is not modified).

Filled circle

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 the one-pixel-thick border color; bg is the fill color. Pass either as -1 to omit that part.

Line

void GPrimitiveLine(int id, int x1, int y1, int x2, int y2, int color);
Draws a line from (x1, y1) to (x2, y2) by stepping along the longer axis, rounding each coordinate to the nearest integer. Example — drawing multiple primitives then flushing once:
GPrimitiveRect(10, 5, 5, 50, 30, 15, 1);    // White border, Dark Blue fill
GPrimitiveCircle(10, 160, 120, 40, 15, 4);  // White border, Red fill
GPrimitiveLine(10, 0, 0, 319, 239, 14);     // Yellow diagonal line
GUpdateImage(10);                            // Single flush for all three

Sprite rendering

void GPrimitiveSprite(int id, int sx, int sy, int color, const char* sprite, int scale);
Renders a run-length encoded (RLE) sprite into the canvas at origin (sx, sy). color is the foreground palette index. scale multiplies each logical pixel into a scale × scale block.

Sprite string format

CharacterMeaning
#Draw a pixel in color
.Draw a pixel in color 0 (black / background)
$End of row — move to the next row, reset X to sx
>Skip one pixel position without drawing
Digit(s) before a characterRepeat the following character that many times: 5# = five filled pixels
[...] with optional leading countRepeat the group: 3[##.] = ##.##.##.

Example — a 5×5 cross

const char* cross = ">>#$>>#$5#$>>#$>>#";
GPrimitiveSprite(10, 10, 10, 12, cross, 2); // Draw at (10,10), scale=2, Light Red
GUpdateImage(10);
Groups can be nested and combined with digit multipliers for compact sprite definitions.

Custom bitmap font

void GImageSetFont(int id, unsigned char* font, int h);
void GDrawString(int id, int x, int y, const char* txt, int color);
Load a raw bitmap font into a canvas element so that GDrawString can render text directly into the pixel buffer. Font buffer layout: 256 consecutive entries (one per ASCII value), each h bytes tall. Each byte encodes one 8-pixel-wide row as a bitmask — bit 7 (MSB) is the leftmost pixel. Characters are rendered 9 pixels wide (8px glyph + 1px spacing). Newlines (\n, ASCII 10) move the cursor down by h pixels.
// Load an 8×8 bitmap font from a file into a 256×8-byte buffer:
unsigned char font_buf[256 * 8];
FILE* f = fopen("font8x8.bin", "rb");
fread(font_buf, 1, sizeof(font_buf), f);
fclose(f);

GImageSetFont(10, font_buf, 8);
GDrawString(10, 4, 4, "Hello, World!", 15);
GUpdateImage(10);
Each canvas stores its own font independently; calling GImageSetFont on one canvas does not affect others.
Always call GUpdateImage (or GRedrawAllImages) after any modification to the pixel buffer — whether through direct array writes, GClearImage, or the primitive functions. Changes are not visible on screen until a flush is performed.
GRedrawAllImages() forces a full pixel-by-pixel redraw of every image canvas element, bypassing the diff optimization. Use it after a palette modification via GPaletteModify to ensure all canvases reflect the new colors immediately.

Build docs developers (and LLMs) love