Skip to documentation
SLOP

tiny.filigree.layout.coverage

Reference tiny.filigree layout coverage

Defined in layout.

API (3)

Types and contracts

Public types and contracts.

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

Source

Source: lib/filigree/src/layout/coverage.zig

zig
const std = @import("std");const binary = @import("binary.zig");const LayoutError = binary.LayoutError;const hasBytes = binary.hasBytes;const readU16 = binary.readU16;pub const Coverage = union(enum) {    format_1: CoverageFormat1,    format_2: CoverageFormat2,    pub fn init(data: []const u8, offset: usize) LayoutError!Coverage {        if (!hasBytes(data, offset, 2)) return error.InvalidLayout;        return switch (try readU16(data, offset)) {            1 => .{ .format_1 = try CoverageFormat1.init(data, offset) },            2 => .{ .format_2 = try CoverageFormat2.init(data, offset) },            else => error.UnsupportedCoverage,        };    }    pub fn index(self: Coverage, data: []const u8, glyph_id: u32) LayoutError!?u16 {        return switch (self) {            .format_1 => |format| format.index(data, glyph_id),            .format_2 => |format| format.index(data, glyph_id),        };    }};pub const CoverageFormat1 = struct {    glyph_array_offset: usize,    glyph_count: u16,    fn init(data: []const u8, offset: usize) LayoutError!CoverageFormat1 {        if (!hasBytes(data, offset, 4)) return error.InvalidLayout;        const glyph_count = try readU16(data, offset + 2);        const array_offset = offset + 4;        const array_len = @as(usize, glyph_count) * 2;        if (!hasBytes(data, array_offset, array_len)) return error.InvalidLayout;        var previous: ?u16 = null;        for (0..glyph_count) |i| {            const glyph = try readU16(data, array_offset + i * 2);            if (previous) |seen| {                if (glyph <= seen) return error.InvalidLayout;            }            previous = glyph;        }        return .{            .glyph_array_offset = array_offset,            .glyph_count = glyph_count,        };    }    fn index(self: CoverageFormat1, data: []const u8, glyph_id: u32) LayoutError!?u16 {        if (glyph_id > std.math.maxInt(u16)) return null;        const glyph: u16 = @intCast(glyph_id);        var left: usize = 0;        var right: usize = self.glyph_count;        while (left < right) {            const mid = left + (right - left) / 2;            const candidate = try readU16(data, self.glyph_array_offset + mid * 2);            if (glyph < candidate) {                right = mid;            } else if (glyph > candidate) {                left = mid + 1;            } else {                return @intCast(mid);            }        }        return null;    }};pub const CoverageFormat2 = struct {    range_array_offset: usize,    range_count: u16,    fn init(data: []const u8, offset: usize) LayoutError!CoverageFormat2 {        if (!hasBytes(data, offset, 4)) return error.InvalidLayout;        const range_count = try readU16(data, offset + 2);        const array_offset = offset + 4;        const array_len = @as(usize, range_count) * 6;        if (!hasBytes(data, array_offset, array_len)) return error.InvalidLayout;        var previous_end: ?u16 = null;        for (0..range_count) |i| {            const record = array_offset + i * 6;            const start = try readU16(data, record);            const end = try readU16(data, record + 2);            if (start > end) return error.InvalidLayout;            if (previous_end) |seen| {                if (start <= seen) return error.InvalidLayout;            }            previous_end = end;        }        return .{            .range_array_offset = array_offset,            .range_count = range_count,        };    }    fn index(self: CoverageFormat2, data: []const u8, glyph_id: u32) LayoutError!?u16 {        if (glyph_id > std.math.maxInt(u16)) return null;        const glyph: u16 = @intCast(glyph_id);        var left: usize = 0;        var right: usize = self.range_count;        while (left < right) {            const mid = left + (right - left) / 2;            const record = self.range_array_offset + mid * 6;            const start = try readU16(data, record);            const end = try readU16(data, record + 2);            if (glyph < start) {                right = mid;            } else if (glyph > end) {                left = mid + 1;            } else {                const start_index = try readU16(data, record + 4);                const delta = glyph - start;                if (start_index > std.math.maxInt(u16) - delta) return error.InvalidLayout;                return start_index + delta;            }        }        return null;    }};test "Coverage format 1 maps sorted glyph array to indexes" {    const data = [_]u8{        0, 1,        0, 3,        0, 5,        0, 9,        0, 20,    };    const coverage = try Coverage.init(&data, 0);    try std.testing.expectEqual(@as(?u16, 0), try coverage.index(&data, 5));    try std.testing.expectEqual(@as(?u16, 1), try coverage.index(&data, 9));    try std.testing.expectEqual(@as(?u16, 2), try coverage.index(&data, 20));    try std.testing.expectEqual(@as(?u16, null), try coverage.index(&data, 6));    try std.testing.expectEqual(@as(?u16, null), try coverage.index(&data, 0x1_0000));}test "Coverage format 1 rejects unsorted glyph array" {    const data = [_]u8{        0, 1,        0, 2,        0, 7,        0, 7,    };    try std.testing.expectError(error.InvalidLayout, Coverage.init(&data, 0));}test "Coverage format 2 maps glyph ranges to indexes" {    const data = [_]u8{        0, 2,        0, 2,        0, 10,        0, 12,        0, 0,        0, 20,        0, 21,        0, 3,    };    const coverage = try Coverage.init(&data, 0);    try std.testing.expectEqual(@as(?u16, 0), try coverage.index(&data, 10));    try std.testing.expectEqual(@as(?u16, 2), try coverage.index(&data, 12));    try std.testing.expectEqual(@as(?u16, 3), try coverage.index(&data, 20));    try std.testing.expectEqual(@as(?u16, 4), try coverage.index(&data, 21));    try std.testing.expectEqual(@as(?u16, null), try coverage.index(&data, 13));}test "Coverage format 2 rejects overlapping ranges" {    const data = [_]u8{        0, 2,        0, 2,        0, 10,        0, 12,        0, 0,        0, 12,        0, 14,        0, 3,    };    try std.testing.expectError(error.InvalidLayout, Coverage.init(&data, 0));}test "Coverage honors nonzero table offsets" {    const data = [_]u8{        0xaa, 0xbb,        0,    1,        0,    1,        0,    42,    };    const coverage = try Coverage.init(&data, 2);    try std.testing.expectEqual(@as(?u16, 0), try coverage.index(&data, 42));}

Source: lib/filigree/src/layout/root.zig:3

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

Audit

Definitions3
Public names5
Members4
Version26.7.0
Revisiondaab053ee433