raster

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package raster turns a vtengine frame snapshot into RGBA pixels: HarfBuzz shaping in style runs (ligature clusters anchored to their origin cell), FreeType glyph rendering with an atlas cache, synthesized sprites for box-drawing/blocks/braille (sprites.go — cell-exact tiling, like every real terminal), color emoji (CBDT strikes), kitty graphics compositing by z-layer, cursor and decorations, at 1x or 2x. Quality is pinned by the typographic golden suite (byte-exact frames).

DETERMINISM RULE: frames must be byte-identical across OS and CPU architecture (the PRD's north metric). Blending and span math stay integer-only. Any float expression shaped like c + a*b in the render path must round the product through an explicit conversion — e.g. c + float32(a*b), see mask() in text.go — because on arm64 the Go compiler otherwise fuses it into a single-rounding FMA and coverage can drift by one alpha step relative to amd64 (found empirically: one pixel in the first cross-arch CI run, bisected with -d=fmahash).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DownscaleHalf

func DownscaleHalf(dst, src *image.RGBA) *image.RGBA

DownscaleHalf shrinks src into dst at exactly 2:1 with the integer area mean — the output-scale knob's final pass (this file's scaler: deterministic by construction). dst is reallocated when it does not match; the result is returned either way.

func KeysBandFor

func KeysBandFor(capCell int) int

KeysBandFor is the band's logical height for a cap cell height (the grid cell scaled by the chosen size): matte above, the strip — a frame row between two sprocket rows — and matte below.

Types

type BarStyle

type BarStyle uint8

BarStyle is a WindowBar variant. The zero value means no bar.

const (
	BarNone          BarStyle = iota
	BarColorful               // macOS traffic lights, left
	BarColorfulRight          // macOS traffic lights, right
	BarRings
	BarRingsRight
	BarLinuxControls // minimize/maximize/close strokes, right
	BarGnomeCSD      // a close button in a circle, right (CSD-like)
)

The window bar styles: VHS's four, plus foley's genre controls (dress-reachable; a tape using them still degrades in VHS, which silently draws no bar for unknown styles).

type CameraTrack

type CameraTrack struct {
	// contains filtered or unexported fields
}

CameraTrack holds the camera's movements and serves the driver's Overlay contract (SetTime/Breakpoints). Like HighlightTrack it is mutated by the recording goroutine while realtime's loop reads it — mutex; single-goroutine and contention-free in deterministic mode.

func NewCameraTrack

func NewCameraTrack(world image.Rectangle) *CameraTrack

NewCameraTrack returns a camera at identity over the given world.

func (*CameraTrack) Breakpoints

func (ct *CameraTrack) Breakpoints(from, to time.Duration) []time.Duration

Breakpoints reports the animation instants in [from, to): each move's quantized steps plus its exact end.

func (*CameraTrack) MoveTo

func (ct *CameraTrack) MoveTo(target image.Rectangle, at, dur time.Duration)

MoveTo animates the camera to target starting at the given instant. The departure point is the camera's state AT that instant — never a teleport. A move to where the camera already rests is a no-op: it must not emit a transition's worth of identical frames (`zoom off` at identity, re-zooming the same rect).

func (*CameraTrack) Reset

func (ct *CameraTrack) Reset(at, dur time.Duration)

Reset animates back to identity — `zoom off`, reversible by construction.

func (*CameraTrack) SetTime

func (ct *CameraTrack) SetTime(t time.Duration)

SetTime fixes the camera clock for the next render.

func (*CameraTrack) Viewport

func (ct *CameraTrack) Viewport() image.Rectangle

Viewport reports the camera rect at the track's current clock.

type Fill

type Fill struct {
	Color color.RGBA
	Image image.Image
}

Fill is a margin fill: a solid color, or an image file already decoded by the caller (scaled to the canvas here). Image wins when non-nil.

type HighlightSpec

type HighlightSpec struct {
	Pattern        *regexp.Regexp
	Col, Row, W, H int
	Rect           bool
	Occurrence     int
	Pick           bool
	Name           string
}

HighlightSpec is one highlight: a regex over each row's text, or a cell rectangle (Col,Row,W,H). Exactly one form is set. With Pick, Occurrence narrows a pattern to that match of the FRAME — 0-based in screen order, the same standard as the rect's cells. Name lets a targeted off close just this highlight.

type HighlightTrack

type HighlightTrack struct {
	// contains filtered or unexported fields
}

HighlightTrack holds the active highlights and serves the driver's Overlay contract (SetTime/Breakpoints — snap on/off, no fades). Unlike KeysTrack (fed by OnKey ON the driver's goroutine), this one is mutated by the RECORDING goroutine while realtime's loop reads it at render — hence the mutex; in deterministic mode everything is one goroutine and it never contends.

