Skip to documentation
SLOP

tiny.gui.paint.text

Reference tiny.gui paint text

Defined in paint.

API (68)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

No direct callersNo direct callspainttext
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callerspaint.TextAtlascaretLinepaint.TextAtlasadvanceForByteOffset
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callerspaint.TextAtlasCacheStoragestatuspaint.TextAtlascacheStatus
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallspaint.TextAtlasadvanceForByteOffsetpaint.TextAtlashitTestAdvancepaint.TextAtlasshapepaint.TextAtlascaretLine
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerspaint.TextAtlasCacheStoragedeinitprivate sourcelib.gui.src.paint.text.CompositeWorkspacedeinitpaint.text.OwnedAtlasImagedeinitpaint.TextAtlasdeinit
Static calls · unresolved targets: 1 · external targets: 9.
Called byCallsNo direct callerspaint.TextAtlascaretLinepaint.TextAtlashitTestAdvance
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallstest sourcelib.gui.src.paint.texttest: Atlas cache bypasses oversized ...test sourcelib.gui.src.paint.texttest: appendFrameCommands draws curso...test sourcelib.gui.src.paint.texttest: appendFrameCommands draws text ...test sourcelib.gui.src.paint.texttest: appendFrameCommands keeps glyph...test sourcelib.gui.src.paint.texttest: appendFrameCommands paints the ...+28 morepaint.TextAtlasCacheStorageactivatepaint.TextAtlasCacheStoragedeinitpaint.TextAtlasCacheStorageinitprivate sourcelib.gui.src.paint.textglyphIndexAllocpaint.textpackAtlasImageAllocprivate sourcelib.gui.src.paint.textpixelCountpaint.TextAtlasinitFromBitmapGlyphs
Static calls · unresolved targets: 1 · external targets: 5.
Called byCallstest sourcelib.gui.src.paint.texttest: Atlas shapes fixture bytes and ...test sourcelib.gui.src.paint.texttest: atlas metrics derive from face ...test sourcelib.gui.src.paint.texttest: composer prompt glyph renders e...test sourcelib.gui.src.paint.texttest: fallback face segments preserve...test sourcelib.gui.src.paint.texttest: missing terminal glyphs synthes...test sourcelib.gui.src.paint.texttest: outline atlas scratch admits it...private sourcelib.gui.src.paint.text.AtlasinitOutlineFromOwnedBytespaint.TextAtlasinitFromOwnedBytes
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallspaint.TextAtlascaretLineprivate sourcelib.gui.src.paint.text.AtlasshapeUncachedprivate sourcelib.gui.src.paint.text.AtlasCacheStoragelookupShapeprivate sourcelib.gui.src.paint.text.AtlasCacheStoragestoreShapepaint.TextAtlasshape
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.gui.src.paint.textexpectAtlasCacheCapacityErrorstest sourcelib.gui.src.paint.texttest: Atlas cache capacity matches an...test sourcelib.gui.src.paint.texttest: Atlas cache storage acquires on...private sourcelib.gui.src.paint.textcacheAddedprivate sourcelib.gui.src.paint.textcacheIndexSlotsprivate sourcelib.gui.src.paint.textcacheLimitsValidprivate sourcelib.gui.src.paint.textcacheMultipliedprivate sourcelib.gui.src.paint.textcachePlacedprivate sourcelib.gui.src.paint.textcachePlacedBytespaint.TextAtlasCacheCapacityderive
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallspaint.TextAtlasinitFromBitmapGlyphsprivate sourcelib.gui.src.paint.text.AtlasinitOutlineFromOwnedBytesprivate sourcelib.gui.src.paint.textexpectAtlasCacheDifferentialprivate sourcelib.gui.src.paint.textexpectDisabledAtlasCachesprivate sourcelib.gui.src.paint.textexpectMeasureCacheBoundaries+7 moreprivate sourcelib.gui.src.paint.text.AtlasCacheStorageassertStoragepaint.TextAtlasCacheStorageactivate
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.gui.src.paint.text.AtlasCacheStorageprepareShapeprivate sourcelib.gui.src.paint.textexpectDisabledAtlasCachesprivate sourcelib.gui.src.paint.text.AtlasCacheStorageassertStoragepaint.TextAtlasCacheStorageadmitShapePayload
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallspaint.TextAtlasdeinitpaint.TextAtlasinitFromBitmapGlyphsprivate sourcelib.gui.src.paint.text.AtlasinitOutlineFromOwnedBytesprivate sourcelib.gui.src.paint.textcheckAtlasCacheInitFailuresprivate sourcelib.gui.src.paint.textexpectAtlasCacheDifferential+8 moreprivate sourcelib.gui.src.paint.text.AtlasCacheStorageassertStoragepaint.TextAtlasCacheStoragedeinit
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallspaint.TextAtlasinitFromBitmapGlyphsprivate sourcelib.gui.src.paint.text.AtlasinitOutlineFromOwnedBytesprivate sourcelib.gui.src.paint.textcheckAtlasCacheInitFailuresprivate sourcelib.gui.src.paint.textexpectAtlasCacheDifferentialprivate sourcelib.gui.src.paint.textexpectDisabledAtlasCaches+8 moreprivate sourcelib.gui.src.paint.textcacheTypedSlicepaint.TextAtlasCacheStorageinit
Static calls · unresolved targets: 1 · external targets: 1.
Called byCallspaint.TextAtlascacheStatusprivate sourcelib.gui.src.paint.textexpectAtlasCacheDifferentialprivate sourcelib.gui.src.paint.textexpectDisabledAtlasCachesprivate sourcelib.gui.src.paint.textexpectMeasureCacheBoundariesprivate sourcelib.gui.src.paint.textexpectShapeCacheBoundariestest sourcelib.gui.src.paint.texttest: Atlas cache storage acquires on...private sourcelib.gui.src.paint.text.AtlasCacheStorageassertStorageprivate sourcelib.gui.src.paint.textcacheEpochStatuspaint.TextAtlasCacheStoragestatus
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest sourcelib.gui.src.paint.texttest: Atlas shapes fixture bytes and ...test sourcelib.gui.src.paint.texttest: atlas metrics derive from face ...test sourcelib.gui.src.paint.texttest: composer prompt glyph renders e...test sourcelib.gui.src.paint.texttest: fallback face segments preserve...test sourcelib.gui.src.paint.texttest: missing terminal glyphs synthes...test sourcelib.gui.src.paint.texttest: outline atlas scratch admits it...paint.text.AtlasScratchdeinit
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callstest sourcelib.gui.src.paint.texttest: Atlas shapes fixture bytes and ...test sourcelib.gui.src.paint.texttest: atlas metrics derive from face ...test sourcelib.gui.src.paint.texttest: composer prompt glyph renders e...test sourcelib.gui.src.paint.texttest: fallback face segments preserve...test sourcelib.gui.src.paint.texttest: missing terminal glyphs synthes...test sourcelib.gui.src.paint.texttest: outline atlas scratch admits it...paint.text.AtlasScratchinit
Static calls · unresolved targets: 1 · external targets: 1.
Called byCallsNo direct callstest sourcelib.gui.src.paint.texttest: outline atlas scratch admits it...paint.text.AtlasScratchstatus
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallspaint.text.AtlasSetforTextprivate sourcelib.gui.src.paint.text.AtlasSetsizeCostpaint.text.AtlasSetforStyle
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerspaint.text.AtlasSetforStylepaint.text.AtlasSetforText
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callspaint.TextAtlasdeinitpaint.text.OwnedAtlasImagedeinit
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsprivate sourcelib.gui.src.paint.textappendComposerPromptCommandstest sourcelib.gui.src.paint.texttest: Atlas shapes fixture bytes and ...test sourcelib.gui.src.paint.texttest: appendFrameCommands draws curso...test sourcelib.gui.src.paint.texttest: appendFrameCommands draws text ...test sourcelib.gui.src.paint.texttest: appendFrameCommands keeps glyph...+16 moreprivate sourcelib.gui.src.paint.textappendWidgetCommandspaint.textappendFrameCommands
Static calls · unresolved targets: 1 · external targets: 1.
Called byCallsNo direct callersprivate sourcelib.gui.src.paint.textappendWidgetCommandsprivate sourcelib.gui.src.paint.textintersectsprivate sourcelib.gui.src.paint.textregionRectprivate sourcelib.gui.src.paint.textscaleRectpaint.textappendFrameRegionCommands
Static calls · unresolved targets: 1 · external targets: 1.
Called byCallstest sourcelib.gui.src.paint.texttest: bitmap atlas rasterizes cells a...test sourcelib.gui.src.paint.texttest: bitmap atlas skips glyphs missi...test sourcelib.gui.src.paint.texttest: drawGlyphRun consumes filigree ...test sourcelib.gui.src.paint.texttest: drawGlyphRun emits atlas-backed...private sourcelib.gui.src.paint.textaddClampedI32private sourcelib.gui.src.paint.textfindAtlasGlyphprivate sourcelib.gui.src.paint.textround26Dot6paint.textdrawGlyphRun
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callsprivate sourcelib.gui.src.paint.textappendComposerPromptCommandstest sourcelib.gui.src.paint.texttest: fallback face segments preserve...test sourcelib.gui.src.paint.texttest: mixed metric runs share a basel...test sourcelib.gui.src.paint.texttest: resolved equal metric slots pre...test sourcelib.gui.src.paint.texttest: warmed mixed metric measure pla...paint.textframeResolvers
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.gui.src.paint.texttest: Atlas cache bypasses oversized ...test sourcelib.gui.src.paint.texttest: bitmap atlas measures and paint...test sourcelib.gui.src.paint.texttest: bitmap atlas measures scaled mu...test sourcelib.gui.src.paint.texttest: measure and paint reject malfor...test sourcelib.gui.src.paint.texttest: resolved equal metric slots pre...+3 moreprivate sourcelib.gui.src.paint.texthasMixedTextMetricsprivate sourcelib.gui.src.paint.textmeasureCachedpaint.textmeasure
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callerspaint.textmeasureSetpaint.textmeasureFrameText
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.gui.src.paint.text.TextLayoutinitpaint.textmeasureFrameTexttest sourcelib.gui.src.paint.texttest: mixed metric measurement keys d...test sourcelib.gui.src.paint.texttest: mixed metric runs share a basel...test sourcelib.gui.src.paint.texttest: warmed mixed metric measure pla...private sourcelib.gui.src.paint.texthasMixedTextMetricsprivate sourcelib.gui.src.paint.textmeasureCachedpaint.textmeasureSet
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallspaint.TextAtlasinitFromBitmapGlyphsprivate sourcelib.gui.src.paint.text.AtlasinitOutlineFromOwnedBytestest sourcelib.gui.src.paint.texttest: drawGlyphRun consumes filigree ...test sourcelib.gui.src.paint.texttest: packAtlasImageAlloc converts fi...private sourcelib.gui.src.paint.textpackRgbaprivate sourcelib.gui.src.paint.textpixelCountpaint.textpackAtlasImageAlloc
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallstest sourcelib.gui.src.paint.texttest: mixed metric runs share a basel...private sourcelib.gui.src.paint.texttextCaretPlanpaint.texttextAdvanceForByteOffset
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallstest sourcelib.gui.src.paint.texttest: multiline query geometry matche...test sourcelib.gui.src.paint.texttest: multiline text geometry disting...test sourcelib.gui.src.paint.texttest: multiline text geometry follows...test sourcelib.gui.src.paint.texttest: warmed multiline text geometry ...private sourcelib.gui.src.paint.text.TextLayoutinitprivate sourcelib.gui.src.paint.text.TextLayoutiteratorpaint.texttextCaretGeometry
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallstest sourcelib.gui.src.paint.texttest: mixed metric runs share a basel...private sourcelib.gui.src.paint.texttextCaretPlanpaint.texttextHitTestAdvance
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallstest sourcelib.gui.src.paint.texttest: multiline text geometry disting...test sourcelib.gui.src.paint.texttest: warmed multiline text geometry ...test sourcelib.gui.src.paint.texttest: widget text hit query honors tr...private sourcelib.gui.src.paint.texttextHitTestWidgetLocalPointprivate sourcelib.gui.src.paint.text.TextLayoutinitprivate sourcelib.gui.src.paint.text.TextLayoutiteratorpaint.texttextHitTestPoint
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallstest sourcelib.gui.src.paint.texttest: widget text hit query honors tr...private sourcelib.gui.src.paint.texttextHitTestWidgetLocalPointpaint.texttextHitTestWidgetPoint
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallstest sourcelib.gui.src.paint.texttest: widget text hit query honors tr...private sourcelib.gui.src.paint.texttextHitTestWidgetLocalPointpaint.texttextHitTestWidgetPointClamped
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/gui/src/paint/root.zig:13

zig
pub const text = @import("text.zig");

Source: lib/gui/src/paint/text.zig

