tiny.filigree.layout.class
Defined in layout.
API (3)
Types and contracts
Public types and contracts.
Source
Source: lib/filigree/src/layout/class.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 ClassDef = union(enum) { format_1: ClassDefFormat1, format_2: ClassDefFormat2, pub fn init(data: []const u8, offset: usize) LayoutError!ClassDef { if (!hasBytes(data, offset, 2)) return error.InvalidLayout; return switch (try readU16(data, offset)) { 1 => .{ .format_1 = try ClassDefFormat1.init(data, offset) }, 2 => .{ .format_2 = try ClassDefFormat2.init(data, offset) }, else => error.UnsupportedClassDef, }; } pub fn class(self: ClassDef, data: []const u8, glyph_id: u32) LayoutError!u16 { return switch (self) { .format_1 => |format| format.class(data, glyph_id), .format_2 => |format| format.class(data, glyph_id), }; }};pub const ClassDefFormat1 = struct { start_glyph_id: u16, class_value_offset: usize, glyph_count: u16, fn init(data: []const u8, offset: usize) LayoutError!ClassDefFormat1 { if (!hasBytes(data, offset, 6)) return error.InvalidLayout; const glyph_count = try readU16(data, offset + 4); const array_offset = offset + 6; const array_len = @as(usize, glyph_count) * 2; if (!hasBytes(data, array_offset, array_len)) return error.InvalidLayout; return .{ .start_glyph_id = try readU16(data, offset + 2), .class_value_offset = array_offset, .glyph_count = glyph_count, }; } fn class(self: ClassDefFormat1, data: []const u8, glyph_id: u32) LayoutError!u16 { if (glyph_id > std.math.maxInt(u16)) return 0; const glyph: u16 = @intCast(glyph_id); if (glyph < self.start_glyph_id) return 0; const index = @as(usize, glyph - self.start_glyph_id); if (index >= self.glyph_count) return 0; return try readU16(data, self.class_value_offset + index * 2); }};pub const ClassDefFormat2 = struct { class_range_array_offset: usize, class_range_count: u16, fn init(data: []const u8, offset: usize) LayoutError!ClassDefFormat2 { 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 .{ .class_range_array_offset = array_offset, .class_range_count = range_count, }; } fn class(self: ClassDefFormat2, data: []const u8, glyph_id: u32) LayoutError!u16 { if (glyph_id > std.math.maxInt(u16)) return 0; const glyph: u16 = @intCast(glyph_id); var left: usize = 0; var right: usize = self.class_range_count; while (left < right) { const mid = left + (right - left) / 2; const record = self.class_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 { return try readU16(data, record + 4); } } return 0; }};test "ClassDef format 1 maps consecutive glyph classes" { const data = [_]u8{ 0, 1, 0, 5, 0, 3, 0, 1, 0, 7, 0, 2, }; const class_def = try ClassDef.init(&data, 0); try std.testing.expectEqual(@as(u16, 0), try class_def.class(&data, 4)); try std.testing.expectEqual(@as(u16, 1), try class_def.class(&data, 5)); try std.testing.expectEqual(@as(u16, 7), try class_def.class(&data, 6)); try std.testing.expectEqual(@as(u16, 2), try class_def.class(&data, 7)); try std.testing.expectEqual(@as(u16, 0), try class_def.class(&data, 8));}test "ClassDef format 2 maps class ranges" { const data = [_]u8{ 0, 2, 0, 2, 0, 10, 0, 12, 0, 4, 0, 30, 0, 31, 0, 8, }; const class_def = try ClassDef.init(&data, 0); try std.testing.expectEqual(@as(u16, 4), try class_def.class(&data, 10)); try std.testing.expectEqual(@as(u16, 4), try class_def.class(&data, 12)); try std.testing.expectEqual(@as(u16, 8), try class_def.class(&data, 31)); try std.testing.expectEqual(@as(u16, 0), try class_def.class(&data, 13)); try std.testing.expectEqual(@as(u16, 0), try class_def.class(&data, 0x1_0000));}test "ClassDef honors nonzero table offsets" { const data = [_]u8{ 0xaa, 0xbb, 0, 1, 0, 7, 0, 1, 0, 5, }; const class_def = try ClassDef.init(&data, 2); try std.testing.expectEqual(@as(u16, 5), try class_def.class(&data, 7));}test "ClassDef rejects unsupported format" { const data = [_]u8{ 0, 3 }; try std.testing.expectError(error.UnsupportedClassDef, ClassDef.init(&data, 0));}Source: lib/filigree/src/layout/root.zig:2
zig
pub const class = @import("class.zig");Audit
| Definitions | 3 |
|---|---|
| Public names | 5 |
| Members | 5 |
| Version | 26.7.0 |
| Revision | daab053ee433 |