denise-render 0.25.0

Software rasteriser for Denise: rectangles, rounded rectangles, circles, arcs, lines and alpha blending.
Documentation

denise-render

crates.io docs.rs Licence

The software rasteriser for Denise, a direct-rendering UI toolkit in Rust for embedded Linux and systems without a desktop environment.

Rectangles, rounded rectangles, circles, arcs, stars, lines, image blitting, rectangular clipping and source-over alpha blending, straight into a denise::Frame. No GPU, no path builder, no allocator: this crate needs neither std nor alloc, and every operation writes through a borrowed slice the caller already owns.

use denise::{Color, Frame, Point, Rect};
use denise_render::Canvas;

# fn draw(frame: &mut Frame<'_>, damage: &[Rect]) {
let mut canvas = Canvas::new(frame);
for region in damage {
    // Everything inside this borrow is confined to `region`.
    let mut c = canvas.with_clip(*region);
    c.clear(Color::from_rgb888(0x1E1E2E));
    c.fill_rounded_rect(Rect::new(40, 40, 200, 64), 12, Color::rgba(255, 255, 255, 32));
    c.draw_line(Point::new(40, 120), Point::new(240, 121), Color::WHITE);
    // A 70% progress ring: angles are binary turns, 0 is twelve o'clock,
    // clockwise positive. No radians, no floats, no libm.
    c.stroke_arc(Point::new(300, 90), 40, 8, 0, 70 * denise_render::TURN / 100, Color::WHITE);
}
# }

No floating point

Integer throughout, including anti-aliasing coverage. That avoids a libm dependency on no_std targets and keeps output bit-identical between x86 and ARM — so a reference test means the same thing on a developer's laptop and on the Pi.

No unsafe

#![forbid(unsafe_code)], deliberately. Bounds checks are hoisted by working through row slices rather than indexing pixel by pixel. If the benches ever show that costing real time, that is the evidence needed to justify unchecked access — not before.

The built-in font

An 8×8 bitmap face covering Latin plus æøå, compiled in at no cost, scaled by whole numbers. It is what makes a panel with no font files still able to show a number. Anything more — real TrueType, proportional metrics, wrapping — is denise-text, which is a separate crate precisely so this one stays a rasteriser.

Pictures

Canvas::blit draws a borrowed block of pixels at a position, and Canvas::blit_scaled resamples it nearest-neighbour into a rectangle — clipped and alpha-composited like everything else. The one contract: source pixels are premultiplied 0xAARRGGBB, so the multiply happens once when an image is loaded, never per frame. blend::premultiply converts a straight-alpha buffer in place, and fully opaque pixels are the same either way. Decoding files into pixels is deliberately somebody else's job.

Features

Feature Default What it does
std Passes through to denise/std. Off gives no_std, with no alloc either.

Where this sits

Depends only on denise. Used by denise-text and denise-ui. An application that draws its own scene can use this directly and link no widget code at all.

Status

M5 complete, M6 in progress. Benchmarked with criterion in CI; the numbers and the reasoning are in docs/design.md. Part of Denise — see the repository README for the whole picture.

MIT licensed.