latkit 0.2.1

Columnar data drawn as vertices, edges, lines, and areas on the GPU.
Documentation
// Labels: where a labeled row's text hangs, how large it draws, and whether it can show. Draws place
// every label from its anchor each frame, so labels follow the camera and the rows they name exactly;
// placement measures the same box only to decide which labels give way. Text is a distance field set
// at `TEXT_BASE`, drawn at any size: CSS pixels, or units in a diagram, where text scales with the
// sheet and fades out once too small to read.

import package::lib::types::{
    POINTS, STROKES, MARKER_BLOCK, SIZED, GROUP, PATH_TRACE, PATH_GEOMETRY, TEXT_BASE, TEXT_SPREAD, HEADER_BAND,
    SPACE_DIAGRAM,
};
import package::lib::bind::{frame, eye, mark};
import package::lib::mark::PRIMITIVE;
import package::lib::project::{to_screen, clip_of};
import package::lib::points::point;
import package::lib::path::{PATH, Segment, segment_screen, path_count};
import package::lib::triangles::{triangle_corner, area_anchor};

// Where row `row`'s label hangs, CSS pixels, how it aligns to that point (0 left or top, 0.5
// centered), the room it must fit in (none when zero), and whether its row shows.
struct Anchor {
    at: vec2f,
    align: vec2f,
    room: vec2f,
    shown: bool,
}

// CSS pixels a size in length units spans this frame.
fn length_px(size: f32) -> f32 {
    return size * frame.unit;
}

fn anchor(row: u32) -> Anchor {
    var a: Anchor;
    switch PRIMITIVE {
        case POINTS: {
            let p = point(row);
            a.shown = p.shown;
            let center = to_screen(p.clip);
            let text = length_px(mark.label_size);
            if (mark.flags & GROUP) != 0u {
                // A group's title sits in its header band, inset from the left.
                let header = text * HEADER_BAND;
                a.at = center + vec2f(-p.half.x + frame.group_padding, -p.half.y + 0.5 * header);
                a.align = vec2f(0.0, 0.5);
                a.room = vec2f(2.0 * (p.half.x - frame.group_padding), header);
            } else if mark.marker == MARKER_BLOCK || (mark.flags & SIZED) != 0u {
                // A block, or any marker given a width and height, holds its label while it fits.
                a.at = center;
                a.align = vec2f(0.5);
                a.room = vec2f(2.0 * p.half.x - text, 2.0 * p.half.y);
            } else {
                a.at = center + vec2f(p.half.x + 0.4 * text, 0.0);
                a.align = vec2f(0.0, 0.5);
            }
        }
        case STROKES: {
            let count = path_count(row);
            // A trace labels its last sample; other paths their middle.
            let last = PATH == PATH_TRACE;
            let on = segment_screen(Segment(row, select(count / 2u, max(count, 1u) - 1u, last), 0.0));
            a.shown = count > 0u && on.shown;
            if last {
                a.at = on.b + vec2f(6.0, 0.0);
                a.align = vec2f(0.0, 0.5);
            } else {
                a.at = 0.5 * (on.a + on.b);
                a.align = vec2f(0.5);
            }
        }
        default: {
            a.align = vec2f(0.5);
            if PATH == PATH_GEOMETRY {
                // An area's label hangs inside its largest polygon, farthest from its edges.
                let c = area_anchor(row);
                let clip = clip_of(c.world);
                a.shown = c.shown && c.ahead && clip.w > 0.0;
                a.at = to_screen(clip);
                return a;
            }
            var sum = vec2f(0.0);
            a.shown = true;
            for (var k = 0u; k < 3u; k++) {
                let c = triangle_corner(row, k);
                let clip = clip_of(c.world);
                a.shown = a.shown && c.shown && c.ahead && clip.w > 0.0;
                sum += to_screen(clip);
            }
            a.at = sum / 3.0;
        }
    }
    return a;
}

// How much text `px` CSS pixels tall shows: in a diagram it fades out as the view zooms away from
// it; elsewhere it is set at a size that reads.
fn legibility(px: f32) -> f32 {
    if frame.space != SPACE_DIAGRAM {
        return 1.0;
    }
    return smoothstep(3.5, 6.0, px);
}

// A run of text placed on screen: the text's box and the quad around it, which reaches over the
// distance field's spread, in CSS pixels; its corners in the atlas, texels; and CSS pixels per
// texel.
struct Text {
    lo: vec2f,
    hi: vec2f,
    quad_lo: vec2f,
    quad_hi: vec2f,
    uv_lo: vec2f,
    uv_hi: vec2f,
    scale: f32,
}

// A rectangle's corner in the atlas: 16 bits of x, then 16 of y.
fn corner(word: u32) -> vec2f {
    return vec2f(f32(word & 0xffffu), f32(word >> 16u));
}

// The run at atlas corners `uv0` and `uv1`, set `size` CSS pixels tall, hung at `at` by `align`.
fn text_at(uv0: u32, uv1: u32, size: f32, at: vec2f, align: vec2f) -> Text {
    var t: Text;
    t.uv_lo = corner(uv0);
    t.uv_hi = corner(uv1);
    t.scale = size / TEXT_BASE;
    let pad = TEXT_SPREAD * t.scale;
    let extent = max((t.uv_hi - t.uv_lo) * t.scale - 2.0 * pad, vec2f(0.0));
    t.lo = at - extent * align;
    t.hi = t.lo + extent;
    t.quad_lo = t.lo - pad;
    t.quad_hi = t.hi + pad;
    return t;
}

// Whether text of extent `extent` fits `room`; no room holds any.
fn fits(extent: vec2f, room: vec2f) -> bool {
    return room.x <= 0.0 || all(extent <= room);
}

// Whether a box reaches into the view.
fn in_view(lo: vec2f, hi: vec2f) -> bool {
    return all(hi > vec2f(0.0)) && all(lo < eye.size);
}