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.
Source
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
| Definitions | 13 |
|---|---|
| Public names | 19 |
| Members | 17 |
| Version | 26.7.0 |
| Revision | daab053ee433 |