func NewHighlightTrack

func NewHighlightTrack() *HighlightTrack

NewHighlightTrack returns an empty track.

func (*HighlightTrack) Activate

func (ht *HighlightTrack) Activate(spec HighlightSpec, at time.Duration)

Activate turns a highlight on from the given virtual instant.

func (*HighlightTrack) Breakpoints

func (ht *HighlightTrack) Breakpoints(from, to time.Duration) []time.Duration

Breakpoints reports the on/off instants in [from, to) — highlights snap, so those are the only frames they need.

func (*HighlightTrack) Clear

func (ht *HighlightTrack) Clear(at time.Duration)

Clear turns every open highlight off at the given virtual instant.

func (*HighlightTrack) ClearNamed

func (ht *HighlightTrack) ClearNamed(name string, at time.Duration)

ClearNamed turns off every open highlight carrying the name.

func (*HighlightTrack) SetTime

func (ht *HighlightTrack) SetTime(t time.Duration)

SetTime fixes the overlay clock for the next render.

type ImageSource

type ImageSource interface {
	ImagePixels(id uint32) (vtengine.ImageData, error)
}

ImageSource resolves kitty-graphics pixels for placements in a frame. vtengine.Engine satisfies it; so does the test fake.

type KeysNotation

type KeysNotation uint8

KeysNotation is the cap vocabulary.

const (
	// KeysKeycap prints what a real keycap prints: lowercase words in
	// the grid font, drawn arrows, a blank spacebar.
	KeysKeycap KeysNotation = iota
	// KeysIcons swaps the words for compact drawn symbols (enter, tab,
	// bksp, del) — esc stays a word: keyboards never icon it.
	KeysIcons
)

type KeysStyle

type KeysStyle struct {
	// Notation picks the cap vocabulary.
	Notation KeysNotation
	// Accent overrides the special-cap color; nil keeps the theme's
	// bright magenta. AccentOff mutes the hierarchy entirely.
	Accent    *color.RGBA
	AccentOff bool
	// Plain drops the celluloid: caps float straight on the margin.
	Plain bool
}

KeysStyle is the band's styling knobs: notation, accent override, and the plain (stripless) variant.

type KeysTrack

type KeysTrack struct {
	// contains filtered or unexported fields
}

KeysTrack accumulates the injected input track and serves the driver's overlay contract structurally (SetTime/Breakpoints) — the driver stays raster-agnostic, the raster driver-agnostic. Chips are a pure function of the track and the render time.

func NewKeysTrack

func NewKeysTrack(notation KeysNotation) *KeysTrack

NewKeysTrack returns an empty input track speaking the given notation (the cap face derives at AddKey time — coalescing compares faces, so the vocabulary is fixed per recording).

func (*KeysTrack) AddKey

func (kt *KeysTrack) AddKey(k key.Key, at time.Duration, hidden bool)

AddKey records one injected keystroke. Hidden input is dropped: if the setup is not shown, its typing must not leak either.

func (*KeysTrack) Breakpoints

func (kt *KeysTrack) Breakpoints(from, to time.Duration) []time.Duration

Breakpoints reports every overlay-state change taking effect in [from, to): cap births, phrase reveals, fade steps. The driver splits time advances there so the animation lands on exact frames.

func (*KeysTrack) SetTime

func (kt *KeysTrack) SetTime(t time.Duration)

