Skip to documentation
SLOP

tiny.ui.layout.store

Reference tiny.ui layout store

Defined in layout.

API (12)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

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

Source

Called byCallslayout.Storeinitprivate sourcelib.ui.src.layout.store.Capacitybyteslayout.Capacityderive
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerslayout.Capacityderivelayout.Storeinit
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callersprivate sourcelib.ui.src.layout.store.StorebuildClipsprivate sourcelib.ui.src.layout.store.StoreplaceSolvedlayout.Storesolve
Static calls · unresolved targets: 0 · external targets: 4.

Source: lib/ui/src/layout/root.zig:2

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

Source: lib/ui/src/layout/store.zig

zig
const std = @import("std");const alloc_phase = @import("alloc_phase");const arrange = @import("arrange");const abi = @import("../abi/root.zig");const fact = @import("../fact/root.zig");const tree = @import("../tree/root.zig");const input = @import("input.zig");const Allocator = std.mem.Allocator;pub const Limits = struct {    nodes: u32 = 16_384,};pub const Capacity = struct {    nodes: usize,    children: usize,    rect_bytes: usize,    cache_bytes: usize,    metric_bytes: usize,    line_bytes: usize,    clip_bytes: usize,    clip_index_bytes: usize,    total_bytes: usize,    pub fn derive(limits: Limits) error{CapacityOverflow}!Capacity {        if (limits.nodes == 0 or limits.nodes == std.math.maxInt(u32)) return error.CapacityOverflow;        const nodes: usize = limits.nodes;        const children = nodes - 1;        const rect_bytes = try bytes(nodes, @sizeOf(arrange.Rect));        const cache_bytes = try bytes(try bytes(nodes, 4), @sizeOf(arrange.IndexedCacheSlot));        const metric_bytes = try bytes(children, @sizeOf(arrange.ChildMetrics));        const line_bytes = try bytes(children, @sizeOf(arrange.Line));        const clip_bytes = try bytes(nodes + 1, @sizeOf(fact.Clip));        const clip_index_bytes = try bytes(nodes, @sizeOf(u32));        var total: usize = 0;        for ([_]usize{            rect_bytes,            cache_bytes,            metric_bytes,            line_bytes,            clip_bytes,            clip_index_bytes,        }) |part| {            total = std.math.add(usize, total, part) catch return error.CapacityOverflow;        }        return .{            .nodes = nodes,            .children = children,            .rect_bytes = rect_bytes,            .cache_bytes = cache_bytes,            .metric_bytes = metric_bytes,            .line_bytes = line_bytes,            .clip_bytes = clip_bytes,            .clip_index_bytes = clip_index_bytes,            .total_bytes = total,        };    }    fn bytes(count: usize, width: usize) error{CapacityOverflow}!usize {        return std.math.mul(usize, count, width) catch return error.CapacityOverflow;    }};pub const Store = struct {    pub const claim: alloc_phase.capacity.Declaration = .{        .source = .{            .id = "ui.layout_workspace",            .kind = .phase_static,            .limit_source = .caller,            .storage = .{                .covered = &.{                    .{ .id = "rects", .lifetime = .steady, .detail = "one arrange rectangle per admitted node" },                    .{ .id = "size_cache", .lifetime = .steady, .detail = "four indexed size slots per admitted node" },                    .{ .id = "child_scratch", .lifetime = .steady, .detail = "metrics and lines for at most nodes minus one live children" },                    .{ .id = "clips", .lifetime = .steady, .detail = "one viewport clip, plus one clip slot and clip index per admitted node" },                },                .excluded = &.{                    "the admitted publish envelope and computed style pools",                    "shaped-run and measurement caches owned by the text lane",                },            },            .capacity = .{                .inputs = &.{                    alloc_phase.capacity.bindInput(Capacity, "nodes", "nodes"),                    alloc_phase.capacity.bindInput(Capacity, "children", "children"),                },                .type_selectors = &.{                    alloc_phase.capacity.bindType(arrange.Rect, "rect"),                    alloc_phase.capacity.bindType(arrange.IndexedCacheSlot, "cache_slot"),                    alloc_phase.capacity.bindType(arrange.ChildMetrics, "child_metric"),                    alloc_phase.capacity.bindType(arrange.Line, "line"),                    alloc_phase.capacity.bindType(fact.Clip, "clip"),                    alloc_phase.capacity.bindType(u32, "clip_index"),                },                .nodes = &.{                    .{ .input = 0 },                    .{ .input = 1 },                    .{ .scale = .{ .node = 0, .coefficient = .{ .size_of_concrete_type = 0 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .literal = 4 } } },                    .{ .scale = .{ .node = 3, .coefficient = .{ .size_of_concrete_type = 1 } } },                    .{ .scale = .{ .node = 1, .coefficient = .{ .size_of_concrete_type = 2 } } },                    .{ .scale = .{ .node = 1, .coefficient = .{ .size_of_concrete_type = 3 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .size_of_concrete_type = 4 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .size_of_concrete_type = 5 } } },                    .{ .constant = @sizeOf(fact.Clip) },                    .{ .add = .{ .left = 2, .right = 4 } },                    .{ .add = .{ .left = 10, .right = 5 } },                    .{ .add = .{ .left = 11, .right = 6 } },                    .{ .add = .{ .left = 12, .right = 7 } },                    .{ .add = .{ .left = 13, .right = 8 } },                    .{ .add = .{ .left = 14, .right = 9 } },                },                .assertions = &.{.{                    .scope = .closure_total,                    .measure = .retained,                    .relation = .exact,                    .expression = 15,                }},            },            .overload = .{                .kind = .reject_before_seal,                .detail = "a node count over Limits.nodes is rejected before any retained layout span is written",            },            .risks = .{                .transitive = .{ .status = .open, .detail = "arrange and style accessors allocate no memory during solve; a machine call graph certificate remains open" },                .foreign = .{ .status = .excluded, .detail = "layout invokes no foreign runtime" },            },            .obligations = &.{                .{ .key = "ui_layout_capacity", .role = .capacity_model },                .{ .key = "ui_layout_acquisition", .role = .acquisition },                .{ .key = "ui_layout_depth_bound", .role = .work_bound },                .{ .key = "ui_layout_oom", .role = .initialization_failure },                .{ .key = "ui_layout_teardown", .role = .teardown },            },        },        .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 },            },        },    };    phase: alloc_phase.capacity.Phase = .initialization,    limits: Limits,    capacity: Capacity,    rects: []arrange.Rect,    cache: []arrange.IndexedCacheSlot,    metrics: []arrange.ChildMetrics,    lines: []arrange.Line,    clips: []fact.Clip,    clip_indices: []u32,    node_count: u32 = 0,    clip_count: u32 = 0,    cache_epoch: u32 = 0,    pub fn init(allocator: Allocator, limits: Limits) (error{CapacityOverflow} || Allocator.Error)!Store {        const capacity = try Capacity.derive(limits);        const rects = try allocator.alloc(arrange.Rect, capacity.nodes);        errdefer allocator.free(rects);        const cache = try allocator.alloc(arrange.IndexedCacheSlot, capacity.nodes * 4);        errdefer allocator.free(cache);        const metrics = try allocator.alloc(arrange.ChildMetrics, capacity.children);        errdefer allocator.free(metrics);        const lines = try allocator.alloc(arrange.Line, capacity.children);        errdefer allocator.free(lines);        const clips = try allocator.alloc(fact.Clip, capacity.nodes + 1);        errdefer allocator.free(clips);        const clip_indices = try allocator.alloc(u32, capacity.nodes);        @memset(cache, .{});        return .{            .limits = limits,            .capacity = capacity,            .rects = rects,            .cache = cache,            .metrics = metrics,            .lines = lines,            .clips = clips,            .clip_indices = clip_indices,        };    }    pub fn activate(self: *Store) void {        std.debug.assert(self.phase == .initialization);        self.phase = .steady;    }    pub fn solve(        self: *Store,        view: tree.View,        styles: input.Styles,        measurer: ?*arrange.Measurer,    ) error{ CapacityExceeded, EmptyTree, StyleCountMismatch }!Result {        std.debug.assert(self.phase == .steady);        if (view.nodes.len == 0) return error.EmptyTree;        if (view.nodes.len > self.limits.nodes) return error.CapacityExceeded;        if (styles.count() < view.nodes.len) return error.StyleCountMismatch;        if (measurer) |value| value.reset();        var source = input.Input{ .view = view, .styles = styles, .rects = self.rects };        var scratch = arrange.Scratch{            .results = &.{},            .metrics = self.metrics,            .lines = self.lines,            .states = &.{},            .child_indices = &.{},            .indexed_cache = self.cache,            .cache_epoch = self.cache_epoch,        };        const size = arrange.computeLayoutIndexed(            &scratch,            source.indexed(),            0,            .{ .width = view.header.viewport.width, .height = view.header.viewport.height },            .{ .x = view.header.viewport.x, .y = view.header.viewport.y },            measurer,        );        self.cache_epoch = scratch.cache_epoch;        self.placeSolved(view);        self.buildClips(view, styles);        self.node_count = @intCast(view.nodes.len);        return .{ .size = size, .work = scratch.work, .clips = self.clip_count };    }    fn placeSolved(self: *Store, view: tree.View) void {        for (view.solved_roots) |root| {            const supplied = view.solvedRectsOf(root);            const placed = self.rects[root.node];            const dx = placed.x - supplied[0].x;            const dy = placed.y - supplied[0].y;            for (supplied[1..], 1..) |rect, offset| {                self.rects[@as(usize, root.node) + offset] = .{                    .x = rect.x + dx,                    .y = rect.y + dy,                    .width = rect.width,                    .height = rect.height,                };            }        }    }    fn buildClips(self: *Store, view: tree.View, styles: input.Styles) void {        self.clips[0] = .{ .rect = view.header.viewport };        self.clip_count = 1;        for (view.nodes, 0..) |node, index| {            const parent = if (index == 0) @as(u32, 0) else self.clip_indices[node.parent];            const clipped = abi.holds(node.flags, .clip) or                abi.holds(node.flags, .scroll_x) or                abi.holds(node.flags, .scroll_y);            if (!clipped) {                self.clip_indices[index] = parent;                continue;            }            const clip_index = self.clip_count;            std.debug.assert(clip_index < self.clips.len);            self.clip_count += 1;            const rect = self.rects[index];            const padding = styles.record(@intCast(index)).layout.padding;            self.clips[clip_index] = .{                .rect = .{ .x = rect.x, .y = rect.y, .width = rect.width, .height = rect.height },                .origin_x = rect.x + @max(0, padding.left orelse 0),                .origin_y = rect.y + @max(0, padding.top orelse 0),                .parent = parent,                .flags = node.flags,            };            self.clip_indices[index] = clip_index;        }    }    pub fn retainedRects(self: *const Store) []const arrange.Rect {        std.debug.assert(self.phase == .steady);        return self.rects[0..self.node_count];    }    pub fn retainedClips(self: *const Store) []const fact.Clip {        std.debug.assert(self.phase == .steady);        return self.clips[0..self.clip_count];    }    pub fn deinit(self: *Store, allocator: Allocator) void {        std.debug.assert(self.phase != .teardown);        self.phase = .teardown;        allocator.free(self.clip_indices);        allocator.free(self.clips);        allocator.free(self.lines);        allocator.free(self.metrics);        allocator.free(self.cache);        allocator.free(self.rects);        self.clip_indices = &.{};        self.clips = &.{};        self.lines = &.{};        self.metrics = &.{};        self.cache = &.{};        self.rects = &.{};    }};pub const Result = struct {    size: arrange.Size,    work: arrange.Work,    clips: u32,};

Audit

Definitions13
Public names25
Members25
Version26.7.0
Revisiondaab053ee433