Canvas Widget
A free-draw surface with pixel-level control. Supports individual pixel setting, geometric primitives (line, rectangle, circle), text drawing, and sprite operations with caching.
Creating a Canvas
from tuix.core import builders, objects, buffers
uid = objects.create_object(
builders.CANVAS, b"main",
1.0, 1.0, # full terminal width and height
0.0, 0.0 # no margin (top-left corner)
)
# Operational object handle
buf = buffers.get_buffer_by_uid(uid)
obj = buf.contents.obj.contents
# Read-only inspection (lock-safe snapshots)
buffer_info = buffers.get_buffer_snapshot_by_uid(uid)
object_info = objects.get_object_snapshot_by_uid(uid)Pixel Operations
tuix_canvas_set_pixel(obj, x, y, sym, fgr, fgg, fgb, bgr, bgg, bgb)
Sets a single pixel at (x, y) to the given symbol and colors.
| Parameter | Type | Description |
|---|---|---|
| obj | TuixObject | Object pointer |
| x, y | int | Pixel coordinates (0-based) |
| sym | int/char | Character value (single byte) |
| fgr, fgg, fgb | int (0–255) | Foreground RGB color |
| bgr, bgg, bgb | int (0–255) | Background RGB color |
# Draw a red 'X' on black background at position (10, 5)
objects.tuix_canvas_set_pixel(obj, 10, 5, ord(b'X'), 255, 0, 0, 0, 0, 0)tuix_canvas_insert_buffer(obj, pixels_ptr, size)
Replaces the canvas pixel buffer with a pre-built pixel array. Used for bulk pixel operations.
| Parameter | Type | Description |
|---|---|---|
| obj | TuixObject | Object pointer |
| pixels_ptr | ctypes pointer | Pointer to TuixPixel array |
| size | int | Number of pixels in the array |
Drawing Primitives
tuix_canvas_draw_line(obj, x0, y0, x1, y1, sym, fgr, fgg, fgb, bgr, bgg, bgb)
Draws a line from (x0, y0) to (x1, y1) using the Bresenham algorithm.
| Parameter | Type | Description |
|---|---|---|
| x0, y0 | int | Start coordinates |
| x1, y1 | int | End coordinates |
| sym | int/char | Character to draw with |
| fgr, fgg, fgb | int (0–255) | Foreground RGB |
| bgr, bgg, bgb | int (0–255) | Background RGB |
# Draw a green line from (0,0) to (20,10)
objects.tuix_canvas_draw_line(obj, 0, 0, 20, 10, ord(b'*'), 0, 255, 0, 0, 0, 0)tuix_canvas_draw_rect(obj, x, y, w, h, sym, filled, fgr, fgg, fgb, bgr, bgg, bgb)
Draws a rectangle. Set filled=1 for a solid rectangle, filled=0 for an outline.
| Parameter | Type | Description |
|---|---|---|
| x, y | int | Top-left corner |
| w, h | int | Width and height |
| sym | int/char | Character to draw with |
| filled | int | 1 for solid, 0 for outline only |
| fgr, fgg, fgb | int (0–255) | Foreground RGB |
| bgr, bgg, bgb | int (0–255) | Background RGB |
# Draw a blue filled rectangle
objects.tuix_canvas_draw_rect(obj, 5, 2, 15, 8, ord(b'#'), 1, 0, 100, 255, 0, 0, 0)
# Draw a red outline rectangle
objects.tuix_canvas_draw_rect(obj, 5, 2, 15, 8, ord(b'+'), 0, 255, 0, 0, 0, 0, 0)tuix_canvas_draw_circle(obj, cx, cy, radius, sym, filled, fgr, fgg, fgb, bgr, bgg, bgb)
Draws a circle centered at (cx, cy) with the given radius.
| Parameter | Type | Description |
|---|---|---|
| cx, cy | int | Center coordinates |
| radius | int | Circle radius |
| sym | int/char | Character to draw with |
| filled | int | 1 for solid, 0 for outline only |
| fgr, fgg, fgb | int (0–255) | Foreground RGB |
| bgr, bgg, bgb | int (0–255) | Background RGB |
# Draw a yellow filled circle
objects.tuix_canvas_draw_circle(obj, 20, 10, 5, ord(b'O'), 1, 255, 255, 0, 0, 0, 0)Text Drawing
tuix_canvas_draw_text(obj, x, y, text, fgr, fgg, fgb, bgr, bgg, bgb)
Draws a text string starting at (x, y). Supports newline characters (\n) for multi-line text.
| Parameter | Type | Description |
|---|---|---|
| x, y | int | Starting position |
| text | bytes | Text to draw (e.g. b"Hello\nWorld") |
| fgr, fgg, fgb | int (0–255) | Foreground RGB |
| bgr, bgg, bgb | int (0–255) | Background RGB |
objects.tuix_canvas_draw_text(obj, 5, 2, b"Hello World!", 255, 255, 255, 0, 0, 0)Sprite Operations
tuix_canvas_draw_sprite(obj, dst_x, dst_y, sprite_w, sprite_h, sprite_ptr)
Draws a sprite (pre-built TuixPixel array) at the given position.
| Parameter | Type | Description |
|---|---|---|
| dst_x, dst_y | int | Destination position on canvas |
| sprite_w, sprite_h | int | Sprite dimensions |
| sprite_ptr | ctypes pointer | Pointer to TuixPixel array |
Sprite Caching
For sprites drawn multiple times, use the caching API to avoid repeated data transfer:
# Cache a sprite (upload to C-side memory)
sprite_id = objects.tuix_canvas_cache_sprite(obj, sprite_w, sprite_h, sprite_ptr)
# Draw cached sprite at multiple positions (fast — no data transfer)
objects.tuix_canvas_draw_cached_sprite(obj, sprite_id, 10, 5)
objects.tuix_canvas_draw_cached_sprite(obj, sprite_id, 30, 5)
objects.tuix_canvas_draw_cached_sprite(obj, sprite_id, 50, 5)
# Free cached sprite when no longer needed
objects.tuix_canvas_free_cached_sprite(obj, sprite_id)| Function | Returns | Description |
|---|---|---|
| tuix_canvas_cache_sprite(obj, w, h, ptr) | int | Non-negative cache ID, or -1 on error |
| tuix_canvas_draw_cached_sprite(obj, id, x, y) | int | 0 on success |
| tuix_canvas_free_cached_sprite(obj, id) | None | Frees the cached sprite |
Complete Example: Bouncing Ball
from tuix.core import engine, builders, scenes, registry, objects, buffers, input
import time, math
engine.init()
builders.register_standard()
scenes.init_scene(b"main")
registry.registry.current_scene_name = b"main"
input.listen()
uid = objects.create_object(builders.CANVAS, b"main", 1.0, 1.0, 0.0, 0.0)
buf = buffers.get_buffer_by_uid(uid)
obj = buf.contents.obj.contents
# Run main_loop once to resolve geometry
engine.main_loop()
w = buf.contents.width
h = buf.contents.height
# Ball state
bx, by = w // 2, h // 2
vx, vy = 1, 1
hue = 0
for frame in range(600):
# Clear with background
objects.tuix_canvas_draw_rect(obj, 0, 0, w, h, ord(b' '), 1, 0, 0, 0, 20, 20, 30)
# Draw border
objects.tuix_canvas_draw_rect(obj, 0, 0, w, h, ord(b'.'), 0, 60, 60, 60, 20, 20, 30)
# Move ball
bx += vx
by += vy
if bx <= 1 or bx >= w - 2:
vx = -vx
if by <= 1 or by >= h - 2:
vy = -vy
# HSL color cycling
r = int(127 + 127 * math.sin(hue))
g = int(127 + 127 * math.sin(hue + 2.094))
b_color = int(127 + 127 * math.sin(hue + 4.189))
hue += 0.05
# Draw ball
objects.tuix_canvas_draw_circle(obj, bx, by, 2, ord(b'O'), 1, r, g, b_color, 20, 20, 30)
engine.main_loop()
time.sleep(0.016)
buffers.free_buffer(b"main", uid)
input.stop()
engine.shutdown()