SetTime fixes the overlay clock for the next render (the frame's START instant on the virtual timeline).

type Options

type Options struct {
	Pack *fontpack.Pack
	// UserFonts loads a user primary font over the pack.
	UserFonts UserFonts
	// FontSizePx is the glyph size in pixels at Scale 1.
	FontSizePx int
	// Scale multiplies every metric (2 = native supersampling).
	Scale int
	// SuperSample renders the frame at N× the output for the camera's
	// master; 0/1 = none. Cell METRICS still derive at the
	// base Scale and multiply exactly — the logical grid (and so the
	// footage) is identical with or without a camera.
	SuperSample int
	// Window configures the chrome around the grid (VHS parity: margin,
	// window bar, padding, rounded corners). Zero value = no chrome, the
	// canvas is exactly the grid.
	Window Window
	// Keys is the injected input track for the keys band;
	// nil = no chips. Window.KeysBand sizes the band itself.
	Keys *KeysTrack
	// KeysFontPx is the cap label size in logical px (the reel's
	// small/medium/large); zero = FontSizePx.
	KeysFontPx int
	// KeysStyle tunes the band's look and vocabulary:
	// accent override and the plain (stripless) variant. The notation
	// lives on the KeysTrack — cap faces derive as keys arrive.
	KeysStyle KeysStyle
	// Highlights is the highlight track; nil = none.
	// SelectionColor paints the matches — the theme's Selection.
	Highlights     *HighlightTrack
	SelectionColor color.RGBA
}

Options configures a Rasterizer.

type Rasterizer

type Rasterizer struct {
	// contains filtered or unexported fields
}

Rasterizer turns engine frames into RGBA images. It caches parsed faces, glyph masks and decoded images; it is not safe for concurrent use (one rasterizer per recording, like the engine).

func New

func New(opts Options) (*Rasterizer, error)

New parses the pack's faces and computes the cell metrics that the engine geometry must match (Geometry.CellW/CellH = CellSize()).

func (*Rasterizer) CellSize

func (r *Rasterizer) CellSize() (w, h int)

CellSize returns the cell size in output pixels (already scaled).

func (*Rasterizer) Composite

func (r *Rasterizer) Composite(master *image.RGBA, vp image.Rectangle, dst *image.RGBA) *image.RGBA

Composite develops the master through the camera: the WORLD part of the frame is the viewport downscaled into the output; the HUD band (the keys reel) is glued under it at a fixed 2:1 — pinned to the camera glass, never zoomed (stratification). dst is reused when it already has the output size.

func (*Rasterizer) LogicalCellSize

func (r *Rasterizer) LogicalCellSize() (w, h int)

LogicalCellSize returns the cell size in LOGICAL pixels — the values the engine geometry and the pty winsize must use (kitty-graphics math happens in logical space; Render multiplies by Scale).

func (*Rasterizer) Render

func (r *Rasterizer) Render(f *vtengine.Frame, src ImageSource, dst *image.RGBA) (*image.RGBA, error)

Render draws the frame into dst (reused when it has the right bounds, reallocated otherwise) and returns the image.

func (*Rasterizer) SuperSample

func (r *Rasterizer) SuperSample() int

SuperSample reports the master's supersample factor (1 = no camera).

func (*Rasterizer) Warnings

func (r *Rasterizer) Warnings() []string

Warnings reports assembly findings for the recorder to surface. The slice is a copy — callers cannot corrupt the rasterizer's record.

func (*Rasterizer) WorldRect

func (r *Rasterizer) WorldRect() image.Rectangle

WorldRect is the camera's world on the master: the canvas minus the keys band — the HUD stays glued to the camera glass.

func (*Rasterizer) ZoomTarget

func (r *Rasterizer) ZoomTarget(col, row, w, h int) (image.Rectangle, error)

ZoomTarget maps a CELL rect (0-based, the house standard) to a master viewport: expanded to the world's aspect around its center, capped at the supersample's sharp limit — beyond it foley would ship a blurry frame, and blurry never ships silently: it refuses with the recipe — then clamped inside the world.

type TitleAlign

type TitleAlign uint8

TitleAlign positions the window title inside the bar.

const (
	TitleCenter TitleAlign = iota
	TitleLeft
)

Title alignments.

type UserFonts

type UserFonts struct {
	// Label names the font in errors and warnings (a file path or a
	// catalog family name).
	Label                             string
	Regular, Bold, Italic, BoldItalic []byte
}

UserFonts is a user-supplied primary font. A single file fills Regular and serves every style; a family gives styles their own files — absent styles fall back to the Regular face, keeping the grid metrics whole. The primary drives cell metrics and titles the window bar; the pack stays as per-cell coverage fallback, emoji stay Noto, and block sprites stay synthesized.

type Window

type Window struct {
	// CanvasW, CanvasH are the final output size in logical pixels.
	// Zero means "grid only" (no chrome).
	CanvasW, CanvasH int
	// Padding is the inner border between the terminal background and
	// the grid, painted in the theme background.
	Padding int
	// Margin is the border outside the window block, painted MarginFill.
	Margin int
	// MarginFill paints the margin band (and the corner reveals).
	MarginFill Fill
	// Bar selects the window bar style; BarSize its height; BarColor its
	// background.
	Bar      BarStyle
	BarSize  int
	BarColor color.RGBA
	// Title is drawn inside the bar (static text: recordings must not
	// leak hostnames — determinism). TitleAlign positions it.
	Title      string
	TitleAlign TitleAlign
	// TitleFollow lets the bar follow the title the APPLICATION
	// declares via OSC 0/2 (Frame.Title), falling back to Title while
	// none is set. Footage, not host state: deterministic.
	TitleFollow bool
	// KeysBand is the height of the input-caption band under the
	// window; zero = no band. The canvas GROWS by it — a cue
	// never eats grid rows and the footage is never covered.
	KeysBand int
	// Radius rounds the window block's corners, revealing MarginFill.
	Radius int
}

Window configures the chrome. Zero value = no chrome at all: the canvas is exactly the grid (every pre-chrome recording and golden).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL