raster.rs

crates/veilvoice-video/src/raster.rs

veilvoice-video · 594 lines · read the source here · or on GitHub

Pixels, and a PNG to put them in.

Why the video's pictures are drawn here rather than converted

Everything else this crate draws is SVG, which is right for a page: the reader's browser has a renderer and a font library and neither is this project's problem. A video file is not a page. ffmpeg reads a directory of raster images, and no build of ffmpeg can be assumed to read SVG: that needs librsvg, which most builds do not have, and a picture that fails to encode on somebody's machine is worse than one that was never offered.

The other way is to convert the SVG here, which means an SVG rasteriser. Every usable one is large, and crate::ffmpeg already spends a page explaining why this project will not pull in a large library to make a video file. Doing it anyway, one module over, would make that argument a thing this project says rather than a thing it does.

So the picture is a few hundred lines: rectangles, circles, a face (crate::font) and a PNG writer. That is the whole of what the drawing needs, and it is small enough to read.

The same picture on every machine

No system fonts, no floating-point that varies by platform in a way that reaches a pixel, and no dependency that could quietly change its output. Two people rendering the same recording get identical files, which is the same property the reproducible builds have and is checked the same way: by comparing bytes.

One dependency, and what it is for

miniz_oxide deflates the pixel data, because PNG is deflate and a PNG written with stored blocks is roughly six megabytes a frame. It is pure Rust and it is already in this tree, underneath flate2, which lofty and pgp both pull in, so naming it here adds nothing to the dependency graph that was not being compiled already.

In plain words

The part that draws the video's pictures, dot by dot, and writes them as PNG files.

It is written here rather than borrowed because the video tool this hands its pictures to cannot be relied on to read drawings, and converting them would mean carrying a large piece of somebody else's code, which is the thing this program is careful not to do.

WHAT THIS FILE CONTAINS

594 lines defining 17 functions (12 public), 2 types and 0 constants. Everything below is read out of the source, so it cannot disagree with the code.

The types it owns.

  • struct Canvas line 74 · A picture being drawn, one byte per channel, three channels per pixel.
  • struct Crc line 349 · The CRC-32 PNG puts on every chunk.

What happens when it runs. These are the ways in: public, and nothing else in this file calls them, so they are what an outside caller reaches first.

  • colour line 61 · Read #rrggbb into three bytes.
  • Canvas::width line 95 · How wide it is.
  • Canvas::height line 100 · How tall it is.
  • Canvas::rounded_rect line 157 · A rectangle with rounded ends, which is how the level bars are drawn.
    reaches circle, rect, blend
  • Canvas::ring line 222 · A ring, drawn as a filled disc with the middle taken back out.
    reaches at, blend, circle
  • Canvas::text_centred line 283 · Draw text centred on centre_x, with its top at y.
    reaches text, rect
  • Canvas::png line 306 · The picture as a PNG file.
    reaches chunk, new

WHAT CALLS WHAT

colour line 61 Canvas::new line 82 Canvas::width line 95 Canvas::height line 100 Canvas::at line 105 Canvas::blend line 118 Canvas::rect line 137 Canvas::rounded_rect line 157 Canvas::circle line 183 Canvas::ring line 222 Canvas::text line 255 Canvas::text_centred line 283 Canvas::png line 306 chunk line 335 Crc::new line 352 Crc::eat line 356 Crc::done line 370 entry: a way in: public, and nothing in this file calls it api: public, and also used inside this file helper: private to this file dashed: a call that goes back up, or across a wrapped rank The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.

The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.

The same graph as Mermaid source
%%{init: {"theme":"base","themeVariables":{"background":"#1a1b26","primaryColor":"#1f2335","primaryTextColor":"#c0caf5","primaryBorderColor":"#7aa2f7","secondaryColor":"#16161e","tertiaryColor":"#16161e","lineColor":"#737aa2","textColor":"#c0caf5","mainBkg":"#1f2335","nodeBorder":"#7aa2f7","clusterBkg":"#16161e","clusterBorder":"#2f3549","fontFamily":"ui-monospace, SFMono-Regular, Consolas, monospace","fontSize":"14px"}}}%%
flowchart TD
    n_colour(["colour<br/>line 61"])
    n_new["Canvas::new<br/>line 82"]
    n_width(["Canvas::width<br/>line 95"])
    n_height(["Canvas::height<br/>line 100"])
    n_at["Canvas::at<br/>line 105"]
    n_blend["Canvas::blend<br/>line 118"]
    n_rect["Canvas::rect<br/>line 137"]
    n_rounded_rect(["Canvas::rounded_rect<br/>line 157"])
    n_circle["Canvas::circle<br/>line 183"]
    n_ring(["Canvas::ring<br/>line 222"])
    n_text["Canvas::text<br/>line 255"]
    n_text_centred(["Canvas::text_centred<br/>line 283"])
    n_png(["Canvas::png<br/>line 306"])
    n_chunk["chunk<br/>line 335"]
    n_new["Crc::new<br/>line 352"]
    n_eat["Crc::eat<br/>line 356"]
    n_done["Crc::done<br/>line 370"]
    n_chunk --> n_new
    n_circle --> n_blend
    n_png --> n_chunk
    n_ring --> n_at
    n_ring --> n_blend
    n_ring --> n_circle
    n_rounded_rect --> n_circle
    n_rounded_rect --> n_rect
    n_text --> n_rect
    n_text_centred --> n_text
    click n_colour href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L61" "open the source"
    click n_new href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L82" "open the source"
    click n_width href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L95" "open the source"
    click n_height href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L100" "open the source"
    click n_at href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L105" "open the source"
    click n_blend href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L118" "open the source"
    click n_rect href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L137" "open the source"
    click n_rounded_rect href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L157" "open the source"
    click n_circle href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L183" "open the source"
    click n_ring href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L222" "open the source"
    click n_text href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L255" "open the source"
    click n_text_centred href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L283" "open the source"
    click n_png href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L306" "open the source"
    click n_chunk href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L335" "open the source"
    click n_new href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L352" "open the source"
    click n_eat href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L356" "open the source"
    click n_done href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/raster.rs#L370" "open the source"
    classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
    class n_colour,n_width,n_height,n_rounded_rect,n_ring,n_text_centred,n_png entry
    classDef api fill:#1f2335,stroke:#7dcfff,color:#c0caf5
    class n_new,n_at,n_rect,n_circle,n_text api
    classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
    class n_blend,n_chunk,n_new,n_eat,n_done helper

This site loads no third-party script, so it cannot run Mermaid; the diagram above is the same nodes and edges drawn by the generator instead. GitHub renders the source below directly.

ITEMS

ItemLineDocumentation
Rgb pub type52A colour, as the three bytes a PNG stores.
colour pub fn61Read #rrggbb into three bytes.
Canvas pub struct74A picture being drawn, one byte per channel, three channels per pixel.
Canvas::new pub fn82A canvas of width by height, filled with background.
Canvas::width pub fn95How wide it is.
Canvas::height pub fn100How tall it is.
Canvas::at pub fn105The colour at a point, or None outside the canvas.
Canvas::blend fn118Mix colour into the pixel at x, y by alpha, from 0.0 to 1.0.
Canvas::rect pub fn137A filled rectangle, clipped to the canvas.
Canvas::rounded_rect pub fn157A rectangle with rounded ends, which is how the level bars are drawn.
Canvas::circle pub fn183A filled circle with a smooth edge.
Canvas::ring pub fn222A ring, drawn as a filled disc with the middle taken back out.
Canvas::text pub fn255Draw text with its left edge at x and its top at y.
Canvas::text_centred pub fn283Draw text centred on centre_x, with its top at y.
Canvas::png pub fn306The picture as a PNG file.
chunk fn335Append one PNG chunk: length, type, data, and the checksum over both.
Crc struct349The CRC-32 PNG puts on every chunk.
Crc::new fn352
Crc::eat fn356
Crc::done fn370