Skip to documentation
SLOP

tiny.ui.style.computed

Reference tiny.ui style computed

Defined in style.

API (5)

Actions

Public operations.

Types and contracts

Public types and contracts.

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

Source

Called byCallstest sourcelib.ui.src.style.computedtest: lowering fills all text flags a...test sourcelib.ui.src.style.computedtest: lowering places outline reach a...style.share.Poolinternprivate sourcelib.ui.src.style.computedcolorprivate sourcelib.ui.src.style.computedinsetprivate sourcelib.ui.src.style.computedlengthprivate sourcelib.ui.src.style.computednumberprivate sourcelib.ui.src.style.computedstyleCode+2 morestyle.computedlower
Static calls · unresolved targets: 0 · external targets: 7.

Source: lib/ui/src/style/computed.zig

zig
const std = @import("std");const arrange = @import("arrange");const css = @import("css");const abi = @import("../abi/root.zig");const asset = @import("../asset/root.zig");const paint_mod = @import("paint.zig");const Value = css.value.Value;pub const Metrics = struct {    root_font_size: f32 = 16,    viewport_width: f32 = 0,    viewport_height: f32 = 0,};pub const FontSource = struct {    registry: *const asset.Registry,    source: []const u8,};pub const FontEnvironment = struct {    source: FontSource,    fallback_out: []asset.AssetHandle,    first: u32,};pub const Record = struct {    computed: css.cascade.Computed = .{},    layout: arrange.Style = .{},    dimensions: arrange.Dimensions = .{},    paint: paint_mod.Paint = .{},    text: paint_mod.TextStyle = .{},    layer: i16 = 0,};fn value(style: *const css.cascade.Computed, id: css.property.Id) Value {    return style.get(id);}fn number(item: Value, fallback: f32) f32 {    return switch (item.valueKind()) {        .number, .length, .percent => item.asNumber(),        else => fallback,    };}fn length(item: Value, metrics: Metrics, font_size: f32, line_height: f32) ?f32 {    if (item.valueKind() != .length) return null;    const amount = item.asNumber();    return amount * switch (item.valueUnit()) {        .px => @as(f32, 1),        .em => font_size,        .rem => metrics.root_font_size,        .ch => font_size * 0.5,        .lh => line_height,        .ex => font_size * 0.5,        .vw => metrics.viewport_width / 100,        .vh => metrics.viewport_height / 100,        .vmin => @min(metrics.viewport_width, metrics.viewport_height) / 100,        .vmax => @max(metrics.viewport_width, metrics.viewport_height) / 100,        else => return null,    };}fn color(item: Value, foreground: abi.Color) abi.Color {    if (item.asKeyword() == .currentcolor) return foreground;    if (item.valueKind() != .color) return .{};    return .{        .r = css.value.color.red(item.a),        .g = css.value.color.green(item.a),        .b = css.value.color.blue(item.a),        .a = css.value.color.alpha(item.a),    };}fn styleCode(item: Value) u8 {    return switch (item.asKeyword()) {        .solid => 1,        .dashed => 2,        .dotted => 3,        .double => 4,        .groove => 5,        .ridge => 6,        .inset => 7,        .outset => 8,        else => 0,    };}fn textFlags(style: *const css.cascade.Computed) u16 {    const white_space: u16 = switch (value(style, .white_space).asKeyword()) {        .nowrap => 1,        .pre => 2,        .pre_wrap => 3,        .pre_line => 4,        .break_spaces => 5,        else => 0,    };    const word_break: u16 = switch (value(style, .word_break).asKeyword()) {        .break_all => 1,        .keep_all => 2,        else => 0,    };    const overflow_wrap: u16 = switch (value(style, .overflow_wrap).asKeyword()) {        .break_word => 1,        .anywhere => 2,        else => 0,    };    const direction: u16 = @intFromBool(value(style, .direction).asKeyword() == .rtl);    const user_select: u16 = switch (value(style, .user_select).asKeyword()) {        .none => 1,        .text => 2,        .all => 3,        else => 0,    };    const slant: u16 = switch (value(style, .font_style).asKeyword()) {        .italic => 1,        .oblique => 2,        else => 0,    };    return (white_space << paint_mod.TextFlags.white_space_shift) |        (word_break << paint_mod.TextFlags.word_break_shift) |        (overflow_wrap << paint_mod.TextFlags.overflow_wrap_shift) |        (direction << paint_mod.TextFlags.direction_shift) |        (user_select << paint_mod.TextFlags.user_select_shift) |        (slant << paint_mod.TextFlags.slant_shift);}fn inset(style: *const css.cascade.Computed, metrics: Metrics, size: f32, leading: f32, ids: [4]css.property.Id) arrange.Insets {    return .{        .top = length(value(style, ids[0]), metrics, size, leading),        .right = length(value(style, ids[1]), metrics, size, leading),        .bottom = length(value(style, ids[2]), metrics, size, leading),        .left = length(value(style, ids[3]), metrics, size, leading),    };}pub fn lower(style: css.cascade.Computed, metrics: Metrics, fonts: ?FontEnvironment) Record {    var record = Record{ .computed = style };    const font = length(value(&style, .font_size), metrics, metrics.root_font_size, metrics.root_font_size) orelse metrics.root_font_size;    const leading_value = value(&style, .line_height);    const leading = if (leading_value.valueKind() == .number)        font * leading_value.asNumber()    else        length(leading_value, metrics, font, font) orelse font * 1.2;    record.layout.flex_direction = switch (value(&style, .flex_direction).asKeyword()) {        .column, .column_reverse => .column,        else => .row,    };    record.layout.wrap = switch (value(&style, .flex_wrap).asKeyword()) {        .wrap, .wrap_reverse => .wrap,        else => .no_wrap,    };    record.layout.justify_content = switch (value(&style, .justify_content).asKeyword()) {        .flex_end, .end => .flex_end,        .center => .center,        .space_between => .space_between,        .space_around => .space_around,        .space_evenly => .space_evenly,        else => .flex_start,    };    record.layout.align_items = switch (value(&style, .align_items).asKeyword()) {        .flex_start, .start => .flex_start,        .flex_end, .end => .flex_end,        .center => .center,        else => .stretch,    };    record.layout.align_self = switch (value(&style, .align_self).asKeyword()) {        .flex_start, .start => .flex_start,        .flex_end, .end => .flex_end,        .center => .center,        .stretch => .stretch,        else => .auto,    };    record.layout.gap = length(value(&style, .row_gap), metrics, font, leading) orelse 0;    record.layout.padding = inset(&style, metrics, font, leading, .{ .padding_top, .padding_right, .padding_bottom, .padding_left });    record.layout.constraints = .{        .min_width = length(value(&style, .min_width), metrics, font, leading),        .min_height = length(value(&style, .min_height), metrics, font, leading),        .max_width = length(value(&style, .max_width), metrics, font, leading),        .max_height = length(value(&style, .max_height), metrics, font, leading),    };    record.layout.flex_grow = number(value(&style, .flex_grow), 0);    record.layout.flex_shrink = number(value(&style, .flex_shrink), 1);    record.layout.flex_basis = length(value(&style, .flex_basis), metrics, font, leading);    record.layout.position = if (value(&style, .position).asKeyword() == .absolute) .absolute else .relative;    record.layout.inset = inset(&style, metrics, font, leading, .{ .top, .right, .bottom, .left });    record.dimensions = .{        .width = length(value(&style, .width), metrics, font, leading),        .height = length(value(&style, .height), metrics, font, leading),    };    record.paint.foreground = color(value(&style, .color), .{});    record.paint.background = color(value(&style, .background_color), record.paint.foreground);    record.paint.border_color = .{        color(value(&style, .border_top_color), record.paint.foreground),        color(value(&style, .border_right_color), record.paint.foreground),        color(value(&style, .border_bottom_color), record.paint.foreground),        color(value(&style, .border_left_color), record.paint.foreground),    };    record.paint.outline_color = color(value(&style, .outline_color), record.paint.foreground);    record.paint.border_width = .{        length(value(&style, .border_top_width), metrics, font, leading) orelse 0,        length(value(&style, .border_right_width), metrics, font, leading) orelse 0,        length(value(&style, .border_bottom_width), metrics, font, leading) orelse 0,        length(value(&style, .border_left_width), metrics, font, leading) orelse 0,    };    record.paint.radius = .{        length(value(&style, .border_top_left_radius), metrics, font, leading) orelse 0,        length(value(&style, .border_top_right_radius), metrics, font, leading) orelse 0,        length(value(&style, .border_bottom_right_radius), metrics, font, leading) orelse 0,        length(value(&style, .border_bottom_left_radius), metrics, font, leading) orelse 0,    };    record.paint.border_style = .{        styleCode(value(&style, .border_top_style)),        styleCode(value(&style, .border_right_style)),        styleCode(value(&style, .border_bottom_style)),        styleCode(value(&style, .border_left_style)),    };    record.paint.outline_style = styleCode(value(&style, .outline_style));    record.paint.outline_width = length(value(&style, .outline_width), metrics, font, leading) orelse 0;    record.paint.outline_offset = length(value(&style, .outline_offset), metrics, font, leading) orelse 0;    record.paint.outset = if (record.paint.outline_style == 0) 0 else @max(0, record.paint.outline_width + record.paint.outline_offset);    record.paint.opacity = @intFromFloat(@round(std.math.clamp(number(value(&style, .opacity), 1), 0, 1) * 255));    record.text.size = font;    record.text.line_height = leading;    record.text.letter_spacing = length(value(&style, .letter_spacing), metrics, font, leading) orelse 0;    record.text.word_spacing = length(value(&style, .word_spacing), metrics, font, leading) orelse 0;    record.text.indent = length(value(&style, .text_indent), metrics, font, leading) orelse 0;    record.text.underline_offset = length(value(&style, .text_underline_offset), metrics, font, leading) orelse 0;    record.text.decoration_thickness = length(value(&style, .text_decoration_thickness), metrics, font, leading) orelse 0;    record.text.decoration_color = color(value(&style, .text_decoration_color), record.paint.foreground);    const weight = value(&style, .font_weight);    record.text.weight = @intFromFloat(std.math.clamp(switch (weight.asKeyword()) {        .bold, .bolder => @as(f32, 700),        .lighter => @as(f32, 300),        else => number(weight, 400),    }, 1, 1000));    record.text.flags = textFlags(&style);    if (fonts) |environment| {        const raw_family = value(&style, .font_family);        if (raw_family.valueKind() == .asset) {            const handle = asset.AssetHandle{ .index = raw_family.a, .generation = raw_family.b };            if (environment.source.registry.hasFont(handle)) record.text.face = handle;        } else {            const family = if (raw_family.valueKind() == .string and                raw_family.a <= environment.source.source.len and                raw_family.b <= environment.source.source.len - raw_family.a)                raw_family.asString(environment.source.source)            else                "";            const selection = asset.resolveAuthored(                environment.source.registry,                family,                record.text.weight,                @intCast((record.text.flags >> paint_mod.TextFlags.slant_shift) & 3),                environment.fallback_out,            ) catch unreachable;            if (selection.face) |face| record.text.face = face;            record.text.fallback_first = environment.first;            record.text.fallback_count = @intCast(selection.fallback.len);        }    }    record.text.text_align = @intCast(@backingInt(value(&style, .text_align).asKeyword()));    record.text.transform = @intCast(@backingInt(value(&style, .text_transform).asKeyword()));    record.text.decoration_line = @intCast(@backingInt(value(&style, .text_decoration_line).asKeyword()));    record.text.decoration_style = styleCode(value(&style, .text_decoration_style));    const z = number(value(&style, .z_index), 0);    record.layer = @intFromFloat(std.math.clamp(z, -32768, 32767));    return record;}test "lowering places outline reach and z index in computed records" {    var computed = css.cascade.Computed.initial();    computed.set(.outline_style, Value.keyword(.solid));    computed.set(.outline_width, Value.length(2, .px));    computed.set(.outline_offset, Value.length(2, .px));    computed.set(.z_index, Value.number(7));    const record = lower(computed, .{}, null);    try std.testing.expectEqual(@as(f32, 4), record.paint.outset);    try std.testing.expectEqual(@as(i16, 7), record.layer);    try std.testing.expectEqual(@as(u32, 0), record.text.face.index);}test "lowering fills all text flags and keyword weight" {    var source = css.cascade.Computed.initial();    source.set(.white_space, Value.keyword(.pre_wrap));    source.set(.word_break, Value.keyword(.keep_all));    source.set(.overflow_wrap, Value.keyword(.anywhere));    source.set(.direction, Value.keyword(.rtl));    source.set(.user_select, Value.keyword(.text));    source.set(.font_style, Value.keyword(.oblique));    source.set(.font_weight, Value.keyword(.bold));    const record = lower(source, .{}, null);    try std.testing.expectEqual(@as(u16, 700), record.text.weight);    try std.testing.expectEqual(@as(u16, 3 | (2 << 3) | (2 << 5) | (1 << 7) | (2 << 8) | (2 << 10)), record.text.flags);}

Source: lib/ui/src/style/root.zig:3

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

Complete call list for style.computed.lower

7 direct calls.

Audit

Definitions6
Public names7
Members14
Version26.7.0
Revisiondaab053ee433