zig
const std = @import("std");const alloc_phase = @import("alloc_phase");const filigree = @import("filigree");const command = @import("command.zig");const gui = @import("../root.zig");const cpu = @import("cpu/root.zig");const fallback_mod = @import("fallback.zig");const synth = @import("synth.zig");const Allocator = std.mem.Allocator;const Color = gui.model.UiColor;const Image = command.Image;const Region = cpu.Region;const Size = gui.layout.Size;const UiFrame = gui.model.UiFrame;const UiNode = gui.model.UiNode;const UiText = gui.model.UiText;const UiTextRun = gui.model.UiTextRun;const UiTextStyle = gui.model.UiTextStyle;const UiTextSelection = gui.model.UiTextSelection;const WidgetFrame = gui.model.WidgetFrame;const Rect = gui.layout.Rect;pub const OwnedAtlasImage = struct {    image: Image,    pixels: []u32,    pub fn deinit(self: *OwnedAtlasImage, allocator: Allocator) void {        allocator.free(self.pixels);        self.* = undefined;    }};pub const BitmapGlyph = struct {    codepoint: u21,    rows: []const u8,};pub const BitmapMetrics = struct {    width: u16,    height: u16,    stride: u16,};pub const AtlasScratch = struct {    capacity: Capacity,    bytes: []align(storage_alignment) u8,    fixed: std.heap.FixedBufferAllocator,    active: bool = false,    epoch_peak_bytes: usize = 0,    last_epoch_peak_bytes: usize = 0,    high_water_bytes: usize = 0,    epochs: usize = 0,    exhaustions: usize = 0,    pub const storage_alignment: usize = 64;    pub const Limits = struct {        bytes: usize,    };    pub const Capacity = struct {        bytes: usize,        total_bytes: usize,        pub fn derive(limits: Limits) Capacity {            return .{                .bytes = limits.bytes,                .total_bytes = limits.bytes,            };        }    };    pub const Status = struct {        capacity: Capacity,        last_epoch_peak_bytes: usize,        high_water_bytes: usize,        epochs: usize,        exhaustions: usize,    };    pub fn init(allocator: Allocator, limits: Limits) Allocator.Error!AtlasScratch {        const capacity = Capacity.derive(limits);        const bytes = try allocator.alignedAlloc(u8, .fromByteUnits(storage_alignment), capacity.bytes);        return .{            .capacity = capacity,            .bytes = bytes,            .fixed = std.heap.FixedBufferAllocator.init(bytes),        };    }    pub fn deinit(self: *AtlasScratch, allocator: Allocator) void {        std.debug.assert(!self.active);        allocator.free(self.bytes);        self.* = undefined;    }    pub fn begin(self: *AtlasScratch) Allocator {        std.debug.assert(!self.active);        self.fixed = std.heap.FixedBufferAllocator.init(self.bytes);        self.epoch_peak_bytes = 0;        self.active = true;        return .{            .ptr = self,            .vtable = &.{                .alloc = alloc,                .resize = resize,                .remap = remap,                .free = free,            },        };    }    pub fn end(self: *AtlasScratch) void {        std.debug.assert(self.active);        self.last_epoch_peak_bytes = self.epoch_peak_bytes;        self.high_water_bytes = @max(self.high_water_bytes, self.epoch_peak_bytes);        self.fixed = std.heap.FixedBufferAllocator.init(self.bytes);        self.active = false;        self.epochs +|= 1;    }    pub fn status(self: *const AtlasScratch) Status {        std.debug.assert(!self.active);        return .{            .capacity = self.capacity,            .last_epoch_peak_bytes = self.last_epoch_peak_bytes,            .high_water_bytes = self.high_water_bytes,            .epochs = self.epochs,            .exhaustions = self.exhaustions,        };    }    fn observe(self: *AtlasScratch) void {        self.epoch_peak_bytes = @max(self.epoch_peak_bytes, self.fixed.end_index);    }    fn alloc(context: *anyopaque, len: usize, alignment: std.mem.Alignment, return_address: usize) ?[*]u8 {        const self: *AtlasScratch = @ptrCast(@alignCast(context));        const result = std.heap.FixedBufferAllocator.alloc(&self.fixed, len, alignment, return_address) orelse {            self.exhaustions +|= 1;            return null;        };        self.observe();        return result;    }    fn resize(context: *anyopaque, memory: []u8, alignment: std.mem.Alignment, new_len: usize, return_address: usize) bool {        const self: *AtlasScratch = @ptrCast(@alignCast(context));        const resized = std.heap.FixedBufferAllocator.resize(&self.fixed, memory, alignment, new_len, return_address);        if (resized) self.observe();        return resized;    }    fn remap(context: *anyopaque, memory: []u8, alignment: std.mem.Alignment, new_len: usize, return_address: usize) ?[*]u8 {        const self: *AtlasScratch = @ptrCast(@alignCast(context));        const result = std.heap.FixedBufferAllocator.remap(&self.fixed, memory, alignment, new_len, return_address);        if (result != null) self.observe();        return result;    }    fn free(context: *anyopaque, memory: []u8, alignment: std.mem.Alignment, return_address: usize) void {        const self: *AtlasScratch = @ptrCast(@alignCast(context));        std.heap.FixedBufferAllocator.free(&self.fixed, memory, alignment, return_address);    }};pub const Atlas = struct {    allocator: Allocator,    pixel_size: i32,    atlas: filigree.GlyphAtlas,    image: OwnedAtlasImage,    glyph_index: std.AutoHashMapUnmanaged(u32, usize) = .empty,    cache: AtlasCacheStorage,    line_break_workspace: filigree.LineBreakWorkspace = .{},    composite_workspace: CompositeWorkspace = .{},    backend: Backend,    pub const Backend = union(enum) {        outline: Outline,        bitmap: Bitmap,    };    pub const Outline = struct {        font_bytes: []u8,        font: filigree.Font,        context: filigree.Context,        output: filigree.Output,    };    pub const Bitmap = struct {        advance: i32,        height: i32,        map: std.AutoHashMapUnmanaged(u21, u32) = .empty,        shaped: std.ArrayListUnmanaged(filigree.ShapedGlyph) = .empty,        clusters: std.ArrayListUnmanaged(filigree.Cluster) = .empty,    };    pub const CaretLine = struct {        content: []const u8,        run: filigree.GlyphRun,        pub inline fn advanceForByteOffset(self: CaretLine, byte_offset: usize) f32 {            return @call(.always_inline, filigree.caret.advanceForByteOffset, .{                self.run,                byte_offset,                self.content.len,            });        }        pub fn hitTestAdvance(self: CaretLine, advance: f32) filigree.caret.LineHit {            return filigree.caret.hitTestAdvance(self.run, advance, self.content);        }    };    pub fn initFromOwnedBytes(        allocator: Allocator,        scratch: *AtlasScratch,        bytes: []u8,        pixel_size: i32,        cache_limits: AtlasCacheStorage.Limits,        output_limits: filigree.Output.Limits,    ) !Atlas {        return initOutlineFromOwnedBytes(allocator, scratch, bytes, pixel_size, cache_limits, output_limits);    }    fn initOutlineFromOwnedBytes(        allocator: Allocator,        scratch: *AtlasScratch,        bytes: []u8,        pixel_size: i32,        cache_limits: AtlasCacheStorage.Limits,        output_limits: filigree.Output.Limits,    ) !Atlas {        errdefer allocator.free(bytes);        const scratch_allocator = scratch.begin();        defer scratch.end();        var font = filigree.Font.initFromBytes(bytes.ptr, bytes.len) orelse return error.InvalidFont;        errdefer font.deinit();        font.setScale(@floatFromInt(pixel_size), 72);        const glyph_count: u32 = font.face.num_glyphs;        const first_glyph_id: u32 = 1;        if (glyph_count <= first_glyph_id) return error.FontHasNoPrintableAscii;        const raster_glyph_count = glyph_count - first_glyph_id;        var glyph_ids: std.ArrayListUnmanaged(i32) = .empty;        defer glyph_ids.deinit(scratch_allocator);        var codepoints: std.ArrayListUnmanaged(i32) = .empty;        defer codepoints.deinit(scratch_allocator);        try glyph_ids.ensureTotalCapacity(scratch_allocator, raster_glyph_count);        try codepoints.ensureTotalCapacity(scratch_allocator, raster_glyph_count);        var glyph_id: u32 = first_glyph_id;        while (glyph_id < glyph_count) : (glyph_id += 1) {            glyph_ids.appendAssumeCapacity(std.math.cast(i32, glyph_id) orelse return error.GlyphIdTooLarge);            codepoints.appendAssumeCapacity(0);        }        var atlas = try filigree.glyphAtlasAlloc(allocator, scratch_allocator, bytes, pixel_size, glyph_ids.items, codepoints.items, 1);        errdefer atlas.deinit(allocator);        var image = try packAtlasImageAlloc(allocator, atlas);        errdefer image.deinit(allocator);        var glyph_index = try glyphIndexAlloc(allocator, atlas);        errdefer glyph_index.deinit(allocator);        var cache = try AtlasCacheStorage.init(allocator, cache_limits);        errdefer cache.deinit(allocator);        cache.activate();        return .{            .allocator = allocator,            .pixel_size = pixel_size,            .atlas = atlas,            .image = image,            .glyph_index = glyph_index,            .cache = cache,            .backend = .{ .outline = .{                .font_bytes = bytes,                .font = font,                .context = filigree.Context.init(allocator, .{}),                .output = try filigree.Output.init(allocator, output_limits),            } },        };    }    pub fn initFromBitmapGlyphs(        allocator: Allocator,        glyphs: []const BitmapGlyph,        cell: BitmapMetrics,        pixel_size: i32,        cache_limits: AtlasCacheStorage.Limits,    ) !Atlas {        if (glyphs.len == 0 or cell.width == 0 or cell.height == 0) return error.FontHasNoPrintableAscii;        const cell_width: usize = cell.width;        const cell_height: usize = cell.height;        const padded = cell_width + 1;        const atlas_width = std.math.mul(usize, padded, glyphs.len) catch return error.InvalidAtlas;        const pixel_total = try pixelCount(            std.math.cast(u32, atlas_width) orelse return error.InvalidAtlas,            std.math.cast(u32, cell_height) orelse return error.InvalidAtlas,        );        const rgba = try allocator.alloc(u8, pixel_total * 4);        errdefer allocator.free(rgba);        @memset(rgba, 0);        const atlas_glyphs = try allocator.alloc(filigree.GlyphAtlasGlyph, glyphs.len);        errdefer allocator.free(atlas_glyphs);        const recs = try allocator.alloc(filigree.GlyphAtlasRectangle, glyphs.len);        errdefer allocator.free(recs);        var map: std.AutoHashMapUnmanaged(u21, u32) = .empty;        errdefer map.deinit(allocator);        for (glyphs, 0..) |glyph, index| {            if (glyph.rows.len < @as(usize, cell.stride) * cell_height) return error.InvalidAtlas;            const origin_x = index * padded;            for (0..cell_height) |y| {                const row = glyph.rows[y * cell.stride ..][0..cell.stride];                for (0..cell_width) |x| {                    const bit = (row[x / 8] >> @intCast(7 - (x % 8))) & 1;                    if (bit == 0) continue;                    const base = ((y * atlas_width) + origin_x + x) * 4;                    rgba[base] = 255;                    rgba[base + 1] = 255;                    rgba[base + 2] = 255;                    rgba[base + 3] = 255;                }            }            atlas_glyphs[index] = .{                .codepoint = std.math.cast(i32, glyph.codepoint) orelse return error.CodepointTooLarge,                .glyph_id = glyph.codepoint,                .width = @intCast(cell_width),                .height = @intCast(cell_height),                .offset_x = 0,                .offset_y = 0,                .advance_x = @intCast(cell_width),            };            recs[index] = .{                .x = @floatFromInt(origin_x),                .y = 0,                .width = @floatFromInt(cell_width),                .height = @floatFromInt(cell_height),            };            try map.put(allocator, glyph.codepoint, glyph.codepoint);        }        const atlas = filigree.GlyphAtlas{            .rgba = rgba,            .width = @intCast(atlas_width),            .height = @intCast(cell_height),            .glyphs = atlas_glyphs,            .recs = recs,            .base_size = @intCast(cell_height),            .glyph_padding = 1,        };        var image = try packAtlasImageAlloc(allocator, atlas);        errdefer image.deinit(allocator);        var glyph_index = try glyphIndexAlloc(allocator, atlas);        errdefer glyph_index.deinit(allocator);        var cache = try AtlasCacheStorage.init(allocator, cache_limits);        errdefer cache.deinit(allocator);        cache.activate();        return .{            .allocator = allocator,            .pixel_size = pixel_size,            .atlas = atlas,            .image = image,            .glyph_index = glyph_index,            .cache = cache,            .backend = .{ .bitmap = .{                .advance = @as(i32, @intCast(cell_width)) * 64,                .height = @intCast(cell_height),                .map = map,            } },        };    }    pub fn deinit(self: *Atlas) void {        self.cache.deinit(self.allocator);        self.line_break_workspace.deinit(self.allocator);        self.composite_workspace.deinit(self.allocator);        self.glyph_index.deinit(self.allocator);        self.image.deinit(self.allocator);        self.atlas.deinit(self.allocator);        switch (self.backend) {            .outline => |*outline| {                outline.output.deinit(self.allocator);                outline.context.deinit();                outline.font.deinit();                self.allocator.free(outline.font_bytes);            },            .bitmap => |*bitmap| {                bitmap.map.deinit(self.allocator);                bitmap.shaped.deinit(self.allocator);                bitmap.clusters.deinit(self.allocator);            },        }        self.* = undefined;    }    pub fn cacheStatus(self: *const Atlas) AtlasCacheStorage.Status {        return self.cache.status();    }    pub fn shape(self: *Atlas, content: []const u8) !filigree.GlyphRun {        if (self.cache.lookupShape(content)) |cached| return cached;        const fresh = try self.shapeUncached(content);        return self.cache.storeShape(content, fresh) catch fresh;    }    pub fn caretLine(self: *Atlas, content: []const u8) !CaretLine {        return .{ .content = content, .run = try self.shape(content) };    }    pub fn advanceForByteOffset(self: *Atlas, content: []const u8, byte_offset: usize) !f32 {        const line = try self.caretLine(content);        return line.advanceForByteOffset(byte_offset);    }    pub fn hitTestAdvance(self: *Atlas, content: []const u8, advance: f32) !filigree.caret.LineHit {        const line = try self.caretLine(content);        return line.hitTestAdvance(advance);    }    fn shapeUncached(self: *Atlas, content: []const u8) !filigree.GlyphRun {        switch (self.backend) {            .outline => |*outline| {                try outline.context.shapeRun(.{                    .font = &outline.font,                    .text = .{ .utf8 = content },                }, &outline.output);                return outline.output.run();            },            .bitmap => |*bitmap| return shapeBitmap(self.allocator, bitmap, content),        }    }    fn outlineFont(self: *Atlas) ?*const filigree.Font {        return switch (self.backend) {            .outline => |*outline| &outline.font,            .bitmap => null,        };    }    fn coversUtf8(self: *Atlas, content: []const u8) !bool {        const selected = self.outlineFont() orelse return true;        var index: usize = 0;        while (index < content.len) {            const sequence_len = std.unicode.utf8ByteSequenceLength(content[index]) catch return error.InvalidUtf8;            if (index + sequence_len > content.len) return error.InvalidUtf8;            const codepoint = std.unicode.utf8Decode(content[index .. index + sequence_len]) catch return error.InvalidUtf8;            if (selected.face.glyphId(codepoint) == 0) return false;            index += sequence_len;        }        return true;    }    pub fn metrics(self: *const Atlas) Metrics {        switch (self.backend) {            .outline => |*outline| {                const face = outline.font.face;                const upem: f32 = @floatFromInt(if (face.units_per_em == 0) 1000 else face.units_per_em);                const to_pixels = @as(f32, @floatFromInt(self.pixel_size)) / upem;                return .{                    .ascent = @as(f32, @floatFromInt(face.ascender)) * to_pixels,                    .descent = @as(f32, @floatFromInt(-@as(i32, face.descender))) * to_pixels,                    .line_gap = @as(f32, @floatFromInt(face.line_gap)) * to_pixels,                };            },            .bitmap => |*bitmap| return .{                .ascent = @floatFromInt(bitmap.height),                .descent = 0,                .line_gap = 0,            },        }    }};pub const Metrics = struct {    ascent: f32,    descent: f32,    line_gap: f32,    pub fn height(self: Metrics) f32 {        return self.ascent + self.descent;    }};const CompositeGlyphSource = struct {    segment_index: u32,};const CompositeMetricSpan = struct {    byte_start: u32,    byte_end: u32,    atlas: *const Atlas,    image_index: u32,    scale_ratio: f32,    point_size: f32,    ascent: f32,    descent: f32,};const CompositeWorkspace = struct {    glyphs: std.ArrayListUnmanaged(filigree.ShapedGlyph) = .empty,    clusters: std.ArrayListUnmanaged(filigree.Cluster) = .empty,    ligature_carets: std.ArrayListUnmanaged(filigree.LigatureCaret) = .empty,    glyph_sources: std.ArrayListUnmanaged(CompositeGlyphSource) = .empty,    spans: std.ArrayListUnmanaged(CompositeMetricSpan) = .empty,    fn clear(self: *CompositeWorkspace) void {        self.glyphs.clearRetainingCapacity();        self.clusters.clearRetainingCapacity();        self.ligature_carets.clearRetainingCapacity();        self.glyph_sources.clearRetainingCapacity();        self.spans.clearRetainingCapacity();    }    fn deinit(self: *CompositeWorkspace, allocator: Allocator) void {        self.spans.deinit(allocator);        self.glyph_sources.deinit(allocator);        self.ligature_carets.deinit(allocator);        self.clusters.deinit(allocator);        self.glyphs.deinit(allocator);        self.* = .{};    }};const MeasureKey = struct {    content: []const u8,    styles: []const UiTextStyle,    runs: []const UiTextRun,    atlas_entries: []const AtlasSet.Entry,    fallback_entries: []const AtlasSet.Entry,    fallback_identity: usize,    font_asset_id: u64,    point_size_bits: u64,    line_height_bits: u64,    wrap_width_bits: u64,    device_scale_bits: u32,    fn fromText(text: UiText, atlases: ?*const AtlasSet) MeasureKey {        const include_metric_plan = atlases != null;        return .{            .content = text.content,            .styles = if (include_metric_plan) text.styles else &.{},            .runs = if (include_metric_plan) text.runs else &.{},            .atlas_entries = if (atlases) |set| set.entries else &.{},            .fallback_entries = if (atlases) |set| set.fallback_entries else &.{},            .fallback_identity = if (atlases) |set| if (set.fallback) |value| @intFromPtr(value) else 0 else 0,            .font_asset_id = if (include_metric_plan) text.font_asset_id else 0,            .point_size_bits = floatBits(text.point_size),            .line_height_bits = floatBits(text.line_height),            .wrap_width_bits = floatBits(text.wrap_width),            .device_scale_bits = if (atlases) |set| @bitCast(set.device_scale) else 0,        };    }};const MeasureContext = struct {    pub fn hash(_: MeasureContext, key: MeasureKey) u64 {        var hasher = std.hash.Wyhash.init(0);        hasher.update(key.content);        std.hash.autoHash(&hasher, key.font_asset_id);        hasher.update(std.mem.asBytes(&key.point_size_bits));        hasher.update(std.mem.asBytes(&key.line_height_bits));        hasher.update(std.mem.asBytes(&key.wrap_width_bits));        hasher.update(std.mem.asBytes(&key.device_scale_bits));        for (key.styles) |style| {            std.hash.autoHash(&hasher, style.font_asset_id);            std.hash.autoHash(&hasher, floatBits(style.point_size));        }        for (key.runs) |run| hashTextRun(&hasher, run);        for (key.atlas_entries) |entry| {            std.hash.autoHash(&hasher, entry.face);            std.hash.autoHash(&hasher, entry.image_index);            std.hash.autoHash(&hasher, @intFromPtr(entry.atlas));        }        for (key.fallback_entries) |entry| {            std.hash.autoHash(&hasher, entry.face);            std.hash.autoHash(&hasher, entry.image_index);            std.hash.autoHash(&hasher, @intFromPtr(entry.atlas));        }        std.hash.autoHash(&hasher, key.fallback_identity);        return hasher.final();    }    pub fn eql(_: MeasureContext, left: MeasureKey, right: MeasureKey) bool {        if (left.font_asset_id != right.font_asset_id or            left.point_size_bits != right.point_size_bits or            left.line_height_bits != right.line_height_bits or            left.wrap_width_bits != right.wrap_width_bits or            left.device_scale_bits != right.device_scale_bits or            left.fallback_identity != right.fallback_identity)        {            return false;        }        if (!std.mem.eql(u8, left.content, right.content)) return false;        if (left.styles.len != right.styles.len or            left.runs.len != right.runs.len or            left.atlas_entries.len != right.atlas_entries.len or            left.fallback_entries.len != right.fallback_entries.len)        {            return false;        }        for (left.styles, right.styles) |left_style, right_style| {            if (!gui.model.textStylesEqual(left_style, right_style)) return false;        }        for (left.runs, right.runs) |left_run, right_run| {            if (!textRunsEqual(left_run, right_run)) return false;        }        for (left.atlas_entries, right.atlas_entries) |left_entry, right_entry| {            if (left_entry.face != right_entry.face or                left_entry.image_index != right_entry.image_index or                left_entry.atlas != right_entry.atlas)            {                return false;            }        }        for (left.fallback_entries, right.fallback_entries) |left_entry, right_entry| {            if (left_entry.face != right_entry.face or                left_entry.image_index != right_entry.image_index or                left_entry.atlas != right_entry.atlas)            {                return false;            }        }        return true;    }};fn hashTextRun(hasher: anytype, run: UiTextRun) void {    std.hash.autoHash(hasher, run.byte_start);    std.hash.autoHash(hasher, run.byte_end);    std.hash.autoHash(hasher, run.style_slot);    hashOptionalTextColor(hasher, run.foreground);    hashOptionalTextColor(hasher, run.background);    std.hash.autoHash(hasher, run.underline);    std.hash.autoHash(hasher, run.strikethrough);}fn hashOptionalTextColor(hasher: anytype, color: ?Color) void {    std.hash.autoHash(hasher, color != null);    if (color) |value| {        std.hash.autoHash(hasher, value.r);        std.hash.autoHash(hasher, value.g);        std.hash.autoHash(hasher, value.b);        std.hash.autoHash(hasher, value.a);    }}fn textRunsEqual(left: UiTextRun, right: UiTextRun) bool {    return left.byte_start == right.byte_start and        left.byte_end == right.byte_end and        left.style_slot == right.style_slot and        std.meta.eql(left.foreground, right.foreground) and        std.meta.eql(left.background, right.background) and        left.underline == right.underline and        left.strikethrough == right.strikethrough;}const ShapedRun = struct {    glyphs: []const filigree.ShapedGlyph,    clusters: []const filigree.Cluster,    ligature_carets: []const filigree.LigatureCaret,    total_x_advance: i32,    total_y_advance: i32,    direction: filigree.Direction,    writing_mode: filigree.WritingMode,    output_order: filigree.OutputOrder,    fn run(self: ShapedRun) filigree.GlyphRun {        return .{            .glyphs = self.glyphs,            .clusters = self.clusters,            .ligature_carets = self.ligature_carets,            .total_x_advance = self.total_x_advance,            .total_y_advance = self.total_y_advance,            .direction = self.direction,            .writing_mode = self.writing_mode,            .output_order = self.output_order,        };    }};const MeasureCacheEntry = struct {    hash: u64,    key: MeasureKey,    value: Size,};const ShapeCacheEntry = struct {    hash: u64,    content: []const u8,    shaped: ShapedRun,};const CacheEpochUsage = struct {    entries: usize = 0,    payload_bytes: usize = 0,    high_water_entries: usize = 0,    high_water_payload_bytes: usize = 0,    high_water_physical_payload_bytes: usize = 0,    rollovers: u64 = 0,    disabled_bypasses: u64 = 0,    oversize_bypasses: u64 = 0,    fn inserted(self: *CacheEpochUsage, raw_bytes: usize, physical_bytes: usize) void {        self.entries += 1;        self.payload_bytes += raw_bytes;        self.high_water_entries = @max(self.high_water_entries, self.entries);        self.high_water_payload_bytes = @max(self.high_water_payload_bytes, self.payload_bytes);        self.high_water_physical_payload_bytes = @max(            self.high_water_physical_payload_bytes,            physical_bytes,        );    }    fn replaced(self: *CacheEpochUsage) void {        self.entries = 0;        self.payload_bytes = 0;        self.rollovers +|= 1;    }};const CachePayload = struct {    bytes: []u8,    cursor: usize = 0,    fn reset(self: *CachePayload) void {        self.cursor = 0;    }    fn dupe(self: *CachePayload, comptime T: type, source: []const T) []T {        const start = cacheAligned(self.cursor, @alignOf(T)) catch unreachable;        const byte_count = cacheMultiplied(source.len, @sizeOf(T)) catch unreachable;        const end = cacheAdded(start, byte_count) catch unreachable;        std.debug.assert(end <= self.bytes.len);        const region: []align(@alignOf(T)) u8 = @alignCast(self.bytes[start..end]);        const owned = std.mem.bytesAsSlice(T, region);        @memcpy(owned, source);        self.cursor = end;        return owned;    }};pub const AtlasCacheStorage = struct {    phase: alloc_phase.capacity.Phase,    capacity: Capacity,    bytes: []align(storage_alignment) u8,    measure_slots: []u32,    measure_entries: []MeasureCacheEntry,    measure_payload: CachePayload,    measure_usage: CacheEpochUsage = .{},    shape_slots: []u32,    shape_entries: []ShapeCacheEntry,    shape_payload: CachePayload,    shape_usage: CacheEpochUsage = .{},    pub const storage_alignment: usize = @max(        @alignOf(MeasureCacheEntry),        @max(            @alignOf(ShapeCacheEntry),            @max(measure_payload_alignment, shape_payload_alignment),        ),    );    pub const Limits = struct {        measure_entries: usize,        measure_payload_bytes: usize,        shape_entries: usize,        shape_payload_bytes: usize,    };    pub const DeriveError = error{        InvalidMeasureLimits,        InvalidShapeLimits,        EntryLimitTooLarge,        CapacityOverflow,    };    pub const Exhaustion = error{        CacheDisabled,        EntryTooLarge,    };    pub const Capacity = struct {        limits: Limits,        measure_index_slots: usize,        measure_index_offset: usize,        measure_entries_offset: usize,        measure_payload_offset: usize,        measure_payload_storage_bytes: usize,        shape_index_slots: usize,        shape_index_offset: usize,        shape_entries_offset: usize,        shape_payload_offset: usize,        shape_payload_storage_bytes: usize,        storage_bytes: usize,        pub fn derive(limits: Limits) DeriveError!Capacity {            try cacheLimitsValid(limits);            const measure_index_slots = try cacheIndexSlots(limits.measure_entries);            const shape_index_slots = try cacheIndexSlots(limits.shape_entries);            const measure_padding = try cacheMultiplied(                limits.measure_entries,                measure_padding_per_entry,            );            const shape_padding = try cacheMultiplied(                limits.shape_entries,                shape_padding_per_entry,            );            const measure_payload_bytes = try cacheAdded(                limits.measure_payload_bytes,                measure_padding,            );            const shape_payload_bytes = try cacheAdded(                limits.shape_payload_bytes,                shape_padding,            );            const measure_index = try cachePlaced(u32, 0, measure_index_slots);            const measure_entries = try cachePlaced(                MeasureCacheEntry,                measure_index.end,                limits.measure_entries,            );            const measure_payload = try cachePlacedBytes(                measure_entries.end,                measure_payload_alignment,                measure_payload_bytes,            );            const shape_index = try cachePlaced(u32, measure_payload.end, shape_index_slots);            const shape_entries = try cachePlaced(                ShapeCacheEntry,                shape_index.end,                limits.shape_entries,            );            const shape_payload = try cachePlacedBytes(                shape_entries.end,                shape_payload_alignment,                shape_payload_bytes,            );            return .{                .limits = limits,                .measure_index_slots = measure_index_slots,                .measure_index_offset = measure_index.start,                .measure_entries_offset = measure_entries.start,                .measure_payload_offset = measure_payload.start,                .measure_payload_storage_bytes = measure_payload.bytes,                .shape_index_slots = shape_index_slots,                .shape_index_offset = shape_index.start,                .shape_entries_offset = shape_entries.start,                .shape_payload_offset = shape_payload.start,                .shape_payload_storage_bytes = shape_payload.bytes,                .storage_bytes = shape_payload.end,            };        }    };    pub const EpochStatus = struct {        entry_capacity: usize,        payload_capacity_bytes: usize,        physical_payload_capacity_bytes: usize,        entries: usize,        payload_bytes: usize,        physical_payload_bytes: usize,        high_water_entries: usize,        high_water_payload_bytes: usize,        high_water_physical_payload_bytes: usize,        rollovers: u64,        disabled_bypasses: u64,        oversize_bypasses: u64,    };    pub const Status = struct {        phase: alloc_phase.capacity.Phase,        capacity: Capacity,        storage_bytes: usize,        measure: EpochStatus,        shape: EpochStatus,    };    pub const claim: alloc_phase.capacity.Declaration = .{        .source = .{            .id = "gui.text_atlas_cache_storage",            .kind = .phase_static,            .limit_source = .caller,            .storage = .{                .covered = &.{                    .{                        .id = "measure_cache_fixed_index_and_dense_entries",                        .lifetime = .steady,                        .detail = "measure cache fixed index and dense entries",                    },                    .{                        .id = "measure_cache_aligned_payload_bytes",                        .lifetime = .steady,                        .detail = "measure cache aligned payload bytes",                    },                    .{                        .id = "shape_cache_fixed_index_and_dense_entries",                        .lifetime = .steady,                        .detail = "shape cache fixed index and dense entries",                    },                    .{                        .id = "shape_cache_aligned_payload_bytes",                        .lifetime = .steady,                        .detail = "shape cache aligned payload bytes",                    },                },                .excluded = &.{                    "outline shaping context, output, and foreign backend storage",                    "bitmap shaping, line-break, and composite workspaces",                    "font bytes, glyph atlas, image, glyph index, and bitmap map",                    "caller-owned text, returned data, and Renderer storage",                },            },            .capacity = .{                .inputs = &.{                    alloc_phase.capacity.bindInput(Limits, "measure_entries", "measure_entries"),                    alloc_phase.capacity.bindInput(Limits, "shape_entries", "shape_entries"),                    alloc_phase.capacity.bindInput(Limits, "measure_payload_bytes", "measure_payload_bytes"),                    alloc_phase.capacity.bindInput(Limits, "shape_payload_bytes", "shape_payload_bytes"),                },                .type_selectors = &.{                    alloc_phase.capacity.bindType(u32, "u32"),                    alloc_phase.capacity.bindType(MeasureCacheEntry, "measureentry"),                    alloc_phase.capacity.bindType(ShapeCacheEntry, "shapeentry"),                },                .nodes = &.{                    .{ .input = 0 },                    .{ .scale = .{ .node = 0, .coefficient = .{ .literal = 2 } } },                    .{ .next_power_of_two = 1 },                    .{ .input = 1 },                    .{ .scale = .{ .node = 3, .coefficient = .{ .literal = 2 } } },                    .{ .next_power_of_two = 4 },                    .{ .scale = .{ .node = 2, .coefficient = .{ .size_of_concrete_type = 0 } } },                    .{ .alignment = .{ .node = 6, .alignment = .{ .literal = 16 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .size_of_concrete_type = 1 } } },                    .{ .alignment = .{ .node = 8, .alignment = .{ .literal = 16 } } },                    .{ .input = 2 },                    .{ .alignment = .{ .node = 10, .alignment = .{ .literal = 16 } } },                    .{ .scale = .{ .node = 5, .coefficient = .{ .size_of_concrete_type = 0 } } },                    .{ .alignment = .{ .node = 12, .alignment = .{ .literal = 16 } } },                    .{ .scale = .{ .node = 3, .coefficient = .{ .size_of_concrete_type = 2 } } },                    .{ .alignment = .{ .node = 14, .alignment = .{ .literal = 16 } } },                    .{ .input = 3 },                    .{ .alignment = .{ .node = 16, .alignment = .{ .literal = 16 } } },                    .{ .add = .{ .left = 7, .right = 9 } },                    .{ .add = .{ .left = 18, .right = 11 } },                    .{ .add = .{ .left = 19, .right = 13 } },                    .{ .add = .{ .left = 20, .right = 15 } },                    .{ .add = .{ .left = 21, .right = 17 } },                },                .assertions = &.{.{                    .scope = .closure_total,                    .measure = .retained,                    .relation = .exact,                    .expression = 22,                }},            },            .overload = .{                .kind = .replace,                .detail = "aggregate entry or payload exhaustion replaces one epoch; disabled and individually oversized records bypass before mutation",            },            .risks = .{                .transitive = .{                    .status = .excluded,                    .detail = "uncached Atlas shaping and measurement can allocate in backend and workspace owners outside this cache-only claim",                },                .foreign = .{                    .status = .excluded,                    .detail = "cache lookup, copying, and replacement cross no foreign boundary; outline shaping remains excluded",                },            },            .obligations = &.{                .{ .key = "gui_text_atlas_cache_capacity", .role = .capacity_model },                .{ .key = "gui_text_atlas_cache_acquisition", .role = .custom },                .{ .key = "gui_text_atlas_cache_oom", .role = .custom },                .{ .key = "gui_text_atlas_cache_boundaries", .role = .overload },                .{ .key = "gui_text_atlas_cache_sealed_transitive_risk", .role = .transitive_risk },                .{ .key = "gui_text_atlas_cache_sealed_foreign_risk", .role = .foreign_risk },                .{ .key = "gui_text_atlas_cache_collisions", .role = .custom },                .{ .key = "gui_text_atlas_cache_stability", .role = .custom },                .{ .key = "gui_text_atlas_cache_differential", .role = .overload },                .{ .key = "gui_text_atlas_cache_root", .role = .custom },            },        },        .bindings = .{            .owner = @This(),            .seal = .{                .family = alloc_phase.capacity.selector(@This().activate),                .premise = .{                    .class = .checked_semantic_fact,                    .authority = .checker,                },            },            .teardown = .{                .family = alloc_phase.capacity.selector(@This().deinit),                .premise = .{                    .class = .checked_semantic_fact,                    .authority = .checker,                },            },        },    };    pub fn init(allocator: Allocator, limits: Limits) (Allocator.Error || DeriveError)!AtlasCacheStorage {        const capacity = try Capacity.derive(limits);        const bytes = try allocator.alignedAlloc(            u8,            .fromByteUnits(storage_alignment),            capacity.storage_bytes,        );        return .{            .phase = .initialization,            .capacity = capacity,            .bytes = bytes,            .measure_slots = cacheTypedSlice(                u32,                bytes,                capacity.measure_index_offset,                capacity.measure_index_slots,            ),            .measure_entries = cacheTypedSlice(                MeasureCacheEntry,                bytes,                capacity.measure_entries_offset,                limits.measure_entries,            ),            .measure_payload = .{ .bytes = bytes[capacity.measure_payload_offset..][0..capacity.measure_payload_storage_bytes] },            .shape_slots = cacheTypedSlice(                u32,                bytes,                capacity.shape_index_offset,                capacity.shape_index_slots,            ),            .shape_entries = cacheTypedSlice(                ShapeCacheEntry,                bytes,                capacity.shape_entries_offset,                limits.shape_entries,            ),            .shape_payload = .{ .bytes = bytes[capacity.shape_payload_offset..][0..capacity.shape_payload_storage_bytes] },        };    }    pub fn activate(self: *AtlasCacheStorage) void {        self.assertStorage();        std.debug.assert(self.phase == .initialization);        @memset(self.measure_slots, 0);        @memset(self.shape_slots, 0);        self.phase = .steady;        self.assertStorage();    }    pub fn deinit(self: *AtlasCacheStorage, allocator: Allocator) void {        self.assertStorage();        std.debug.assert(self.phase != .teardown);        self.phase = .teardown;        allocator.free(self.bytes);        self.bytes = &.{};        self.measure_slots = &.{};        self.measure_entries = &.{};        self.measure_payload = .{ .bytes = &.{} };        self.shape_slots = &.{};        self.shape_entries = &.{};        self.shape_payload = .{ .bytes = &.{} };    }    pub fn status(self: *const AtlasCacheStorage) Status {        self.assertStorage();        return .{            .phase = self.phase,            .capacity = self.capacity,            .storage_bytes = self.capacity.storage_bytes,            .measure = cacheEpochStatus(                self.capacity.limits.measure_entries,                self.capacity.limits.measure_payload_bytes,                self.capacity.measure_payload_storage_bytes,                self.measure_payload.cursor,                self.measure_usage,            ),            .shape = cacheEpochStatus(                self.capacity.limits.shape_entries,                self.capacity.limits.shape_payload_bytes,                self.capacity.shape_payload_storage_bytes,                self.shape_payload.cursor,                self.shape_usage,            ),        };    }    fn lookupMeasure(self: *const AtlasCacheStorage, key: MeasureKey) ?Size {        self.assertStorage();        std.debug.assert(self.phase == .steady);        if (self.measure_slots.len == 0) return null;        const hash = MeasureContext.hash(.{}, key);        var slot = cacheStartSlot(hash, self.measure_slots.len);        var probes: usize = 0;        while (probes < self.measure_slots.len) : (probes += 1) {            const encoded = self.measure_slots[slot];            if (encoded == 0) return null;            const entry = self.measure_entries[encoded - 1];            if (entry.hash == hash and MeasureContext.eql(.{}, entry.key, key)) {                return entry.value;            }            slot = cacheNextSlot(slot, self.measure_slots.len);        }        unreachable;    }    fn lookupShape(self: *const AtlasCacheStorage, content: []const u8) ?filigree.GlyphRun {        self.assertStorage();        std.debug.assert(self.phase == .steady);        if (self.shape_slots.len == 0) return null;        const hash = std.hash_map.hashString(content);        var slot = cacheStartSlot(hash, self.shape_slots.len);        var probes: usize = 0;        while (probes < self.shape_slots.len) : (probes += 1) {            const encoded = self.shape_slots[slot];            if (encoded == 0) return null;            const entry = self.shape_entries[encoded - 1];            if (entry.hash == hash and std.mem.eql(u8, entry.content, content)) {                return entry.shaped.run();            }            slot = cacheNextSlot(slot, self.shape_slots.len);        }        unreachable;    }    fn storeMeasure(        self: *AtlasCacheStorage,        key: MeasureKey,        value: Size,    ) Exhaustion!Size {        self.assertStorage();        defer self.assertStorage();        std.debug.assert(self.phase == .steady);        std.debug.assert(self.lookupMeasure(key) == null);        const payload_bytes = measurePayloadBytes(key) orelse {            self.measure_usage.oversize_bypasses +|= 1;            return error.EntryTooLarge;        };        try self.prepareMeasure(payload_bytes);        const hash = MeasureContext.hash(.{}, key);        const slot = cacheEmptySlot(self.measure_slots, hash);        const entry_index = self.measure_usage.entries;        var owned_key = key;        owned_key.content = self.measure_payload.dupe(u8, key.content);        owned_key.styles = self.measure_payload.dupe(UiTextStyle, key.styles);        owned_key.runs = self.measure_payload.dupe(UiTextRun, key.runs);        owned_key.atlas_entries = self.measure_payload.dupe(AtlasSet.Entry, key.atlas_entries);        owned_key.fallback_entries = self.measure_payload.dupe(AtlasSet.Entry, key.fallback_entries);        self.measure_entries[entry_index] = .{ .hash = hash, .key = owned_key, .value = value };        self.measure_slots[slot] = @intCast(entry_index + 1);        self.measure_usage.inserted(payload_bytes, self.measure_payload.cursor);        return value;    }    fn storeShape(        self: *AtlasCacheStorage,        content: []const u8,        fresh: filigree.GlyphRun,    ) Exhaustion!filigree.GlyphRun {        self.assertStorage();        defer self.assertStorage();        std.debug.assert(self.phase == .steady);        std.debug.assert(self.lookupShape(content) == null);        const payload_bytes = shapePayloadBytes(content, fresh) orelse {            self.shape_usage.oversize_bypasses +|= 1;            return error.EntryTooLarge;        };        try self.prepareShape(payload_bytes);        const hash = std.hash_map.hashString(content);        const slot = cacheEmptySlot(self.shape_slots, hash);        const entry_index = self.shape_usage.entries;        const owned_content = self.shape_payload.dupe(u8, content);        const shaped = ShapedRun{            .glyphs = self.shape_payload.dupe(filigree.ShapedGlyph, fresh.glyphs),            .clusters = self.shape_payload.dupe(filigree.Cluster, fresh.clusters),            .ligature_carets = self.shape_payload.dupe(                filigree.LigatureCaret,                fresh.ligature_carets,            ),            .total_x_advance = fresh.total_x_advance,            .total_y_advance = fresh.total_y_advance,            .direction = fresh.direction,            .writing_mode = fresh.writing_mode,            .output_order = fresh.output_order,        };        self.shape_entries[entry_index] = .{            .hash = hash,            .content = owned_content,            .shaped = shaped,        };        self.shape_slots[slot] = @intCast(entry_index + 1);        self.shape_usage.inserted(payload_bytes, self.shape_payload.cursor);        return shaped.run();    }    pub fn admitShapePayload(        self: *const AtlasCacheStorage,        payload_bytes: usize,    ) Exhaustion!void {        self.assertStorage();        std.debug.assert(self.phase == .steady);        const limits = self.capacity.limits;        if (limits.shape_entries == 0) return error.CacheDisabled;        if (payload_bytes > limits.shape_payload_bytes) return error.EntryTooLarge;    }    fn prepareMeasure(self: *AtlasCacheStorage, payload_bytes: usize) Exhaustion!void {        const limits = self.capacity.limits;        if (limits.measure_entries == 0) {            self.measure_usage.disabled_bypasses +|= 1;            return error.CacheDisabled;        }        if (payload_bytes > limits.measure_payload_bytes) {            self.measure_usage.oversize_bypasses +|= 1;            return error.EntryTooLarge;        }        std.debug.assert(self.measure_usage.payload_bytes <= limits.measure_payload_bytes);        const payload_full = payload_bytes >            limits.measure_payload_bytes - self.measure_usage.payload_bytes;        if (self.measure_usage.entries == limits.measure_entries or payload_full) {            self.replaceMeasure();        }    }    fn prepareShape(self: *AtlasCacheStorage, payload_bytes: usize) Exhaustion!void {        const limits = self.capacity.limits;        self.admitShapePayload(payload_bytes) catch |err| {            switch (err) {                error.CacheDisabled => self.shape_usage.disabled_bypasses +|= 1,                error.EntryTooLarge => self.shape_usage.oversize_bypasses +|= 1,            }            return err;        };        std.debug.assert(self.shape_usage.payload_bytes <= limits.shape_payload_bytes);        const payload_full = payload_bytes >            limits.shape_payload_bytes - self.shape_usage.payload_bytes;        if (self.shape_usage.entries == limits.shape_entries or payload_full) {            self.replaceShape();        }    }    fn replaceMeasure(self: *AtlasCacheStorage) void {        self.assertStorage();        defer self.assertStorage();        @memset(self.measure_slots, 0);        self.measure_payload.reset();        self.measure_usage.replaced();    }    fn replaceShape(self: *AtlasCacheStorage) void {        self.assertStorage();        defer self.assertStorage();        @memset(self.shape_slots, 0);        self.shape_payload.reset();        self.shape_usage.replaced();    }    fn assertStorage(self: *const AtlasCacheStorage) void {        const limits = self.capacity.limits;        std.debug.assert(self.bytes.len == self.capacity.storage_bytes);        std.debug.assert(self.measure_slots.len == self.capacity.measure_index_slots);        std.debug.assert(self.measure_entries.len == limits.measure_entries);        std.debug.assert(            self.measure_payload.bytes.len == self.capacity.measure_payload_storage_bytes,        );        std.debug.assert(self.shape_slots.len == self.capacity.shape_index_slots);        std.debug.assert(self.shape_entries.len == limits.shape_entries);        std.debug.assert(            self.shape_payload.bytes.len == self.capacity.shape_payload_storage_bytes,        );        const base = @intFromPtr(self.bytes.ptr);        assertCacheAddress(base, self.capacity.measure_index_offset, self.measure_slots);        assertCacheAddress(base, self.capacity.measure_entries_offset, self.measure_entries);        assertCacheAddress(base, self.capacity.measure_payload_offset, self.measure_payload.bytes);        assertCacheAddress(base, self.capacity.shape_index_offset, self.shape_slots);        assertCacheAddress(base, self.capacity.shape_entries_offset, self.shape_entries);        assertCacheAddress(base, self.capacity.shape_payload_offset, self.shape_payload.bytes);        std.debug.assert(self.measure_usage.entries <= limits.measure_entries);        std.debug.assert(self.measure_usage.payload_bytes <= limits.measure_payload_bytes);        std.debug.assert(self.measure_payload.cursor <= self.measure_payload.bytes.len);        std.debug.assert(self.shape_usage.entries <= limits.shape_entries);        std.debug.assert(self.shape_usage.payload_bytes <= limits.shape_payload_bytes);        std.debug.assert(self.shape_payload.cursor <= self.shape_payload.bytes.len);    }};const measure_payload_alignment: usize = @max(    @alignOf(UiTextStyle),    @max(@alignOf(UiTextRun), @alignOf(AtlasSet.Entry)),);const shape_payload_alignment: usize = @max(    @alignOf(filigree.ShapedGlyph),    @max(@alignOf(filigree.Cluster), @alignOf(filigree.LigatureCaret)),);const measure_padding_per_entry: usize = @alignOf(UiTextStyle) - 1 +    @alignOf(UiTextRun) - 1 + @alignOf(AtlasSet.Entry) - 1;const shape_padding_per_entry: usize = @alignOf(filigree.ShapedGlyph) - 1 +    @alignOf(filigree.Cluster) - 1 + @alignOf(filigree.LigatureCaret) - 1;const CacheRegion = struct {    start: usize,    bytes: usize,    end: usize,};fn cacheLimitsValid(limits: AtlasCacheStorage.Limits) AtlasCacheStorage.DeriveError!void {    const measure_disabled = limits.measure_entries == 0 and limits.measure_payload_bytes == 0;    const measure_enabled = limits.measure_entries != 0 and limits.measure_payload_bytes != 0;    if (!measure_disabled and !measure_enabled) return error.InvalidMeasureLimits;    const shape_disabled = limits.shape_entries == 0 and limits.shape_payload_bytes == 0;    const shape_enabled = limits.shape_entries != 0 and limits.shape_payload_bytes != 0;    if (!shape_disabled and !shape_enabled) return error.InvalidShapeLimits;    if (limits.measure_entries > std.math.maxInt(u32)) return error.EntryLimitTooLarge;    if (limits.shape_entries > std.math.maxInt(u32)) return error.EntryLimitTooLarge;}fn cacheIndexSlots(entries: usize) AtlasCacheStorage.DeriveError!usize {    if (entries == 0) return 0;    const doubled = try cacheMultiplied(entries, 2);    return std.math.ceilPowerOfTwo(usize, doubled) catch error.CapacityOverflow;}fn cacheAdded(left: usize, right: usize) AtlasCacheStorage.DeriveError!usize {    return std.math.add(usize, left, right) catch error.CapacityOverflow;}fn cacheMultiplied(left: usize, right: usize) AtlasCacheStorage.DeriveError!usize {    return std.math.mul(usize, left, right) catch error.CapacityOverflow;}fn cacheAligned(offset: usize, alignment: usize) AtlasCacheStorage.DeriveError!usize {    const mask = alignment - 1;    return (try cacheAdded(offset, mask)) & ~mask;}fn cachePlaced(comptime T: type, offset: usize, count: usize) AtlasCacheStorage.DeriveError!CacheRegion {    return cachePlacedBytes(offset, @alignOf(T), try cacheMultiplied(count, @sizeOf(T)));}fn cachePlacedBytes(    offset: usize,    alignment: usize,    byte_count: usize,) AtlasCacheStorage.DeriveError!CacheRegion {    const start = try cacheAligned(offset, alignment);    return .{ .start = start, .bytes = byte_count, .end = try cacheAdded(start, byte_count) };}fn cacheTypedSlice(    comptime T: type,    bytes: []align(AtlasCacheStorage.storage_alignment) u8,    offset: usize,    count: usize,) []T {    if (count == 0) return &.{};    const byte_count = count * @sizeOf(T);    const region: []align(@alignOf(T)) u8 = @alignCast(bytes[offset..][0..byte_count]);    return std.mem.bytesAsSlice(T, region);}fn assertCacheAddress(base: usize, offset: usize, region: anytype) void {    if (region.len == 0) return;    std.debug.assert(@intFromPtr(region.ptr) == base + offset);}fn cacheStartSlot(hash: u64, slot_count: usize) usize {    std.debug.assert(std.math.isPowerOfTwo(slot_count));    const truncated: usize = @truncate(hash);    return truncated & (slot_count - 1);}fn cacheNextSlot(slot: usize, slot_count: usize) usize {    std.debug.assert(std.math.isPowerOfTwo(slot_count));    return (slot + 1) & (slot_count - 1);}fn cacheEmptySlot(slots: []const u32, hash: u64) usize {    var slot = cacheStartSlot(hash, slots.len);    var probes: usize = 0;    while (probes < slots.len) : (probes += 1) {        if (slots[slot] == 0) return slot;        slot = cacheNextSlot(slot, slots.len);    }    unreachable;}fn cacheEpochStatus(    entry_capacity: usize,    payload_capacity_bytes: usize,    physical_payload_capacity_bytes: usize,    physical_payload_bytes: usize,    usage: CacheEpochUsage,) AtlasCacheStorage.EpochStatus {    return .{        .entry_capacity = entry_capacity,        .payload_capacity_bytes = payload_capacity_bytes,        .physical_payload_capacity_bytes = physical_payload_capacity_bytes,        .entries = usage.entries,        .payload_bytes = usage.payload_bytes,        .physical_payload_bytes = physical_payload_bytes,        .high_water_entries = usage.high_water_entries,        .high_water_payload_bytes = usage.high_water_payload_bytes,        .high_water_physical_payload_bytes = usage.high_water_physical_payload_bytes,        .rollovers = usage.rollovers,        .disabled_bypasses = usage.disabled_bypasses,        .oversize_bypasses = usage.oversize_bypasses,    };}const CacheModelRegion = struct {    start: u128,    bytes: u128,    end: u128,};const CacheModelLayout = struct {    measure_slots: u128,    measure_index: CacheModelRegion,    measure_entries: CacheModelRegion,    measure_payload: CacheModelRegion,    shape_slots: u128,    shape_index: CacheModelRegion,    shape_entries: CacheModelRegion,    shape_payload: CacheModelRegion,    fn capacity(        self: CacheModelLayout,        limits: AtlasCacheStorage.Limits,    ) AtlasCacheStorage.DeriveError!AtlasCacheStorage.Capacity {        const values = [_]u128{            self.measure_slots,            self.measure_index.start,            self.measure_entries.start,            self.measure_payload.start,            self.measure_payload.bytes,            self.shape_slots,            self.shape_index.start,            self.shape_entries.start,            self.shape_payload.start,            self.shape_payload.bytes,            self.shape_payload.end,        };        for (values) |value| {            if (value > std.math.maxInt(usize)) return error.CapacityOverflow;        }        return .{            .limits = limits,            .measure_index_slots = @intCast(self.measure_slots),            .measure_index_offset = @intCast(self.measure_index.start),            .measure_entries_offset = @intCast(self.measure_entries.start),            .measure_payload_offset = @intCast(self.measure_payload.start),            .measure_payload_storage_bytes = @intCast(self.measure_payload.bytes),            .shape_index_slots = @intCast(self.shape_slots),            .shape_index_offset = @intCast(self.shape_index.start),            .shape_entries_offset = @intCast(self.shape_entries.start),            .shape_payload_offset = @intCast(self.shape_payload.start),            .shape_payload_storage_bytes = @intCast(self.shape_payload.bytes),            .storage_bytes = @intCast(self.shape_payload.end),        };    }};fn modelAtlasCacheLimitsValid(    limits: AtlasCacheStorage.Limits,) AtlasCacheStorage.DeriveError!void {    const measure_disabled = limits.measure_entries == 0 and limits.measure_payload_bytes == 0;    const measure_enabled = limits.measure_entries != 0 and limits.measure_payload_bytes != 0;    if (!measure_disabled and !measure_enabled) return error.InvalidMeasureLimits;    const shape_disabled = limits.shape_entries == 0 and limits.shape_payload_bytes == 0;    const shape_enabled = limits.shape_entries != 0 and limits.shape_payload_bytes != 0;    if (!shape_disabled and !shape_enabled) return error.InvalidShapeLimits;    if (limits.measure_entries > std.math.maxInt(u32)) return error.EntryLimitTooLarge;    if (limits.shape_entries > std.math.maxInt(u32)) return error.EntryLimitTooLarge;}fn modelAtlasCacheCapacity(    limits: AtlasCacheStorage.Limits,) AtlasCacheStorage.DeriveError!AtlasCacheStorage.Capacity {    try modelAtlasCacheLimitsValid(limits);    const measure_slots = modelCacheIndexSlots(limits.measure_entries);    const shape_slots = modelCacheIndexSlots(limits.shape_entries);    const measure_index = modelCachePlaced(0, @alignOf(u32), measure_slots, @sizeOf(u32));    const measure_entries = modelCachePlaced(        measure_index.end,        @alignOf(MeasureCacheEntry),        limits.measure_entries,        @sizeOf(MeasureCacheEntry),    );    const measure_payload_bytes = @as(u128, limits.measure_payload_bytes) +        @as(u128, limits.measure_entries) * measure_padding_per_entry;    const measure_payload = modelCachePlaced(        measure_entries.end,        measure_payload_alignment,        measure_payload_bytes,        1,    );    const shape_index = modelCachePlaced(        measure_payload.end,        @alignOf(u32),        shape_slots,        @sizeOf(u32),    );    const shape_entries = modelCachePlaced(        shape_index.end,        @alignOf(ShapeCacheEntry),        limits.shape_entries,        @sizeOf(ShapeCacheEntry),    );    const shape_payload_bytes = @as(u128, limits.shape_payload_bytes) +        @as(u128, limits.shape_entries) * shape_padding_per_entry;    const shape_payload = modelCachePlaced(        shape_entries.end,        shape_payload_alignment,        shape_payload_bytes,        1,    );    return (CacheModelLayout{        .measure_slots = measure_slots,        .measure_index = measure_index,        .measure_entries = measure_entries,        .measure_payload = measure_payload,        .shape_slots = shape_slots,        .shape_index = shape_index,        .shape_entries = shape_entries,        .shape_payload = shape_payload,    }).capacity(limits);}fn modelCacheIndexSlots(entries: usize) u128 {    if (entries == 0) return 0;    const minimum = @as(u128, entries) * 2;    var slots: u128 = 1;    var steps: usize = 0;    while (steps < 64 and slots < minimum) : (steps += 1) slots *= 2;    std.debug.assert(slots >= minimum);    return slots;}fn modelCachePlaced(offset: u128, alignment: usize, count: u128, size: usize) CacheModelRegion {    const mask = @as(u128, alignment - 1);    const start = (offset + mask) & ~mask;    const bytes = count * size;    return .{ .start = start, .bytes = bytes, .end = start + bytes };}comptime {    alloc_phase.capacity.requireAllocatorRejectingOwnerShape(AtlasCacheStorage);}fn shapePayloadBytes(content: []const u8, run: filigree.GlyphRun) ?usize {    var bytes = content.len;    inline for (.{        .{ filigree.ShapedGlyph, run.glyphs.len },        .{ filigree.Cluster, run.clusters.len },        .{ filigree.LigatureCaret, run.ligature_carets.len },    }) |slice| {        const slice_bytes = std.math.mul(usize, @sizeOf(slice[0]), slice[1]) catch return null;        bytes = std.math.add(usize, bytes, slice_bytes) catch return null;    }    return bytes;}fn floatBits(value: f64) u64 {    return @bitCast(value);}pub const AtlasSet = struct {    entries: []const Entry = &.{},    fallback_entries: []const Entry = &.{},    fallback: ?*fallback_mod.Engine = null,    device_scale: f32 = 1,    pub const Entry = struct {        face: u64,        image_index: u32,        atlas: *Atlas,    };    pub fn forText(self: *const AtlasSet, text: UiText) ?Entry {        return self.forStyle(gui.model.resolvedTextStyle(text, 0));    }    pub fn forStyle(self: *const AtlasSet, style: UiTextStyle) ?Entry {        if (self.entries.len == 0) return null;        const point: f32 = @floatCast(style.point_size);        const scaled_point = point * @max(self.device_scale, 1);        var best: ?Entry = null;        var best_face = false;        var best_cost: f32 = std.math.floatMax(f32);        for (self.entries) |entry| {            const face_match = entry.face == style.font_asset_id;            if (best_face and !face_match) continue;            const cost = sizeCost(entry.atlas.pixel_size, scaled_point);            if (face_match and !best_face) {                best = entry;                best_face = true;                best_cost = cost;                continue;            }            if (cost < best_cost) {                best = entry;                best_cost = cost;            }        }        return best;    }    fn fallbackFor(self: *const AtlasSet, primary: Entry) ?Entry {        if (self.fallback == null or primary.atlas.outlineFont() == null) return null;        var best: ?Entry = null;        var best_cost: u64 = std.math.maxInt(u64);        for (self.fallback_entries) |entry| {            if (entry.atlas.outlineFont() == null) continue;            const cost = @abs(@as(i64, entry.atlas.pixel_size) - primary.atlas.pixel_size);            if (cost < best_cost) {                best = entry;                best_cost = cost;            }        }        return best;    }    fn requiresFallback(self: *const AtlasSet, primary: Entry, content: []const u8) !bool {        if (self.fallbackFor(primary) == null) return false;        return !(try primary.atlas.coversUtf8(content));    }    fn faceSegments(self: *const AtlasSet, primary: Entry, content: []const u8) !?FaceSegments {        const fallback_entry = self.fallbackFor(primary) orelse return null;        if (try primary.atlas.coversUtf8(content)) return null;        const primary_font = primary.atlas.outlineFont().?;        const fallback_font = fallback_entry.atlas.outlineFont().?;        return .{            .fallback_entry = fallback_entry,            .items = try self.fallback.?.segments(primary_font, fallback_font, content),        };    }    fn sizeCost(pixel_size: i32, point: f32) f32 {        const size: f32 = @floatFromInt(pixel_size);        if (size >= point) return size - point;        return (point - size) * 4;    }};const FaceSegments = struct {    fallback_entry: AtlasSet.Entry,    items: []const fallback_mod.FaceSegment,};fn requestedPointSize(text: UiText) f32 {    if (std.math.isFinite(text.point_size) and text.point_size > 0) return @floatCast(text.point_size);    return 16;}pub fn frameResolvers(atlases: *const AtlasSet) gui.frame.FrameResolvers {    return .{        .context = @constCast(atlases),        .text_size = measureFrameText,    };}pub fn measureFrameText(context: ?*anyopaque, node: *const UiNode) anyerror!?Size {    const text = node.text orelse return null;    if (text.content.len == 0) return null;    const atlases: *const AtlasSet = @ptrCast(@alignCast(context orelse return null));    return try measureSet(atlases, text);}pub fn measure(atlas: *Atlas, text: UiText) !Size {    try gui.model.validateText(text);    if (hasMixedTextMetrics(text)) return error.MixedTextRequiresAtlasSet;    return measureCached(atlas, text, .single);}pub fn measureSet(atlases: *const AtlasSet, text: UiText) !Size {    try gui.model.validateText(text);    const entry = atlases.forText(text) orelse return error.MissingTextAtlas;    const composite = hasMixedTextMetrics(text) or try atlases.requiresFallback(entry, text.content);    return measureCached(        entry.atlas,        text,        if (composite) .{ .composite = atlases } else .single,    );}pub fn textAdvanceForByteOffset(    atlases: *const AtlasSet,    text: UiText,    byte_offset: usize,) !f32 {    const line = try textCaretPlan(atlases, text);    return filigree.caret.advanceForByteOffset(        line.plan.run,        byte_offset,        text.content.len,    ) * line.scale;}pub fn textHitTestAdvance(    atlases: *const AtlasSet,    text: UiText,    advance: f32,) !filigree.caret.LineHit {    const line = try textCaretPlan(atlases, text);    var hit = filigree.caret.hitTestAdvance(        line.plan.run,        advance / line.scale,        text.content,    );    hit.advance *= line.scale;    return hit;}pub const TextCaretAffinity = enum {    upstream,    downstream,};pub const TextCaretGeometry = struct {    byte_offset: usize,    affinity: TextCaretAffinity,    line_index: usize,    x: f32,    y: f32,    height: f32,};pub fn textCaretGeometry(    atlases: *const AtlasSet,    text: UiText,    box: Size,    byte_offset: usize,    affinity: TextCaretAffinity,) !TextCaretGeometry {    const layout = try TextLayout.init(atlases, text, .{        .width = box.width,        .height = box.height,    }, 1);    const target = @min(byte_offset, text.content.len);    var iterator = layout.iterator();    while (try iterator.next()) |line| {        if (target < line.hard_line_start) continue;        if (!line.visual.containsCaret(target - line.hard_line_start, affinity)) continue;        return line.caret(target, affinity);    }    return error.MissingTextCaret;}pub fn textHitTestPoint(    atlases: *const AtlasSet,    text: UiText,    box: Size,    point: gui.model.UiPoint,) !TextCaretGeometry {    const layout = try TextLayout.init(atlases, text, .{        .width = box.width,        .height = box.height,    }, 1);    var iterator = layout.iterator();    var candidate: ?TextCaretGeometry = null;    while (try iterator.next()) |line| {        const hit = line.hit(point.x);        if (point.y < line.y + line.height) return hit;        candidate = hit;    }    return candidate orelse error.MissingTextCaret;}pub fn textHitTestWidgetPoint(    atlases: *const AtlasSet,    widget: WidgetFrame,    point: gui.model.UiPoint,) !?TextCaretGeometry {    if (!gui.model.pointInRect(widget.rect, point.x, point.y)) return null;    if (!gui.model.pointInRect(widget.visible_rect, point.x, point.y)) return null;    return try textHitTestWidgetLocalPoint(atlases, widget, point);}pub fn textHitTestWidgetPointClamped(    atlases: *const AtlasSet,    widget: WidgetFrame,    point: gui.model.UiPoint,) !?TextCaretGeometry {    if (!std.math.isFinite(point.x) or !std.math.isFinite(point.y)) return null;    const left = @max(widget.rect.x, widget.visible_rect.x);    const top = @max(widget.rect.y, widget.visible_rect.y);    const right = @min(        widget.rect.x + widget.rect.width,        widget.visible_rect.x + widget.visible_rect.width,    );    const bottom = @min(        widget.rect.y + widget.rect.height,        widget.visible_rect.y + widget.visible_rect.height,    );    if (right <= left or bottom <= top) return null;    return try textHitTestWidgetLocalPoint(atlases, widget, .{        .x = std.math.clamp(point.x, left, right),        .y = std.math.clamp(point.y, top, bottom),    });}fn textHitTestWidgetLocalPoint(    atlases: *const AtlasSet,    widget: WidgetFrame,    point: gui.model.UiPoint,) !?TextCaretGeometry {    const text = widget.text orelse return null;    return try textHitTestPoint(        atlases,        text,        .{ .width = widget.rect.width, .height = widget.rect.height },        .{            .x = point.x - widget.rect.x,            .y = point.y - widget.rect.y,        },    );}const TextCaretPlan = struct {    plan: LinePlan,    scale: f32,};fn textCaretPlan(atlases: *const AtlasSet, text: UiText) !TextCaretPlan {    try gui.model.validateText(text);    if (std.mem.indexOfScalar(u8, text.content, '\n') != null) return error.MultilineText;    const entry = atlases.forText(text) orelse return error.MissingTextAtlas;    const scale = textScale(entry.atlas, text);    const composite = hasMixedTextMetrics(text) or try atlases.requiresFallback(entry, text.content);    const plan = if (composite)        try LinePlan.initComposite(            entry.atlas,            atlases,            text,            text.content,            0,            0,        )    else        try LinePlan.init(entry.atlas, text.content, 0);    return .{ .plan = plan, .scale = scale };}const MeasureMode = union(enum) {    single,    composite: *const AtlasSet,};fn measureCached(atlas: *Atlas, text: UiText, mode: MeasureMode) !Size {    const metric_atlases: ?*const AtlasSet = switch (mode) {        .single => null,        .composite => |atlases| atlases,    };    const key = MeasureKey.fromText(text, metric_atlases);    if (atlas.cache.lookupMeasure(key)) |cached| return cached;    const measured = switch (mode) {        .single => try measureUncached(atlas, text),        .composite => |atlases| try measureCompositeUncached(atlas, atlases, text),    };    return atlas.cache.storeMeasure(key, measured) catch measured;}fn measurePayloadBytes(key: MeasureKey) ?usize {    var bytes = key.content.len;    bytes = std.math.add(usize, bytes, std.math.mul(usize, key.styles.len, @sizeOf(UiTextStyle)) catch return null) catch return null;    bytes = std.math.add(usize, bytes, std.math.mul(usize, key.runs.len, @sizeOf(UiTextRun)) catch return null) catch return null;    bytes = std.math.add(usize, bytes, std.math.mul(usize, key.atlas_entries.len, @sizeOf(AtlasSet.Entry)) catch return null) catch return null;    bytes = std.math.add(usize, bytes, std.math.mul(usize, key.fallback_entries.len, @sizeOf(AtlasSet.Entry)) catch return null) catch return null;    return bytes;}fn hasMixedTextMetrics(text: UiText) bool {    const base = gui.model.resolvedTextStyle(text, 0);    for (text.runs) |run| {        if (!gui.model.textStylesEqual(base, gui.model.resolvedTextStyle(text, run.style_slot))) return true;    }    return false;}const VisualLine = struct {    glyph_start: usize,    glyph_end: usize,    byte_start: usize,    byte_end: usize,    advance_start: f32,    advance: f32,    is_last: bool,    fn glyphs(self: VisualLine, run: filigree.GlyphRun) []const filigree.ShapedGlyph {        return run.glyphs[self.glyph_start..self.glyph_end];    }    fn advanceForByteOffset(self: VisualLine, run: filigree.GlyphRun, byte_offset: usize, text_len: usize) f32 {        const absolute = filigree.caret.advanceForByteOffset(run, byte_offset, text_len);        return std.math.clamp(absolute - self.advance_start, @as(f32, 0), self.advance);    }    fn containsCaret(        self: VisualLine,        byte_offset: usize,        affinity: TextCaretAffinity,    ) bool {        if (byte_offset < self.byte_start) return false;        if (byte_offset < self.byte_end) return true;        if (byte_offset != self.byte_end) return false;        return self.is_last or affinity == .upstream;    }};const LinePlan = struct {    content: []const u8,    run: filigree.GlyphRun,    glyph_ends: []const u32,    wrapped: bool,    glyph_sources: []const CompositeGlyphSource = &.{},    metric_spans: []const CompositeMetricSpan = &.{},    base_metric: ?CompositeMetricSpan = null,    fn init(atlas: *Atlas, content: []const u8, wrap_width: f32) !LinePlan {        const run = try atlas.shape(content);        if (wrap_width <= 0) {            return .{                .content = content,                .run = run,                .glyph_ends = &.{},                .wrapped = false,            };        }        const glyph_ends = try filigree.breakLinesInto(            atlas.allocator,            run.glyphs,            .{ .utf8 = content },            wrap_width,            &atlas.line_break_workspace,        );        std.debug.assert(glyph_ends.len > 0);        std.debug.assert(glyph_ends.len <= run.glyphs.len + 1);        return .{            .content = content,            .run = run,            .glyph_ends = glyph_ends,            .wrapped = true,        };    }    fn initComposite(        base_atlas: *Atlas,        atlases: *const AtlasSet,        text: UiText,        content: []const u8,        content_start: usize,        wrap_width: f32,    ) !LinePlan {        const content_end = std.math.add(usize, content_start, content.len) catch            return error.SourceTooLong;        if (content_end > text.content.len) return error.SourceTooLong;        if (content.len > std.math.maxInt(u32)) return error.SourceTooLong;        const base_style = gui.model.resolvedTextStyle(text, 0);        const base_entry = atlases.forStyle(base_style) orelse return error.MissingTextAtlas;        const base_scale = textStyleScale(base_entry.atlas, base_style);        if (!(base_scale > 0)) return error.InvalidTextScale;        const base_metric = compositeMetricSpan(            base_entry,            base_style,            base_scale,            0,            @intCast(content.len),        );        const workspace = &base_atlas.composite_workspace;        workspace.clear();        errdefer workspace.clear();        var cursor = MetricSegmentCursor{            .text = text,            .position = content_start,            .end = content_end,        };        while (cursor.next()) |segment| {            const entry = atlases.forStyle(segment.style) orelse return error.MissingTextAtlas;            const local_start = segment.byte_start - content_start;            const local_end = segment.byte_end - content_start;            if (local_start > std.math.maxInt(u32) or local_end > std.math.maxInt(u32)) {                return error.SourceTooLong;            }            try appendMetricSegment(                workspace,                base_atlas.allocator,                atlases,                entry,                segment.style,                base_scale,                content[local_start..local_end],                local_start,            );        }        var total_x: i32 = 0;        var total_y: i32 = 0;        for (workspace.glyphs.items) |glyph| {            total_x = std.math.add(i32, total_x, glyph.x_advance) catch                return error.TextGeometryOverflow;            total_y = std.math.add(i32, total_y, glyph.y_advance) catch                return error.TextGeometryOverflow;        }        const run = filigree.GlyphRun{            .glyphs = workspace.glyphs.items,            .clusters = workspace.clusters.items,            .ligature_carets = workspace.ligature_carets.items,            .total_x_advance = total_x,            .total_y_advance = total_y,            .direction = .ltr,            .writing_mode = .horizontal,            .output_order = .visual,        };        const glyph_ends = if (wrap_width > 0) try filigree.breakLinesInto(            base_atlas.allocator,            run.glyphs,            .{ .utf8 = content },            wrap_width,            &base_atlas.line_break_workspace,        ) else &.{};        if (wrap_width > 0) {            std.debug.assert(glyph_ends.len > 0);            std.debug.assert(glyph_ends.len <= run.glyphs.len + 1);        }        return .{            .content = content,            .run = run,            .glyph_ends = glyph_ends,            .wrapped = wrap_width > 0,            .glyph_sources = workspace.glyph_sources.items,            .metric_spans = workspace.spans.items,            .base_metric = base_metric,        };    }    fn iterator(_: *const LinePlan) Iterator {        return .{};    }    fn compositeLineBox(self: *const LinePlan, visual: VisualLine, multiplier: f32) CompositeLineBox {        var ascent: f32 = 0;        var descent: f32 = 0;        var requested: f32 = 0;        for (self.metric_spans) |span| {            if (span.byte_end <= visual.byte_start or span.byte_start >= visual.byte_end) continue;            ascent = @max(ascent, span.ascent);            descent = @max(descent, span.descent);            requested = @max(requested, span.point_size * multiplier);        }        if (ascent == 0 and descent == 0) {            const base = self.base_metric.?;            ascent = base.ascent;            descent = base.descent;            requested = base.point_size * multiplier;        }        const font_height = ascent + descent;        const height = @max(requested, font_height);        return .{            .ascent = ascent,            .descent = descent,            .height = height,            .half_leading = @max(0, height - font_height) / 2,        };    }    const Iterator = struct {        break_index: usize = 0,        glyph_start: usize = 0,        advance_start: f32 = 0,        fn next(self: *Iterator, plan: *const LinePlan) ?VisualLine {            const line_count = if (plan.wrapped) plan.glyph_ends.len else 1;            if (self.break_index >= line_count) return null;            const raw_end = if (plan.wrapped)                plan.glyph_ends[self.break_index]            else                plan.run.glyphs.len;            const glyph_end = @min(@as(usize, @intCast(raw_end)), plan.run.glyphs.len);            std.debug.assert(glyph_end >= self.glyph_start);            const advance = glyphSliceAdvance(plan.run.glyphs[self.glyph_start..glyph_end]);            const byte_start = if (self.glyph_start == 0)                0            else                sourceOffset(plan.run.glyphs[self.glyph_start].source_start, plan.content.len);            const byte_end = if (glyph_end >= plan.run.glyphs.len)                plan.content.len            else                sourceOffset(plan.run.glyphs[glyph_end].source_start, plan.content.len);            const visual = VisualLine{                .glyph_start = self.glyph_start,                .glyph_end = glyph_end,                .byte_start = byte_start,                .byte_end = @max(byte_start, byte_end),                .advance_start = self.advance_start,                .advance = advance,                .is_last = self.break_index + 1 == line_count,            };            self.glyph_start = glyph_end;            self.advance_start += advance;            self.break_index += 1;            return visual;        }    };};const CompositeLineBox = struct {    ascent: f32,    descent: f32,    height: f32,    half_leading: f32,};const TextLayout = struct {    atlases: *const AtlasSet,    text: UiText,    rect: Rect,    base_atlas: *Atlas,    scale: f32,    single_line_height: f32,    single_half_leading: f32,    line_height_multiplier: f32,    plan_wrap_width: f32,    block_y: f32,    composite: bool,    fn init(        atlases: *const AtlasSet,        text: UiText,        rect: Rect,        unit_scale: f32,    ) !TextLayout {        try gui.model.validateText(text);        if (!std.math.isFinite(unit_scale) or unit_scale <= 0) {            return error.InvalidTextScale;        }        const entry = atlases.forText(text) orelse return error.MissingTextAtlas;        const base_atlas = entry.atlas;        const scale = textScale(base_atlas, text) * unit_scale;        if (!std.math.isFinite(scale) or scale <= 0) return error.InvalidTextScale;        const line_height = textLineHeight(base_atlas, text) * unit_scale;        const half_leading = @max(            0,            line_height - base_atlas.metrics().height() * scale,        ) / 2;        const wrap_width = textWrapWidth(text) * unit_scale;        const measured_height = if (text.vertical_align == .start)            0        else            (try measureSet(atlases, text)).height * unit_scale;        const composite = hasMixedTextMetrics(text) or try atlases.requiresFallback(entry, text.content);        return .{            .atlases = atlases,            .text = text,            .rect = rect,            .base_atlas = base_atlas,            .scale = scale,            .single_line_height = line_height,            .single_half_leading = half_leading,            .line_height_multiplier = textLineHeightMultiplier(text),            .plan_wrap_width = if (wrap_width > 0) wrap_width / scale else 0,            .block_y = if (text.vertical_align == .start)                rect.y            else                alignedStart(                    rect.y,                    rect.height,                    measured_height,                    text.vertical_align,                ),            .composite = composite,        };    }    fn iterator(self: *const TextLayout) Iterator {        return .{            .layout = self,            .line_y = self.block_y,        };    }    const Iterator = struct {        layout: *const TextLayout,        next_hard_line_start: usize = 0,        hard_lines_done: bool = false,        has_plan: bool = false,        current_hard_line_start: usize = 0,        current_hard_line: []const u8 = &.{},        current_plan: LinePlan = undefined,        visual_iterator: LinePlan.Iterator = .{},        line_index: usize = 0,        line_y: f32,        fn next(self: *Iterator) !?TextLayoutLine {            while (true) {                if (self.has_plan) {                    if (self.visual_iterator.next(&self.current_plan)) |visual| {                        const box = if (self.layout.composite)                            self.current_plan.compositeLineBox(                                visual,                                self.layout.line_height_multiplier,                            )                        else                            CompositeLineBox{                                .ascent = self.layout.base_atlas.metrics().ascent,                                .descent = self.layout.base_atlas.metrics().descent,                                .height = self.layout.single_line_height / self.layout.scale,                                .half_leading = self.layout.single_half_leading / self.layout.scale,                            };                        const line_height = if (self.layout.composite)                            box.height * self.layout.scale                        else                            self.layout.single_line_height;                        const line_width = visual.advance * self.layout.scale;                        const line = TextLayoutLine{                            .plan = &self.current_plan,                            .visual = visual,                            .hard_line = self.current_hard_line,                            .hard_line_start = self.current_hard_line_start,                            .line_index = self.line_index,                            .origin_x = alignedStart(                                self.layout.rect.x,                                self.layout.rect.width,                                line_width,                                self.layout.text.horizontal_align,                            ),                            .origin_y = self.line_y + box.half_leading * self.layout.scale,                            .y = self.line_y,                            .height = line_height,                            .scale = self.layout.scale,                            .ascent = box.ascent,                            .descent = box.descent,                        };                        self.line_y += line_height;                        self.line_index += 1;                        return line;                    }                    self.has_plan = false;                }                if (!try self.loadHardLine()) return null;            }        }        fn loadHardLine(self: *Iterator) !bool {            if (self.hard_lines_done) return false;            const content = self.layout.text.content;            const start = self.next_hard_line_start;            const relative_end = std.mem.indexOfScalar(                u8,                content[start..],                '\n',            );            const end = if (relative_end) |offset| start + offset else content.len;            if (end < content.len) {                self.next_hard_line_start = end + 1;            } else {                self.hard_lines_done = true;            }            const hard_line = content[start..end];            self.current_hard_line_start = start;            self.current_hard_line = hard_line;            self.current_plan = if (self.layout.composite)                try LinePlan.initComposite(                    self.layout.base_atlas,                    self.layout.atlases,                    self.layout.text,                    hard_line,                    start,                    self.layout.plan_wrap_width,                )            else                try LinePlan.init(                    self.layout.base_atlas,                    hard_line,                    self.layout.plan_wrap_width,                );            self.visual_iterator = .{};            self.has_plan = true;            return true;        }    };};const TextLayoutLine = struct {    plan: *const LinePlan,    visual: VisualLine,    hard_line: []const u8,    hard_line_start: usize,    line_index: usize,    origin_x: f32,    origin_y: f32,    y: f32,    height: f32,    scale: f32,    ascent: f32,    descent: f32,    fn caret(        self: TextLayoutLine,        byte_offset: usize,        affinity: TextCaretAffinity,    ) TextCaretGeometry {        const local_offset = byte_offset - self.hard_line_start;        return .{            .byte_offset = byte_offset,            .affinity = affinity,            .line_index = self.line_index,            .x = self.origin_x + self.visual.advanceForByteOffset(                self.plan.run,                local_offset,                self.plan.content.len,            ) * self.scale,            .y = self.y,            .height = self.height,        };    }    fn hit(self: TextLayoutLine, x: f32) TextCaretGeometry {        const absolute_advance = self.visual.advance_start +            (x - self.origin_x) / self.scale;        const raw = filigree.caret.hitTestAdvance(            self.plan.run,            absolute_advance,            self.plan.content,        );        const local_offset = std.math.clamp(            raw.byte_offset,            self.visual.byte_start,            self.visual.byte_end,        );        const affinity: TextCaretAffinity = if (!self.visual.is_last and            local_offset == self.visual.byte_end)            .upstream        else            .downstream;        return self.caret(self.hard_line_start + local_offset, affinity);    }};const MetricSegment = struct {    byte_start: usize,    byte_end: usize,    style: UiTextStyle,};const MetricSegmentCursor = struct {    text: UiText,    position: usize,    end: usize,    fn next(self: *MetricSegmentCursor) ?MetricSegment {        if (self.position >= self.end) return null;        const byte_start = self.position;        const style = textStyleAt(self.text, byte_start);        var byte_end = nextTextMetricBoundary(self.text, byte_start, self.end);        while (byte_end < self.end and            gui.model.textStylesEqual(style, textStyleAt(self.text, byte_end)))        {            byte_end = nextTextMetricBoundary(self.text, byte_end, self.end);        }        std.debug.assert(byte_end > byte_start);        self.position = byte_end;        return .{            .byte_start = byte_start,            .byte_end = byte_end,            .style = style,        };    }};fn textStyleAt(text: UiText, byte_offset: usize) UiTextStyle {    const run = findTextRun(text.runs, byte_offset) orelse        return gui.model.resolvedTextStyle(text, 0);    return gui.model.resolvedTextStyle(text, run.style_slot);}fn nextTextMetricBoundary(text: UiText, byte_offset: usize, end: usize) usize {    const index = firstRunEndingAfter(text.runs, byte_offset);    if (index >= text.runs.len) return end;    const run = text.runs[index];    if (byte_offset < run.byte_start) return @min(end, run.byte_start);    return @min(end, run.byte_end);}fn textStyleScale(atlas: *const Atlas, style: UiTextStyle) f32 {    if (atlas.pixel_size <= 0) return 1;    return @as(f32, @floatCast(style.point_size)) /        @as(f32, @floatFromInt(atlas.pixel_size));}fn appendMetricSegment(    workspace: *CompositeWorkspace,    allocator: Allocator,    atlases: *const AtlasSet,    primary: AtlasSet.Entry,    style: UiTextStyle,    base_scale: f32,    content: []const u8,    content_start: usize,) !void {    const segmented = try atlases.faceSegments(primary, content) orelse {        return appendStyledFaceSegment(            workspace,            allocator,            primary,            style,            base_scale,            content,            content_start,        );    };    for (segmented.items) |segment| {        const start: usize = @intCast(segment.source.start);        const end: usize = @intCast(segment.source.end);        if (start > end or end > content.len) return error.SourceTooLong;        const entry = try entryForFaceSegment(            primary,            segmented.fallback_entry,            segment.candidate_index,            segment.missing_everywhere,        );        try appendLookupOrderedFaceSegment(            workspace,            allocator,            primary,            entry,            style,            base_scale,            content[start..end],            try std.math.add(usize, content_start, start),        );    }}fn entryForFaceSegment(    primary: AtlasSet.Entry,    fallback: AtlasSet.Entry,    candidate_index: usize,    missing_everywhere: bool,) !AtlasSet.Entry {    if (candidate_index == 1) return fallback;    if (candidate_index != 0) return error.InvalidFallbackCandidate;    return if (missing_everywhere) fallback else primary;}fn appendLookupOrderedFaceSegment(    workspace: *CompositeWorkspace,    allocator: Allocator,    primary: AtlasSet.Entry,    selected: AtlasSet.Entry,    style: UiTextStyle,    base_scale: f32,    content: []const u8,    content_start: usize,) !void {    if (selected.atlas == primary.atlas or content.len == 0) {        return appendStyledFaceSegment(            workspace,            allocator,            selected,            style,            base_scale,            content,            content_start,        );    }    const append = OrderedFaceAppend{        .workspace = workspace,        .allocator = allocator,        .primary = primary,        .selected = selected,        .style = style,        .base_scale = base_scale,        .content = content,        .content_start = content_start,    };    var iterator = try filigree.unicode.SourceIterator.init(.{ .utf8 = content }, 0);    var grapheme: filigree.unicode.GraphemeState = .{};    var cluster_start: usize = 0;    var cluster_first: u21 = 0;    var cluster_count: usize = 0;    var runs = OrderedRunState{};    while (try iterator.next()) |scalar| {        if (grapheme.consume(scalar.codepoint)) {            cluster_count += 1;            continue;        }        if (cluster_count > 0) {            try runs.accept(append, cluster_start, cluster_count == 1 and synth.covered(cluster_first));        }        cluster_start = @intCast(scalar.source.start);        cluster_first = scalar.codepoint;        cluster_count = 1;    }    std.debug.assert(cluster_count > 0);    try runs.accept(append, cluster_start, cluster_count == 1 and synth.covered(cluster_first));    return append.run(runs.start, content.len, runs.synthetic.?);}const OrderedFaceAppend = struct {    workspace: *CompositeWorkspace,    allocator: Allocator,    primary: AtlasSet.Entry,    selected: AtlasSet.Entry,    style: UiTextStyle,    base_scale: f32,    content: []const u8,    content_start: usize,    fn run(self: OrderedFaceAppend, start: usize, end: usize, synthetic: bool) !void {        std.debug.assert(start < end);        std.debug.assert(end <= self.content.len);        return appendStyledFaceSegment(            self.workspace,            self.allocator,            if (synthetic) self.primary else self.selected,            self.style,            self.base_scale,            self.content[start..end],            std.math.add(usize, self.content_start, start) catch return error.SourceTooLong,        );    }};const OrderedRunState = struct {    start: usize = 0,    synthetic: ?bool = null,    fn accept(self: *OrderedRunState, append: OrderedFaceAppend, cluster_start: usize, synthetic: bool) !void {        if (self.synthetic) |current| {            if (current != synthetic) {                try append.run(self.start, cluster_start, current);                self.start = cluster_start;            }        }        self.synthetic = synthetic;    }};fn appendStyledFaceSegment(    workspace: *CompositeWorkspace,    allocator: Allocator,    entry: AtlasSet.Entry,    style: UiTextStyle,    base_scale: f32,    content: []const u8,    content_start: usize,) !void {    if (content_start > std.math.maxInt(u32) or content.len > std.math.maxInt(u32) - content_start) {        return error.SourceTooLong;    }    const scale_ratio = textStyleScale(entry.atlas, style) / base_scale;    if (!std.math.isFinite(scale_ratio) or scale_ratio <= 0) return error.InvalidTextScale;    const span_index = workspace.spans.items.len;    if (span_index > std.math.maxInt(u32)) return error.SourceTooLong;    const content_end = content_start + content.len;    try workspace.spans.append(allocator, compositeMetricSpan(        entry,        style,        base_scale,        @intCast(content_start),        @intCast(content_end),    ));    try appendCompositeSegment(        workspace,        allocator,        try entry.atlas.shape(content),        @intCast(content_start),        @intCast(span_index),        scale_ratio,    );}fn compositeMetricSpan(    entry: AtlasSet.Entry,    style: UiTextStyle,    base_scale: f32,    byte_start: u32,    byte_end: u32,) CompositeMetricSpan {    const scale_ratio = textStyleScale(entry.atlas, style) / base_scale;    const metrics = entry.atlas.metrics();    return .{        .byte_start = byte_start,        .byte_end = byte_end,        .atlas = entry.atlas,        .image_index = entry.image_index,        .scale_ratio = scale_ratio,        .point_size = @as(f32, @floatCast(style.point_size)) / base_scale,        .ascent = metrics.ascent * scale_ratio,        .descent = metrics.descent * scale_ratio,    };}fn appendCompositeSegment(    workspace: *CompositeWorkspace,    allocator: Allocator,    run: filigree.GlyphRun,    source_base: u32,    segment_index: u32,    scale_ratio: f32,) !void {    const glyph_base = workspace.glyphs.items.len;    const cluster_base = workspace.clusters.items.len;    const caret_base = workspace.ligature_carets.items.len;    try workspace.glyphs.ensureUnusedCapacity(allocator, run.glyphs.len);    try workspace.clusters.ensureUnusedCapacity(allocator, run.clusters.len);    try workspace.ligature_carets.ensureUnusedCapacity(allocator, run.ligature_carets.len);    try workspace.glyph_sources.ensureUnusedCapacity(allocator, run.glyphs.len);    for (run.ligature_carets) |source| {        var caret = source;        caret.x_offset = try scaleCompositeValue(caret.x_offset, scale_ratio);        workspace.ligature_carets.appendAssumeCapacity(caret);    }    for (run.clusters) |source| {        var cluster = source;        cluster.source.start = try addCompositeIndex(cluster.source.start, source_base);        cluster.source.end = try addCompositeIndex(cluster.source.end, source_base);        cluster.glyphs.start = try addCompositeIndex(cluster.glyphs.start, glyph_base);        cluster.glyphs.end = try addCompositeIndex(cluster.glyphs.end, glyph_base);        workspace.clusters.appendAssumeCapacity(cluster);    }    for (run.glyphs) |source| {        var glyph = source;        glyph.cluster = try addCompositeIndex(glyph.cluster, source_base);        glyph.cluster_index = try addCompositeIndex(glyph.cluster_index, cluster_base);        glyph.source_start = try addCompositeIndex(glyph.source_start, source_base);        glyph.source_end = try addCompositeIndex(glyph.source_end, source_base);        glyph.x_advance = try scaleCompositeValue(glyph.x_advance, scale_ratio);        glyph.y_advance = try scaleCompositeValue(glyph.y_advance, scale_ratio);        glyph.x_offset = try scaleCompositeValue(glyph.x_offset, scale_ratio);        glyph.y_offset = try scaleCompositeValue(glyph.y_offset, scale_ratio);        if (glyph.attachment) |*attachment| {            attachment.target_glyph_index = try addCompositeIndex(                attachment.target_glyph_index,                glyph_base,            );        }        if (glyph.ligature_caret_count > 0) {            glyph.ligature_caret_start = try addCompositeIndex(                glyph.ligature_caret_start,                caret_base,            );        }        workspace.glyphs.appendAssumeCapacity(glyph);        workspace.glyph_sources.appendAssumeCapacity(.{ .segment_index = segment_index });    }}fn addCompositeIndex(value: u32, base: anytype) !u32 {    const wide = std.math.add(u64, value, @intCast(base)) catch        return error.SourceTooLong;    if (wide > std.math.maxInt(u32)) return error.SourceTooLong;    return @intCast(wide);}fn scaleCompositeValue(value: i32, ratio: f32) !i32 {    const scaled = @as(f64, @floatFromInt(value)) * @as(f64, ratio);    if (!std.math.isFinite(scaled) or        scaled < @as(f64, @floatFromInt(std.math.minInt(i32))) or        scaled > @as(f64, @floatFromInt(std.math.maxInt(i32))))    {        return error.TextGeometryOverflow;    }    return @intFromFloat(@round(scaled));}fn measureUncached(atlas: *Atlas, text: UiText) !Size {    const scale = textScale(atlas, text);    const line_height = textLineHeight(atlas, text);    const wrap_width = textWrapWidth(text);    var line_count: usize = 0;    var max_width: f32 = 0;    var lines = std.mem.splitScalar(u8, text.content, '\n');    while (lines.next()) |line| {        const plan = try LinePlan.init(atlas, line, wrap_width / scale);        var iterator = plan.iterator();        while (iterator.next(&plan)) |visual| {            max_width = @max(max_width, visual.advance * scale);            line_count += 1;        }    }    if (line_count == 0) line_count = 1;    return .{        .width = if (wrap_width > 0) @min(max_width, wrap_width) else max_width,        .height = line_height * @as(f32, @floatFromInt(line_count)),    };}fn measureCompositeUncached(base_atlas: *Atlas, atlases: *const AtlasSet, text: UiText) !Size {    const base_scale = textScale(base_atlas, text);    const wrap_width = textWrapWidth(text);    const multiplier = textLineHeightMultiplier(text);    var max_width: f32 = 0;    var total_height: f32 = 0;    var line_start: usize = 0;    var lines = std.mem.splitScalar(u8, text.content, '\n');    while (lines.next()) |line| {        defer line_start = nextLineStart(text.content.len, line_start, line.len);        const plan = try LinePlan.initComposite(            base_atlas,            atlases,            text,            line,            line_start,            if (wrap_width > 0) wrap_width / base_scale else 0,        );        var iterator = plan.iterator();        while (iterator.next(&plan)) |visual| {            const box = plan.compositeLineBox(visual, multiplier);            max_width = @max(max_width, visual.advance * base_scale);            total_height += box.height * base_scale;        }    }    if (total_height == 0) {        const base = compositeMetricSpan(            atlases.forText(text) orelse return error.MissingTextAtlas,            gui.model.resolvedTextStyle(text, 0),            base_scale,            0,            0,        );        total_height = @max(            base.point_size * multiplier,            base.ascent + base.descent,        ) * base_scale;    }    return .{        .width = if (wrap_width > 0) @min(max_width, wrap_width) else max_width,        .height = total_height,    };}fn shapeBitmap(allocator: Allocator, bitmap: *Atlas.Bitmap, content: []const u8) !filigree.GlyphRun {    bitmap.shaped.clearRetainingCapacity();    bitmap.clusters.clearRetainingCapacity();    var total: i32 = 0;    var index: usize = 0;    while (index < content.len) {        const sequence_len = std.unicode.utf8ByteSequenceLength(content[index]) catch {            index += 1;            continue;        };        if (index + sequence_len > content.len) break;        const cluster: u32 = @intCast(index);        const codepoint = std.unicode.utf8Decode(content[index .. index + sequence_len]) catch {            index += sequence_len;            continue;        };        index += sequence_len;        const glyph_start: u32 = @intCast(bitmap.shaped.items.len);        const cluster_index: u32 = @intCast(bitmap.clusters.items.len);        if (codepoint < 0x20) {            try bitmap.clusters.append(allocator, .{                .source = .{ .start = cluster, .end = @intCast(index) },                .glyphs = .{ .start = glyph_start, .end = glyph_start },            });            continue;        }        const glyph_id = bitmap.map.get(codepoint) orelse            bitmap.map.get('?') orelse            std.math.maxInt(u32);        try bitmap.shaped.append(allocator, .{            .glyph_id = glyph_id,            .cluster = cluster,            .cluster_index = cluster_index,            .source_start = cluster,            .source_end = @intCast(index),            .x_advance = bitmap.advance,            .y_advance = 0,            .x_offset = 0,            .y_offset = 0,        });        try bitmap.clusters.append(allocator, .{            .source = .{ .start = cluster, .end = @intCast(index) },            .glyphs = .{ .start = glyph_start, .end = glyph_start + 1 },        });        total = addClampedI32(total, bitmap.advance);    }    return .{        .glyphs = bitmap.shaped.items,        .clusters = bitmap.clusters.items,        .ligature_carets = &.{},        .total_x_advance = total,        .total_y_advance = 0,        .direction = .ltr,        .writing_mode = .horizontal,        .output_order = .visual,    };}pub fn packAtlasImageAlloc(allocator: Allocator, atlas: filigree.GlyphAtlas) !OwnedAtlasImage {    if (atlas.width <= 0 or atlas.height <= 0) return error.InvalidAtlas;    const width = std.math.cast(u32, atlas.width) orelse return error.InvalidAtlas;    const height = std.math.cast(u32, atlas.height) orelse return error.InvalidAtlas;    const pixel_count = try pixelCount(width, height);    const byte_count = std.math.mul(usize, pixel_count, 4) catch return error.InvalidAtlas;    if (atlas.rgba.len < byte_count) return error.BufferTooSmall;    const pixels = try allocator.alloc(u32, pixel_count);    errdefer allocator.free(pixels);    for (pixels, 0..) |*pixel, index| {        const base = index * 4;        pixel.* = packRgba(.{            .r = atlas.rgba[base],            .g = atlas.rgba[base + 1],            .b = atlas.rgba[base + 2],            .a = atlas.rgba[base + 3],        });    }    return .{        .image = .{ .width = width, .height = height, .pixels = pixels },        .pixels = pixels,    };}fn glyphIndexAlloc(allocator: Allocator, atlas: filigree.GlyphAtlas) !std.AutoHashMapUnmanaged(u32, usize) {    var index: std.AutoHashMapUnmanaged(u32, usize) = .empty;    errdefer index.deinit(allocator);    try index.ensureTotalCapacity(allocator, @intCast(atlas.glyphs.len));    for (atlas.glyphs, 0..) |glyph, position| {        index.putAssumeCapacity(glyph.glyph_id, position);    }    return index;}pub fn drawGlyphRun(    writer: anytype,    atlas_image_index: u32,    atlas: filigree.GlyphAtlas,    run: filigree.GlyphRun,    origin_x: f32,    origin_y: f32,    color: Color,) void {    var pen_x: i32 = 0;    var pen_y: i32 = 0;    for (run.glyphs) |glyph| {        const atlas_index = findAtlasGlyph(atlas, glyph.glyph_id) orelse {            pen_x = addClampedI32(pen_x, glyph.x_advance);            pen_y = addClampedI32(pen_y, glyph.y_advance);            continue;        };        const atlas_glyph = atlas.glyphs[atlas_index];        const source = atlas.recs[atlas_index];        if (atlas_glyph.width <= 0 or atlas_glyph.height <= 0) {            pen_x = addClampedI32(pen_x, glyph.x_advance);            pen_y = addClampedI32(pen_y, glyph.y_advance);            continue;        }        const rect = Rect{            .x = origin_x + @as(f32, @floatFromInt(round26Dot6(addClampedI32(pen_x, glyph.x_offset)) + atlas_glyph.offset_x)),            .y = origin_y + @as(f32, @floatFromInt(round26Dot6(addClampedI32(pen_y, glyph.y_offset)) + atlas_glyph.offset_y)),            .width = @floatFromInt(atlas_glyph.width),            .height = @floatFromInt(atlas_glyph.height),        };        writer.drawGlyph(rect, atlas_image_index, .{            .x = source.x,            .y = source.y,            .width = source.width,            .height = source.height,        }, color);        pen_x = addClampedI32(pen_x, glyph.x_advance);        pen_y = addClampedI32(pen_y, glyph.y_advance);    }}pub fn appendFrameCommands(commands: *command.CommandBuffer, frame: UiFrame, atlases: *const AtlasSet, device_scale: f32, layer: u8) !void {    const start = commands.items().len;    errdefer commands.rollback(start);    for (frame.widgets) |widget| {        if (widget.layer != layer) continue;        try appendWidgetCommands(commands, widget, atlases, device_scale);    }}pub fn appendFrameRegionCommands(commands: *command.CommandBuffer, frame: UiFrame, atlases: *const AtlasSet, region: Region, device_scale: f32, layer: u8) !void {    const start = commands.items().len;    errdefer commands.rollback(start);    const rect = regionRect(region);    for (frame.widgets) |widget| {        if (widget.layer != layer) continue;        if (!intersects(scaleRect(widget.visible_rect, device_scale), rect)) continue;        try appendWidgetCommands(commands, widget, atlases, device_scale);    }}fn appendWidgetCommands(commands: *command.CommandBuffer, widget: WidgetFrame, atlases: *const AtlasSet, device_scale: f32) !void {    const text = widget.text orelse return;    try gui.model.validateText(text);    const entry = atlases.forText(text) orelse return;    if (hasMixedTextMetrics(text) or try atlases.requiresFallback(entry, text.content)) {        return appendCompositeWidgetCommands(commands, widget, atlases, device_scale);    }    return appendSingleWidgetCommands(commands, widget, atlases, device_scale);}fn appendSingleWidgetCommands(commands: *command.CommandBuffer, widget: WidgetFrame, atlases: *const AtlasSet, device_scale: f32) !void {    const text = widget.text.?;    const has_markers = widget.text_selection.cursor_visible or widget.text_selection.selection_active;    if (text.content.len == 0 and !has_markers) return;    const entry = atlases.forText(text) orelse return;    const atlas = entry.atlas;    const foreground = widget.paint.foreground orelse Color{ .r = 28, .g = 34, .b = 31, .a = 255 };    const rect = scaleRect(widget.rect, device_scale);    const layout = try TextLayout.init(atlases, text, rect, device_scale);    const font_metrics = atlas.metrics();    var writer = GlyphCommandWriter{        .commands = commands,        .clip = scaleRect(widget.visible_rect, device_scale),    };    var pending_caret: ?TextMarker = null;    var glyph_runs = TextRunCursor{ .runs = text.runs };    var background_runs = TextRunRangeCursor{ .runs = text.runs };    var decoration_runs = TextRunRangeCursor{ .runs = text.runs };    const caret_run = findTextRun(text.runs, widget.text_selection.cursor_byte_offset);    const caret_foreground = if (caret_run) |run| run.foreground orelse foreground else foreground;    const caret_background = if (caret_run) |run| run.background else null;    var iterator = layout.iterator();    while (try iterator.next()) |line| {        if (text.runs.len > 0) {            appendRunBackgroundCommands(                &writer,                &background_runs,                line.plan,                line.visual,                line.hard_line_start,                line.origin_x,                line.y,                line.height,                line.scale,            );        }        const cursor = if (has_markers) blk: {            appendSelectionCommand(                &writer,                widget.text_selection,                line.plan,                line.visual,                line.hard_line_start,                line.origin_x,                line.y,                line.height,                line.scale,                foreground,            );            if (caretMarker(                atlas,                widget.text_selection,                line.plan,                line.visual,                line.hard_line_start,                line.origin_x,                line.y,                line.height,                line.scale,                device_scale,                caret_foreground,            )) |marker| {                if (widget.text_selection.cursor_block) {                    writer.fillRect(marker.rect, marker.color);                } else {                    pending_caret = marker;                }            }            break :blk blockCursorHighlight(                widget,                line.plan,                line.visual,                line.hard_line_start,                caret_foreground,                caret_background,            );        } else null;        var line_run = line.plan.run;        line_run.glyphs = line.visual.glyphs(line.plan.run);        if (text.runs.len == 0) {            drawGlyphRunScaled(                &writer,                entry.image_index,                atlas,                line_run,                line.hard_line,                line.y,                line.height,                line.origin_x,                line.origin_y,                line.scale,                foreground,                cursor,            );        } else {            drawStyledGlyphRunScaled(                &writer,                entry.image_index,                atlas,                line_run,                line.hard_line,                line.hard_line_start,                line.y,                line.height,                line.origin_x,                line.origin_y,                line.scale,                foreground,                cursor,                &glyph_runs,            );            appendRunDecorationCommands(                &writer,                &decoration_runs,                line.plan,                line.visual,                line.hard_line_start,                line.origin_x,                line.y,                line.origin_y,                line.height,                line.scale,                device_scale,                font_metrics,                foreground,            );        }    }    if (pending_caret) |caret| writer.fillRect(caret.rect, caret.color);    if (writer.failure) |failure| return failure;}fn appendCompositeWidgetCommands(    commands: *command.CommandBuffer,    widget: WidgetFrame,    atlases: *const AtlasSet,    device_scale: f32,) !void {    const text = widget.text.?;    const has_markers = widget.text_selection.cursor_visible or        widget.text_selection.selection_active;    if (text.content.len == 0 and !has_markers) return;    const entry = atlases.forText(text) orelse return;    const base_atlas = entry.atlas;    const foreground = widget.paint.foreground orelse        Color{ .r = 28, .g = 34, .b = 31, .a = 255 };    const rect = scaleRect(widget.rect, device_scale);    const layout = try TextLayout.init(atlases, text, rect, device_scale);    var writer = GlyphCommandWriter{        .commands = commands,        .clip = scaleRect(widget.visible_rect, device_scale),    };    var pending_caret: ?TextMarker = null;    var glyph_runs = TextRunCursor{ .runs = text.runs };    var background_runs = TextRunRangeCursor{ .runs = text.runs };    var decoration_runs = TextRunRangeCursor{ .runs = text.runs };    const caret_run = findTextRun(text.runs, widget.text_selection.cursor_byte_offset);    const caret_foreground = if (caret_run) |run|        run.foreground orelse foreground    else        foreground;    const caret_background = if (caret_run) |run| run.background else null;    var iterator = layout.iterator();    while (try iterator.next()) |line| {        appendRunBackgroundCommands(            &writer,            &background_runs,            line.plan,            line.visual,            line.hard_line_start,            line.origin_x,            line.y,            line.height,            line.scale,        );        const cursor = if (has_markers) blk: {            appendSelectionCommand(                &writer,                widget.text_selection,                line.plan,                line.visual,                line.hard_line_start,                line.origin_x,                line.y,                line.height,                line.scale,                foreground,            );            if (caretMarker(                base_atlas,                widget.text_selection,                line.plan,                line.visual,                line.hard_line_start,                line.origin_x,                line.y,                line.height,                line.scale,                device_scale,                caret_foreground,            )) |marker| {                if (widget.text_selection.cursor_block) {                    writer.fillRect(marker.rect, marker.color);                } else {                    pending_caret = marker;                }            }            break :blk blockCursorHighlight(                widget,                line.plan,                line.visual,                line.hard_line_start,                caret_foreground,                caret_background,            );        } else null;        drawCompositeStyledGlyphRunScaled(            &writer,            line.plan,            line.visual,            line.hard_line,            line.hard_line_start,            line.y,            line.height,            line.origin_x,            line.origin_y,            line.scale,            line.ascent,            foreground,            cursor,            &glyph_runs,        );        appendRunDecorationCommands(            &writer,            &decoration_runs,            line.plan,            line.visual,            line.hard_line_start,            line.origin_x,            line.y,            line.origin_y,            line.height,            line.scale,            device_scale,            .{ .ascent = line.ascent, .descent = line.descent, .line_gap = 0 },            foreground,        );    }    if (pending_caret) |caret| writer.fillRect(caret.rect, caret.color);    if (writer.failure) |failure| return failure;}fn scaleRect(rect: Rect, scale: f32) Rect {    return .{        .x = rect.x * scale,        .y = rect.y * scale,        .width = rect.width * scale,        .height = rect.height * scale,    };}fn regionRect(region: Region) Rect {    return .{        .x = @floatFromInt(region.x),        .y = @floatFromInt(region.y),        .width = @floatFromInt(region.width),        .height = @floatFromInt(region.height),    };}fn intersects(left: Rect, right: Rect) bool {    return left.x < right.x + right.width and        right.x < left.x + left.width and        left.y < right.y + right.height and        right.y < left.y + left.height;}const GlyphCommandWriter = struct {    commands: *command.CommandBuffer,    clip: Rect,    failure: ?Allocator.Error = null,    fn drawGlyph(self: *GlyphCommandWriter, rect: Rect, image_index: u32, source: Rect, color: Color) void {        if (self.failure != null) return;        self.commands.append(.{            .kind = .glyph,            .rect = rect,            .clip = self.clip,            .source = source,            .color = color,            .image_index = image_index,        }) catch |failure| {            self.failure = failure;        };    }    pub fn fillRect(self: *GlyphCommandWriter, rect: Rect, color: Color) void {        if (self.failure != null) return;        self.commands.append(.{            .kind = .fill,            .rect = rect,            .clip = self.clip,            .color = color,        }) catch |failure| {            self.failure = failure;        };    }};const TextRunCursor = struct {    runs: []const UiTextRun,    index: usize = 0,    last_offset: usize = 0,    started: bool = false,    fn find(self: *TextRunCursor, byte_offset: usize) ?UiTextRun {        if (!self.started or byte_offset < self.last_offset) {            self.index = firstRunEndingAfter(self.runs, byte_offset);            self.started = true;        } else {            while (self.index < self.runs.len and self.runs[self.index].byte_end <= byte_offset) {                self.index += 1;            }        }        self.last_offset = byte_offset;        if (self.index >= self.runs.len) return null;        const run = self.runs[self.index];        if (byte_offset < run.byte_start) return null;        return run;    }};const TextRunRangeCursor = struct {    runs: []const UiTextRun,    index: usize = 0,    fn firstOverlap(self: *TextRunRangeCursor, byte_start: usize) usize {        while (self.index < self.runs.len and self.runs[self.index].byte_end <= byte_start) {            self.index += 1;        }        return self.index;    }};fn firstRunEndingAfter(runs: []const UiTextRun, byte_offset: usize) usize {    var low: usize = 0;    var high = runs.len;    while (low < high) {        const middle = low + (high - low) / 2;        if (runs[middle].byte_end <= byte_offset) {            low = middle + 1;        } else {            high = middle;        }    }    return low;}fn findTextRun(runs: []const UiTextRun, byte_offset: usize) ?UiTextRun {    const index = firstRunEndingAfter(runs, byte_offset);    if (index >= runs.len or byte_offset < runs[index].byte_start) return null;    return runs[index];}fn appendRunBackgroundCommands(    writer: *GlyphCommandWriter,    cursor: *TextRunRangeCursor,    plan: *const LinePlan,    visual: VisualLine,    line_start: usize,    origin_x: f32,    line_y: f32,    line_height: f32,    scale: f32,) void {    const visual_start = line_start + visual.byte_start;    const visual_end = line_start + visual.byte_end;    if (visual_end <= visual_start) return;    var index = cursor.firstOverlap(visual_start);    while (index < cursor.runs.len and cursor.runs[index].byte_start < visual_end) : (index += 1) {        const run = cursor.runs[index];        const color = run.background orelse continue;        const rect = textRunRect(            plan,            visual,            line_start,            @max(run.byte_start, visual_start),            @min(run.byte_end, visual_end),            origin_x,            line_y,            line_height,            scale,        ) orelse continue;        writer.fillRect(rect, color);    }}fn appendRunDecorationCommands(    writer: *GlyphCommandWriter,    cursor: *TextRunRangeCursor,    plan: *const LinePlan,    visual: VisualLine,    line_start: usize,    origin_x: f32,    line_y: f32,    origin_y: f32,    line_height: f32,    scale: f32,    device_scale: f32,    metrics: Metrics,    foreground: Color,) void {    const visual_start = line_start + visual.byte_start;    const visual_end = line_start + visual.byte_end;    if (visual_end <= visual_start) return;    const thickness = @max(device_scale, @min(line_height * 0.08, @max(device_scale, scale)));    const bottom = line_y + line_height - thickness;    const baseline = origin_y + metrics.ascent * scale;    const underline_y = @min(bottom, baseline + @max(device_scale, scale * 0.5));    const strike_y = std.math.clamp(origin_y + metrics.ascent * scale * 0.55, line_y, bottom);    var index = cursor.firstOverlap(visual_start);    while (index < cursor.runs.len and cursor.runs[index].byte_start < visual_end) : (index += 1) {        const run = cursor.runs[index];        if (!run.underline and !run.strikethrough) continue;        const range = textRunRect(            plan,            visual,            line_start,            @max(run.byte_start, visual_start),            @min(run.byte_end, visual_end),            origin_x,            0,            thickness,            scale,        ) orelse continue;        const color = run.foreground orelse foreground;        if (run.underline) {            writer.fillRect(.{                .x = range.x,                .y = underline_y,                .width = range.width,                .height = thickness,            }, color);        }        if (run.strikethrough) {            writer.fillRect(.{                .x = range.x,                .y = strike_y,                .width = range.width,                .height = thickness,            }, color);        }    }}fn textRunRect(    plan: *const LinePlan,    visual: VisualLine,    line_start: usize,    byte_start: usize,    byte_end: usize,    origin_x: f32,    y: f32,    height: f32,    scale: f32,) ?Rect {    if (byte_end <= byte_start) return null;    const start_x = origin_x + visual.advanceForByteOffset(        plan.run,        byte_start - line_start,        plan.content.len,    ) * scale;    const end_x = origin_x + visual.advanceForByteOffset(        plan.run,        byte_end - line_start,        plan.content.len,    ) * scale;    const left = @min(start_x, end_x);    const right = @max(start_x, end_x);    if (right <= left) return null;    return .{        .x = left,        .y = y,        .width = right - left,        .height = height,    };}const TextMarker = struct {    rect: Rect,    color: Color,};fn appendSelectionCommand(    writer: *GlyphCommandWriter,    selection: UiTextSelection,    plan: *const LinePlan,    visual: VisualLine,    line_start: usize,    origin_x: f32,    line_y: f32,    line_height: f32,    scale: f32,    foreground: Color,) void {    if (!selection.selection_active) return;    const selected = sortedSelection(selection);    const visual_start = line_start + visual.byte_start;    const visual_end = line_start + visual.byte_end;    const start = @max(selected.start, visual_start);    const end = @min(selected.end, visual_end);    if (end <= start) return;    const start_x = origin_x + visual.advanceForByteOffset(plan.run, start - line_start, plan.content.len) * scale;    const end_x = origin_x + visual.advanceForByteOffset(plan.run, end - line_start, plan.content.len) * scale;    writer.fillRect(.{        .x = start_x,        .y = line_y,        .width = end_x - start_x,        .height = line_height,    }, .{ .r = foreground.r, .g = foreground.g, .b = foreground.b, .a = 64 });}fn caretMarker(    atlas: *Atlas,    selection: UiTextSelection,    plan: *const LinePlan,    visual: VisualLine,    line_start: usize,    origin_x: f32,    line_y: f32,    line_height: f32,    scale: f32,    device_scale: f32,    foreground: Color,) ?TextMarker {    if (!selection.cursor_visible) return null;    if (selection.cursor_byte_offset < line_start) return null;    const cursor_offset = selection.cursor_byte_offset - line_start;    if (!visual.containsCaret(cursor_offset, .downstream)) return null;    const x = origin_x + visual.advanceForByteOffset(plan.run, cursor_offset, plan.content.len) * scale;    if (selection.cursor_block) {        return .{            .rect = .{                .x = x,                .y = line_y,                .width = caretBlockWidth(atlas, plan, visual, cursor_offset, scale, device_scale),                .height = @max(1, line_height),            },            .color = .{ .r = foreground.r, .g = foreground.g, .b = foreground.b, .a = 176 },        };    }    const inset = @min(line_height * 0.12, @max(device_scale, scale));    return .{        .rect = .{            .x = x,            .y = line_y + inset,            .width = @max(device_scale, scale),            .height = @max(1, line_height - inset * 2),        },        .color = foreground,    };}fn blockCursorHighlight(    widget: WidgetFrame,    plan: *const LinePlan,    visual: VisualLine,    line_start: usize,    foreground: Color,    run_background: ?Color,) ?CursorHighlight {    const selection = widget.text_selection;    if (!selection.cursor_visible or !selection.cursor_block) return null;    if (selection.cursor_byte_offset < line_start) return null;    const start = selection.cursor_byte_offset - line_start;    if (!visual.containsCaret(start, .downstream) or start >= visual.byte_end) return null;    const end = @min(nextCaretByteOffset(plan.run, plan.content, start), visual.byte_end);    if (end <= start) return null;    return .{        .lead_advance = visual.advanceForByteOffset(plan.run, start, plan.content.len),        .trail_advance = visual.advanceForByteOffset(plan.run, end, plan.content.len),        .color = run_background orelse widget.paint.background orelse contrastColor(foreground),    };}fn contrastColor(foreground: Color) Color {    const luminance = (@as(u32, foreground.r) * 299 + @as(u32, foreground.g) * 587 + @as(u32, foreground.b) * 114) / 1000;    if (luminance > 128) return .{ .r = 24, .g = 27, .b = 26, .a = 255 };    return .{ .r = 245, .g = 246, .b = 244, .a = 255 };}fn caretBlockWidth(atlas: *Atlas, plan: *const LinePlan, visual: VisualLine, cursor_offset: usize, scale: f32, device_scale: f32) f32 {    if (cursor_offset < visual.byte_end) {        const end = @min(nextCaretByteOffset(plan.run, plan.content, cursor_offset), visual.byte_end);        const lead = visual.advanceForByteOffset(plan.run, cursor_offset, plan.content.len) * scale;        const trail = visual.advanceForByteOffset(plan.run, end, plan.content.len) * scale;        if (trail > lead) return trail - lead;    }    const run = atlas.shape("M") catch return @max(device_scale, scale);    return @max(1, runAdvance(run) * scale);}const TextRange = struct {    start: usize,    end: usize,};fn sortedSelection(selection: UiTextSelection) TextRange {    const anchor = selection.selection_anchor_byte_offset;    const focus = selection.selection_focus_byte_offset;    return if (anchor <= focus)        .{ .start = anchor, .end = focus }    else        .{ .start = focus, .end = anchor };}fn findAtlasGlyph(atlas: filigree.GlyphAtlas, glyph_id: u32) ?usize {    for (atlas.glyphs, 0..) |glyph, index| {        if (glyph.glyph_id == glyph_id) return index;    }    return null;}fn synthCodepoint(line: []const u8, glyph: filigree.ShapedGlyph) ?u21 {    if (glyph.source_codepoint_count != 1) return null;    const start: usize = glyph.source_start;    const end: usize = glyph.source_end;    if (start >= end or end > line.len) return null;    const sequence = line[start..end];    const length = std.unicode.utf8ByteSequenceLength(sequence[0]) catch return null;    if (length > sequence.len) return null;    const codepoint = std.unicode.utf8Decode(sequence[0..length]) catch return null;    return if (synth.covered(codepoint)) codepoint else null;}fn drawSyntheticOrNotdef(    writer: anytype,    line: []const u8,    glyph: filigree.ShapedGlyph,    pen_x: i32,    line_y: f32,    line_height: f32,    origin_x: f32,    scale: f32,    color: Color,) void {    std.debug.assert(glyph.glyph_id == 0);    const cell = Rect{        .x = origin_x +            @as(f32, @floatFromInt(round26Dot6(addClampedI32(pen_x, glyph.x_offset)))) * scale,        .y = line_y,        .width = @as(f32, @floatFromInt(glyph.x_advance)) / 64 * scale,        .height = line_height,    };    if (synthCodepoint(line, glyph)) |codepoint| {        const drawn = synth.draw(writer, codepoint, cell, color);        std.debug.assert(drawn);        return;    }    synth.drawNotdef(writer, cell, color);}const CursorHighlight = struct {    lead_advance: f32,    trail_advance: f32,    color: Color,};fn glyphRunColor(pen_x: i32, cursor: ?CursorHighlight, color: Color) Color {    const highlight = cursor orelse return color;    const pen = @as(f32, @floatFromInt(pen_x)) / 64;    const epsilon = 0.01;    if (pen >= highlight.lead_advance - epsilon and pen < highlight.trail_advance - epsilon) return highlight.color;    return color;}fn drawCompositeStyledGlyphRunScaled(    writer: anytype,    plan: *const LinePlan,    visual: VisualLine,    line: []const u8,    line_start: usize,    line_y: f32,    line_height: f32,    origin_x: f32,    origin_y: f32,    scale: f32,    line_ascent: f32,    color: Color,    cursor: ?CursorHighlight,    run_cursor: *TextRunCursor,) void {    var pen_x: i32 = 0;    var pen_y: i32 = 0;    for (plan.run.glyphs[visual.glyph_start..visual.glyph_end], visual.glyph_start..) |glyph, glyph_index| {        const byte_offset = line_start + sourceOffset(glyph.source_start, line.len);        const text_run = run_cursor.find(byte_offset);        const styled_color = if (text_run) |value|            value.foreground orelse color        else            color;        const glyph_color = glyphRunColor(pen_x, cursor, styled_color);        if (glyph.glyph_id == 0) {            drawSyntheticOrNotdef(                writer,                line,                glyph,                pen_x,                line_y,                line_height,                origin_x,                scale,                glyph_color,            );            pen_x = addClampedI32(pen_x, glyph.x_advance);            pen_y = addClampedI32(pen_y, glyph.y_advance);            continue;        }        const source_index = plan.glyph_sources[glyph_index].segment_index;        const span = plan.metric_spans[source_index];        const atlas = span.atlas;        const atlas_index = atlas.glyph_index.get(glyph.glyph_id) orelse {            pen_x = addClampedI32(pen_x, glyph.x_advance);            pen_y = addClampedI32(pen_y, glyph.y_advance);            continue;        };        const atlas_glyph = atlas.atlas.glyphs[atlas_index];        const source = atlas.atlas.recs[atlas_index];        if (atlas_glyph.width <= 0 or atlas_glyph.height <= 0) {            pen_x = addClampedI32(pen_x, glyph.x_advance);            pen_y = addClampedI32(pen_y, glyph.y_advance);            continue;        }        const style_origin_y = origin_y + (line_ascent - span.ascent) * scale;        const rect = Rect{            .x = origin_x +                @as(f32, @floatFromInt(round26Dot6(addClampedI32(pen_x, glyph.x_offset)))) * scale +                @as(f32, @floatFromInt(atlas_glyph.offset_x)) * span.scale_ratio * scale,            .y = style_origin_y +                @as(f32, @floatFromInt(round26Dot6(addClampedI32(pen_y, glyph.y_offset)))) * scale +                @as(f32, @floatFromInt(atlas_glyph.offset_y)) * span.scale_ratio * scale,            .width = @as(f32, @floatFromInt(atlas_glyph.width)) * span.scale_ratio * scale,            .height = @as(f32, @floatFromInt(atlas_glyph.height)) * span.scale_ratio * scale,        };        writer.drawGlyph(rect, span.image_index, .{            .x = source.x,            .y = source.y,            .width = source.width,            .height = source.height,        }, glyph_color);        pen_x = addClampedI32(pen_x, glyph.x_advance);        pen_y = addClampedI32(pen_y, glyph.y_advance);    }}fn drawGlyphRunScaled(    writer: anytype,    atlas_image_index: u32,    atlas: *const Atlas,    run: filigree.GlyphRun,    line: []const u8,    line_y: f32,    line_height: f32,    origin_x: f32,    origin_y: f32,    scale: f32,    color: Color,    cursor: ?CursorHighlight,) void {    drawGlyphRunScaledMode(        false,        writer,        atlas_image_index,        atlas,        run,        line,        0,        line_y,        line_height,        origin_x,        origin_y,        scale,        color,        cursor,        null,    );}fn drawStyledGlyphRunScaled(    writer: anytype,    atlas_image_index: u32,    atlas: *const Atlas,    run: filigree.GlyphRun,    line: []const u8,    line_start: usize,    line_y: f32,    line_height: f32,    origin_x: f32,    origin_y: f32,    scale: f32,    color: Color,    cursor: ?CursorHighlight,    run_cursor: *TextRunCursor,) void {    drawGlyphRunScaledMode(        true,        writer,        atlas_image_index,        atlas,        run,        line,        line_start,        line_y,        line_height,        origin_x,        origin_y,        scale,        color,        cursor,        run_cursor,    );}fn drawGlyphRunScaledMode(    comptime styled: bool,    writer: anytype,    atlas_image_index: u32,    atlas: *const Atlas,    run: filigree.GlyphRun,    line: []const u8,    line_start: usize,    line_y: f32,    line_height: f32,    origin_x: f32,    origin_y: f32,    scale: f32,    color: Color,    cursor: ?CursorHighlight,    run_cursor: ?*TextRunCursor,) void {    var pen_x: i32 = 0;    var pen_y: i32 = 0;    for (run.glyphs) |glyph| {        const styled_color = if (styled) blk: {            const byte_offset = line_start + sourceOffset(glyph.source_start, line.len);            const text_run = run_cursor.?.find(byte_offset);            break :blk if (text_run) |value| value.foreground orelse color else color;        } else color;        const glyph_color = glyphRunColor(pen_x, cursor, styled_color);        if (glyph.glyph_id == 0) {            drawSyntheticOrNotdef(                writer,                line,                glyph,                pen_x,                line_y,                line_height,                origin_x,                scale,                glyph_color,            );            pen_x = addClampedI32(pen_x, glyph.x_advance);            pen_y = addClampedI32(pen_y, glyph.y_advance);            continue;        }        const atlas_index = atlas.glyph_index.get(glyph.glyph_id) orelse {            pen_x = addClampedI32(pen_x, glyph.x_advance);            pen_y = addClampedI32(pen_y, glyph.y_advance);            continue;        };        const atlas_glyph = atlas.atlas.glyphs[atlas_index];        const source = atlas.atlas.recs[atlas_index];        if (atlas_glyph.width <= 0 or atlas_glyph.height <= 0) {            pen_x = addClampedI32(pen_x, glyph.x_advance);            pen_y = addClampedI32(pen_y, glyph.y_advance);            continue;        }        const rect = Rect{            .x = origin_x + @as(f32, @floatFromInt(round26Dot6(addClampedI32(pen_x, glyph.x_offset)) + atlas_glyph.offset_x)) * scale,            .y = origin_y + @as(f32, @floatFromInt(round26Dot6(addClampedI32(pen_y, glyph.y_offset)) + atlas_glyph.offset_y)) * scale,            .width = @as(f32, @floatFromInt(atlas_glyph.width)) * scale,            .height = @as(f32, @floatFromInt(atlas_glyph.height)) * scale,        };        writer.drawGlyph(rect, atlas_image_index, .{            .x = source.x,            .y = source.y,            .width = source.width,            .height = source.height,        }, glyph_color);        pen_x = addClampedI32(pen_x, glyph.x_advance);        pen_y = addClampedI32(pen_y, glyph.y_advance);    }}fn runAdvance(run: filigree.GlyphRun) f32 {    return @as(f32, @floatFromInt(run.total_x_advance)) / 64;}fn glyphSliceAdvance(glyphs: []const filigree.ShapedGlyph) f32 {    var advance: f32 = 0;    for (glyphs) |glyph| advance += @as(f32, @floatFromInt(glyph.x_advance)) / 64;    return advance;}fn nextCaretByteOffset(run: filigree.GlyphRun, text: []const u8, byte_offset: usize) usize {    const target = @min(byte_offset, text.len);    if (target >= text.len) return text.len;    const map = run.clusterMap();    for (run.clusters, 0..) |cluster, cluster_index| {        const start = sourceOffset(cluster.source.start, text.len);        const end = sourceOffset(cluster.source.end, text.len);        if (end <= target) continue;        if (target < start) return start;        const stop_count = map.clusterCaretStopCount(cluster_index) orelse 0;        if (stop_count > 2) {            var stop_index: usize = 1;            while (stop_index < stop_count) : (stop_index += 1) {                const stop = map.clusterCaretStop(cluster_index, stop_index) orelse continue;                const offset = sourceOffset(stop, text.len);                if (offset > target) return offset;            }            return end;        }        return nextGraphemeBoundary(text, start, end, target);    }    return text.len;}fn nextGraphemeBoundary(text: []const u8, start: usize, end: usize, target: usize) usize {    if (end <= start) return end;    const source_start = std.math.cast(u32, start) orelse return end;    var iterator = filigree.unicode.SourceIterator.init(.{ .utf8 = text[start..end] }, source_start) catch return end;    var state: filigree.unicode.GraphemeState = .{};    while (iterator.next() catch return end) |scalar| {        const boundary = !state.consume(scalar.codepoint);        const offset = sourceOffset(scalar.source.start, text.len);        if (boundary and offset > target) return offset;    }    return end;}fn sourceOffset(offset: u32, text_len: usize) usize {    return @min(@as(usize, @intCast(offset)), text_len);}fn nextLineStart(content_len: usize, line_start: usize, line_len: usize) usize {    const line_end = @min(content_len, line_start + line_len);    return if (line_end < content_len) line_end + 1 else line_end;}fn textPointSize(atlas: *const Atlas, text: UiText) f32 {    if (std.math.isFinite(text.point_size) and text.point_size > 0) return @floatCast(text.point_size);    if (atlas.pixel_size > 0) return @floatFromInt(atlas.pixel_size);    return 16;}fn textScale(atlas: *const Atlas, text: UiText) f32 {    if (atlas.pixel_size <= 0) return 1;    return textPointSize(atlas, text) / @as(f32, @floatFromInt(atlas.pixel_size));}fn textWrapWidth(text: UiText) f32 {    if (std.math.isFinite(text.wrap_width) and text.wrap_width > 0) return @floatCast(text.wrap_width);    return 0;}fn textLineHeight(atlas: *const Atlas, text: UiText) f32 {    const multiplier = textLineHeightMultiplier(text);    const requested = textPointSize(atlas, text) * multiplier;    return @max(requested, atlas.metrics().height() * textScale(atlas, text));}fn textLineHeightMultiplier(text: UiText) f32 {    return if (std.math.isFinite(text.line_height) and text.line_height > 0)        @floatCast(text.line_height)    else        1.2;}fn alignedStart(start: f32, container: f32, content: f32, alignment: gui.model.UiTextAlign) f32 {    return switch (alignment) {        .start => start,        .center => start + @max(container - content, 0) / 2,        .end => start + @max(container - content, 0),    };}fn pixelCount(width: u32, height: u32) !usize {    return std.math.mul(usize, width, height) catch error.InvalidAtlas;}fn packRgba(color: Color) u32 {    return @as(u32, color.r) |        (@as(u32, color.g) << 8) |        (@as(u32, color.b) << 16) |        (@as(u32, color.a) << 24);}fn round26Dot6(value: i32) i32 {    if (value >= 0) return @divTrunc(value + 32, 64);    return @divTrunc(value - 32, 64);}fn addClampedI32(left: i32, right: i32) i32 {    const value = @as(i64, left) + @as(i64, right);    if (value > std.math.maxInt(i32)) return std.math.maxInt(i32);    if (value < std.math.minInt(i32)) return std.math.minInt(i32);    return @intCast(value);}const TestRecorder = struct {    glyph_count: usize = 0,    last_rect: Rect = .{},    last_source: Rect = .{},    last_color: Color = .{},    last_image_index: u32 = 0,    fn drawGlyph(self: *TestRecorder, rect: Rect, image_index: u32, source: Rect, color: Color) void {        self.glyph_count += 1;        self.last_rect = rect;        self.last_source = source;        self.last_color = color;        self.last_image_index = image_index;    }};const test_output_limits: filigree.Output.Limits = .{    .max_glyphs = 4096,    .max_ligature_carets = 4096,};const test_atlas_cache_limits: AtlasCacheStorage.Limits = .{    .measure_entries = 512,    .measure_payload_bytes = 64 * 1024,    .shape_entries = 1024,    .shape_payload_bytes = 512 * 1024,};fn initShapeOnlyAtlas(allocator: Allocator, bytes: []u8, pixel_size: i32) !Atlas {    errdefer allocator.free(bytes);    var font = filigree.Font.initFromBytes(bytes.ptr, bytes.len) orelse return error.InvalidFont;    errdefer font.deinit();    font.setScale(@floatFromInt(pixel_size), 72);    var cache = try AtlasCacheStorage.init(allocator, test_atlas_cache_limits);    errdefer cache.deinit(allocator);    cache.activate();    return .{        .allocator = allocator,        .pixel_size = pixel_size,        .atlas = .{},        .image = .{            .image = .{ .width = 0, .height = 0, .pixels = &.{} },            .pixels = &.{},        },        .cache = cache,        .backend = .{ .outline = .{            .font_bytes = bytes,            .font = font,            .context = filigree.Context.init(allocator, .{}),            .output = try filigree.Output.init(allocator, test_output_limits),        } },    };}test "packAtlasImageAlloc converts filigree atlas rgba to packed image" {    const allocator = std.testing.allocator;    var rgba = [_]u8{        255, 255, 255, 128,        10,  20,  30,  40,    };    const atlas = filigree.GlyphAtlas{        .rgba = rgba[0..],        .width = 2,        .height = 1,    };    var owned = try packAtlasImageAlloc(allocator, atlas);    defer owned.deinit(allocator);    try std.testing.expectEqual(@as(u32, 2), owned.image.width);    try std.testing.expectEqual(@as(u32, 1), owned.image.height);    try std.testing.expectEqual(@as(u32, 0x80ff_ffff), owned.pixels[0]);    try std.testing.expectEqual(@as(u32, 0x281e_140a), owned.pixels[1]);}test "drawGlyphRun emits atlas-backed glyph commands" {    var atlas_glyphs = [_]filigree.GlyphAtlasGlyph{.{        .glyph_id = 7,        .width = 3,        .height = 4,        .offset_x = 1,        .offset_y = 2,    }};    var atlas_recs = [_]filigree.GlyphAtlasRectangle{.{        .x = 5,        .y = 6,        .width = 3,        .height = 4,    }};    const atlas = filigree.GlyphAtlas{        .width = 8,        .height = 8,        .glyphs = atlas_glyphs[0..],        .recs = atlas_recs[0..],    };    const shaped = [_]filigree.ShapedGlyph{.{        .glyph_id = 7,        .cluster = 0,        .x_advance = 8 * 64,        .y_advance = 0,        .x_offset = 64,        .y_offset = 0,    }};    const run = filigree.GlyphRun{        .glyphs = shaped[0..],        .clusters = &.{},        .ligature_carets = &.{},        .total_x_advance = 8 * 64,        .total_y_advance = 0,        .direction = .ltr,        .writing_mode = .horizontal,        .output_order = .visual,    };    var recorder = TestRecorder{};    drawGlyphRun(&recorder, 4, atlas, run, 10, 20, .{ .r = 1, .g = 2, .b = 3, .a = 200 });    try std.testing.expectEqual(@as(usize, 1), recorder.glyph_count);    try std.testing.expectEqual(@as(u32, 4), recorder.last_image_index);    try std.testing.expectEqual(@as(f32, 12), recorder.last_rect.x);    try std.testing.expectEqual(@as(f32, 22), recorder.last_rect.y);    try std.testing.expectEqual(@as(f32, 3), recorder.last_rect.width);    try std.testing.expectEqual(@as(f32, 5), recorder.last_source.x);    try std.testing.expectEqual(@as(u8, 200), recorder.last_color.a);}test "drawGlyphRun consumes filigree shaped atlas output" {    const allocator = std.testing.allocator;    const bytes = try filigree.fixtures.createWithOutlines(allocator);    defer allocator.free(bytes);    var font = filigree.Font.initFromBytes(bytes.ptr, bytes.len) orelse return error.InvalidFont;    defer font.deinit();    font.setPixelHeightScale(20);    var context = filigree.Context.init(allocator, .{});    defer context.deinit();    var output = try filigree.Output.init(allocator, test_output_limits);    defer output.deinit(allocator);    try context.shapeRun(.{        .font = &font,        .text = .{ .utf8 = "A" },    }, &output);    const run = output.run();    try std.testing.expect(run.glyphs.len > 0);    var glyph_ids = try allocator.alloc(i32, run.glyphs.len);    defer allocator.free(glyph_ids);    var codepoints = try allocator.alloc(i32, run.glyphs.len);    defer allocator.free(codepoints);    for (run.glyphs, 0..) |glyph, index| {        glyph_ids[index] = std.math.cast(i32, glyph.glyph_id) orelse return error.GlyphIdTooLarge;        codepoints[index] = 'A';    }    const atlas = try filigree.glyphAtlasAlloc(allocator, allocator, bytes, 20, glyph_ids, codepoints, 2);    defer atlas.deinit(allocator);    var owned = try packAtlasImageAlloc(allocator, atlas);    defer owned.deinit(allocator);    var recorder = TestRecorder{};    drawGlyphRun(&recorder, 0, atlas, run, 0, 0, .{ .r = 20, .g = 30, .b = 40, .a = 255 });    try std.testing.expectEqual(run.glyphs.len, recorder.glyph_count);    try std.testing.expect(owned.image.width > 0);    try std.testing.expect(owned.image.height > 0);    try std.testing.expect(owned.pixels.len > 0);}test "bitmap atlas rasterizes cells and shapes ascii with fallback" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0x81, 0xFF } },        .{ .codepoint = '?', .rows = &.{ 0xFF, 0x00 } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    try std.testing.expectEqual(@as(i32, 18), atlas.atlas.width);    try std.testing.expectEqual(@as(i32, 2), atlas.atlas.height);    try std.testing.expectEqual(@as(u8, 255), atlas.atlas.rgba[3]);    try std.testing.expectEqual(@as(u8, 0), atlas.atlas.rgba[7]);    try std.testing.expect(atlas.image.image.width == 18);    const run = try atlas.shape("AZ\n");    try std.testing.expectEqual(@as(usize, 2), run.glyphs.len);    try std.testing.expectEqual(@as(u32, 'A'), run.glyphs[0].glyph_id);    try std.testing.expectEqual(@as(u32, '?'), run.glyphs[1].glyph_id);    try std.testing.expectEqual(@as(i32, 2 * 8 * 64), run.total_x_advance);    var recorder = TestRecorder{};    drawGlyphRun(&recorder, 0, atlas.atlas, run, 100, 200, .{ .r = 9, .g = 8, .b = 7, .a = 255 });    try std.testing.expectEqual(@as(usize, 2), recorder.glyph_count);    try std.testing.expectEqual(@as(f32, 108), recorder.last_rect.x);    try std.testing.expectEqual(@as(f32, 200), recorder.last_rect.y);    try std.testing.expectEqual(@as(f32, 9), recorder.last_source.x);}test "bitmap atlas measures scaled multiline text" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0x81, 0xFF } },        .{ .codepoint = '?', .rows = &.{ 0xFF, 0x00 } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const measured = try measure(&atlas, .{        .content = "AZ\nA",        .point_size = 20,        .line_height = 1.5,    });    try std.testing.expectApproxEqAbs(@as(f32, 20), measured.width, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 60), measured.height, 0.001);}test "bitmap atlas measures and paints Unicode wrapped text with one line plan" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = ' ', .rows = &.{ 0x00, 0x00 } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'D', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const wrapped = UiText{        .content = "AB CD",        .point_size = 16,        .line_height = 1,        .wrap_width = 24,    };    const measured = try measure(&atlas, wrapped);    try std.testing.expectApproxEqAbs(@as(f32, 24), measured.width, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 32), measured.height, 0.001);    const child = [_]UiNode{.{        .widget_id = 2,        .kind = .label,        .text = wrapped,        .paint = .{ .foreground = .{ .r = 255, .g = 255, .b = 255, .a = 255 } },        .size = .{ .width = 24, .height = 32 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 24, .height = 32 },        .root = .{            .widget_id = 1,            .children = child[0..],        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = entries[0..] };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    try std.testing.expectEqual(@as(usize, 5), commands.items().len);    try std.testing.expectApproxEqAbs(@as(f32, 16), commands.items()[3].rect.y - commands.items()[0].rect.y, 0.001);}test "multiline text geometry distinguishes soft affinity and hard empty lines" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'D', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'E', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'F', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = ' ', .rows = &.{ 0x00, 0x00 } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const entries = [_]AtlasSet.Entry{.{        .face = 0,        .image_index = 0,        .atlas = &atlas,    }};    const atlases = AtlasSet{ .entries = &entries };    const text = UiText{        .content = "AB CD\n\nEF",        .point_size = 16,        .line_height = 1,        .wrap_width = 24,        .horizontal_align = .center,        .vertical_align = .center,    };    const box = Size{ .width = 64, .height = 80 };    const upstream = try textCaretGeometry(        &atlases,        text,        box,        3,        .upstream,    );    try std.testing.expectEqual(@as(usize, 0), upstream.line_index);    try std.testing.expectApproxEqAbs(@as(f32, 44), upstream.x, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 8), upstream.y, 0.001);    const downstream = try textCaretGeometry(        &atlases,        text,        box,        3,        .downstream,    );    try std.testing.expectEqual(@as(usize, 1), downstream.line_index);    try std.testing.expectApproxEqAbs(@as(f32, 24), downstream.x, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 24), downstream.y, 0.001);    const hard_end = try textCaretGeometry(        &atlases,        text,        box,        5,        .downstream,    );    try std.testing.expectEqual(@as(usize, 1), hard_end.line_index);    try std.testing.expectApproxEqAbs(@as(f32, 40), hard_end.x, 0.001);    const empty = try textCaretGeometry(        &atlases,        text,        box,        6,        .downstream,    );    try std.testing.expectEqual(@as(usize, 2), empty.line_index);    try std.testing.expectApproxEqAbs(@as(f32, 32), empty.x, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 40), empty.y, 0.001);    const upstream_hit = try textHitTestPoint(        &atlases,        text,        box,        .{ .x = 60, .y = 12 },    );    try std.testing.expectEqual(@as(usize, 3), upstream_hit.byte_offset);    try std.testing.expectEqual(TextCaretAffinity.upstream, upstream_hit.affinity);    const downstream_hit = try textHitTestPoint(        &atlases,        text,        box,        .{ .x = 0, .y = 24 },    );    try std.testing.expectEqual(@as(usize, 3), downstream_hit.byte_offset);    try std.testing.expectEqual(TextCaretAffinity.downstream, downstream_hit.affinity);    const bottom = try textHitTestPoint(        &atlases,        text,        box,        .{ .x = 100, .y = 200 },    );    try std.testing.expectEqual(text.content.len, bottom.byte_offset);    try std.testing.expectEqual(@as(usize, 3), bottom.line_index);}test "widget text hit query honors translated clip and clamps to cluster boundaries" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 0x00E9, .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const entries = [_]AtlasSet.Entry{.{        .face = 0,        .image_index = 0,        .atlas = &atlas,    }};    const atlases = AtlasSet{ .entries = &entries };    const widget = WidgetFrame{        .root_id = 1,        .widget_id = 2,        .kind = .label,        .rect = .{ .x = 30, .y = -8, .width = 24, .height = 32 },        .visible_rect = .{ .x = 34, .y = 0, .width = 16, .height = 16 },        .paint = .{},        .scroll = .{},        .constraints = .{},        .content_size = .{ .width = 24, .height = 32 },        .focusable = false,        .has_text = true,        .text = .{            .content = "AéB\nAB",            .point_size = 16,            .line_height = 1,            .wrap_width = 24,        },    };    try std.testing.expect((try textHitTestWidgetPoint(        &atlases,        widget,        .{ .x = 33, .y = 4 },    )) == null);    const visible = (try textHitTestWidgetPoint(        &atlases,        widget,        .{ .x = 42, .y = 4 },    )).?;    const direct = try textHitTestPoint(        &atlases,        widget.text.?,        .{ .width = widget.rect.width, .height = widget.rect.height },        .{ .x = 12, .y = 12 },    );    try std.testing.expectEqual(direct.byte_offset, visible.byte_offset);    try std.testing.expectEqual(direct.affinity, visible.affinity);    const leading = (try textHitTestWidgetPointClamped(        &atlases,        widget,        .{ .x = -100, .y = -100 },    )).?;    const trailing = (try textHitTestWidgetPointClamped(        &atlases,        widget,        .{ .x = 100, .y = 100 },    )).?;    try std.testing.expect(leading.byte_offset <= trailing.byte_offset);    try std.testing.expect(        leading.byte_offset == 0 or            leading.byte_offset == widget.text.?.content.len or            widget.text.?.content[leading.byte_offset] & 0b1100_0000 != 0b1000_0000,    );    try std.testing.expect(        trailing.byte_offset == 0 or            trailing.byte_offset == widget.text.?.content.len or            widget.text.?.content[trailing.byte_offset] & 0b1100_0000 != 0b1000_0000,    );    try std.testing.expect((try textHitTestWidgetPointClamped(        &atlases,        .{            .root_id = widget.root_id,            .widget_id = widget.widget_id,            .kind = widget.kind,            .rect = widget.rect,            .visible_rect = .{},            .paint = widget.paint,            .scroll = widget.scroll,            .constraints = widget.constraints,            .content_size = widget.content_size,            .focusable = false,            .text = widget.text,        },        .{},    )) == null);}test "multiline text geometry follows mixed metric line boxes and end alignment" {    const allocator = std.testing.allocator;    const base_glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },    };    const large_glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F } },    };    var base_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &base_glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer base_atlas.deinit();    var large_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &large_glyphs,        .{ .width = 12, .height = 4, .stride = 2 },        24,        test_atlas_cache_limits,    );    defer large_atlas.deinit();    const styles = [_]UiTextStyle{.{        .font_asset_id = 2,        .point_size = 24,    }};    const runs = [_]UiTextRun{.{        .byte_start = 2,        .byte_end = 3,        .style_slot = 1,    }};    const text = UiText{        .content = "A\nBC",        .runs = &runs,        .styles = &styles,        .font_asset_id = 1,        .point_size = 16,        .line_height = 1,        .horizontal_align = .end,        .vertical_align = .end,    };    const entries = [_]AtlasSet.Entry{        .{ .face = 1, .image_index = 0, .atlas = &base_atlas },        .{ .face = 2, .image_index = 1, .atlas = &large_atlas },    };    const atlases = AtlasSet{ .entries = &entries };    const box = Size{ .width = 48, .height = 60 };    const first = try textCaretGeometry(        &atlases,        text,        box,        1,        .downstream,    );    try std.testing.expectEqual(@as(usize, 0), first.line_index);    try std.testing.expectApproxEqAbs(@as(f32, 48), first.x, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 20), first.y, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 16), first.height, 0.001);    const mixed = try textCaretGeometry(        &atlases,        text,        box,        3,        .downstream,    );    try std.testing.expectEqual(@as(usize, 1), mixed.line_index);    try std.testing.expectApproxEqAbs(@as(f32, 40), mixed.x, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 36), mixed.y, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 24), mixed.height, 0.001);}test "warmed multiline text geometry needs no backing allocation" {    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    const allocator = failing.allocator();    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = ' ', .rows = &.{ 0x00, 0x00 } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const entries = [_]AtlasSet.Entry{.{        .face = 0,        .image_index = 0,        .atlas = &atlas,    }};    const atlases = AtlasSet{ .entries = &entries };    const text = UiText{        .content = "AB AB\n\nAB AB",        .point_size = 16,        .line_height = 1,        .wrap_width = 24,        .vertical_align = .center,    };    const box = Size{ .width = 48, .height = 96 };    for (0..text.content.len + 1) |byte_offset| {        _ = try textCaretGeometry(            &atlases,            text,            box,            byte_offset,            .downstream,        );    }    _ = try textHitTestPoint(&atlases, text, box, .{ .x = 12, .y = 32 });    failing.fail_index = failing.alloc_index;    failing.resize_fail_index = failing.resize_index;    for (0..8) |_| {        for (0..text.content.len + 1) |byte_offset| {            _ = try textCaretGeometry(                &atlases,                text,                box,                byte_offset,                .downstream,            );        }        _ = try textHitTestPoint(&atlases, text, box, .{ .x = 12, .y = 32 });    }    try std.testing.expect(!failing.has_induced_failure);}test "multiline query geometry matches painted caret at device scales" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'D', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'E', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'F', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = ' ', .rows = &.{ 0x00, 0x00 } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const text = UiText{        .content = "AB CD\nEF",        .point_size = 16,        .line_height = 1,        .wrap_width = 24,        .horizontal_align = .center,        .vertical_align = .center,    };    const child = [_]UiNode{.{        .widget_id = 2,        .kind = .text_input,        .text = text,        .text_selection = .{            .cursor_visible = true,            .cursor_byte_offset = 3,        },        .paint = .{            .foreground = .{ .r = 240, .g = 240, .b = 240, .a = 255 },        },        .size = .{ .width = 64, .height = 80 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 80, .height = 96 },        .root = .{ .widget_id = 1, .children = &child },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    const widget = frame.widgets[1];    const entries = [_]AtlasSet.Entry{.{        .face = 0,        .image_index = 0,        .atlas = &atlas,    }};    const atlases = AtlasSet{ .entries = &entries };    const geometry = try textCaretGeometry(        &atlases,        text,        .{ .width = widget.rect.width, .height = widget.rect.height },        3,        .downstream,    );    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    for ([_]f32{ 1, 2 }) |device_scale| {        commands.reset();        try appendFrameCommands(            &commands,            frame,            &atlases,            device_scale,            0,        );        const caret = commands.items()[commands.items().len - 1];        try std.testing.expectEqual(command.Kind.fill, caret.kind);        try std.testing.expectApproxEqAbs(            (widget.rect.x + geometry.x) * device_scale,            caret.rect.x,            0.001,        );        try std.testing.expect(            caret.rect.y >= (widget.rect.y + geometry.y) * device_scale,        );        try std.testing.expect(            caret.rect.y + caret.rect.height <=                (widget.rect.y + geometry.y + geometry.height) * device_scale,        );    }}test "shape cache preserves cluster and ligature caret geometry" {    const allocator = std.testing.allocator;    const bytes = try filigree.fixtures.createWithGsubLigatureAndGdefCarets(allocator);    var atlas = try initShapeOnlyAtlas(allocator, bytes, 20);    defer atlas.deinit();    const text = "fi";    const fresh = try atlas.shapeUncached(text);    const expected_glyphs = try allocator.dupe(filigree.ShapedGlyph, fresh.glyphs);    defer allocator.free(expected_glyphs);    const expected_clusters = try allocator.dupe(filigree.Cluster, fresh.clusters);    defer allocator.free(expected_clusters);    const expected_carets = try allocator.dupe(filigree.LigatureCaret, fresh.ligature_carets);    defer allocator.free(expected_carets);    const expected = filigree.GlyphRun{        .glyphs = expected_glyphs,        .clusters = expected_clusters,        .ligature_carets = expected_carets,        .total_x_advance = fresh.total_x_advance,        .total_y_advance = fresh.total_y_advance,        .direction = fresh.direction,        .writing_mode = fresh.writing_mode,        .output_order = fresh.output_order,    };    const cached = try atlas.shape(text);    try expectGlyphRunEqual(expected, cached);    try std.testing.expect(cached.clusters.len > 0);    try std.testing.expect(cached.ligature_carets.len > 0);    try std.testing.expectEqual(        shapePayloadBytes(text, cached).?,        atlas.cacheStatus().shape.payload_bytes,    );    try std.testing.expectEqual(        filigree.caret.advanceForByteOffset(expected, 1, text.len),        try atlas.advanceForByteOffset(text, 1),    );    try std.testing.expectEqual(        filigree.caret.hitTestAdvance(expected, 4.6, text),        try atlas.hitTestAdvance(text, 4.6),    );    _ = try atlas.shape("A");    const retained = try atlas.shape(text);    try expectGlyphRunEqual(expected, retained);    try std.testing.expectEqual(cached.glyphs.ptr, retained.glyphs.ptr);    try std.testing.expectEqual(cached.clusters.ptr, retained.clusters.ptr);    try std.testing.expectEqual(cached.ligature_carets.ptr, retained.ligature_carets.ptr);}test "style boundaries inside ligatures keep one glyph and use its cluster start" {    const allocator = std.testing.allocator;    const bytes = try filigree.fixtures.createWithGsubLigatureAndGdefCarets(allocator);    var atlas = try initShapeOnlyAtlas(allocator, bytes, 20);    defer atlas.deinit();    const content = "fi";    const run = try atlas.shape(content);    try std.testing.expectEqual(@as(usize, 1), run.glyphs.len);    try std.testing.expectEqual(@as(u32, 0), run.glyphs[0].source_start);    const glyph_start = sourceOffset(run.glyphs[0].source_start, content.len);    const trailing_style = [_]UiTextRun{.{        .byte_start = 1,        .byte_end = 2,        .foreground = .{ .r = 220, .g = 30, .b = 20 },    }};    var trailing_cursor = TextRunCursor{ .runs = &trailing_style };    try std.testing.expect(trailing_cursor.find(glyph_start) == null);    const leading_style = [_]UiTextRun{.{        .byte_start = 0,        .byte_end = 1,        .foreground = .{ .r = 20, .g = 80, .b = 220 },    }};    var leading_cursor = TextRunCursor{ .runs = &leading_style };    try std.testing.expectEqual(        leading_style[0],        leading_cursor.find(glyph_start).?,    );    try std.testing.expectEqual(        try measure(&atlas, .{ .content = content }),        try measure(&atlas, .{ .content = content, .runs = &trailing_style }),    );}test "cached combining and ZWJ caret queries match fresh shaping" {    const allocator = std.testing.allocator;    const bytes = try filigree.fixtures.createWithOutlines(allocator);    var atlas = try initShapeOnlyAtlas(allocator, bytes, 20);    defer atlas.deinit();    const cases = [_][]const u8{        "e\u{0301}",        "\u{1f469}\u{200d}\u{1f4bb}",    };    for (cases) |text| {        const fresh = try atlas.shapeUncached(text);        const expected_glyphs = try allocator.dupe(filigree.ShapedGlyph, fresh.glyphs);        defer allocator.free(expected_glyphs);        const expected_clusters = try allocator.dupe(filigree.Cluster, fresh.clusters);        defer allocator.free(expected_clusters);        const expected_carets = try allocator.dupe(filigree.LigatureCaret, fresh.ligature_carets);        defer allocator.free(expected_carets);        const expected = filigree.GlyphRun{            .glyphs = expected_glyphs,            .clusters = expected_clusters,            .ligature_carets = expected_carets,            .total_x_advance = fresh.total_x_advance,            .total_y_advance = fresh.total_y_advance,            .direction = fresh.direction,            .writing_mode = fresh.writing_mode,            .output_order = fresh.output_order,        };        try std.testing.expect(expected.clusters.len > 0);        for (0..text.len + 1) |byte_offset| {            try std.testing.expectEqual(                filigree.caret.advanceForByteOffset(expected, byte_offset, text.len),                try atlas.advanceForByteOffset(text, byte_offset),            );        }        for (0..33) |raw_advance| {            const advance: f32 = @floatFromInt(raw_advance);            try std.testing.expectEqual(                filigree.caret.hitTestAdvance(expected, advance, text),                try atlas.hitTestAdvance(text, advance),            );        }    }}test "wrapped markers preserve glyph geometry and partition selection by visual line" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'D', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'E', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'F', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = ' ', .rows = &.{ 0x00, 0x00 } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const text = UiText{        .content = "AB CD EF",        .point_size = 16,        .line_height = 1,        .wrap_width = 24,    };    const nodes = [_]UiNode{        .{            .widget_id = 2,            .kind = .text_input,            .text = text,            .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },            .size = .{ .width = 24, .height = 48 },        },        .{            .widget_id = 2,            .kind = .text_input,            .text = text,            .text_selection = .{                .cursor_visible = true,                .cursor_byte_offset = 7,                .selection_active = true,                .selection_anchor_byte_offset = 1,                .selection_focus_byte_offset = 7,            },            .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },            .size = .{ .width = 24, .height = 48 },        },        .{            .widget_id = 2,            .kind = .text_input,            .text = text,            .text_selection = .{                .cursor_visible = true,                .cursor_byte_offset = 7,            },            .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },            .size = .{ .width = 24, .height = 48 },        },    };    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = &entries };    var frames: [3]gui.frame.Workspace = .{        gui.frame.Workspace.init(allocator),        gui.frame.Workspace.init(allocator),        gui.frame.Workspace.init(allocator),    };    defer for (&frames) |*frame| frame.deinit();    var buffers: [3]command.CommandBuffer = .{        command.CommandBuffer.init(allocator),        command.CommandBuffer.init(allocator),        command.CommandBuffer.init(allocator),    };    defer for (&buffers) |*buffer| buffer.deinit();    for (0..nodes.len) |index| {        const surface = gui.model.UiSurfaceTree{            .available_size = .{ .width = 24, .height = 48 },            .root = .{ .widget_id = 1, .children = nodes[index .. index + 1] },        };        const frame = try frames[index].buildSurface(&surface, .{});        try appendFrameCommands(&buffers[index], frame, &atlases, 1, 0);    }    var unfocused_glyphs: [16]command.Command = undefined;    var unfocused_count: usize = 0;    for (buffers[0].items()) |item| {        if (item.kind != .glyph) continue;        unfocused_glyphs[unfocused_count] = item;        unfocused_count += 1;    }    var focused_count: usize = 0;    var selection_y: [3]f32 = undefined;    var selection_count: usize = 0;    for (buffers[1].items()) |item| {        if (item.kind == .glyph) {            const expected = unfocused_glyphs[focused_count];            try std.testing.expectEqual(expected.kind, item.kind);            try std.testing.expectEqual(expected.rect, item.rect);            try std.testing.expectEqual(expected.clip, item.clip);            try std.testing.expectEqual(expected.source, item.source);            try std.testing.expectEqual(expected.color, item.color);            try std.testing.expectEqual(expected.image_index, item.image_index);            focused_count += 1;        }        if (item.kind == .fill and item.color.a == 64) {            selection_y[selection_count] = item.rect.y;            selection_count += 1;        }    }    try std.testing.expectEqual(@as(usize, 8), unfocused_count);    try std.testing.expectEqual(unfocused_count, focused_count);    try std.testing.expectEqual(@as(usize, 3), selection_count);    try std.testing.expectApproxEqAbs(@as(f32, 16), selection_y[1] - selection_y[0], 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 16), selection_y[2] - selection_y[1], 0.001);    const fragment_id = command.FragmentId{        .root_id = 1,        .element_id = 2,        .namespace = command.fragment_namespace_widget,        .part = command.fragment_part_text,    };    try buffers[0].commitFragment(fragment_id, 0);    try buffers[2].commitFragment(fragment_id, 0);    var retained = gui.paint.RetainedCommands.init(allocator);    defer retained.deinit();    try retained.retain(&buffers[0]);    const damage = try retained.diff(        &buffers[2],        &.{Region.full(320, 200)},        320,        200,    );    const narrowed = switch (damage) {        .semantic => return error.ExpectedNarrowedDamage,        .narrowed => |value| value,    };    try std.testing.expectEqual(@as(usize, 1), narrowed.slice().len);    const bounds = narrowed.bounding().?;    try std.testing.expect(bounds.width <= 3);    try std.testing.expect(bounds.height <= 20);}test "bitmap wrapped measurement reuses warmed line workspace" {    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    const allocator = failing.allocator();    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = ' ', .rows = &.{ 0x00, 0x00 } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'D', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const wrapped = UiText{        .content = "AB CD",        .point_size = 16,        .line_height = 1,        .wrap_width = 24,    };    _ = try measureUncached(&atlas, wrapped);    failing.fail_index = failing.alloc_index;    failing.resize_fail_index = failing.resize_index;    const repeated = try measureUncached(&atlas, wrapped);    try std.testing.expectApproxEqAbs(@as(f32, 32), repeated.height, 0.001);    try std.testing.expect(!failing.has_induced_failure);}test "warmed visual line and caret queries need no backing allocation" {    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    const allocator = failing.allocator();    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = ' ', .rows = &.{ 0x00, 0x00 } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const text = "AB AB AB AB AB AB";    _ = try LinePlan.init(&atlas, text, 24);    for (0..text.len + 1) |byte_offset| {        _ = try atlas.advanceForByteOffset(text, byte_offset);    }    failing.fail_index = failing.alloc_index;    failing.resize_fail_index = failing.resize_index;    for (0..8) |_| {        const plan = try LinePlan.init(&atlas, text, 24);        var iterator = plan.iterator();        while (iterator.next(&plan)) |visual| {            _ = visual.advanceForByteOffset(plan.run, visual.byte_start, text.len);            _ = visual.advanceForByteOffset(plan.run, visual.byte_end, text.len);        }        for (0..text.len + 1) |byte_offset| {            const advance = try atlas.advanceForByteOffset(text, byte_offset);            _ = try atlas.hitTestAdvance(text, advance);        }    }    try std.testing.expect(!failing.has_induced_failure);}test "atlas metrics derive from face and bitmap cell geometry" {    const allocator = std.testing.allocator;    var scratch = try AtlasScratch.init(allocator, .{ .bytes = 1024 * 1024 });    defer scratch.deinit(allocator);    const bytes = try filigree.fixtures.createWithOutlines(allocator);    var outline_atlas = try Atlas.initFromOwnedBytes(        allocator,        &scratch,        bytes,        20,        test_atlas_cache_limits,        test_output_limits,    );    defer outline_atlas.deinit();    const outline_metrics = outline_atlas.metrics();    const face = outline_atlas.backend.outline.font.face;    const upem: f32 = @floatFromInt(face.units_per_em);    try std.testing.expectApproxEqAbs(        @as(f32, @floatFromInt(face.ascender)) * 20.0 / upem,        outline_metrics.ascent,        0.001,    );    try std.testing.expectApproxEqAbs(        @as(f32, @floatFromInt(-@as(i32, face.descender))) * 20.0 / upem,        outline_metrics.descent,        0.001,    );    try std.testing.expect(outline_metrics.height() > 0);    const glyphs = [_]BitmapGlyph{.{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } }};    var bitmap_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer bitmap_atlas.deinit();    const bitmap_metrics = bitmap_atlas.metrics();    try std.testing.expectApproxEqAbs(@as(f32, 2), bitmap_metrics.ascent, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 0), bitmap_metrics.descent, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 2), bitmap_metrics.height(), 0.001);}test "fallback face segments preserve primary runs and paint final notdef" {    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    const allocator = failing.allocator();    var scratch = try AtlasScratch.init(allocator, .{ .bytes = 1024 * 1024 });    defer scratch.deinit(allocator);    const primary_bytes = try filigree.fixtures.createWithOutlines(allocator);    var primary = try Atlas.initFromOwnedBytes(        allocator,        &scratch,        primary_bytes,        18,        test_atlas_cache_limits,        test_output_limits,    );    defer primary.deinit();    const fallback_bytes = try filigree.fixtures.createFallbackWithOutlines(allocator);    var fallback_atlas = try Atlas.initFromOwnedBytes(        allocator,        &scratch,        fallback_bytes,        18,        test_atlas_cache_limits,        test_output_limits,    );    defer fallback_atlas.deinit();    var fallback = try fallback_mod.Engine.init(allocator, .{        .max_source_units = 32,        .cache_entries = 8,        .cache_payload_bytes = 1024,    }, test_output_limits);    defer fallback.deinit();    const entries = [_]AtlasSet.Entry{.{        .face = 1,        .image_index = 3,        .atlas = &primary,    }};    const fallback_entries = [_]AtlasSet.Entry{.{        .face = 0,        .image_index = 9,        .atlas = &fallback_atlas,    }};    const atlases = AtlasSet{        .entries = &entries,        .fallback_entries = &fallback_entries,        .fallback = &fallback,    };    const content = "A\u{3b2}B\u{3bb}";    const text = UiText{        .content = content,        .font_asset_id = 1,        .point_size = 18,        .line_height = 1,    };    const plan = try LinePlan.initComposite(&primary, &atlases, text, content, 0, 0);    try std.testing.expectEqual(@as(usize, 4), plan.run.glyphs.len);    try std.testing.expectEqual(@as(usize, 4), plan.metric_spans.len);    try std.testing.expectEqual(@as(u32, 3), plan.metric_spans[plan.glyph_sources[0].segment_index].image_index);    try std.testing.expectEqual(@as(u32, 9), plan.metric_spans[plan.glyph_sources[1].segment_index].image_index);    try std.testing.expectEqual(@as(u32, 3), plan.metric_spans[plan.glyph_sources[2].segment_index].image_index);    try std.testing.expectEqual(@as(u32, 9), plan.metric_spans[plan.glyph_sources[3].segment_index].image_index);    try std.testing.expectEqual(@as(u32, 0), plan.run.glyphs[3].glyph_id);    try std.testing.expect(!fallback_atlas.glyph_index.contains(0));    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 96, .height = 24 },        .root = .{            .widget_id = 1,            .children = &.{.{                .widget_id = 2,                .kind = .label,                .text = text,                .size = .{ .width = 96, .height = 24 },            }},        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{        .resolvers = frameResolvers(&atlases),    });    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    var glyph_images: [3]u32 = undefined;    var glyph_count: usize = 0;    var fill_count: usize = 0;    for (commands.items()) |item| {        switch (item.kind) {            .glyph => {                glyph_images[glyph_count] = item.image_index;                glyph_count += 1;            },            .fill => fill_count += 1,            else => {},        }    }    try std.testing.expectEqual(@as(usize, 3), glyph_count);    try std.testing.expectEqualSlices(u32, &.{ 3, 9, 3 }, &glyph_images);    try std.testing.expectEqual(@as(usize, 4), fill_count);    const primary_plan = try textCaretPlan(&atlases, .{        .content = "AB",        .font_asset_id = 1,        .point_size = 18,        .line_height = 1,    });    try std.testing.expectEqual(@as(usize, 0), primary_plan.plan.glyph_sources.len);    try expectGlyphRunEqual(try primary.shape("AB"), primary_plan.plan.run);    const primary_font = primary.outlineFont().?;    const fallback_font = fallback_atlas.outlineFont().?;    _ = try fallback.segments(primary_font, fallback_font, content);    failing.fail_index = failing.alloc_index;    failing.resize_fail_index = failing.resize_index;    for (0..1024) |_| {        _ = try fallback.segments(primary_font, fallback_font, content);    }    try std.testing.expect(!failing.has_induced_failure);}fn appendComposerPromptCommands(    atlases: *const AtlasSet,    workspace: *gui.frame.Workspace,    commands: *command.CommandBuffer,) !void {    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 256, .height = 24 },        .root = .{            .widget_id = 1,            .children = &.{.{                .widget_id = 2,                .kind = .label,                .text = .{                    .content = "\u{276f} review styled text",                    .font_asset_id = 1,                    .point_size = 18,                    .line_height = 1,                },                .size = .{ .width = 256, .height = 24 },            }},        },    };    const frame = try workspace.buildSurface(&surface, .{        .resolvers = frameResolvers(atlases),    });    try appendFrameCommands(commands, frame, atlases, 1, 0);}test "composer prompt glyph renders exactly with and without fallback face" {    const allocator = std.testing.allocator;    var scratch = try AtlasScratch.init(allocator, .{ .bytes = 1024 * 1024 });    defer scratch.deinit(allocator);    const primary_bytes = try filigree.fixtures.createWithOutlines(allocator);    var primary = try Atlas.initFromOwnedBytes(        allocator,        &scratch,        primary_bytes,        18,        test_atlas_cache_limits,        test_output_limits,    );    defer primary.deinit();    const fallback_bytes = try filigree.fixtures.createFallbackWithOutlines(allocator);    var fallback_atlas = try Atlas.initFromOwnedBytes(        allocator,        &scratch,        fallback_bytes,        18,        test_atlas_cache_limits,        test_output_limits,    );    defer fallback_atlas.deinit();    var fallback = try fallback_mod.Engine.init(allocator, .{        .max_source_units = 64,        .cache_entries = 4,        .cache_payload_bytes = 1024,    }, test_output_limits);    defer fallback.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 1, .image_index = 3, .atlas = &primary }};    const fallback_entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 9, .atlas = &fallback_atlas }};    const atlas_sets = [_]AtlasSet{        .{ .entries = &entries },        .{ .entries = &entries, .fallback_entries = &fallback_entries, .fallback = &fallback },    };    var workspaces = [_]gui.frame.Workspace{ gui.frame.Workspace.init(allocator), gui.frame.Workspace.init(allocator) };    defer for (&workspaces) |*workspace| workspace.deinit();    var buffers = [_]command.CommandBuffer{ command.CommandBuffer.init(allocator), command.CommandBuffer.init(allocator) };    defer for (&buffers) |*buffer| buffer.deinit();    for (&atlas_sets, 0..) |*atlases, index| {        try appendComposerPromptCommands(atlases, &workspaces[index], &buffers[index]);    }    try std.testing.expectEqual(buffers[0].items().len, buffers[1].items().len);    for (buffers[0].items(), buffers[1].items()) |without_fallback, with_fallback| {        try std.testing.expect(std.meta.eql(without_fallback, with_fallback));    }}test "outline atlas scratch admits its measured maximum and rejects one byte less" {    const allocator = std.testing.allocator;    var survey = try AtlasScratch.init(allocator, .{ .bytes = 1024 * 1024 });    defer survey.deinit(allocator);    const survey_bytes = try filigree.fixtures.createWithOutlines(allocator);    var surveyed = try Atlas.initFromOwnedBytes(        allocator,        &survey,        survey_bytes,        20,        test_atlas_cache_limits,        test_output_limits,    );    surveyed.deinit();    const measured = survey.status().high_water_bytes;    try std.testing.expect(measured > 0);    var exact = try AtlasScratch.init(allocator, .{ .bytes = measured });    defer exact.deinit(allocator);    const exact_bytes = try filigree.fixtures.createWithOutlines(allocator);    var admitted = try Atlas.initFromOwnedBytes(        allocator,        &exact,        exact_bytes,        20,        test_atlas_cache_limits,        test_output_limits,    );    admitted.deinit();    try std.testing.expectEqual(measured, exact.status().high_water_bytes);    try std.testing.expectEqual(@as(usize, 0), exact.status().exhaustions);    var short = try AtlasScratch.init(allocator, .{ .bytes = measured - 1 });    defer short.deinit(allocator);    const short_bytes = try filigree.fixtures.createWithOutlines(allocator);    try std.testing.expectError(        error.OutOfMemory,        Atlas.initFromOwnedBytes(            allocator,            &short,            short_bytes,            20,            test_atlas_cache_limits,            test_output_limits,        ),    );    try std.testing.expectEqual(@as(usize, 1), short.status().epochs);    try std.testing.expect(short.status().exhaustions > 0);}test "appendFrameCommands keeps glyph runs inside their line box" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'g', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const child = [_]gui.model.UiNode{.{        .widget_id = 2,        .kind = .label,        .text = .{ .content = "Ag\ngA", .point_size = 16, .line_height = 1.5 },        .paint = .{ .foreground = .{ .r = 255, .g = 255, .b = 255, .a = 255 } },        .size = .{ .width = 64, .height = 48 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 80, .height = 64 },        .root = .{            .widget_id = 1,            .children = child[0..],        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = entries[0..] };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    var block_y: f32 = 0;    for (frame.widgets) |widget| {        if (widget.text != null) block_y = widget.rect.y;    }    const line_height: f32 = 24;    const half_leading: f32 = (line_height - 2) / 2;    var glyph_index: usize = 0;    for (commands.items()) |item| {        if (item.kind != .glyph) continue;        const line_index: f32 = if (glyph_index < 2) 0 else 1;        const line_top = block_y + line_index * line_height;        try std.testing.expectApproxEqAbs(line_top + half_leading, item.rect.y, 0.001);        try std.testing.expect(item.rect.y >= line_top);        try std.testing.expect(item.rect.y + item.rect.height <= line_top + line_height);        glyph_index += 1;    }    try std.testing.expectEqual(@as(usize, 4), glyph_index);}test "appendFrameCommands paints the glyph under a block cursor in the background color" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'm', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'e', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const background = gui.model.UiColor{ .r = 30, .g = 33, .b = 39, .a = 255 };    const child = [_]gui.model.UiNode{.{        .widget_id = 2,        .kind = .label,        .text = .{ .content = "me", .point_size = 16, .line_height = 1.5 },        .text_selection = .{ .cursor_visible = true, .cursor_block = true, .cursor_byte_offset = 0 },        .paint = .{            .foreground = .{ .r = 220, .g = 223, .b = 228, .a = 255 },            .background = background,        },        .size = .{ .width = 64, .height = 24 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 80, .height = 32 },        .root = .{            .widget_id = 1,            .children = child[0..],        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = entries[0..] };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    var saw_fill = false;    var glyph_colors: [2]Color = undefined;    var glyph_count: usize = 0;    for (commands.items()) |item| {        switch (item.kind) {            .fill => saw_fill = true,            .glyph => {                glyph_colors[glyph_count] = item.color;                glyph_count += 1;            },            else => {},        }    }    try std.testing.expect(saw_fill);    try std.testing.expectEqual(@as(usize, 2), glyph_count);    try std.testing.expectEqual(background.r, glyph_colors[0].r);    try std.testing.expectEqual(background.g, glyph_colors[0].g);    try std.testing.expectEqual(background.b, glyph_colors[0].b);    try std.testing.expectEqual(@as(u8, 220), glyph_colors[1].r);}test "appendFrameCommands scales glyph commands to text point size" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0x81, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const child = [_]gui.model.UiNode{.{        .widget_id = 2,        .kind = .label,        .text = .{ .content = "A", .point_size = 32, .line_height = 1.0 },        .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },        .size = .{ .width = 64, .height = 40 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 80, .height = 48 },        .root = .{            .widget_id = 1,            .children = child[0..],        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = entries[0..] };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    try std.testing.expect(commands.items().len > 0);    try std.testing.expectApproxEqAbs(@as(f32, 16), commands.items()[0].rect.width, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 4), commands.items()[0].rect.height, 0.001);}test "appendFrameCommands scales glyph geometry by device scale and keeps atlas sources" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0x81, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const child = [_]gui.model.UiNode{.{        .widget_id = 2,        .kind = .label,        .text = .{ .content = "A", .point_size = 16, .line_height = 1.0 },        .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },        .size = .{ .width = 64, .height = 40 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 80, .height = 48 },        .root = .{            .widget_id = 1,            .children = child[0..],        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = entries[0..] };    var logical = command.CommandBuffer.init(allocator);    defer logical.deinit();    try appendFrameCommands(&logical, frame, &atlases, 1, 0);    var device = command.CommandBuffer.init(allocator);    defer device.deinit();    try appendFrameCommands(&device, frame, &atlases, 2, 0);    try std.testing.expectEqual(logical.items().len, device.items().len);    for (logical.items(), device.items()) |one, two| {        try std.testing.expectEqual(one.kind, two.kind);        try std.testing.expectApproxEqAbs(one.rect.x * 2, two.rect.x, 0.001);        try std.testing.expectApproxEqAbs(one.rect.y * 2, two.rect.y, 0.001);        try std.testing.expectApproxEqAbs(one.rect.width * 2, two.rect.width, 0.001);        try std.testing.expectApproxEqAbs(one.rect.height * 2, two.rect.height, 0.001);        try std.testing.expectApproxEqAbs(one.clip.x * 2, two.clip.x, 0.001);        try std.testing.expectEqual(one.source.x, two.source.x);        try std.testing.expectEqual(one.source.width, two.source.width);    }}test "appendFrameCommands draws text selection fills before glyph commands" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'D', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const child = [_]gui.model.UiNode{.{        .widget_id = 2,        .kind = .text_input,        .text = .{ .content = "ABCD", .point_size = 16, .line_height = 1.0 },        .text_selection = .{            .cursor_visible = true,            .cursor_byte_offset = 2,            .selection_active = true,            .selection_anchor_byte_offset = 1,            .selection_focus_byte_offset = 3,        },        .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },        .size = .{ .width = 64, .height = 20 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 80, .height = 32 },        .root = .{            .widget_id = 1,            .children = child[0..],        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = entries[0..] };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    try std.testing.expectEqual(@as(usize, 6), commands.items().len);    try std.testing.expectEqual(command.Kind.fill, commands.items()[0].kind);    try std.testing.expectEqual(command.Kind.glyph, commands.items()[1].kind);    try std.testing.expectEqual(command.Kind.fill, commands.items()[5].kind);    try std.testing.expectApproxEqAbs(@as(f32, 8), commands.items()[0].rect.x, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 16), commands.items()[0].rect.width, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 16), commands.items()[5].rect.x, 0.001);    try std.testing.expect(commands.items()[0].rect.width > commands.items()[5].rect.width);}test "styled text runs preserve layout caret and selection geometry" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'D', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const runs = [_]UiTextRun{        .{            .byte_start = 1,            .byte_end = 2,            .foreground = .{ .r = 220, .g = 30, .b = 20, .a = 255 },            .background = .{ .r = 15, .g = 35, .b = 90, .a = 180 },            .underline = true,        },        .{            .byte_start = 2,            .byte_end = 4,            .foreground = .{ .r = 20, .g = 190, .b = 70, .a = 255 },            .strikethrough = true,        },    };    const plain = UiText{ .content = "ABCD", .point_size = 16, .line_height = 1 };    const styled = UiText{        .content = plain.content,        .runs = &runs,        .point_size = plain.point_size,        .line_height = plain.line_height,        .wrap_width = plain.wrap_width,    };    const selection = UiTextSelection{        .cursor_visible = true,        .cursor_byte_offset = 3,        .selection_active = true,        .selection_anchor_byte_offset = 1,        .selection_focus_byte_offset = 4,    };    try std.testing.expectEqual(try measure(&atlas, plain), try measure(&atlas, styled));    try std.testing.expectEqual(@as(usize, 1), atlas.cacheStatus().measure.entries);    const nodes = [_]UiNode{        .{            .widget_id = 2,            .kind = .label,            .text = plain,            .text_selection = selection,            .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },            .size = .{ .width = 64, .height = 16 },        },        .{            .widget_id = 2,            .kind = .label,            .text = styled,            .text_selection = selection,            .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },            .size = .{ .width = 64, .height = 16 },        },    };    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = &entries };    var frames = [_]gui.frame.Workspace{        gui.frame.Workspace.init(allocator),        gui.frame.Workspace.init(allocator),    };    defer for (&frames) |*frame| frame.deinit();    var buffers = [_]command.CommandBuffer{        command.CommandBuffer.init(allocator),        command.CommandBuffer.init(allocator),    };    defer for (&buffers) |*buffer| buffer.deinit();    var widget_geometry: [2]WidgetFrame = undefined;    for (0..nodes.len) |index| {        const surface = gui.model.UiSurfaceTree{            .available_size = .{ .width = 64, .height = 16 },            .root = .{ .widget_id = 1, .children = nodes[index .. index + 1] },        };        const frame = try frames[index].buildSurface(&surface, .{});        widget_geometry[index] = frame.widgets[1];        try appendFrameCommands(&buffers[index], frame, &atlases, 1, 0);    }    try std.testing.expectEqual(widget_geometry[0].rect, widget_geometry[1].rect);    try std.testing.expectEqual(widget_geometry[0].visible_rect, widget_geometry[1].visible_rect);    try std.testing.expectEqual(widget_geometry[0].constraints, widget_geometry[1].constraints);    try std.testing.expectEqual(widget_geometry[0].content_size, widget_geometry[1].content_size);    var plain_glyphs: [4]command.Command = undefined;    var styled_glyphs: [4]command.Command = undefined;    var plain_count: usize = 0;    var styled_count: usize = 0;    for (buffers[0].items()) |item| {        if (item.kind != .glyph) continue;        plain_glyphs[plain_count] = item;        plain_count += 1;    }    for (buffers[1].items()) |item| {        if (item.kind != .glyph) continue;        styled_glyphs[styled_count] = item;        styled_count += 1;    }    try std.testing.expectEqual(@as(usize, 4), plain_count);    try std.testing.expectEqual(plain_count, styled_count);    for (plain_glyphs, styled_glyphs) |plain_glyph, styled_glyph| {        try std.testing.expectEqual(plain_glyph.rect, styled_glyph.rect);        try std.testing.expectEqual(plain_glyph.source, styled_glyph.source);        try std.testing.expectEqual(plain_glyph.clip, styled_glyph.clip);    }    try std.testing.expectEqual(@as(u8, 12), styled_glyphs[0].color.r);    try std.testing.expectEqual(@as(u8, 220), styled_glyphs[1].color.r);    try std.testing.expectEqual(@as(u8, 20), styled_glyphs[2].color.r);    try std.testing.expectEqual(@as(u8, 20), styled_glyphs[3].color.r);    const plain_commands = buffers[0].items();    const styled_commands = buffers[1].items();    try std.testing.expectEqual(@as(usize, 6), plain_commands.len);    try std.testing.expectEqual(@as(usize, 9), styled_commands.len);    try std.testing.expectEqual(command.Kind.fill, styled_commands[0].kind);    try std.testing.expectEqual(@as(u8, 15), styled_commands[0].color.r);    try std.testing.expectApproxEqAbs(@as(f32, 8), styled_commands[0].rect.x, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 8), styled_commands[0].rect.width, 0.001);    try std.testing.expectEqual(command.Kind.fill, styled_commands[6].kind);    try std.testing.expectEqual(@as(u8, 220), styled_commands[6].color.r);    try std.testing.expectEqual(command.Kind.fill, styled_commands[7].kind);    try std.testing.expectEqual(@as(u8, 20), styled_commands[7].color.r);    try std.testing.expectEqual(plain_commands[0].rect, styled_commands[1].rect);    try std.testing.expectEqual(plain_commands[plain_commands.len - 1].rect, styled_commands[styled_commands.len - 1].rect);}test "resolved equal metric slots preserve measure and command bytes" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const plain = UiText{        .content = "ABC",        .point_size = 16,        .line_height = 1,        .wrap_width = 16,    };    const styles = [_]UiTextStyle{.{        .font_asset_id = plain.font_asset_id,        .point_size = plain.point_size,    }};    const runs = [_]UiTextRun{.{        .byte_start = 1,        .byte_end = 2,        .style_slot = 1,    }};    const slotted = UiText{        .content = plain.content,        .styles = &styles,        .runs = &runs,        .point_size = plain.point_size,        .line_height = plain.line_height,        .wrap_width = plain.wrap_width,    };    try std.testing.expectEqual(try measure(&atlas, plain), try measure(&atlas, slotted));    try std.testing.expectEqual(@as(usize, 1), atlas.cacheStatus().measure.entries);    const entries = [_]AtlasSet.Entry{.{        .face = 0,        .image_index = 4,        .atlas = &atlas,    }};    const atlases = AtlasSet{ .entries = &entries };    var workspaces = [_]gui.frame.Workspace{        gui.frame.Workspace.init(allocator),        gui.frame.Workspace.init(allocator),    };    defer for (&workspaces) |*workspace| workspace.deinit();    var buffers = [_]command.CommandBuffer{        command.CommandBuffer.init(allocator),        command.CommandBuffer.init(allocator),    };    defer for (&buffers) |*buffer| buffer.deinit();    const texts = [_]UiText{ plain, slotted };    for (texts, 0..) |text, index| {        const tree = gui.model.UiSurfaceTree{            .available_size = .{ .width = 64, .height = 24 },            .root = .{                .widget_id = 1,                .children = &.{.{                    .widget_id = 2,                    .kind = .text_input,                    .text = text,                    .text_selection = .{                        .cursor_visible = true,                        .cursor_byte_offset = 2,                        .selection_active = true,                        .selection_anchor_byte_offset = 0,                        .selection_focus_byte_offset = 3,                    },                    .size = .{ .width = 64, .height = 48 },                }},            },        };        const frame = try workspaces[index].buildSurface(&tree, .{            .resolvers = frameResolvers(&atlases),        });        try appendFrameCommands(&buffers[index], frame, &atlases, 1, 0);    }    try std.testing.expectEqual(buffers[0].items().len, buffers[1].items().len);    for (buffers[0].items(), buffers[1].items()) |plain_command, slotted_command| {        try std.testing.expect(std.meta.eql(plain_command, slotted_command));    }}test "mixed metric measurement keys distinguish alternate atlas sets" {    const allocator = std.testing.allocator;    const base_glyphs = [_]BitmapGlyph{.{        .codepoint = 'A',        .rows = &.{ 0xFF, 0xFF },    }};    const narrow_glyphs = [_]BitmapGlyph{.{        .codepoint = 'B',        .rows = &.{ 0xFF, 0xF0, 0xFF, 0xF0 },    }};    const wide_glyphs = [_]BitmapGlyph{.{        .codepoint = 'B',        .rows = &.{ 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xF0 },    }};    var base_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &base_glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer base_atlas.deinit();    var narrow_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &narrow_glyphs,        .{ .width = 12, .height = 2, .stride = 2 },        16,        test_atlas_cache_limits,    );    defer narrow_atlas.deinit();    var wide_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &wide_glyphs,        .{ .width = 20, .height = 2, .stride = 3 },        16,        test_atlas_cache_limits,    );    defer wide_atlas.deinit();    const styles = [_]UiTextStyle{.{        .font_asset_id = 2,        .point_size = 16,    }};    const runs = [_]UiTextRun{.{        .byte_start = 1,        .byte_end = 2,        .style_slot = 1,    }};    const text = UiText{        .content = "AB",        .runs = &runs,        .styles = &styles,        .font_asset_id = 1,        .point_size = 16,        .line_height = 1,    };    const narrow_entries = [_]AtlasSet.Entry{        .{ .face = 1, .image_index = 0, .atlas = &base_atlas },        .{ .face = 2, .image_index = 1, .atlas = &narrow_atlas },    };    const wide_entries = [_]AtlasSet.Entry{        .{ .face = 1, .image_index = 0, .atlas = &base_atlas },        .{ .face = 2, .image_index = 2, .atlas = &wide_atlas },    };    const narrow = AtlasSet{ .entries = &narrow_entries };    const wide = AtlasSet{ .entries = &wide_entries };    try std.testing.expectEqual(@as(f32, 20), (try measureSet(&narrow, text)).width);    try std.testing.expectEqual(@as(f32, 28), (try measureSet(&wide, text)).width);    try std.testing.expectEqual(@as(usize, 2), base_atlas.cacheStatus().measure.entries);}test "mixed metric runs share a baseline and retain per glyph atlas identity" {    const allocator = std.testing.allocator;    const base_glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },    };    const large_glyphs = [_]BitmapGlyph{        .{ .codepoint = 'B', .rows = &.{            0xFF, 0xF0,            0xFF, 0xF0,            0xFF, 0xF0,            0xFF, 0xF0,        } },    };    var base_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &base_glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer base_atlas.deinit();    var large_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &large_glyphs,        .{ .width = 12, .height = 4, .stride = 2 },        24,        test_atlas_cache_limits,    );    defer large_atlas.deinit();    const styles = [_]UiTextStyle{.{        .font_asset_id = 2,        .point_size = 24,    }};    const runs = [_]UiTextRun{.{        .byte_start = 1,        .byte_end = 2,        .style_slot = 1,        .background = .{ .r = 12, .g = 24, .b = 48, .a = 180 },        .underline = true,    }};    const text = UiText{        .content = "ABC",        .runs = &runs,        .styles = &styles,        .font_asset_id = 1,        .point_size = 16,        .line_height = 1,    };    const entries = [_]AtlasSet.Entry{        .{ .face = 1, .image_index = 3, .atlas = &base_atlas },        .{ .face = 2, .image_index = 9, .atlas = &large_atlas },    };    const atlases = AtlasSet{ .entries = &entries };    try std.testing.expectEqual(Size{ .width = 28, .height = 24 }, try measureSet(&atlases, text));    const plan = try LinePlan.initComposite(        &base_atlas,        &atlases,        text,        text.content,        0,        0,    );    try std.testing.expectEqual(@as(usize, 3), plan.run.glyphs.len);    try std.testing.expectEqual(@as(i32, 8 * 64), plan.run.glyphs[0].x_advance);    try std.testing.expectEqual(@as(i32, 12 * 64), plan.run.glyphs[1].x_advance);    try std.testing.expectEqual(@as(i32, 8 * 64), plan.run.glyphs[2].x_advance);    for (0..text.content.len + 1) |byte_offset| {        const advance = try textAdvanceForByteOffset(&atlases, text, byte_offset);        const hit = try textHitTestAdvance(&atlases, text, advance);        try std.testing.expectEqual(byte_offset, hit.byte_offset);        try std.testing.expectApproxEqAbs(advance, hit.advance, 0.001);    }    _ = try base_atlas.shape("CC");    try std.testing.expectEqual(@as(u32, 'A'), plan.run.glyphs[0].glyph_id);    try std.testing.expectEqual(@as(u32, 'B'), plan.run.glyphs[1].glyph_id);    const tree = gui.model.UiSurfaceTree{        .available_size = .{ .width = 64, .height = 24 },        .root = .{            .widget_id = 1,            .children = &.{.{                .widget_id = 2,                .kind = .label,                .text = text,                .text_selection = .{                    .selection_active = true,                    .selection_anchor_byte_offset = 0,                    .selection_focus_byte_offset = 3,                },                .size = .{ .width = 64, .height = 24 },            }},        },    };    var workspace = gui.frame.Workspace.init(allocator);    defer workspace.deinit();    const frame = try workspace.buildSurface(&tree, .{        .resolvers = frameResolvers(&atlases),    });    var one = command.CommandBuffer.init(allocator);    defer one.deinit();    var two = command.CommandBuffer.init(allocator);    defer two.deinit();    try appendFrameCommands(&one, frame, &atlases, 1, 0);    try appendFrameCommands(&two, frame, &atlases, 2, 0);    var one_glyphs: [3]command.Command = undefined;    var two_glyphs: [3]command.Command = undefined;    var one_count: usize = 0;    var two_count: usize = 0;    for (one.items()) |item| {        if (item.kind != .glyph) continue;        one_glyphs[one_count] = item;        one_count += 1;    }    for (two.items()) |item| {        if (item.kind != .glyph) continue;        two_glyphs[two_count] = item;        two_count += 1;    }    try std.testing.expectEqual(@as(usize, 3), one_count);    try std.testing.expectEqual(one_count, two_count);    try std.testing.expectEqual(@as(u32, 3), one_glyphs[0].image_index);    try std.testing.expectEqual(@as(u32, 9), one_glyphs[1].image_index);    try std.testing.expectEqual(@as(u32, 3), one_glyphs[2].image_index);    try std.testing.expectApproxEqAbs(        one_glyphs[0].rect.y + one_glyphs[0].rect.height,        one_glyphs[1].rect.y + one_glyphs[1].rect.height,        0.001,    );    try std.testing.expectApproxEqAbs(        one_glyphs[1].rect.y + one_glyphs[1].rect.height,        one_glyphs[2].rect.y + one_glyphs[2].rect.height,        0.001,    );    for (one_glyphs, two_glyphs) |logical, scaled| {        try std.testing.expectEqual(logical.image_index, scaled.image_index);        try std.testing.expectApproxEqAbs(logical.rect.x * 2, scaled.rect.x, 0.001);        try std.testing.expectApproxEqAbs(logical.rect.y * 2, scaled.rect.y, 0.001);        try std.testing.expectApproxEqAbs(logical.rect.width * 2, scaled.rect.width, 0.001);        try std.testing.expectApproxEqAbs(logical.rect.height * 2, scaled.rect.height, 0.001);    }}test "styled text runs rasterize fixed colors gaps decorations and wrapped partitions" {    const allocator = std.testing.allocator;    const ink = @as([8]u8, @splat(0x80));    const blank = @as([8]u8, @splat(0));    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &ink },        .{ .codepoint = 'B', .rows = &ink },        .{ .codepoint = ' ', .rows = &blank },        .{ .codepoint = 'C', .rows = &ink },        .{ .codepoint = 'D', .rows = &ink },        .{ .codepoint = 'E', .rows = &ink },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 4, .height = 8, .stride = 1 },        8,        test_atlas_cache_limits,    );    defer atlas.deinit();    const base = Color{ .r = 20, .g = 30, .b = 40, .a = 255 };    const clear = Color{ .r = 2, .g = 3, .b = 4, .a = 255 };    const red = Color{ .r = 220, .g = 30, .b = 20, .a = 255 };    const blue = Color{ .r = 10, .g = 40, .b = 100, .a = 255 };    const green = Color{ .r = 20, .g = 200, .b = 60, .a = 255 };    const runs = [_]UiTextRun{        .{            .byte_start = 1,            .byte_end = 4,            .foreground = red,            .background = blue,            .underline = true,        },        .{            .byte_start = 4,            .byte_end = 5,            .foreground = green,            .strikethrough = true,        },        .{            .byte_start = 5,            .byte_end = 6,            .foreground = .{ .r = 255, .b = 255, .a = 0 },            .background = .{ .a = 0 },        },    };    const children = [_]UiNode{.{        .widget_id = 2,        .kind = .label,        .text = .{            .content = "AB CDE",            .runs = &runs,            .point_size = 8,            .line_height = 1,            .wrap_width = 12,        },        .paint = .{ .foreground = base },        .size = .{ .width = 12, .height = 16 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 12, .height = 16 },        .root = .{ .widget_id = 1, .children = &children },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{        .face = 0,        .image_index = 0,        .atlas = &atlas,    }};    const atlases = AtlasSet{ .entries = &entries };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    var pixels = @as([(12 * 16)]u32, @splat(0));    const images = [_]command.Image{atlas.image.image};    try cpu.renderCommandsPackedWithImages(        commands.items(),        .{ .width = 12, .height = 16, .pixels = &pixels },        clear,        .{ .images = &images },    );    try std.testing.expectEqual(cpu.packRgba(base), pixels[0 + 2 * 12]);    try std.testing.expectEqual(cpu.packRgba(clear), pixels[2 + 2 * 12]);    try std.testing.expectEqual(cpu.packRgba(red), pixels[4 + 2 * 12]);    try std.testing.expectEqual(cpu.packRgba(blue), pixels[6 + 2 * 12]);    try std.testing.expectEqual(cpu.packRgba(blue), pixels[10 + 2 * 12]);    try std.testing.expectEqual(cpu.packRgba(red), pixels[6 + 7 * 12]);    try std.testing.expectEqual(cpu.packRgba(red), pixels[0 + 10 * 12]);    try std.testing.expectEqual(cpu.packRgba(blue), pixels[2 + 10 * 12]);    try std.testing.expectEqual(cpu.packRgba(red), pixels[2 + 15 * 12]);    try std.testing.expectEqual(cpu.packRgba(green), pixels[4 + 10 * 12]);    try std.testing.expectEqual(        cpu.packRgba(.{ .r = 11, .g = 102, .b = 32, .a = 255 }),        pixels[6 + 12 * 12],    );    try std.testing.expectEqual(cpu.packRgba(clear), pixels[8 + 10 * 12]);    try std.testing.expectEqual(cpu.packRgba(clear), pixels[10 + 10 * 12]);}test "retained text run color changes damage only the styled glyph" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'C', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'D', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const red = [_]UiTextRun{.{        .byte_start = 1,        .byte_end = 2,        .foreground = .{ .r = 220, .g = 30, .b = 20 },    }};    const blue = [_]UiTextRun{.{        .byte_start = 1,        .byte_end = 2,        .foreground = .{ .r = 20, .g = 80, .b = 220 },    }};    const nodes = [_]UiNode{        .{            .widget_id = 2,            .kind = .label,            .text = .{ .content = "ABCD", .runs = &red, .point_size = 16, .line_height = 1 },            .size = .{ .width = 32, .height = 16 },        },        .{            .widget_id = 2,            .kind = .label,            .text = .{ .content = "ABCD", .runs = &blue, .point_size = 16, .line_height = 1 },            .size = .{ .width = 32, .height = 16 },        },    };    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = &entries };    var frames = [_]gui.frame.Workspace{        gui.frame.Workspace.init(allocator),        gui.frame.Workspace.init(allocator),    };    defer for (&frames) |*frame| frame.deinit();    var buffers = [_]command.CommandBuffer{        command.CommandBuffer.init(allocator),        command.CommandBuffer.init(allocator),    };    defer for (&buffers) |*buffer| buffer.deinit();    const fragment_id = command.FragmentId{        .root_id = 1,        .element_id = 2,        .namespace = command.fragment_namespace_widget,        .part = command.fragment_part_text,    };    for (0..nodes.len) |index| {        const surface = gui.model.UiSurfaceTree{            .available_size = .{ .width = 32, .height = 16 },            .root = .{ .widget_id = 1, .children = nodes[index .. index + 1] },        };        const frame = try frames[index].buildSurface(&surface, .{});        try appendFrameCommands(&buffers[index], frame, &atlases, 1, 0);        try buffers[index].commitFragment(fragment_id, 0);    }    var retained = gui.paint.RetainedCommands.init(allocator);    defer retained.deinit();    try retained.retain(&buffers[0]);    const damage = try retained.diff(        &buffers[1],        &.{Region.full(32, 16)},        32,        16,    );    const narrowed = switch (damage) {        .semantic => return error.ExpectedNarrowedDamage,        .narrowed => |value| value,    };    try std.testing.expect(narrowed.slice().len > 0);    try std.testing.expect(narrowed.slice().len <= 2);    const bounds = narrowed.bounding().?;    try std.testing.expect(bounds.x >= 7);    try std.testing.expect(bounds.x <= 8);    try std.testing.expect(bounds.width <= 10);    try std.testing.expect(bounds.height <= 4);}test "warmed identical styled text measure emission and retained diff need no allocation or damage" {    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    const allocator = failing.allocator();    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const runs = [_]UiTextRun{.{        .byte_start = 0,        .byte_end = 1,        .foreground = .{ .r = 220, .g = 30, .b = 20 },        .background = .{ .r = 10, .g = 20, .b = 40, .a = 160 },        .underline = true,    }};    const child = [_]UiNode{.{        .widget_id = 2,        .kind = .label,        .text = .{ .content = "AB", .runs = &runs, .point_size = 16, .line_height = 1 },        .size = .{ .width = 16, .height = 16 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 16, .height = 16 },        .root = .{ .widget_id = 1, .children = &child },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = &entries };    const measured = try measure(&atlas, child[0].text.?);    const fragment_id = command.FragmentId{        .root_id = 1,        .element_id = 2,        .namespace = command.fragment_namespace_widget,        .part = command.fragment_part_text,    };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    try commands.commitFragment(fragment_id, 0);    var retained = gui.paint.RetainedCommands.init(allocator);    defer retained.deinit();    try retained.retain(&commands);    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    try commands.commitFragment(fragment_id, 0);    try std.testing.expect((try retained.diff(&commands, &.{}, 16, 16)) == .semantic);    try retained.retain(&commands);    failing.fail_index = failing.alloc_index;    failing.resize_fail_index = failing.resize_index;    for (0..8) |_| {        try std.testing.expectEqual(measured, try measure(&atlas, child[0].text.?));        try appendFrameCommands(&commands, frame, &atlases, 1, 0);        try std.testing.expectEqual(@as(usize, 4), commands.items().len);        try commands.commitFragment(fragment_id, 0);        try std.testing.expect((try retained.diff(&commands, &.{}, 16, 16)) == .semantic);        try retained.retain(&commands);    }    try std.testing.expect(!failing.has_induced_failure);}test "warmed mixed metric measure planning emission and retained diff need no allocation" {    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    const allocator = failing.allocator();    const base_glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xFF } },    };    const large_glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0 } },        .{ .codepoint = 'B', .rows = &.{ 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0 } },    };    var base_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &base_glyphs,        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer base_atlas.deinit();    var large_atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &large_glyphs,        .{ .width = 12, .height = 3, .stride = 2 },        24,        test_atlas_cache_limits,    );    defer large_atlas.deinit();    const styles = [_]UiTextStyle{.{        .font_asset_id = 2,        .point_size = 24,    }};    const runs = [_]UiTextRun{.{        .byte_start = 1,        .byte_end = 2,        .style_slot = 1,        .foreground = .{ .r = 220, .g = 30, .b = 20 },        .background = .{ .r = 10, .g = 20, .b = 40, .a = 160 },        .underline = true,    }};    const text = UiText{        .content = "AB",        .runs = &runs,        .styles = &styles,        .font_asset_id = 1,        .point_size = 16,        .line_height = 1,    };    const child = [_]UiNode{.{        .widget_id = 2,        .kind = .text_input,        .text = text,        .size = .{ .width = 24, .height = 24 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 24, .height = 24 },        .root = .{ .widget_id = 1, .children = &child },    };    const entries = [_]AtlasSet.Entry{        .{ .face = 1, .image_index = 1, .atlas = &base_atlas },        .{ .face = 2, .image_index = 2, .atlas = &large_atlas },    };    const atlases = AtlasSet{ .entries = &entries };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{        .resolvers = frameResolvers(&atlases),    });    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const measured = try measureSet(&atlases, text);    _ = try LinePlan.initComposite(&base_atlas, &atlases, text, text.content, 0, 0);    const fragment_id = command.FragmentId{        .root_id = 1,        .element_id = 2,        .namespace = command.fragment_namespace_widget,        .part = command.fragment_part_text,    };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    try commands.commitFragment(fragment_id, 0);    var retained = gui.paint.RetainedCommands.init(allocator);    defer retained.deinit();    try retained.retain(&commands);    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    try commands.commitFragment(fragment_id, 0);    try std.testing.expect((try retained.diff(&commands, &.{}, 24, 24)) == .semantic);    try retained.retain(&commands);    failing.fail_index = failing.alloc_index;    failing.resize_fail_index = failing.resize_index;    for (0..8) |_| {        try std.testing.expectEqual(measured, try measureSet(&atlases, text));        _ = try LinePlan.initComposite(&base_atlas, &atlases, text, text.content, 0, 0);        try appendFrameCommands(&commands, frame, &atlases, 1, 0);        try commands.commitFragment(fragment_id, 0);        try std.testing.expect((try retained.diff(&commands, &.{}, 24, 24)) == .semantic);        try retained.retain(&commands);    }    try std.testing.expect(!failing.has_induced_failure);}test "measure and paint reject malformed text runs" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{.{ .codepoint = 'A', .rows = &.{0xFF} }};    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        &glyphs,        .{ .width = 8, .height = 1, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const runs = [_]UiTextRun{.{ .byte_start = 0, .byte_end = 2 }};    const text = UiText{ .content = "A", .runs = &runs };    try std.testing.expectError(error.InvalidTextRun, measure(&atlas, text));    const child = [_]UiNode{.{        .widget_id = 2,        .kind = .label,        .text = text,        .size = .{ .width = 16, .height = 16 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 16, .height = 16 },        .root = .{ .widget_id = 1, .children = &child },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = &entries };    try std.testing.expectError(error.InvalidTextRun, appendFrameCommands(&commands, frame, &atlases, 1, 0));    try std.testing.expectEqual(@as(usize, 0), commands.items().len);}test "appendFrameCommands draws cursor for empty text input" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const child = [_]gui.model.UiNode{.{        .widget_id = 2,        .kind = .text_input,        .text = .{ .content = "", .point_size = 16, .line_height = 1.0 },        .text_selection = .{            .cursor_visible = true,            .cursor_byte_offset = 0,        },        .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },        .size = .{ .width = 64, .height = 20 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 80, .height = 32 },        .root = .{            .widget_id = 1,            .children = child[0..],        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = entries[0..] };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    try std.testing.expectEqual(@as(usize, 1), commands.items().len);    try std.testing.expectEqual(command.Kind.fill, commands.items()[0].kind);    try std.testing.expectApproxEqAbs(@as(f32, 0), commands.items()[0].rect.x, 0.001);    try std.testing.expectApproxEqAbs(@as(f32, 1), commands.items()[0].rect.width, 0.001);    try std.testing.expect(commands.items()[0].rect.height > 0);}test "shape cache reuses stored runs and survives eviction" {    const allocator = std.testing.allocator;    const limits = AtlasCacheStorage.Limits{        .measure_entries = 0,        .measure_payload_bytes = 0,        .shape_entries = 4,        .shape_payload_bytes = 64 * 1024,    };    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'a', .rows = &.{ 0xFF, 0xFF } },        .{ .codepoint = 'b', .rows = &.{ 0x0F, 0xF0 } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        limits,    );    defer atlas.deinit();    const first = try atlas.shape("ab");    try std.testing.expectEqual(@as(usize, 2), first.glyphs.len);    const second = try atlas.shape("ab");    try std.testing.expectEqual(first.glyphs.ptr, second.glyphs.ptr);    try std.testing.expectEqual(first.total_x_advance, second.total_x_advance);    var name_buffer: [32]u8 = undefined;    for (0..limits.shape_entries) |index| {        const name = try std.fmt.bufPrint(name_buffer[0..], "evict {d}", .{index});        _ = try atlas.shape(name);    }    const evicted = try atlas.shape("ab");    try std.testing.expectEqual(@as(usize, 2), evicted.glyphs.len);    try std.testing.expectEqual(first.total_x_advance, evicted.total_x_advance);    try std.testing.expectEqual(@as(u32, 'a'), evicted.glyphs[0].glyph_id);    try std.testing.expectEqual(@as(u32, 'b'), evicted.glyphs[1].glyph_id);    try std.testing.expectEqual(@as(u64, 1), atlas.cacheStatus().shape.rollovers);}test "Atlas cache capacity matches an independent aligned byte model" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(AtlasCacheStorage, "gui_text_atlas_cache_capacity"),            null,            null,            null,            null,            null,            null,        );    }    const cases = [_]AtlasCacheStorage.Limits{        .{            .measure_entries = 0,            .measure_payload_bytes = 0,            .shape_entries = 0,            .shape_payload_bytes = 0,        },        .{            .measure_entries = 1,            .measure_payload_bytes = 1,            .shape_entries = 1,            .shape_payload_bytes = 1,        },        test_atlas_cache_limits,        .{            .measure_entries = std.math.maxInt(u32),            .measure_payload_bytes = 1,            .shape_entries = 1,            .shape_payload_bytes = 1,        },    };    for (cases) |limits| {        try std.testing.expectEqual(            try modelAtlasCacheCapacity(limits),            try AtlasCacheStorage.Capacity.derive(limits),        );    }    try expectAtlasCacheCapacityErrors();}test "Atlas cache storage acquires one exact aligned region" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(AtlasCacheStorage, "gui_text_atlas_cache_acquisition"),            null,            null,            null,            null,            null,            null,        );    }    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    const capacity = try AtlasCacheStorage.Capacity.derive(test_atlas_cache_limits);    var storage = try AtlasCacheStorage.init(failing.allocator(), test_atlas_cache_limits);    defer storage.deinit(failing.allocator());    try std.testing.expectEqual(@as(usize, 1), failing.alloc_index);    try std.testing.expectEqual(capacity.storage_bytes, failing.allocated_bytes);    try std.testing.expectEqual(alloc_phase.capacity.Phase.initialization, storage.status().phase);    try expectAtlasCacheRegionAddresses(&storage);    storage.activate();    try std.testing.expectEqual(alloc_phase.capacity.Phase.steady, storage.status().phase);}test "Atlas cache storage retries after every allocation failure" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(AtlasCacheStorage, "gui_text_atlas_cache_oom"),            null,            null,            null,            null,            null,            null,        );    }    try std.testing.checkAllAllocationFailures(        std.testing.allocator,        checkAtlasCacheInitFailures,        .{},    );}test "Atlas cache storage preserves exact max and max plus one overload behavior" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(AtlasCacheStorage, "gui_text_atlas_cache_boundaries"),            null,            null,            null,            null,            null,            null,        );    }    try expectShapeCacheBoundaries();    try expectMeasureCacheBoundaries();    try expectDisabledAtlasCaches();}test "Activated Atlas cache operations make no backing allocation from cold" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(AtlasCacheStorage, "gui_text_atlas_cache_sealed_transitive_risk"),            null,            null,            null,            null,            null,            null,        );    }    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(AtlasCacheStorage, "gui_text_atlas_cache_sealed_foreign_risk"),            null,            null,            null,            null,            null,            null,        );    }    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{});    const limits = AtlasCacheStorage.Limits{        .measure_entries = 2,        .measure_payload_bytes = 16,        .shape_entries = 2,        .shape_payload_bytes = 16,    };    var storage = try AtlasCacheStorage.init(failing.allocator(), limits);    defer storage.deinit(failing.allocator());    storage.activate();    const allocations = failing.allocations;    const deallocations = failing.deallocations;    const allocated_bytes = failing.allocated_bytes;    const freed_bytes = failing.freed_bytes;    const resize_index = failing.resize_index;    failing.fail_index = failing.alloc_index;    failing.resize_fail_index = failing.resize_index;    try exerciseColdAtlasCache(&storage);    try std.testing.expectEqual(allocations, failing.allocations);    try std.testing.expectEqual(deallocations, failing.deallocations);    try std.testing.expectEqual(allocated_bytes, failing.allocated_bytes);    try std.testing.expectEqual(freed_bytes, failing.freed_bytes);    try std.testing.expectEqual(resize_index, failing.resize_index);}test "Atlas cache bounded probes preserve colliding shape keys" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(AtlasCacheStorage, "gui_text_atlas_cache_collisions"),            null,            null,            null,            null,            null,            null,        );    }    const limits = AtlasCacheStorage.Limits{        .measure_entries = 0,        .measure_payload_bytes = 0,        .shape_entries = 2,        .shape_payload_bytes = 32,    };    var storage = try AtlasCacheStorage.init(std.testing.allocator, limits);    defer storage.deinit(std.testing.allocator);    storage.activate();    const keys = try collidingShapeKeys(storage.capacity.shape_index_slots);    _ = try storage.storeShape(keys.first, testShapedRun(11));    _ = try storage.storeShape(keys.second, testShapedRun(22));    try std.testing.expectEqual(@as(i32, 11), storage.lookupShape(keys.first).?.total_x_advance);    try std.testing.expectEqual(@as(i32, 22), storage.lookupShape(keys.second).?.total_x_advance);}test "Atlas cache storage keeps region pointers and capacity stable" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(AtlasCacheStorage, "gui_text_atlas_cache_stability"),            null,            null,            null,            null,            null,            null,        );    }    var storage = try AtlasCacheStorage.init(std.testing.allocator, .{        .measure_entries = 2,        .measure_payload_bytes = 16,        .shape_entries = 2,        .shape_payload_bytes = 16,    });    defer storage.deinit(std.testing.allocator);    const capacity = storage.capacity;    const pointers = atlasCachePointers(storage);    storage.activate();    var iteration: usize = 0;    while (iteration < 32) : (iteration += 1) {        const key = if (iteration % 2 == 0) "aa" else "bb";        _ = storage.storeShape(key, testShapedRun(@intCast(iteration))) catch {};        storage.replaceShape();    }    try std.testing.expectEqual(capacity, storage.capacity);    try std.testing.expectEqual(pointers, atlasCachePointers(storage));}test "Atlas cache shape operations match a whole epoch reference model" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(AtlasCacheStorage, "gui_text_atlas_cache_differential"),            null,            null,            null,            null,            null,            null,        );    }    try expectAtlasCacheDifferential();}test "Atlas cache bypasses oversized entries without changing either epoch" {    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'a', .rows = &.{ 0xFF, 0xFF } },    };    const limits = AtlasCacheStorage.Limits{        .measure_entries = 2,        .measure_payload_bytes = 128,        .shape_entries = 2,        .shape_payload_bytes = 128,    };    var atlas = try Atlas.initFromBitmapGlyphs(        std.testing.allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        limits,    );    defer atlas.deinit();    const retained_run = try atlas.shape("a");    const retained_measure = try measure(&atlas, cacheEpochText("a"));    const before = atlas.cacheStatus();    const content: [129]u8 = @splat('x');    const first_run = try atlas.shape(&content);    const second_run = try atlas.shape(&content);    try expectGlyphRunEqual(first_run, second_run);    const first_measure = try measure(&atlas, cacheEpochText(&content));    const second_measure = try measure(&atlas, cacheEpochText(&content));    try std.testing.expectEqual(first_measure, second_measure);    const after = atlas.cacheStatus();    try std.testing.expectEqual(before.shape.entries, after.shape.entries);    try std.testing.expectEqual(before.shape.payload_bytes, after.shape.payload_bytes);    try std.testing.expectEqual(before.shape.rollovers, after.shape.rollovers);    try std.testing.expectEqual(before.shape.oversize_bypasses + 4, after.shape.oversize_bypasses);    try std.testing.expectEqual(before.measure.entries, after.measure.entries);    try std.testing.expectEqual(before.measure.payload_bytes, after.measure.payload_bytes);    try std.testing.expectEqual(before.measure.rollovers, after.measure.rollovers);    try std.testing.expectEqual(before.measure.oversize_bypasses + 2, after.measure.oversize_bypasses);    const retained_again = try atlas.shape("a");    try std.testing.expectEqual(retained_run.glyphs.ptr, retained_again.glyphs.ptr);    try std.testing.expectEqual(retained_measure, try measure(&atlas, cacheEpochText("a")));}fn expectAtlasCacheCapacityErrors() !void {    try std.testing.expectError(error.InvalidMeasureLimits, AtlasCacheStorage.Capacity.derive(.{        .measure_entries = 1,        .measure_payload_bytes = 0,        .shape_entries = 0,        .shape_payload_bytes = 0,    }));    try std.testing.expectError(error.InvalidShapeLimits, AtlasCacheStorage.Capacity.derive(.{        .measure_entries = 0,        .measure_payload_bytes = 0,        .shape_entries = 0,        .shape_payload_bytes = 1,    }));    try std.testing.expectError(error.CapacityOverflow, AtlasCacheStorage.Capacity.derive(.{        .measure_entries = 1,        .measure_payload_bytes = std.math.maxInt(usize),        .shape_entries = 0,        .shape_payload_bytes = 0,    }));    if (@bitSizeOf(usize) > @bitSizeOf(u32)) {        try std.testing.expectError(error.EntryLimitTooLarge, AtlasCacheStorage.Capacity.derive(.{            .measure_entries = @as(usize, std.math.maxInt(u32)) + 1,            .measure_payload_bytes = 1,            .shape_entries = 0,            .shape_payload_bytes = 0,        }));    }}fn expectAtlasCacheRegionAddresses(storage: *const AtlasCacheStorage) !void {    const base = @intFromPtr(storage.bytes.ptr);    const capacity = storage.capacity;    try std.testing.expectEqual(        base + capacity.measure_index_offset,        @intFromPtr(storage.measure_slots.ptr),    );    try std.testing.expectEqual(        base + capacity.measure_entries_offset,        @intFromPtr(storage.measure_entries.ptr),    );    try std.testing.expectEqual(        base + capacity.measure_payload_offset,        @intFromPtr(storage.measure_payload.bytes.ptr),    );    try std.testing.expectEqual(        base + capacity.shape_index_offset,        @intFromPtr(storage.shape_slots.ptr),    );    try std.testing.expectEqual(        base + capacity.shape_entries_offset,        @intFromPtr(storage.shape_entries.ptr),    );    try std.testing.expectEqual(        base + capacity.shape_payload_offset,        @intFromPtr(storage.shape_payload.bytes.ptr),    );}fn checkAtlasCacheInitFailures(allocator: Allocator) !void {    var storage = try AtlasCacheStorage.init(allocator, .{        .measure_entries = 3,        .measure_payload_bytes = 31,        .shape_entries = 5,        .shape_payload_bytes = 47,    });    storage.deinit(allocator);}fn expectShapeCacheBoundaries() !void {    var storage = try AtlasCacheStorage.init(std.testing.allocator, .{        .measure_entries = 0,        .measure_payload_bytes = 0,        .shape_entries = 2,        .shape_payload_bytes = 64,    });    defer storage.deinit(std.testing.allocator);    storage.activate();    _ = try storage.storeShape("a", testShapedRun(1));    _ = try storage.storeShape("b", testShapedRun(2));    try std.testing.expectEqual(@as(usize, 2), storage.status().shape.entries);    _ = try storage.storeShape("c", testShapedRun(3));    try std.testing.expectEqual(@as(usize, 1), storage.status().shape.entries);    try std.testing.expectEqual(@as(u64, 1), storage.status().shape.rollovers);    try std.testing.expect(storage.lookupShape("a") == null);    try std.testing.expectEqual(@as(i32, 3), storage.lookupShape("c").?.total_x_advance);    var payload = try shapePayloadBoundaryStorage();    defer payload.deinit(std.testing.allocator);    try payload.admitShapePayload(3);    try std.testing.expectError(error.EntryTooLarge, payload.admitShapePayload(4));    _ = try payload.storeShape("abc", testShapedRun(4));    const before = payload.status();    try std.testing.expectError(        error.EntryTooLarge,        payload.storeShape("abcd", testShapedRun(5)),    );    const after = payload.status();    try expectEpochUnchangedExceptOversize(before.shape, after.shape);}fn shapePayloadBoundaryStorage() !AtlasCacheStorage {    var storage = try AtlasCacheStorage.init(std.testing.allocator, .{        .measure_entries = 0,        .measure_payload_bytes = 0,        .shape_entries = 2,        .shape_payload_bytes = 3,    });    storage.activate();    return storage;}fn expectMeasureCacheBoundaries() !void {    var storage = try AtlasCacheStorage.init(std.testing.allocator, .{        .measure_entries = 2,        .measure_payload_bytes = 3,        .shape_entries = 0,        .shape_payload_bytes = 0,    });    defer storage.deinit(std.testing.allocator);    storage.activate();    _ = try storage.storeMeasure(testMeasureKey("a"), .{ .width = 1 });    _ = try storage.storeMeasure(testMeasureKey("b"), .{ .width = 2 });    try std.testing.expectEqual(@as(usize, 2), storage.status().measure.entries);    _ = try storage.storeMeasure(testMeasureKey("c"), .{ .width = 3 });    try std.testing.expectEqual(@as(usize, 1), storage.status().measure.entries);    try std.testing.expectEqual(@as(u64, 1), storage.status().measure.rollovers);    try std.testing.expect(storage.lookupMeasure(testMeasureKey("a")) == null);    const before = storage.status();    try std.testing.expectError(        error.EntryTooLarge,        storage.storeMeasure(testMeasureKey("abcd"), .{ .width = 4 }),    );    try expectEpochUnchangedExceptOversize(before.measure, storage.status().measure);}fn expectEpochUnchangedExceptOversize(    before: AtlasCacheStorage.EpochStatus,    after: AtlasCacheStorage.EpochStatus,) !void {    try std.testing.expectEqual(before.entries, after.entries);    try std.testing.expectEqual(before.payload_bytes, after.payload_bytes);    try std.testing.expectEqual(before.physical_payload_bytes, after.physical_payload_bytes);    try std.testing.expectEqual(before.rollovers, after.rollovers);    try std.testing.expectEqual(before.disabled_bypasses, after.disabled_bypasses);    try std.testing.expectEqual(before.oversize_bypasses + 1, after.oversize_bypasses);}fn expectDisabledAtlasCaches() !void {    var storage = try AtlasCacheStorage.init(std.testing.allocator, .{        .measure_entries = 0,        .measure_payload_bytes = 0,        .shape_entries = 0,        .shape_payload_bytes = 0,    });    defer storage.deinit(std.testing.allocator);    storage.activate();    try std.testing.expectError(error.CacheDisabled, storage.admitShapePayload(0));    try std.testing.expectError(        error.CacheDisabled,        storage.storeShape("a", testShapedRun(1)),    );    try std.testing.expectError(        error.CacheDisabled,        storage.storeMeasure(testMeasureKey("a"), .{}),    );    const status = storage.status();    try std.testing.expectEqual(@as(usize, 0), status.storage_bytes);    try std.testing.expectEqual(@as(u64, 1), status.shape.disabled_bypasses);    try std.testing.expectEqual(@as(u64, 1), status.measure.disabled_bypasses);}fn exerciseColdAtlasCache(storage: *AtlasCacheStorage) !void {    _ = try storage.storeShape("a", testShapedRun(1));    _ = try storage.storeShape("b", testShapedRun(2));    _ = try storage.storeShape("c", testShapedRun(3));    try std.testing.expectEqual(@as(i32, 3), storage.lookupShape("c").?.total_x_advance);    _ = try storage.storeMeasure(testMeasureKey("a"), .{ .width = 1 });    _ = try storage.storeMeasure(testMeasureKey("b"), .{ .width = 2 });    _ = try storage.storeMeasure(testMeasureKey("c"), .{ .width = 3 });    try std.testing.expectEqual(@as(f32, 3), storage.lookupMeasure(testMeasureKey("c")).?.width);    try std.testing.expectEqual(@as(u64, 1), storage.status().shape.rollovers);    try std.testing.expectEqual(@as(u64, 1), storage.status().measure.rollovers);}const CollidingShapeKeys = struct {    first: []const u8,    second: []const u8,};fn collidingShapeKeys(slot_count: usize) !CollidingShapeKeys {    const candidates = [_][]const u8{ "a", "b", "c", "d", "e", "f", "g", "h" };    for (candidates, 0..) |first, first_index| {        for (candidates[first_index + 1 ..]) |second| {            const first_slot = cacheStartSlot(std.hash_map.hashString(first), slot_count);            const second_slot = cacheStartSlot(std.hash_map.hashString(second), slot_count);            if (first_slot == second_slot) return .{ .first = first, .second = second };        }    }    return error.NoCollision;}const AtlasCachePointers = struct {    bytes: usize,    measure_slots: usize,    measure_entries: usize,    measure_payload: usize,    shape_slots: usize,    shape_entries: usize,    shape_payload: usize,};fn atlasCachePointers(storage: AtlasCacheStorage) AtlasCachePointers {    return .{        .bytes = @intFromPtr(storage.bytes.ptr),        .measure_slots = @intFromPtr(storage.measure_slots.ptr),        .measure_entries = @intFromPtr(storage.measure_entries.ptr),        .measure_payload = @intFromPtr(storage.measure_payload.bytes.ptr),        .shape_slots = @intFromPtr(storage.shape_slots.ptr),        .shape_entries = @intFromPtr(storage.shape_entries.ptr),        .shape_payload = @intFromPtr(storage.shape_payload.bytes.ptr),    };}fn testShapedRun(advance: i32) filigree.GlyphRun {    return .{        .glyphs = &.{},        .clusters = &.{},        .ligature_carets = &.{},        .total_x_advance = advance,        .total_y_advance = 0,        .direction = .ltr,        .writing_mode = .horizontal,        .output_order = .visual,    };}fn testMeasureKey(content: []const u8) MeasureKey {    return .{        .content = content,        .styles = &.{},        .runs = &.{},        .atlas_entries = &.{},        .fallback_entries = &.{},        .fallback_identity = 0,        .font_asset_id = 0,        .point_size_bits = 0,        .line_height_bits = 0,        .wrap_width_bits = 0,        .device_scale_bits = 0,    };}const ShapeCacheReference = struct {    limits: AtlasCacheStorage.Limits,    keys: [3]?[]const u8 = @splat(null),    values: [3]i32 = @splat(0),    entries: usize = 0,    payload_bytes: usize = 0,    rollovers: u64 = 0,    oversize_bypasses: u64 = 0,    fn lookup(self: ShapeCacheReference, content: []const u8) ?i32 {        for (self.keys[0..self.entries], self.values[0..self.entries]) |key, value| {            if (std.mem.eql(u8, key.?, content)) return value;        }        return null;    }    fn store(self: *ShapeCacheReference, content: []const u8, value: i32) bool {        if (content.len > self.limits.shape_payload_bytes) {            self.oversize_bypasses +|= 1;            return false;        }        const payload_full = content.len >            self.limits.shape_payload_bytes - self.payload_bytes;        if (self.entries == self.limits.shape_entries or payload_full) {            self.entries = 0;            self.payload_bytes = 0;            self.rollovers +|= 1;        }        self.keys[self.entries] = content;        self.values[self.entries] = value;        self.entries += 1;        self.payload_bytes += content.len;        return true;    }};fn expectAtlasCacheDifferential() !void {    const limits = AtlasCacheStorage.Limits{        .measure_entries = 0,        .measure_payload_bytes = 0,        .shape_entries = 3,        .shape_payload_bytes = 8,    };    var storage = try AtlasCacheStorage.init(std.testing.allocator, limits);    defer storage.deinit(std.testing.allocator);    storage.activate();    var reference = ShapeCacheReference{ .limits = limits };    const keys = [_][]const u8{ "a", "bb", "ccc", "dddd", "012345678" };    var state: u32 = 0x9E37_79B9;    var step: usize = 0;    while (step < 512) : (step += 1) {        state = state *% 1_664_525 +% 1_013_904_223;        const content = keys[state % keys.len];        try compareAtlasCacheLookup(&storage, reference, content);        if (reference.lookup(content) == null) {            const value: i32 = @intCast(step);            const admitted = reference.store(content, value);            if (admitted) {                _ = try storage.storeShape(content, testShapedRun(value));            } else {                try std.testing.expectError(                    error.EntryTooLarge,                    storage.storeShape(content, testShapedRun(value)),                );            }        }        try compareAtlasCacheStatus(storage.status().shape, reference);    }}fn compareAtlasCacheLookup(    storage: *const AtlasCacheStorage,    reference: ShapeCacheReference,    content: []const u8,) !void {    const expected = reference.lookup(content);    const actual = storage.lookupShape(content);    try std.testing.expectEqual(expected != null, actual != null);    if (expected) |value| try std.testing.expectEqual(value, actual.?.total_x_advance);}fn compareAtlasCacheStatus(    actual: AtlasCacheStorage.EpochStatus,    expected: ShapeCacheReference,) !void {    try std.testing.expectEqual(expected.entries, actual.entries);    try std.testing.expectEqual(expected.payload_bytes, actual.payload_bytes);    try std.testing.expectEqual(expected.rollovers, actual.rollovers);    try std.testing.expectEqual(expected.oversize_bypasses, actual.oversize_bypasses);}fn cacheEpochText(content: []const u8) UiText {    return .{ .content = content, .point_size = 16, .line_height = 1 };}fn expectGlyphRunEqual(expected: filigree.GlyphRun, actual: filigree.GlyphRun) !void {    try std.testing.expectEqualSlices(filigree.ShapedGlyph, expected.glyphs, actual.glyphs);    try std.testing.expectEqualSlices(filigree.Cluster, expected.clusters, actual.clusters);    try std.testing.expectEqualSlices(filigree.LigatureCaret, expected.ligature_carets, actual.ligature_carets);    try std.testing.expectEqual(expected.total_x_advance, actual.total_x_advance);    try std.testing.expectEqual(expected.total_y_advance, actual.total_y_advance);    try std.testing.expectEqual(expected.direction, actual.direction);    try std.testing.expectEqual(expected.writing_mode, actual.writing_mode);    try std.testing.expectEqual(expected.output_order, actual.output_order);}test "bitmap atlas skips glyphs missing from the map without question mark" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{        .{ .codepoint = 'x', .rows = &.{ 0xFF, 0xFF } },    };    var atlas = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer atlas.deinit();    const run = try atlas.shape("xy");    try std.testing.expectEqual(@as(usize, 2), run.glyphs.len);    try std.testing.expectEqual(@as(u32, 'x'), run.glyphs[0].glyph_id);    try std.testing.expectEqual(std.math.maxInt(u32), run.glyphs[1].glyph_id);    var recorder = TestRecorder{};    drawGlyphRun(&recorder, 0, atlas.atlas, run, 0, 0, .{ .a = 255 });    try std.testing.expectEqual(@as(usize, 1), recorder.glyph_count);}test "Atlas shapes fixture bytes and appends frame glyph commands" {    const allocator = std.testing.allocator;    var scratch = try AtlasScratch.init(allocator, .{ .bytes = 1024 * 1024 });    defer scratch.deinit(allocator);    const bytes = try filigree.fixtures.createWithOutlines(allocator);    var atlas = try Atlas.initFromOwnedBytes(        allocator,        &scratch,        bytes,        18,        test_atlas_cache_limits,        test_output_limits,    );    defer atlas.deinit();    const child = [_]gui.model.UiNode{.{        .widget_id = 2,        .kind = .label,        .text = .{ .content = "AB" },        .paint = .{ .foreground = .{ .r = 12, .g = 24, .b = 36, .a = 255 } },        .size = .{ .width = 32, .height = 18 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 48, .height = 24 },        .root = .{            .widget_id = 1,            .children = child[0..],        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = entries[0..] };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    try std.testing.expect(commands.items().len > 0);    try std.testing.expectEqual(command.Kind.glyph, commands.items()[0].kind);    try std.testing.expectEqual(@as(u32, 0), commands.items()[0].image_index);    try std.testing.expectEqual(@as(u8, 255), commands.items()[0].color.a);    try std.testing.expect(atlas.image.image.width > 0);}test "missing terminal glyphs synthesize fills instead of blank advances" {    const allocator = std.testing.allocator;    var scratch = try AtlasScratch.init(allocator, .{ .bytes = 1024 * 1024 });    defer scratch.deinit(allocator);    const bytes = try filigree.fixtures.createWithOutlines(allocator);    var atlas = try Atlas.initFromOwnedBytes(        allocator,        &scratch,        bytes,        18,        test_atlas_cache_limits,        test_output_limits,    );    defer atlas.deinit();    const child = [_]gui.model.UiNode{.{        .widget_id = 2,        .kind = .label,        .text = .{ .content = "\u{258F}\u{280B}\u{276F}" },        .paint = .{ .foreground = .{ .r = 251, .g = 73, .b = 52, .a = 255 } },        .size = .{ .width = 48, .height = 24 },    }};    const surface = gui.model.UiSurfaceTree{        .available_size = .{ .width = 64, .height = 32 },        .root = .{            .widget_id = 1,            .children = child[0..],        },    };    var frame_workspace = gui.frame.Workspace.init(allocator);    defer frame_workspace.deinit();    const frame = try frame_workspace.buildSurface(&surface, .{});    var commands = command.CommandBuffer.init(allocator);    defer commands.deinit();    const entries = [_]AtlasSet.Entry{.{ .face = 0, .image_index = 0, .atlas = &atlas }};    const atlases = AtlasSet{ .entries = entries[0..] };    try appendFrameCommands(&commands, frame, &atlases, 1, 0);    var fills: usize = 0;    for (commands.items()) |item| {        if (item.kind == .fill) fills += 1;    }    try std.testing.expect(fills >= 5);    for (commands.items()) |item| {        try std.testing.expectEqual(@as(u8, 251), item.color.r);    }}test "atlas set picks matching face and nearest downscale size" {    const allocator = std.testing.allocator;    const glyphs = [_]BitmapGlyph{.{ .codepoint = 'A', .rows = &.{ 0xFF, 0xFF } }};    var small = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        13,        test_atlas_cache_limits,    );    defer small.deinit();    var body = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        16,        test_atlas_cache_limits,    );    defer body.deinit();    var mono = try Atlas.initFromBitmapGlyphs(        allocator,        glyphs[0..],        .{ .width = 8, .height = 2, .stride = 1 },        15,        test_atlas_cache_limits,    );    defer mono.deinit();    const entries = [_]AtlasSet.Entry{        .{ .face = 0, .image_index = 0, .atlas = &small },        .{ .face = 0, .image_index = 1, .atlas = &body },        .{ .face = 2, .image_index = 2, .atlas = &mono },    };    const atlases = AtlasSet{ .entries = entries[0..] };    const body_pick = atlases.forText(.{ .content = "A", .point_size = 16 }).?;    try std.testing.expectEqual(@as(u32, 1), body_pick.image_index);    const caption_pick = atlases.forText(.{ .content = "A", .point_size = 13 }).?;    try std.testing.expectEqual(@as(u32, 0), caption_pick.image_index);    const near_pick = atlases.forText(.{ .content = "A", .point_size = 14 }).?;    try std.testing.expectEqual(@as(u32, 1), near_pick.image_index);    const mono_pick = atlases.forText(.{ .content = "A", .point_size = 15, .font_asset_id = 2 }).?;    try std.testing.expectEqual(@as(u32, 2), mono_pick.image_index);    const missing_face_pick = atlases.forText(.{ .content = "A", .point_size = 16, .font_asset_id = 9 }).?;    try std.testing.expectEqual(@as(u32, 1), missing_face_pick.image_index);    const empty = AtlasSet{};    try std.testing.expect(empty.forText(.{ .content = "A" }) == null);}

Complete caller list for paint.TextAtlas.initFromBitmapGlyphs

33 direct callers.

Complete caller list for paint.TextAtlasCacheStorage.activate

12 direct callers.

Complete caller list for paint.TextAtlasCacheStorage.deinit

13 direct callers.

Complete caller list for paint.TextAtlasCacheStorage.init

13 direct callers.

Complete caller list for paint.text.appendFrameCommands

21 direct callers.

Complete caller list for paint.text.measure

8 direct callers.

Audit

Definitions69
Public names104
Members114
Version26.7.0
Revisiondaab053ee433