Skip to documentation
SLOP

tiny.gui.paint.strip

Reference tiny.gui paint strip

Defined in paint.

API (12)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

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

Source

Called byCallsNo direct callerspaint.StripRecordslanepaint.StripRecordsat
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callspaint.StripRecordsatpaint.StripRecordslane
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallspaint.stripreifyAlloctest sourcelib.gui.src.paint.striptest: recordCount clips to the active...private sourcelib.gui.src.paint.stripstripRangepaint.striprecordCount
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallstest sourcelib.gui.src.paint.striptest: reifyAlloc emits globally align...paint.striprecordCountprivate sourcelib.gui.src.paint.stripwriteRecordspaint.stripreifyAlloc
Static calls · unresolved targets: 0 · external targets: 2.

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

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

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

zig
const std = @import("std");const paint_root = @import("root.zig");const Allocator = std.mem.Allocator;const Command = paint_root.command.Command;const Region = paint_root.cpu.Region;pub const default_height: u32 = 16;pub const word_lanes: usize = 7;pub const Options = struct {    height: u32 = default_height,};pub const Lane = enum(usize) {    command_index = 0,    order = 1,    strip = 2,    x0 = 3,    y0 = 4,    x1 = 5,    y1 = 6,};pub const Record = struct {    command_index: u32,    order: u32,    strip: u32,    x0: u32,    y0: u32,    x1: u32,    y1: u32,};pub const Records = struct {    words: []u32,    count: usize,    pub fn lane(self: Records, which: Lane) []const u32 {        const start = @backingInt(which) * self.count;        return self.words[start .. start + self.count];    }    pub fn laneMut(self: *Records, which: Lane) []u32 {        const start = @backingInt(which) * self.count;        return self.words[start .. start + self.count];    }    pub fn at(self: Records, index: usize) Record {        return .{            .command_index = self.lane(.command_index)[index],            .order = self.lane(.order)[index],            .strip = self.lane(.strip)[index],            .x0 = self.lane(.x0)[index],            .y0 = self.lane(.y0)[index],            .x1 = self.lane(.x1)[index],            .y1 = self.lane(.y1)[index],        };    }    pub fn deinit(self: *Records, allocator: Allocator) void {        allocator.free(self.words);        self.* = undefined;    }};const StripRange = struct {    first: u32,    last: u32,    fn count(self: StripRange) usize {        return self.last - self.first + 1;    }};pub fn recordCount(commands: []const Command, width: u32, height: u32, region: Region, options: Options) !usize {    if (options.height == 0) return error.InvalidStripHeight;    const active_region = region.clamped(width, height);    if (active_region.pixelCount() == 0) return 0;    var total: usize = 0;    for (commands) |paint| {        const bounds = paint_root.cpu.clippedBounds(width, height, paint, active_region) orelse continue;        total = std.math.add(usize, total, stripRange(bounds.y0, bounds.y1, options).count()) catch return error.RecordCountTooLarge;    }    return total;}pub fn reifyAlloc(allocator: Allocator, commands: []const Command, width: u32, height: u32, region: Region, options: Options) !Records {    const count = try recordCount(commands, width, height, region, options);    const word_count = std.math.mul(usize, count, word_lanes) catch return error.RecordCountTooLarge;    const words = try allocator.alloc(u32, word_count);    errdefer allocator.free(words);    var records = Records{ .words = words, .count = count };    try writeRecords(&records, commands, width, height, region, options);    return records;}fn writeRecords(records: *Records, commands: []const Command, width: u32, height: u32, region: Region, options: Options) !void {    if (options.height == 0) return error.InvalidStripHeight;    const active_region = region.clamped(width, height);    if (active_region.pixelCount() == 0) return;    var cursor: usize = 0;    for (commands, 0..) |paint, command_index| {        const command_index_u32 = std.math.cast(u32, command_index) orelse return error.CommandCountTooLarge;        const bounds = paint_root.cpu.clippedBounds(width, height, paint, active_region) orelse continue;        const range = stripRange(bounds.y0, bounds.y1, options);        var strip = range.first;        while (strip <= range.last) : (strip += 1) {            const y0 = @max(bounds.y0, stripStart(strip, options.height));            const y1 = @min(bounds.y1, stripEnd(strip, options.height));            writeRecord(records, cursor, .{                .command_index = command_index_u32,                .order = paint.order,                .strip = strip,                .x0 = bounds.x0,                .y0 = y0,                .x1 = bounds.x1,                .y1 = y1,            });            cursor += 1;        }    }    std.debug.assert(cursor == records.count);}fn writeRecord(records: *Records, index: usize, record: Record) void {    records.laneMut(.command_index)[index] = record.command_index;    records.laneMut(.order)[index] = record.order;    records.laneMut(.strip)[index] = record.strip;    records.laneMut(.x0)[index] = record.x0;    records.laneMut(.y0)[index] = record.y0;    records.laneMut(.x1)[index] = record.x1;    records.laneMut(.y1)[index] = record.y1;}fn stripRange(y0: u32, y1: u32, options: Options) StripRange {    std.debug.assert(y0 < y1);    return .{        .first = y0 / options.height,        .last = (y1 - 1) / options.height,    };}fn stripStart(strip: u32, height: u32) u32 {    return @intCast(@as(u64, strip) * height);}fn stripEnd(strip: u32, height: u32) u32 {    return @intCast(@min(@as(u64, std.math.maxInt(u32)), (@as(u64, strip) + 1) * height));}test "reifyAlloc emits globally aligned strip records" {    const allocator = std.testing.allocator;    const commands = [_]Command{        .{            .kind = .fill,            .rect = .{ .x = 2, .y = 0, .width = 12, .height = 40 },            .clip = .{ .x = 0, .y = 0, .width = 64, .height = 64 },            .color = .{ .r = 20, .g = 30, .b = 40, .a = 255 },            .order = 3,        },        .{            .kind = .fill,            .rect = .{ .x = 8, .y = 10, .width = 18, .height = 10 },            .clip = .{ .x = 0, .y = 0, .width = 64, .height = 64 },            .color = .{ .r = 80, .g = 90, .b = 100, .a = 255 },            .order = 7,        },    };    var records = try reifyAlloc(allocator, commands[0..], 64, 64, Region.full(64, 64), .{ .height = 16 });    defer records.deinit(allocator);    try std.testing.expectEqual(@as(usize, 5), records.count);    try std.testing.expectEqualSlices(u32, &.{ 0, 0, 0, 1, 1 }, records.lane(.command_index));    try std.testing.expectEqualSlices(u32, &.{ 3, 3, 3, 7, 7 }, records.lane(.order));    try std.testing.expectEqualSlices(u32, &.{ 0, 1, 2, 0, 1 }, records.lane(.strip));    try std.testing.expectEqualSlices(u32, &.{ 0, 16, 32, 10, 16 }, records.lane(.y0));    try std.testing.expectEqualSlices(u32, &.{ 16, 32, 40, 16, 20 }, records.lane(.y1));}test "recordCount clips to the active region" {    const commands = [_]Command{.{        .kind = .fill,        .rect = .{ .x = 0, .y = 0, .width = 32, .height = 32 },        .clip = .{ .x = 0, .y = 0, .width = 32, .height = 32 },        .color = .{ .r = 20, .g = 30, .b = 40, .a = 255 },    }};    const count = try recordCount(commands[0..], 32, 32, .{ .x = 0, .y = 8, .width = 32, .height = 8 }, .{ .height = 16 });    try std.testing.expectEqual(@as(usize, 1), count);}

Audit

Definitions13
Public names19
Members17
Version26.7.0
Revisiondaab053ee433