Skip to documentation
SLOP

tiny.filigree.font.face

Reference tiny.filigree font face

Defined in font.

API (1)

Types and contracts

Public types and contracts.

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

Source

Source: lib/filigree/src/font/face.zig

zig
const std = @import("std");const binary = @import("binary.zig");const cmap_owner = @import("cmap.zig");const directory = @import("directory.zig");const gdef_owner = @import("gdef.zig");const gsub_owner = @import("gsub.zig");const gpos_owner = @import("gpos.zig");const kern_owner = @import("kern.zig");const lookups = @import("lookups.zig");const math_owner = @import("math.zig");const metrics_table = @import("metrics.zig");const model = @import("model.zig");const names = @import("names.zig");const variations = @import("variations.zig");const test_font = @import("../fixture/root.zig");const fixture_binary = test_font.binary;const Cmap = cmap_owner.Cmap;const FontError = model.FontError;const Table = binary.Table;const Tag = model.Tag;const readI8 = binary.readI8;const readI16 = binary.readI16;const readI32 = binary.readI32;const readU16 = binary.readU16;const readU24 = binary.readU24;const readU32 = binary.readU32;const table = directory.table;const tableAt = directory.tableAt;const tableAtTag = directory.tableAtTag;const tableOptionalAt = directory.optionalAt;const tableOptionalAtTag = directory.optionalAtTag;const fontDirectoryOffset = directory.fontDirectoryOffset;const tag = model.tag;const tagLiteral = model.tag;const GlyphClass = model.GlyphClass;const LigatureCaret = model.LigatureCaret;const FeatureRange = model.FeatureRange;const VariationAxis = model.VariationAxis;const VariationSetting = model.VariationSetting;const NormalizedVariation = model.NormalizedVariation;const LayoutSelection = model.LayoutSelection;const defaultScriptTag = model.defaultScriptTag;const featureEnabled = model.featureEnabled;const fixed16ToFloat = model.fixed16ToFloat;const noGposVariationIndex = model.noGposVariationIndex;const GsubSubstitution = model.GsubSubstitution;const GposValueAdjustment = model.GposValueAdjustment;const GposPairAdjustment = model.GposPairAdjustment;const GposPairAdjustmentBefore = model.GposPairAdjustmentBefore;const GposContextualPairAdjustment = model.GposContextualPairAdjustment;const GposSingleAdjustment = model.GposSingleAdjustment;const GposCursiveAttachment = model.GposCursiveAttachment;const Gpos = gpos_owner.Gpos;const Gdef = gdef_owner.Gdef;const Gsub = gsub_owner.Gsub;const Kern = kern_owner.Kern;const Math = math_owner.Math;const MathConstants = math_owner.Constants;const MathGlyphAssembly = math_owner.GlyphAssembly;const MathGlyphVariant = math_owner.GlyphVariant;const MathValueRecord = math_owner.ValueRecord;const VerticalMetrics = metrics_table.VerticalMetrics;const Vorg = metrics_table.Vorg;const HorizontalMetrics = metrics_table.HorizontalMetrics;const verticalMetrics = metrics_table.verticalMetrics;const horizontalTypoMetrics = metrics_table.horizontalTypoMetrics;const bestNameRecord = names.bestNameRecord;const utf16BeToUtf8Alloc = names.utf16BeToUtf8Alloc;const lookup_use_mark_filtering_set = lookups.use_mark_filtering_set;const lookupGlyphIgnored = lookups.lookupGlyphIgnored;const Fvar = variations.Fvar;const Avar = variations.Avar;const Hvar = variations.Hvar;const Vvar = variations.Vvar;const Mvar = variations.Mvar;const DeltaSetIndex = variations.DeltaSetIndex;const ItemVariationStore = variations.ItemVariationStore;const fixed16FromFloat = variations.fixed16FromFloat;const normalizeVariationAxis = variations.normalizeVariationAxis;const fixed16ToF2Dot14 = variations.fixed16ToF2Dot14;const clampDesignMetric = variations.clampDesignMetric;const clampI32 = variations.clampI32;pub const Face = struct {    data: []const u8,    directory_offset: usize,    units_per_em: u16,    ascender: i16,    descender: i16,    line_gap: i16,    typo_metrics: ?HorizontalMetrics,    num_glyphs: u16,    num_h_metrics: u16,    num_v_metrics: u16,    cmap: Cmap,    hmtx: Table,    vmtx: ?Table,    vorg: ?Vorg,    kern: ?Kern,    gsub: ?Gsub,    gpos: ?Gpos,    gdef: ?Gdef,    fvar: ?Fvar,    avar: ?Avar,    hvar: ?Hvar,    vvar: ?Vvar,    mvar: ?Mvar,    math: ?Math,    pub const init = initImpl;    pub const initAt = initAtImpl;    const initDirectory = initDirectoryImpl;    pub const glyphId = glyphIdImpl;    pub const tableSlice = tableSliceImpl;    pub const tableSliceByTag = tableSliceByTagImpl;    pub const nameUtf8Alloc = nameUtf8AllocImpl;    pub const glyphIdForVariation = glyphIdForVariationImpl;    pub const hasVariationSequences = hasVariationSequencesImpl;    pub const variationAxisCount = variationAxisCountImpl;    pub const variationAxis = variationAxisImpl;    pub const variationAxisFor = variationAxisForImpl;    pub const validateVariations = validateVariationsImpl;    pub const normalizedVariation = normalizedVariationImpl;    pub const normalizedCoordinateAt = normalizedCoordinateAtImpl;    pub const advanceWidth = advanceWidthImpl;    pub const advanceWidthForVariations = advanceWidthForVariationsImpl;    pub const advanceHeight = advanceHeightImpl;    pub const advanceHeightForVariations = advanceHeightForVariationsImpl;    pub const verticalOriginY = verticalOriginYImpl;    pub const metricVariationDelta = metricVariationDeltaImpl;    pub const ascenderForVariations = ascenderForVariationsImpl;    pub const descenderForVariations = descenderForVariationsImpl;    pub const lineGapForVariations = lineGapForVariationsImpl;    pub const heightUnitsForVariations = heightUnitsForVariationsImpl;    pub const kerning = kerningImpl;    pub const hasGpos = hasGposImpl;    pub const gposLookupCount = gposLookupCountImpl;    pub const gposLookupType = gposLookupTypeImpl;    pub const gposVariationValue = gposVariationValueImpl;    const variationContext = variationContextImpl;    pub const hasGsub = hasGsubImpl;    pub const usesAutomaticFractions = usesAutomaticFractionsImpl;    pub const usesArabicJoiningForms = usesArabicJoiningFormsImpl;    pub const gposPairAdjustment = gposPairAdjustmentImpl;    pub const gposPairAdjustmentFor = gposPairAdjustmentForImpl;    pub const gposPairAdjustmentBeforeFor = gposPairAdjustmentBeforeForImpl;    pub const gposPairAdjustmentBeforeForRange = gposPairAdjustmentBeforeForRangeImpl;    pub const gposPairAdjustmentBeforeAtLookupForRange = gposPairAdjustmentBeforeAtLookupForRangeImpl;    pub const gposContextualPairAdjustmentAtFor = gposContextualPairAdjustmentAtForImpl;    pub const gposContextualPairAdjustmentAtForRange = gposContextualPairAdjustmentAtForRangeImpl;    pub const gposContextualPairAdjustmentAtLookupForRange = gposContextualPairAdjustmentAtLookupForRangeImpl;    pub const hasGposContextualPairAdjustmentFor = hasGposContextualPairAdjustmentForImpl;    pub const gposSingleAdjustment = gposSingleAdjustmentImpl;    pub const gposSingleAdjustmentFor = gposSingleAdjustmentForImpl;    pub const gposSingleAdjustmentAtFor = gposSingleAdjustmentAtForImpl;    pub const gposSingleAdjustmentAtForRange = gposSingleAdjustmentAtForRangeImpl;    pub const gposSingleAdjustmentAtLookupForRange = gposSingleAdjustmentAtLookupForRangeImpl;    pub const gposCursiveAttachment = gposCursiveAttachmentImpl;    pub const gposCursiveAttachmentFor = gposCursiveAttachmentForImpl;    pub const gposCursiveAttachmentForRange = gposCursiveAttachmentForRangeImpl;    pub const gposCursiveAttachmentAtLookupForRange = gposCursiveAttachmentAtLookupForRangeImpl;    pub const gposMarkToBaseAdjustment = gposMarkToBaseAdjustmentImpl;    pub const gposMarkToBaseAdjustmentFor = gposMarkToBaseAdjustmentForImpl;    pub const gposMarkToBaseAdjustmentForRange = gposMarkToBaseAdjustmentForRangeImpl;    pub const gposMarkToBaseAdjustmentAtLookupForRange = gposMarkToBaseAdjustmentAtLookupForRangeImpl;    pub const gposMarkToLigatureAdjustment = gposMarkToLigatureAdjustmentImpl;    pub const gposMarkToLigatureAdjustmentFor = gposMarkToLigatureAdjustmentForImpl;    pub const gposMarkToLigatureAdjustmentForRange = gposMarkToLigatureAdjustmentForRangeImpl;    pub const gposMarkToLigatureAdjustmentAtLookupForRange = gposMarkToLigatureAdjustmentAtLookupForRangeImpl;    pub const gposMarkToMarkAdjustment = gposMarkToMarkAdjustmentImpl;    pub const gposMarkToMarkAdjustmentFor = gposMarkToMarkAdjustmentForImpl;    pub const gposMarkToMarkAdjustmentForRange = gposMarkToMarkAdjustmentForRangeImpl;    pub const gposMarkToMarkAdjustmentAtLookupForRange = gposMarkToMarkAdjustmentAtLookupForRangeImpl;    pub const hasGposMarkToBase = hasGposMarkToBaseImpl;    pub const hasGposMarkToBaseFor = hasGposMarkToBaseForImpl;    pub const hasGposMarkToLigature = hasGposMarkToLigatureImpl;    pub const hasGposMarkToLigatureFor = hasGposMarkToLigatureForImpl;    pub const hasGposSingleAdjustment = hasGposSingleAdjustmentImpl;    pub const hasGposSingleAdjustmentFor = hasGposSingleAdjustmentForImpl;    pub const hasGposCursiveAttachment = hasGposCursiveAttachmentImpl;    pub const hasGposCursiveAttachmentFor = hasGposCursiveAttachmentForImpl;    pub const hasGposMarkToMark = hasGposMarkToMarkImpl;    pub const hasGposMarkToMarkFor = hasGposMarkToMarkForImpl;    pub const glyphClass = glyphClassImpl;    pub const ligatureCaretCount = ligatureCaretCountImpl;    pub const ligatureCaret = ligatureCaretImpl;    pub const substituteGlyph = substituteGlyphImpl;    pub const substituteGlyphFor = substituteGlyphForImpl;    pub const gsubLookupCount = gsubLookupCountImpl;    pub const gsubLookupIsReverseFor = gsubLookupIsReverseForImpl;    pub const substitutionAt = substitutionAtImpl;    pub const substitutionAtFor = substitutionAtForImpl;    pub const substitutionAtForRange = substitutionAtForRangeImpl;    pub const substitutionGlyph = substitutionGlyphImpl;    pub const mathConstants = mathConstantsImpl;    pub const mathHorizontalAssemblyAlloc = mathHorizontalAssemblyAllocImpl;    pub const mathHorizontalVariant = mathHorizontalVariantImpl;    pub const mathTopAccentAttachment = mathTopAccentAttachmentImpl;    pub const mathVerticalAssemblyAlloc = mathVerticalAssemblyAllocImpl;    pub const mathVerticalVariant = mathVerticalVariantImpl;    pub const heightUnits = heightUnitsImpl;    const horizontalMetrics = horizontalMetricsImpl;};fn initImpl(data: []const u8) FontError!Face {    return initAtImpl(data, 0);}fn initAtImpl(data: []const u8, face_index: u32) FontError!Face {    const directory_offset = try fontDirectoryOffset(data, face_index);    return initDirectoryImpl(data, directory_offset);}fn initDirectoryImpl(data: []const u8, directory_offset: usize) FontError!Face {    if (data.len < 12) return error.InvalidFont;    const version = try readU32(data, directory_offset);    if (version != 0x00010000 and version != tagLiteral("true") and version != tagLiteral("OTTO")) {        return error.InvalidFont;    }    const has_cff_outlines = version == tagLiteral("OTTO");    const num_tables = try readU16(data, directory_offset + 4);    if (directory_offset > data.len or data.len - directory_offset < 12 or @as(usize, num_tables) > (data.len - directory_offset - 12) / 16) return error.InvalidFont;    const head = try tableAt(data, directory_offset, "head");    const hhea = try tableAt(data, directory_offset, "hhea");    const hmtx = try tableAt(data, directory_offset, "hmtx");    const maxp = try tableAt(data, directory_offset, "maxp");    const cmap_table = try tableAt(data, directory_offset, "cmap");    if (head.len < 54 or hhea.len < 36 or maxp.len < 6) return error.InvalidFont;    const units_per_em = try readU16(data, head.offset + 18);    const ascender = try readI16(data, hhea.offset + 4);    const descender = try readI16(data, hhea.offset + 6);    const line_gap = try readI16(data, hhea.offset + 8);    const num_h_metrics = try readU16(data, hhea.offset + 34);    const num_glyphs = try readU16(data, maxp.offset + 4);    if (num_h_metrics == 0) return error.InvalidFont;    const vertical_metrics = verticalMetrics(data, directory_offset, num_glyphs);    const vorg = if (tableOptionalAt(data, directory_offset, "VORG")) |vorg_table|        Vorg.init(data, vorg_table) catch null    else        null;    const typo_metrics = horizontalTypoMetrics(data, directory_offset);    const kern = if (has_cff_outlines)        null    else if (tableOptionalAt(data, directory_offset, "kern")) |kern_table|        Kern.init(data, kern_table) catch null    else        null;    const gsub = if (tableOptionalAt(data, directory_offset, "GSUB")) |gsub_table|        Gsub.init(data, gsub_table) catch null    else        null;    const gpos = if (tableOptionalAt(data, directory_offset, "GPOS")) |gpos_table|        Gpos.init(data, gpos_table) catch null    else        null;    const fvar = if (tableOptionalAt(data, directory_offset, "fvar")) |fvar_table|        Fvar.init(data, fvar_table) catch null    else        null;    const gdef = if (tableOptionalAt(data, directory_offset, "GDEF")) |gdef_table|        Gdef.init(data, gdef_table, if (fvar) |variation_table| variation_table.axis_count else null) catch null    else        null;    const avar = if (fvar) |variation_table|        if (tableOptionalAt(data, directory_offset, "avar")) |avar_table|            Avar.init(data, avar_table, variation_table.axis_count) catch null        else            null    else        null;    const hvar = if (fvar) |variation_table|        if (tableOptionalAt(data, directory_offset, "HVAR")) |hvar_table|            Hvar.init(data, hvar_table, variation_table.axis_count) catch null        else            null    else        null;    const vvar = if (fvar) |variation_table|        if (tableOptionalAt(data, directory_offset, "VVAR")) |vvar_table|            Vvar.init(data, vvar_table, variation_table.axis_count) catch null        else            null    else        null;    const mvar = if (fvar) |variation_table|        if (tableOptionalAt(data, directory_offset, "MVAR")) |mvar_table|            Mvar.init(data, mvar_table, variation_table.axis_count) catch null        else            null    else        null;    const math = if (tableOptionalAt(data, directory_offset, "MATH")) |math_table|        Math.init(data, math_table) catch null    else        null;    return .{        .data = data,        .directory_offset = directory_offset,        .units_per_em = if (units_per_em == 0) 1000 else units_per_em,        .ascender = ascender,        .descender = descender,        .line_gap = line_gap,        .typo_metrics = typo_metrics,        .num_glyphs = num_glyphs,        .num_h_metrics = num_h_metrics,        .num_v_metrics = vertical_metrics.count,        .cmap = try Cmap.init(data, cmap_table),        .hmtx = hmtx,        .vmtx = vertical_metrics.table,        .vorg = vorg,        .kern = kern,        .gsub = gsub,        .gpos = gpos,        .gdef = gdef,        .fvar = fvar,        .avar = avar,        .hvar = hvar,        .vvar = vvar,        .mvar = mvar,        .math = math,    };}fn glyphIdImpl(self: Face, codepoint: u21) u32 {    const glyph = self.cmap.map(self.data, @intCast(codepoint)) catch return 0;    if (glyph >= self.num_glyphs) return 0;    return glyph;}fn tableSliceImpl(self: Face, comptime name: []const u8) ?[]const u8 {    const found = tableOptionalAt(self.data, self.directory_offset, name) orelse return null;    return self.data[found.offset..][0..found.len];}fn tableSliceByTagImpl(self: Face, table_tag: Tag) ?[]const u8 {    const found = tableOptionalAtTag(self.data, self.directory_offset, table_tag) orelse return null;    return self.data[found.offset..][0..found.len];}fn mathConstantsImpl(self: Face) ?MathConstants {    if (self.math) |math| return math.constants;    return null;}fn mathTopAccentAttachmentImpl(self: Face, glyph_id: u32) ?MathValueRecord {    const math = self.math orelse return null;    return math.topAccentAttachment(self.data, glyph_id) catch null;}fn mathVerticalVariantImpl(self: Face, glyph_id: u32, target_measurement: u16) ?MathGlyphVariant {    const math = self.math orelse return null;    return math.verticalVariant(self.data, glyph_id, target_measurement) catch null;}fn mathHorizontalVariantImpl(self: Face, glyph_id: u32, target_measurement: u16) ?MathGlyphVariant {    const math = self.math orelse return null;    return math.horizontalVariant(self.data, glyph_id, target_measurement) catch null;}fn mathVerticalAssemblyAllocImpl(self: Face, allocator: std.mem.Allocator, glyph_id: u32, target_measurement: u16) std.mem.Allocator.Error!?MathGlyphAssembly {    const math = self.math orelse return null;    return math.verticalAssemblyAlloc(allocator, self.data, glyph_id, target_measurement) catch |err| switch (err) {        error.OutOfMemory => return error.OutOfMemory,        else => return null,    };}fn mathHorizontalAssemblyAllocImpl(self: Face, allocator: std.mem.Allocator, glyph_id: u32, target_measurement: u16) std.mem.Allocator.Error!?MathGlyphAssembly {    const math = self.math orelse return null;    return math.horizontalAssemblyAlloc(allocator, self.data, glyph_id, target_measurement) catch |err| switch (err) {        error.OutOfMemory => return error.OutOfMemory,        else => return null,    };}fn nameUtf8AllocImpl(self: Face, allocator: std.mem.Allocator, name_id: u16) !?[]u8 {    const name_table = tableOptionalAt(self.data, self.directory_offset, "name") orelse return null;    const record = (try bestNameRecord(self.data, name_table, name_id)) orelse return null;    return try utf16BeToUtf8Alloc(allocator, record.bytes);}fn glyphIdForVariationImpl(self: Face, codepoint: u21, variation_selector: u21) ?u32 {    const glyph = self.cmap.mapVariation(self.data, @intCast(codepoint), @intCast(variation_selector)) catch return null;    const mapped = glyph orelse return null;    if (mapped >= self.num_glyphs) return 0;    return mapped;}fn hasVariationSequencesImpl(self: Face) bool {    return self.cmap.variation != null;}fn variationAxisCountImpl(self: Face) u16 {    if (self.fvar) |fvar| return fvar.axis_count;    return 0;}fn variationAxisImpl(self: Face, axis_index: usize) ?VariationAxis {    if (self.fvar) |fvar| return fvar.axis(self.data, axis_index) catch null;    return null;}fn variationAxisForImpl(self: Face, axis_tag: Tag) ?VariationAxis {    const fvar = self.fvar orelse return null;    const axis_index = (fvar.axisIndex(self.data, axis_tag) catch return null) orelse return null;    return fvar.axis(self.data, axis_index) catch null;}fn validateVariationsImpl(self: Face, settings: []const VariationSetting) FontError!void {    if (settings.len == 0) return;    const fvar = self.fvar orelse return error.InvalidVariations;    for (settings) |setting| {        const axis_index = (try fvar.axisIndex(self.data, setting.tag)) orelse return error.InvalidVariations;        _ = try self.normalizedCoordinateAt(settings, axis_index);    }}fn normalizedVariationImpl(self: Face, setting: VariationSetting) FontError!?NormalizedVariation {    const fvar = self.fvar orelse return null;    const axis_index = (try fvar.axisIndex(self.data, setting.tag)) orelse return null;    return .{        .tag = setting.tag,        .value = try self.normalizedCoordinateAt(&.{setting}, axis_index),    };}fn normalizedCoordinateAtImpl(self: Face, settings: []const VariationSetting, axis_index: usize) FontError!i16 {    const fvar = self.fvar orelse return error.InvalidVariations;    const axis = try fvar.axis(self.data, axis_index);    var user_value = axis.default_value;    for (settings) |setting| {        if (setting.tag != axis.tag) continue;        user_value = try fixed16FromFloat(setting.value);    }    var normalized = normalizeVariationAxis(axis, user_value);    if (self.avar) |avar| {        normalized = try avar.map(self.data, axis_index, normalized);    }    return fixed16ToF2Dot14(normalized);}fn advanceWidthImpl(self: Face, glyph_id: u32) u16 {    const metric_count: usize = self.num_h_metrics;    const glyph_index = @as(usize, @intCast(glyph_id));    const metric_index = if (glyph_index < metric_count) glyph_index else metric_count - 1;    const offset = self.hmtx.offset + metric_index * 4;    if (offset + 2 > self.data.len) return self.units_per_em;    return readU16(self.data, offset) catch self.units_per_em;}fn advanceWidthForVariationsImpl(self: Face, glyph_id: u32, settings: []const VariationSetting) i32 {    const base = @as(i32, self.advanceWidth(glyph_id));    if (settings.len == 0) return base;    const delta = if (self.hvar) |hvar|        hvar.advanceWidthDelta(self.data, self, settings, glyph_id) catch 0    else        0;    return clampDesignMetric(base, delta);}fn advanceHeightImpl(self: Face, glyph_id: u32) u16 {    const metrics = self.vmtx orelse return self.heightUnits();    const metric_count: usize = self.num_v_metrics;    if (metric_count == 0) return self.heightUnits();    const glyph_index = @as(usize, @intCast(glyph_id));    const metric_index = if (glyph_index < metric_count) glyph_index else metric_count - 1;    if (metric_index > (std.math.maxInt(usize) - metrics.offset) / 4) return self.heightUnits();    const offset = metrics.offset + metric_index * 4;    if (offset + 2 > self.data.len) return self.heightUnits();    return readU16(self.data, offset) catch self.heightUnits();}fn advanceHeightForVariationsImpl(self: Face, glyph_id: u32, settings: []const VariationSetting) i32 {    const base = @as(i32, self.advanceHeight(glyph_id));    if (settings.len == 0) return base;    const delta = if (self.vvar) |vvar|        vvar.advanceHeightDelta(self.data, self, settings, glyph_id) catch 0    else        0;    return clampDesignMetric(base, delta);}fn verticalOriginYImpl(self: Face, glyph_id: u32) ?i16 {    const vorg = self.vorg orelse return null;    return vorg.originY(self.data, glyph_id) catch null;}fn metricVariationDeltaImpl(self: Face, metric_tag: Tag, settings: []const VariationSetting) i32 {    if (settings.len == 0) return 0;    const mvar = self.mvar orelse return 0;    return mvar.valueDelta(self.data, self, settings, metric_tag) catch 0;}fn ascenderForVariationsImpl(self: Face, settings: []const VariationSetting) i32 {    const metrics = self.horizontalMetrics();    return clampI32(@as(i64, metrics.ascender) + @as(i64, self.metricVariationDelta(tagLiteral("hasc"), settings)));}fn descenderForVariationsImpl(self: Face, settings: []const VariationSetting) i32 {    const metrics = self.horizontalMetrics();    return clampI32(@as(i64, metrics.descender) + @as(i64, self.metricVariationDelta(tagLiteral("hdsc"), settings)));}fn lineGapForVariationsImpl(self: Face, settings: []const VariationSetting) i32 {    const metrics = self.horizontalMetrics();    return clampI32(@as(i64, metrics.line_gap) + @as(i64, self.metricVariationDelta(tagLiteral("hlgp"), settings)));}fn heightUnitsForVariationsImpl(self: Face, settings: []const VariationSetting) i32 {    const height = @as(i64, self.ascenderForVariations(settings)) - @as(i64, self.descenderForVariations(settings));    if (height <= 0) return self.units_per_em;    return clampI32(height);}fn kerningImpl(self: Face, left_glyph: u32, right_glyph: u32) i16 {    if (self.kern) |kern| {        return kern.value(self.data, left_glyph, right_glyph) catch 0;    }    return 0;}fn hasGposImpl(self: Face) bool {    return self.gpos != null;}fn gposLookupCountImpl(self: Face) u16 {    if (self.gpos) |gpos| {        return gpos.lookupCount(self.data) catch 0;    }    return 0;}fn gposLookupTypeImpl(self: Face, lookup_index: u16) u16 {    if (self.gpos) |gpos| {        return gpos.lookupResolvedType(self.data, lookup_index) catch 0;    }    return 0;}fn gposVariationValueImpl(self: Face, base: i32, settings: []const VariationSetting, packed_index: u32) i32 {    return gposVariationValueForFace(base, self, settings, packed_index);}fn variationContextImpl(self: *const Face) lookups.VariationContext {    return .{        .ptr = self,        .variation_axis_count = faceVariationAxisCount,        .normalized_coordinate_at = faceNormalizedCoordinateAt,    };}fn hasGsubImpl(self: Face) bool {    return self.gsub != null;}fn usesAutomaticFractionsImpl(self: Face, selection: LayoutSelection) bool {    if (self.gsub) |gsub| {        return gsub.usesAutomaticFractions(self.data, selection) catch false;    }    return false;}fn usesArabicJoiningFormsImpl(self: Face, selection: LayoutSelection) bool {    if (self.gsub) |gsub| {        return gsub.usesArabicJoiningForms(self.data, selection) catch false;    }    return false;}fn gposPairAdjustmentImpl(self: Face, left_glyph: u32, right_glyph: u32) GposPairAdjustment {    return self.gposPairAdjustmentFor(.{}, left_glyph, right_glyph);}fn gposPairAdjustmentForImpl(self: Face, selection: LayoutSelection, left_glyph: u32, right_glyph: u32) GposPairAdjustment {    if (self.gpos) |gpos| {        return gpos.pairAdjustment(self.data, self.variationContext(), selection, self.gdef, left_glyph, right_glyph) catch .{};    }    return .{};}fn gposPairAdjustmentBeforeForImpl(self: Face, selection: LayoutSelection, glyph_ids: []const u32, glyph_index: usize) ?GposPairAdjustmentBefore {    return self.gposPairAdjustmentBeforeForRange(selection, glyph_ids, glyph_index, null);}fn gposPairAdjustmentBeforeForRangeImpl(self: Face, selection: LayoutSelection, glyph_ids: []const u32, glyph_index: usize, source: ?FeatureRange) ?GposPairAdjustmentBefore {    if (self.gpos) |gpos| {        return gpos.pairAdjustmentBefore(self.data, self.variationContext(), selection, self.gdef, glyph_ids, glyph_index, source) catch null;    }    return null;}fn gposPairAdjustmentBeforeAtLookupForRangeImpl(self: Face, selection: LayoutSelection, lookup_index: u16, glyph_ids: []const u32, glyph_index: usize, source: ?FeatureRange) ?GposPairAdjustmentBefore {    if (self.gpos) |gpos| {        return gpos.pairAdjustmentBeforeAtLookup(self.data, self.variationContext(), selection, self.gdef, lookup_index, glyph_ids, glyph_index, source) catch null;    }    return null;}fn gposContextualPairAdjustmentAtForImpl(self: Face, selection: LayoutSelection, glyph_ids: []const u32, glyph_index: usize) ?GposContextualPairAdjustment {    return self.gposContextualPairAdjustmentAtForRange(selection, glyph_ids, glyph_index, null);}fn gposContextualPairAdjustmentAtForRangeImpl(self: Face, selection: LayoutSelection, glyph_ids: []const u32, glyph_index: usize, source: ?FeatureRange) ?GposContextualPairAdjustment {    if (self.gpos) |gpos| {        return gpos.contextualPairAdjustmentAt(self.data, self.variationContext(), selection, self.gdef, glyph_ids, glyph_index, source) catch null;    }    return null;}fn gposContextualPairAdjustmentAtLookupForRangeImpl(self: Face, selection: LayoutSelection, lookup_index: u16, glyph_ids: []const u32, glyph_index: usize, source: ?FeatureRange) ?GposContextualPairAdjustment {    if (self.gpos) |gpos| {        return gpos.contextualPairAdjustmentAtLookup(self.data, self.variationContext(), selection, self.gdef, lookup_index, glyph_ids, glyph_index, source) catch null;    }    return null;}fn hasGposContextualPairAdjustmentForImpl(self: Face, selection: LayoutSelection) bool {    if (self.gpos) |gpos| {        return gpos.hasActiveContextualPairAdjustment(self.data, self.variationContext(), selection) catch false;    }    return false;}fn gposSingleAdjustmentImpl(self: Face, glyph_id: u32) GposValueAdjustment {    return self.gposSingleAdjustmentFor(.{}, glyph_id);}fn gposSingleAdjustmentForImpl(self: Face, selection: LayoutSelection, glyph_id: u32) GposValueAdjustment {    var glyphs = [_]u32{glyph_id};    const result = self.gposSingleAdjustmentAtFor(selection, &glyphs, 0) orelse return .{};    if (result.target_offset != 0) return .{};    return result.adjustment;}fn gposSingleAdjustmentAtForImpl(self: Face, selection: LayoutSelection, glyph_ids: []const u32, glyph_index: usize) ?GposSingleAdjustment {    return self.gposSingleAdjustmentAtForRange(selection, glyph_ids, glyph_index, null);}fn gposSingleAdjustmentAtForRangeImpl(self: Face, selection: LayoutSelection, glyph_ids: []const u32, glyph_index: usize, source: ?FeatureRange) ?GposSingleAdjustment {    if (self.gpos) |gpos| {        return gpos.singleAdjustmentAt(self.data, self.variationContext(), selection, self.gdef, glyph_ids, glyph_index, source) catch null;    }    return null;}fn gposSingleAdjustmentAtLookupForRangeImpl(self: Face, selection: LayoutSelection, lookup_index: u16, glyph_ids: []const u32, glyph_index: usize, source: ?FeatureRange) ?GposSingleAdjustment {    if (self.gpos) |gpos| {        return gpos.singleAdjustmentAtLookup(self.data, self.variationContext(), selection, self.gdef, lookup_index, glyph_ids, glyph_index, source) catch null;    }    return null;}fn gposCursiveAttachmentImpl(self: Face, exit_glyph: u32, entry_glyph: u32) ?GposCursiveAttachment {    return self.gposCursiveAttachmentFor(.{}, exit_glyph, entry_glyph);}fn gposCursiveAttachmentForImpl(self: Face, selection: LayoutSelection, exit_glyph: u32, entry_glyph: u32) ?GposCursiveAttachment {    return self.gposCursiveAttachmentForRange(selection, exit_glyph, entry_glyph, null);}fn gposCursiveAttachmentForRangeImpl(self: Face, selection: LayoutSelection, exit_glyph: u32, entry_glyph: u32, source: ?FeatureRange) ?GposCursiveAttachment {    if (self.gpos) |gpos| {        return gpos.cursiveAttachment(self.data, self.variationContext(), selection, self.gdef, exit_glyph, entry_glyph, source) catch null;    }    return null;}fn gposCursiveAttachmentAtLookupForRangeImpl(self: Face, selection: LayoutSelection, lookup_index: u16, exit_glyph: u32, entry_glyph: u32, source: ?FeatureRange) ?GposCursiveAttachment {    if (self.gpos) |gpos| {        return gpos.cursiveAttachmentAtLookup(self.data, self.variationContext(), selection, self.gdef, lookup_index, exit_glyph, entry_glyph, source) catch null;    }    return null;}fn gposMarkToBaseAdjustmentImpl(self: Face, base_glyph: u32, mark_glyph: u32) ?GposValueAdjustment {    return self.gposMarkToBaseAdjustmentFor(.{}, base_glyph, mark_glyph);}fn gposMarkToBaseAdjustmentForImpl(self: Face, selection: LayoutSelection, base_glyph: u32, mark_glyph: u32) ?GposValueAdjustment {    return self.gposMarkToBaseAdjustmentForRange(selection, base_glyph, mark_glyph, null);}fn gposMarkToBaseAdjustmentForRangeImpl(self: Face, selection: LayoutSelection, base_glyph: u32, mark_glyph: u32, source: ?FeatureRange) ?GposValueAdjustment {    if (self.gpos) |gpos| {        return gpos.markToBaseAdjustment(self.data, self.variationContext(), selection, self.gdef, base_glyph, mark_glyph, source) catch null;    }    return null;}fn gposMarkToBaseAdjustmentAtLookupForRangeImpl(self: Face, selection: LayoutSelection, lookup_index: u16, base_glyph: u32, mark_glyph: u32, source: ?FeatureRange) ?GposValueAdjustment {    if (self.gpos) |gpos| {        return gpos.markToBaseAdjustmentAtLookup(self.data, self.variationContext(), selection, self.gdef, lookup_index, base_glyph, mark_glyph, source) catch null;    }    return null;}fn gposMarkToLigatureAdjustmentImpl(self: Face, ligature_glyph: u32, mark_glyph: u32, component_index: u16) ?GposValueAdjustment {    return self.gposMarkToLigatureAdjustmentFor(.{}, ligature_glyph, mark_glyph, component_index);}fn gposMarkToLigatureAdjustmentForImpl(self: Face, selection: LayoutSelection, ligature_glyph: u32, mark_glyph: u32, component_index: u16) ?GposValueAdjustment {    return self.gposMarkToLigatureAdjustmentForRange(selection, ligature_glyph, mark_glyph, component_index, null);}fn gposMarkToLigatureAdjustmentForRangeImpl(self: Face, selection: LayoutSelection, ligature_glyph: u32, mark_glyph: u32, component_index: u16, source: ?FeatureRange) ?GposValueAdjustment {    if (self.gpos) |gpos| {        return gpos.markToLigatureAdjustment(self.data, self.variationContext(), selection, self.gdef, ligature_glyph, mark_glyph, component_index, source) catch null;    }    return null;}fn gposMarkToLigatureAdjustmentAtLookupForRangeImpl(self: Face, selection: LayoutSelection, lookup_index: u16, ligature_glyph: u32, mark_glyph: u32, component_index: u16, source: ?FeatureRange) ?GposValueAdjustment {    if (self.gpos) |gpos| {        return gpos.markToLigatureAdjustmentAtLookup(self.data, self.variationContext(), selection, self.gdef, lookup_index, ligature_glyph, mark_glyph, component_index, source) catch null;    }    return null;}fn gposMarkToMarkAdjustmentImpl(self: Face, base_mark_glyph: u32, mark_glyph: u32) ?GposValueAdjustment {    return self.gposMarkToMarkAdjustmentFor(.{}, base_mark_glyph, mark_glyph);}fn gposMarkToMarkAdjustmentForImpl(self: Face, selection: LayoutSelection, base_mark_glyph: u32, mark_glyph: u32) ?GposValueAdjustment {    return self.gposMarkToMarkAdjustmentForRange(selection, base_mark_glyph, mark_glyph, null);}fn gposMarkToMarkAdjustmentForRangeImpl(self: Face, selection: LayoutSelection, base_mark_glyph: u32, mark_glyph: u32, source: ?FeatureRange) ?GposValueAdjustment {    if (self.gpos) |gpos| {        return gpos.markToMarkAdjustment(self.data, self.variationContext(), selection, self.gdef, base_mark_glyph, mark_glyph, source) catch null;    }    return null;}fn gposMarkToMarkAdjustmentAtLookupForRangeImpl(self: Face, selection: LayoutSelection, lookup_index: u16, base_mark_glyph: u32, mark_glyph: u32, source: ?FeatureRange) ?GposValueAdjustment {    if (self.gpos) |gpos| {        return gpos.markToMarkAdjustmentAtLookup(self.data, self.variationContext(), selection, self.gdef, lookup_index, base_mark_glyph, mark_glyph, source) catch null;    }    return null;}fn hasGposMarkToBaseImpl(self: Face) bool {    return self.hasGposMarkToBaseFor(.{});}fn hasGposMarkToBaseForImpl(self: Face, selection: LayoutSelection) bool {    if (self.gpos) |gpos| {        return gpos.hasActiveLookupType(self.data, self.variationContext(), selection, 4) catch false;    }    return false;}fn hasGposMarkToLigatureImpl(self: Face) bool {    return self.hasGposMarkToLigatureFor(.{});}fn hasGposMarkToLigatureForImpl(self: Face, selection: LayoutSelection) bool {    if (self.gpos) |gpos| {        return gpos.hasActiveLookupType(self.data, self.variationContext(), selection, 5) catch false;    }    return false;}fn hasGposSingleAdjustmentImpl(self: Face) bool {    return self.hasGposSingleAdjustmentFor(.{});}fn hasGposSingleAdjustmentForImpl(self: Face, selection: LayoutSelection) bool {    if (self.gpos) |gpos| {        return gpos.hasActiveSingleAdjustment(self.data, self.variationContext(), selection) catch false;    }    return false;}fn hasGposCursiveAttachmentImpl(self: Face) bool {    return self.hasGposCursiveAttachmentFor(.{});}fn hasGposCursiveAttachmentForImpl(self: Face, selection: LayoutSelection) bool {    if (self.gpos) |gpos| {        return gpos.hasActiveLookupType(self.data, self.variationContext(), selection, 3) catch false;    }    return false;}fn hasGposMarkToMarkImpl(self: Face) bool {    return self.hasGposMarkToMarkFor(.{});}fn hasGposMarkToMarkForImpl(self: Face, selection: LayoutSelection) bool {    if (self.gpos) |gpos| {        return gpos.hasActiveLookupType(self.data, self.variationContext(), selection, 6) catch false;    }    return false;}fn glyphClassImpl(self: Face, glyph_id: u32) GlyphClass {    if (self.gdef) |gdef| {        return gdef.glyphClass(self.data, glyph_id) catch .unknown;    }    return .unknown;}fn ligatureCaretCountImpl(self: Face, glyph_id: u32) u16 {    if (self.gdef) |gdef| {        return gdef.ligatureCaretCount(self.data, glyph_id) catch 0;    }    return 0;}fn ligatureCaretImpl(self: Face, glyph_id: u32, caret_index: usize) ?LigatureCaret {    if (self.gdef) |gdef| {        return gdef.ligatureCaret(self.data, glyph_id, caret_index) catch null;    }    return null;}fn substituteGlyphImpl(self: Face, glyph_id: u32) u32 {    return self.substituteGlyphFor(.{}, glyph_id);}fn substituteGlyphForImpl(self: Face, selection: LayoutSelection, glyph_id: u32) u32 {    var glyphs = [_]u32{glyph_id};    const lookup_count = self.gsubLookupCount() catch return glyph_id;    for (0..lookup_count) |lookup_index| {        const substitute = self.substitutionAtFor(selection, @intCast(lookup_index), &glyphs, 0) catch return glyph_id;        if (substitute) |result| {            if (result.component_count == 1 and result.replacement_count == 1 and result.glyph_id < self.num_glyphs) return result.glyph_id;        }    }    return glyph_id;}fn gsubLookupCountImpl(self: Face) FontError!u16 {    if (self.gsub) |gsub| return gsub.lookupCount(self.data);    return 0;}fn gsubLookupIsReverseForImpl(self: Face, selection: LayoutSelection, lookup_index: u16) FontError!bool {    if (self.gsub) |gsub| return gsub.lookupIsReverse(self.data, selection, lookup_index);    return false;}fn substitutionAtImpl(self: Face, lookup_index: u16, glyph_ids: []const u32, glyph_index: usize) FontError!?GsubSubstitution {    return self.substitutionAtFor(.{}, lookup_index, glyph_ids, glyph_index);}fn substitutionAtForImpl(self: Face, selection: LayoutSelection, lookup_index: u16, glyph_ids: []const u32, glyph_index: usize) FontError!?GsubSubstitution {    return self.substitutionAtForRange(selection, lookup_index, glyph_ids, glyph_index, null);}fn substitutionAtForRangeImpl(self: Face, selection: LayoutSelection, lookup_index: u16, glyph_ids: []const u32, glyph_index: usize, source: ?FeatureRange) FontError!?GsubSubstitution {    if (self.gsub) |gsub| {        const result = try gsub.substitutionAtWithGdef(self.data, self.variationContext(), selection, self.gdef, lookup_index, glyph_ids, glyph_index, source);        if (result) |substitution| {            if (substitution.component_count == 0 or substitution.replacement_count == 0) return null;            for (0..substitution.replacement_count) |replacement_index| {                _ = self.substitutionGlyph(substitution, replacement_index) orelse return null;            }            return substitution;        }    }    return null;}fn substitutionGlyphImpl(self: Face, substitution: GsubSubstitution, replacement_index: usize) ?u32 {    if (replacement_index >= substitution.replacement_count) return null;    if (substitution.replacement_glyphs_offset == 0) {        if (replacement_index != 0) return null;        return if (substitution.glyph_id < self.num_glyphs) substitution.glyph_id else null;    }    const byte_delta = replacement_index * 2;    if (substitution.replacement_glyphs_offset > std.math.maxInt(usize) - byte_delta) return null;    const offset = substitution.replacement_glyphs_offset + byte_delta;    const glyph = readU16(self.data, offset) catch return null;    return if (glyph < self.num_glyphs) glyph else null;}fn heightUnitsImpl(self: Face) u16 {    const height = @as(i32, self.ascender) - @as(i32, self.descender);    if (height <= 0 or height > std.math.maxInt(u16)) return self.units_per_em;    return @intCast(height);}fn horizontalMetricsImpl(self: Face) HorizontalMetrics {    return self.typo_metrics orelse .{        .ascender = self.ascender,        .descender = self.descender,        .line_gap = self.line_gap,    };}fn faceVariationAxisCount(ptr: *const anyopaque) u16 {    const face: *const Face = @ptrCast(@alignCast(ptr));    return face.variationAxisCount();}fn faceNormalizedCoordinateAt(ptr: *const anyopaque, settings: []const VariationSetting, axis_index: usize) FontError!i16 {    const face: *const Face = @ptrCast(@alignCast(ptr));    return try face.normalizedCoordinateAt(settings, axis_index);}fn gposVariationValueForFace(base: i32, face: Face, settings: []const VariationSetting, packed_index: u32) i32 {    if (packed_index == noGposVariationIndex or settings.len == 0) return base;    const gdef = face.gdef orelse return base;    const index = DeltaSetIndex{        .outer = packed_index >> 16,        .inner = packed_index & 0xffff,    };    const delta = gdef.variationDelta(face.data, face, settings, index) catch return base;    return clampI32(@as(i64, base) + @as(i64, delta));}test "Face rejects empty data" {    try std.testing.expectError(error.InvalidFont, Face.init(&.{}));}test "Face maps BMP codepoints through cmap format 4" {    const bytes = try test_font.create(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(u16, 1000), face.units_per_em);    try std.testing.expectEqual(@as(u16, 500), face.advanceWidth(face.glyphId('A')));    try std.testing.expectEqual(@as(u32, 'A' - 31), face.glyphId('A'));    try std.testing.expectEqual(@as(u32, 96), face.glyphId(0x25cc));    try std.testing.expectEqual(@as(u32, 0), face.glyphId(0x20ac));}test "Face opens indexed OpenType collection faces" {    const bytes = try test_font.createCollection(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const first = try Face.init(bytes);    const second = try Face.initAt(bytes, 1);    const a = first.glyphId('A');    try std.testing.expectEqual(a, first.substituteGlyph(a));    try std.testing.expectEqual(second.glyphId('Z'), second.substituteGlyph(second.glyphId('A')));    try std.testing.expectError(error.InvalidFont, Face.initAt(bytes, 2));    const plain = try test_font.create(std.testing.allocator);    defer std.testing.allocator.free(plain);    try std.testing.expectError(error.InvalidFont, Face.initAt(plain, 1));}test "Face exposes table slices for indexed faces" {    const bytes = try test_font.createCollection(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const second = try Face.initAt(bytes, 1);    const head = second.tableSlice("head").?;    const by_tag = second.tableSliceByTag(tag("head")).?;    try std.testing.expectEqual(@as(usize, 54), head.len);    try std.testing.expectEqualSlices(u8, head, by_tag);    try std.testing.expectEqual(@as(?[]const u8, null), second.tableSlice("COLR"));}test "Face decodes UTF-16BE name records" {    const bytes = try test_font.create(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const family = (try face.nameUtf8Alloc(std.testing.allocator, 1)).?;    defer std.testing.allocator.free(family);    const full = (try face.nameUtf8Alloc(std.testing.allocator, 4)).?;    defer std.testing.allocator.free(full);    try std.testing.expectEqualStrings("Tiny Fixture", family);    try std.testing.expectEqualStrings("Tiny Fixture Regular", full);    try std.testing.expectEqual(@as(?[]u8, null), try face.nameUtf8Alloc(std.testing.allocator, 6));}test "Face reads vertical advance metrics from vmtx" {    const bytes = try test_font.createWithVerticalMetrics(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(u16, 700), face.advanceHeight(face.glyphId('A')));    try std.testing.expectEqual(@as(u16, 900), face.advanceHeight(face.glyphId('B')));    try std.testing.expectEqual(@as(u16, 700), face.advanceHeight(face.glyphId('!')));}test "Face reads vertical origin metrics from VORG" {    const bytes = try test_font.createWithVerticalOrigins(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(?i16, 760), face.verticalOriginY(face.glyphId('A')));    try std.testing.expectEqual(@as(?i16, 880), face.verticalOriginY(face.glyphId('B')));}test "Face falls back to line height without vertical metrics" {    const bytes = try test_font.create(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(u16, 1000), face.advanceHeight(face.glyphId('A')));}test "Face maps non-default Unicode variation sequences through cmap format 14" {    const bytes = try test_font.createWithVariationSequences(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(u32, 'A' - 31), face.glyphId('A'));    try std.testing.expectEqual(@as(?u32, 96), face.glyphIdForVariation('A', 0xfe0f));    try std.testing.expectEqual(@as(?u32, null), face.glyphIdForVariation('B', 0xfe0f));    try std.testing.expectEqual(@as(?u32, null), face.glyphIdForVariation('A', 0xfe0e));}test "Face reads fvar variation axes" {    const bytes = try test_font.createWithVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(u16, 2), face.variationAxisCount());    const weight = face.variationAxis(0).?;    try std.testing.expectEqual(tag("wght"), weight.tag);    try std.testing.expectEqual(@as(i32, 100 << 16), weight.min_value);    try std.testing.expectEqual(@as(i32, 400 << 16), weight.default_value);    try std.testing.expectEqual(@as(i32, 900 << 16), weight.max_value);    try std.testing.expectEqual(@as(u16, 0), weight.flags);    try std.testing.expectEqual(@as(u16, 256), weight.name_id);    try std.testing.expectEqual(@as(f32, 400), fixed16ToFloat(weight.default_value));    const width = face.variationAxisFor(tag("wdth")).?;    try std.testing.expectEqual(@as(i32, 50 << 16), width.min_value);    try std.testing.expectEqual(@as(i32, 100 << 16), width.default_value);    try std.testing.expectEqual(@as(i32, 200 << 16), width.max_value);    try std.testing.expectEqual(@as(u16, 1), width.flags);    try std.testing.expectEqual(@as(?VariationAxis, null), face.variationAxis(2));    try std.testing.expectEqual(@as(?VariationAxis, null), face.variationAxisFor(tag("opsz")));}test "Face normalizes fvar variation coordinates" {    const bytes = try test_font.createWithVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(i16, 0), try face.normalizedCoordinateAt(&.{}, 0));    try std.testing.expectEqual(@as(i16, -8192), try face.normalizedCoordinateAt(&.{.{ .tag = tag("wght"), .value = 250.0 }}, 0));    try std.testing.expectEqual(@as(i16, 8192), try face.normalizedCoordinateAt(&.{.{ .tag = tag("wght"), .value = 650.0 }}, 0));    try std.testing.expectEqual(@as(i16, 16384), try face.normalizedCoordinateAt(&.{.{ .tag = tag("wght"), .value = 1200.0 }}, 0));    try std.testing.expectEqual(@as(i16, -16384), try face.normalizedCoordinateAt(&.{.{ .tag = tag("wdth"), .value = 25.0 }}, 1));    const normalized = (try face.normalizedVariation(.{ .tag = tag("wght"), .value = 650.0 })).?;    try std.testing.expectEqual(tag("wght"), normalized.tag);    try std.testing.expectEqual(@as(i16, 8192), normalized.value);    try std.testing.expectEqual(@as(?NormalizedVariation, null), try face.normalizedVariation(.{ .tag = tag("opsz"), .value = 12.0 }));    try std.testing.expectError(error.InvalidVariations, face.validateVariations(&.{.{ .tag = tag("opsz"), .value = 12.0 }}));    try std.testing.expectError(error.InvalidVariations, face.validateVariations(&.{.{ .tag = tag("wght"), .value = std.math.nan(f32) }}));}test "Face applies avar variation coordinate remapping" {    const bytes = try test_font.createWithAxisVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(i16, -4096), try face.normalizedCoordinateAt(&.{.{ .tag = tag("wght"), .value = 250.0 }}, 0));    try std.testing.expectEqual(@as(i16, 12288), try face.normalizedCoordinateAt(&.{.{ .tag = tag("wght"), .value = 650.0 }}, 0));    try std.testing.expectEqual(@as(i16, 8192), try face.normalizedCoordinateAt(&.{.{ .tag = tag("wdth"), .value = 150.0 }}, 1));}test "Face applies HVAR advance width deltas" {    const bytes = try test_font.createWithHorizontalMetricVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const v = face.glyphId('V');    try std.testing.expectEqual(@as(u16, 500), face.advanceWidth(a));    try std.testing.expectEqual(@as(i32, 500), face.advanceWidthForVariations(a, &.{}));    try std.testing.expectEqual(@as(i32, 500), face.advanceWidthForVariations(a, &.{.{ .tag = tag("wght"), .value = 400.0 }}));    try std.testing.expectEqual(@as(i32, 550), face.advanceWidthForVariations(a, &.{.{ .tag = tag("wght"), .value = 650.0 }}));    try std.testing.expectEqual(@as(i32, 600), face.advanceWidthForVariations(a, &.{.{ .tag = tag("wght"), .value = 900.0 }}));    try std.testing.expectEqual(@as(i32, 500), face.advanceWidthForVariations(v, &.{.{ .tag = tag("wght"), .value = 900.0 }}));}test "Face applies avar-normalized coordinates to HVAR" {    const bytes = try test_font.createWithHorizontalMetricAxisVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    try std.testing.expectEqual(@as(i32, 575), face.advanceWidthForVariations(a, &.{.{ .tag = tag("wght"), .value = 650.0 }}));}test "Face applies VVAR advance height deltas" {    const bytes = try test_font.createWithVerticalMetricVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const b = face.glyphId('B');    try std.testing.expectEqual(@as(u16, 700), face.advanceHeight(a));    try std.testing.expectEqual(@as(i32, 700), face.advanceHeightForVariations(a, &.{}));    try std.testing.expectEqual(@as(i32, 700), face.advanceHeightForVariations(a, &.{.{ .tag = tag("wght"), .value = 400.0 }}));    try std.testing.expectEqual(@as(i32, 750), face.advanceHeightForVariations(a, &.{.{ .tag = tag("wght"), .value = 650.0 }}));    try std.testing.expectEqual(@as(i32, 800), face.advanceHeightForVariations(a, &.{.{ .tag = tag("wght"), .value = 900.0 }}));    try std.testing.expectEqual(@as(i32, 900), face.advanceHeightForVariations(b, &.{.{ .tag = tag("wght"), .value = 900.0 }}));}test "Face applies avar-normalized coordinates to VVAR" {    const bytes = try test_font.createWithVerticalMetricAxisVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    try std.testing.expectEqual(@as(i32, 775), face.advanceHeightForVariations(a, &.{.{ .tag = tag("wght"), .value = 650.0 }}));}test "Face applies MVAR horizontal metric deltas" {    const bytes = try test_font.createWithMetricVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(i32, 800), face.ascenderForVariations(&.{}));    try std.testing.expectEqual(@as(i32, 800), face.ascenderForVariations(&.{.{ .tag = tag("wght"), .value = 400.0 }}));    try std.testing.expectEqual(@as(i32, 860), face.ascenderForVariations(&.{.{ .tag = tag("wght"), .value = 650.0 }}));    try std.testing.expectEqual(@as(i32, 920), face.ascenderForVariations(&.{.{ .tag = tag("wght"), .value = 900.0 }}));    try std.testing.expectEqual(@as(i32, -200), face.descenderForVariations(&.{}));    try std.testing.expectEqual(@as(i32, -240), face.descenderForVariations(&.{.{ .tag = tag("wght"), .value = 650.0 }}));    try std.testing.expectEqual(@as(i32, -280), face.descenderForVariations(&.{.{ .tag = tag("wght"), .value = 900.0 }}));    try std.testing.expectEqual(@as(i32, 40), face.lineGapForVariations(&.{}));    try std.testing.expectEqual(@as(i32, 50), face.lineGapForVariations(&.{.{ .tag = tag("wght"), .value = 650.0 }}));    try std.testing.expectEqual(@as(i32, 60), face.lineGapForVariations(&.{.{ .tag = tag("wght"), .value = 900.0 }}));    try std.testing.expectEqual(@as(i32, 0), face.metricVariationDelta(tag("vasc"), &.{.{ .tag = tag("wght"), .value = 900.0 }}));    try std.testing.expectEqual(@as(i32, 1000), face.heightUnitsForVariations(&.{}));    try std.testing.expectEqual(@as(i32, 1100), face.heightUnitsForVariations(&.{.{ .tag = tag("wght"), .value = 650.0 }}));    try std.testing.expectEqual(@as(i32, 1200), face.heightUnitsForVariations(&.{.{ .tag = tag("wght"), .value = 900.0 }}));}test "Face applies avar-normalized coordinates to MVAR" {    const bytes = try test_font.createWithMetricAxisVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(i32, 890), face.ascenderForVariations(&.{.{ .tag = tag("wght"), .value = 650.0 }}));    try std.testing.expectEqual(@as(i32, -260), face.descenderForVariations(&.{.{ .tag = tag("wght"), .value = 650.0 }}));    try std.testing.expectEqual(@as(i32, 55), face.lineGapForVariations(&.{.{ .tag = tag("wght"), .value = 650.0 }}));    try std.testing.expectEqual(@as(i32, 1150), face.heightUnitsForVariations(&.{.{ .tag = tag("wght"), .value = 650.0 }}));}test "Face reads classic kern format 0 pairs" {    const bytes = try test_font.createWithKern(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const v = face.glyphId('V');    try std.testing.expectEqual(@as(i16, -80), face.kerning(a, v));    try std.testing.expectEqual(@as(i16, 0), face.kerning(v, a));}test "Face applies GSUB required single substitution" {    const bytes = try test_font.createWithGsubSingleSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const z = face.glyphId('Z');    try std.testing.expectEqual(z, face.substituteGlyph(a));    try std.testing.expectEqual(face.glyphId('B'), face.substituteGlyph(face.glyphId('B')));}test "Face applies GSUB single substitutions with mark filters" {    const bytes = try test_font.createWithGsubSingleIgnoreMarks(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const mark = face.glyphId('^');    const glyphs = [_]u32{ a, mark };    const substitution = (try face.substitutionAt(0, &glyphs, 0)).?;    try std.testing.expectEqual(face.glyphId('Z'), substitution.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &glyphs, 1));}test "Face applies GSUB alternate substitutions" {    const bytes = try test_font.createWithGsubAlternateSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const glyphs = [_]u32{a};    const substitution = (try face.substitutionAt(0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u32, 96), face.substituteGlyph(a));    try std.testing.expectEqual(@as(u32, 96), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 1), substitution.component_count);    try std.testing.expectEqual(face.glyphId('B'), face.substituteGlyph(face.glyphId('B')));}test "Face applies GSUB contextual substitutions" {    const bytes = try test_font.createWithGsubContextualSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const mismatch = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const substitution = (try face.substitutionAt(0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u16, 2), try face.gsubLookupCount());    try std.testing.expectEqual(@as(u32, face.glyphId('Z')), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 1), substitution.component_count);    try std.testing.expectEqual(@as(usize, 1), substitution.target_offset);    try std.testing.expectEqual(@as(usize, 3), substitution.skip_count);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &mismatch, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(1, &glyphs, 1));}test "Face applies GSUB class contextual substitutions" {    const bytes = try test_font.createWithGsubClassContextualSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const mismatch = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const substitution = (try face.substitutionAt(0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u16, 2), try face.gsubLookupCount());    try std.testing.expectEqual(@as(u32, face.glyphId('Z')), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 1), substitution.component_count);    try std.testing.expectEqual(@as(usize, 1), substitution.target_offset);    try std.testing.expectEqual(@as(usize, 3), substitution.skip_count);    try std.testing.expectEqual(face.glyphId('B'), face.substituteGlyph(face.glyphId('B')));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &mismatch, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(1, &glyphs, 1));}test "Face applies GSUB coverage contextual substitutions" {    const bytes = try test_font.createWithGsubCoverageContextualSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const mismatch = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const substitution = (try face.substitutionAt(0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u16, 2), try face.gsubLookupCount());    try std.testing.expectEqual(@as(u32, face.glyphId('Z')), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 1), substitution.component_count);    try std.testing.expectEqual(@as(usize, 1), substitution.target_offset);    try std.testing.expectEqual(@as(usize, 3), substitution.skip_count);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &mismatch, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(1, &glyphs, 1));}test "Face applies GSUB chained contextual substitutions" {    const bytes = try test_font.createWithGsubChainedContextualSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const missing_backtrack = [_]u32{ face.glyphId('!'), face.glyphId('B'), face.glyphId('C') };    const missing_lookahead = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const substitution = (try face.substitutionAt(0, &glyphs, 1)).?;    try std.testing.expectEqual(@as(u16, 2), try face.gsubLookupCount());    try std.testing.expectEqual(@as(u32, face.glyphId('Z')), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 1), substitution.component_count);    try std.testing.expectEqual(@as(usize, 0), substitution.target_offset);    try std.testing.expectEqual(@as(usize, 1), substitution.skip_count);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &missing_backtrack, 1));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &missing_lookahead, 1));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(1, &glyphs, 1));}test "Face applies GSUB chained simple contextual substitutions" {    const bytes = try test_font.createWithGsubChainedSimpleContextualSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const missing_backtrack = [_]u32{ face.glyphId('!'), face.glyphId('B'), face.glyphId('C') };    const missing_lookahead = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const substitution = (try face.substitutionAt(0, &glyphs, 1)).?;    try std.testing.expectEqual(@as(u16, 2), try face.gsubLookupCount());    try std.testing.expectEqual(@as(u32, face.glyphId('Z')), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 1), substitution.component_count);    try std.testing.expectEqual(@as(usize, 0), substitution.target_offset);    try std.testing.expectEqual(@as(usize, 1), substitution.skip_count);    try std.testing.expectEqual(face.glyphId('B'), face.substituteGlyph(face.glyphId('B')));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &missing_backtrack, 1));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &missing_lookahead, 1));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(1, &glyphs, 1));}test "Face applies GSUB chained class contextual substitutions" {    const bytes = try test_font.createWithGsubChainedClassContextualSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const missing_backtrack = [_]u32{ face.glyphId('!'), face.glyphId('B'), face.glyphId('C') };    const missing_lookahead = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const substitution = (try face.substitutionAt(0, &glyphs, 1)).?;    try std.testing.expectEqual(@as(u16, 2), try face.gsubLookupCount());    try std.testing.expectEqual(@as(u32, face.glyphId('Z')), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 1), substitution.component_count);    try std.testing.expectEqual(@as(usize, 0), substitution.target_offset);    try std.testing.expectEqual(@as(usize, 1), substitution.skip_count);    try std.testing.expectEqual(face.glyphId('B'), face.substituteGlyph(face.glyphId('B')));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &missing_backtrack, 1));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &missing_lookahead, 1));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(1, &glyphs, 1));}test "Face exposes GSUB default ligature substitutions" {    const bytes = try test_font.createWithGsubLigature(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('f'), face.glyphId('i') };    const substitution = (try face.substitutionAt(0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u16, 1), try face.gsubLookupCount());    try std.testing.expectEqual(@as(u32, 96), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 2), substitution.component_count);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &glyphs, 1));}test "Face applies GSUB localized forms by default" {    const bytes = try test_font.createWithGsubLocalizedForms(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{face.glyphId('A')};    const disabled = LayoutSelection{ .features = &.{.{ .tag = tag("locl"), .value = 0 }} };    try std.testing.expectEqual(face.glyphId('Z'), (try face.substitutionAtFor(.{}, 0, &glyphs, 0)).?.glyph_id);    try std.testing.expectEqual(face.glyphId('Z'), (try face.substitutionAtFor(.{ .vertical = true }, 0, &glyphs, 0)).?.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(disabled, 0, &glyphs, 0));}test "Face applies GSUB contextual ligatures as a horizontal default" {    const bytes = try test_font.createWithGsubContextualLigature(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('f'), face.glyphId('i') };    const disabled = LayoutSelection{ .features = &.{.{ .tag = tag("clig"), .value = 0 }} };    const vertical_enabled = LayoutSelection{ .vertical = true, .features = &.{.{ .tag = tag("clig"), .value = 1 }} };    const substitution = (try face.substitutionAtFor(.{}, 0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u32, 96), substitution.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(.{ .vertical = true }, 0, &glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(disabled, 0, &glyphs, 0));    try std.testing.expectEqual(@as(u32, 96), (try face.substitutionAtFor(vertical_enabled, 0, &glyphs, 0)).?.glyph_id);}test "Face applies GSUB contextual alternates as horizontal defaults" {    const calt_bytes = try test_font.createWithGsubContextualAlternates(std.testing.allocator);    defer std.testing.allocator.free(calt_bytes);    const rclt_bytes = try test_font.createWithGsubRequiredContextualAlternates(std.testing.allocator);    defer std.testing.allocator.free(rclt_bytes);    const calt_face = try Face.init(calt_bytes);    const rclt_face = try Face.init(rclt_bytes);    const calt_glyphs = [_]u32{ calt_face.glyphId('A'), calt_face.glyphId('B'), calt_face.glyphId('C') };    const rclt_glyphs = [_]u32{ rclt_face.glyphId('A'), rclt_face.glyphId('B'), rclt_face.glyphId('C') };    const disabled_calt = LayoutSelection{ .features = &.{.{ .tag = tag("calt"), .value = 0 }} };    const disabled_rclt = LayoutSelection{ .features = &.{.{ .tag = tag("rclt"), .value = 0 }} };    try std.testing.expectEqual(calt_face.glyphId('Z'), (try calt_face.substitutionAtFor(.{}, 0, &calt_glyphs, 0)).?.glyph_id);    try std.testing.expectEqual(rclt_face.glyphId('Z'), (try rclt_face.substitutionAtFor(.{}, 0, &rclt_glyphs, 0)).?.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try calt_face.substitutionAtFor(.{ .vertical = true }, 0, &calt_glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try rclt_face.substitutionAtFor(.{ .vertical = true }, 0, &rclt_glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try calt_face.substitutionAtFor(disabled_calt, 0, &calt_glyphs, 0));    try std.testing.expectEqual(rclt_face.glyphId('Z'), (try rclt_face.substitutionAtFor(disabled_rclt, 0, &rclt_glyphs, 0)).?.glyph_id);}test "Face applies GSUB direction alternates by resolved direction" {    const ltra_bytes = try test_font.createWithGsubLeftToRightAlternates(std.testing.allocator);    defer std.testing.allocator.free(ltra_bytes);    const ltrm_bytes = try test_font.createWithGsubLeftToRightMirroredForms(std.testing.allocator);    defer std.testing.allocator.free(ltrm_bytes);    const rtla_bytes = try test_font.createWithGsubRightToLeftAlternates(std.testing.allocator);    defer std.testing.allocator.free(rtla_bytes);    const rtlm_bytes = try test_font.createWithGsubRightToLeftMirroredForms(std.testing.allocator);    defer std.testing.allocator.free(rtlm_bytes);    const ltra_face = try Face.init(ltra_bytes);    const ltrm_face = try Face.init(ltrm_bytes);    const rtla_face = try Face.init(rtla_bytes);    const rtlm_face = try Face.init(rtlm_bytes);    const ltra_glyphs = [_]u32{ltra_face.glyphId('A')};    const ltrm_glyphs = [_]u32{ltrm_face.glyphId('A')};    const rtla_glyphs = [_]u32{rtla_face.glyphId('A')};    const rtlm_glyphs = [_]u32{rtlm_face.glyphId('A')};    const rtl_selection = LayoutSelection{ .right_to_left = true };    const disabled_ltra = LayoutSelection{ .features = &.{.{ .tag = tag("ltra"), .value = 0 }} };    const enabled_ltra_rtl = LayoutSelection{ .right_to_left = true, .features = &.{.{ .tag = tag("ltra"), .value = 1 }} };    const disabled_rtla_rtl = LayoutSelection{ .right_to_left = true, .features = &.{.{ .tag = tag("rtla"), .value = 0 }} };    try std.testing.expectEqual(ltra_face.glyphId('Z'), (try ltra_face.substitutionAtFor(.{}, 0, &ltra_glyphs, 0)).?.glyph_id);    try std.testing.expectEqual(ltrm_face.glyphId('Z'), (try ltrm_face.substitutionAtFor(.{}, 0, &ltrm_glyphs, 0)).?.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try ltra_face.substitutionAtFor(rtl_selection, 0, &ltra_glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try ltrm_face.substitutionAtFor(rtl_selection, 0, &ltrm_glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try ltra_face.substitutionAtFor(disabled_ltra, 0, &ltra_glyphs, 0));    try std.testing.expectEqual(ltra_face.glyphId('Z'), (try ltra_face.substitutionAtFor(enabled_ltra_rtl, 0, &ltra_glyphs, 0)).?.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try rtla_face.substitutionAtFor(.{}, 0, &rtla_glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try rtlm_face.substitutionAtFor(.{}, 0, &rtlm_glyphs, 0));    try std.testing.expectEqual(rtla_face.glyphId('Z'), (try rtla_face.substitutionAtFor(rtl_selection, 0, &rtla_glyphs, 0)).?.glyph_id);    try std.testing.expectEqual(rtlm_face.glyphId('Z'), (try rtlm_face.substitutionAtFor(rtl_selection, 0, &rtlm_glyphs, 0)).?.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try rtla_face.substitutionAtFor(disabled_rtla_rtl, 0, &rtla_glyphs, 0));}test "Face detects automatic fraction feature availability" {    const frac_bytes = try test_font.createWithGsubFractions(std.testing.allocator);    defer std.testing.allocator.free(frac_bytes);    const component_bytes = try test_font.createWithGsubFractionComponents(std.testing.allocator);    defer std.testing.allocator.free(component_bytes);    const ordinary_bytes = try test_font.create(std.testing.allocator);    defer std.testing.allocator.free(ordinary_bytes);    const frac_face = try Face.init(frac_bytes);    const component_face = try Face.init(component_bytes);    const ordinary_face = try Face.init(ordinary_bytes);    try std.testing.expect(frac_face.usesAutomaticFractions(.{}));    try std.testing.expect(component_face.usesAutomaticFractions(.{}));    try std.testing.expect(!ordinary_face.usesAutomaticFractions(.{}));}test "Face detects Arabic joining form feature availability" {    const joining_bytes = try test_font.createWithGsubArabicJoiningForms(std.testing.allocator);    defer std.testing.allocator.free(joining_bytes);    const ordinary_bytes = try test_font.create(std.testing.allocator);    defer std.testing.allocator.free(ordinary_bytes);    const joining_face = try Face.init(joining_bytes);    const ordinary_face = try Face.init(ordinary_bytes);    try std.testing.expect(joining_face.usesArabicJoiningForms(.{}));    try std.testing.expect(!ordinary_face.usesArabicJoiningForms(.{}));    try std.testing.expectEqual(@as(u32, 'A' - 31), joining_face.glyphId(0x0628));    try std.testing.expectEqual(@as(u32, 'B' - 31), joining_face.glyphId(0x0627));}test "Face applies GSUB feature variations" {    const bytes = try test_font.createWithGsubFeatureVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{face.glyphId('A')};    const heavy = [_]VariationSetting{.{ .tag = tag("wght"), .value = 900.0 }};    const default_substitution = (try face.substitutionAtFor(.{}, 0, &glyphs, 0)).?;    try std.testing.expectEqual(face.glyphId('Z'), default_substitution.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(.{}, 1, &glyphs, 0));    const heavy_selection = LayoutSelection{ .variations = &heavy };    const heavy_substitution = (try face.substitutionAtFor(heavy_selection, 1, &glyphs, 0)).?;    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(heavy_selection, 0, &glyphs, 0));    try std.testing.expectEqual(face.glyphId('B'), heavy_substitution.glyph_id);    try std.testing.expectEqual(face.glyphId('B'), face.substituteGlyphFor(heavy_selection, face.glyphId('A')));}test "Face applies GSUB required variation alternates" {    const bytes = try test_font.createWithGsubRequiredVariationAlternates(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{face.glyphId('A')};    const ligature_glyphs = [_]u32{ face.glyphId('f'), face.glyphId('i') };    const heavy = [_]VariationSetting{.{ .tag = tag("wght"), .value = 900.0 }};    const heavy_selection = LayoutSelection{ .variations = &heavy };    const disabled_selection = LayoutSelection{ .features = &.{.{ .tag = tag("rvrn"), .value = 0 }} };    const disabled_heavy_selection = LayoutSelection{ .features = disabled_selection.features, .variations = &heavy };    const default_substitution = (try face.substitutionAtFor(.{}, 0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u16, 3), try face.gsubLookupCount());    try std.testing.expectEqual(face.glyphId('Z'), default_substitution.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(.{}, 1, &glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(.{}, 2, &ligature_glyphs, 0));    try std.testing.expectEqual(face.glyphId('Z'), face.substituteGlyphFor(.{}, face.glyphId('A')));    const heavy_substitution = (try face.substitutionAtFor(heavy_selection, 1, &glyphs, 0)).?;    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(heavy_selection, 0, &glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(heavy_selection, 2, &ligature_glyphs, 0));    try std.testing.expectEqual(face.glyphId('B'), heavy_substitution.glyph_id);    try std.testing.expectEqual(face.glyphId('B'), face.substituteGlyphFor(heavy_selection, face.glyphId('A')));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(disabled_selection, 0, &glyphs, 0));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(disabled_heavy_selection, 1, &glyphs, 0));    try std.testing.expectEqual(face.glyphId('A'), face.substituteGlyphFor(disabled_selection, face.glyphId('A')));}test "Face applies GSUB vertical alternates only for vertical selection" {    const bytes = try test_font.createWithGsubVerticalAlternates(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{face.glyphId('A')};    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(.{}, 0, &glyphs, 0));    const vertical_substitution = (try face.substitutionAtFor(.{ .vertical = true }, 0, &glyphs, 0)).?;    try std.testing.expectEqual(face.glyphId('B'), vertical_substitution.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(.{        .vertical = true,        .features = &.{.{ .tag = tag("vert"), .value = 0 }},    }, 0, &glyphs, 0));}test "Face applies GSUB vertical rotation alternates only for vertical selection" {    const bytes = try test_font.createWithGsubVerticalRotationAlternates(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{face.glyphId('A')};    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(.{}, 0, &glyphs, 0));    const vertical_substitution = (try face.substitutionAtFor(.{ .vertical = true }, 0, &glyphs, 0)).?;    try std.testing.expectEqual(face.glyphId('C'), vertical_substitution.glyph_id);    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(.{        .vertical = true,        .features = &.{.{ .tag = tag("vrt2"), .value = 0 }},    }, 0, &glyphs, 0));}test "Face activates GSUB substitutions for selected script tags" {    const bytes = try test_font.createWithGsubLigature(std.testing.allocator);    defer std.testing.allocator.free(bytes);    try fixture_binary.replaceLayoutScript(bytes, "GSUB", "latn");    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('f'), face.glyphId('i') };    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &glyphs, 0));    const substitution = (try face.substitutionAtFor(.{ .script = tag("latn") }, 0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u32, 96), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 2), substitution.component_count);    const fallback = try face.substitutionAtFor(.{ .script = tag("cyrl") }, 0, &glyphs, 0);    try std.testing.expectEqual(@as(?GsubSubstitution, null), fallback);}test "Face resolves GSUB substitutions from ordered script tags" {    const bytes = try test_font.createWithGsubLigature(std.testing.allocator);    defer std.testing.allocator.free(bytes);    try fixture_binary.replaceLayoutScript(bytes, "GSUB", "dev2");    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('f'), face.glyphId('i') };    const script_tags = [_]Tag{ tag("dev3"), tag("dev2"), tag("deva") };    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAtFor(.{ .script = tag("deva") }, 0, &glyphs, 0));    const substitution = (try face.substitutionAtFor(.{ .script = tag("deva"), .script_tags = &script_tags }, 0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u32, 96), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 2), substitution.component_count);}test "Face exposes GSUB default multiple substitutions" {    const bytes = try test_font.createWithGsubMultipleSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const glyphs = [_]u32{ a, face.glyphId('!') };    const substitution = (try face.substitutionAt(0, &glyphs, 0)).?;    try std.testing.expectEqual(@as(u16, 1), try face.gsubLookupCount());    try std.testing.expectEqual(face.glyphId('X'), substitution.glyph_id);    try std.testing.expectEqual(@as(u16, 1), substitution.component_count);    try std.testing.expectEqual(@as(u16, 2), substitution.replacement_count);    try std.testing.expectEqual(@as(?u32, face.glyphId('X')), face.substitutionGlyph(substitution, 0));    try std.testing.expectEqual(@as(?u32, face.glyphId('Y')), face.substitutionGlyph(substitution, 1));    try std.testing.expectEqual(@as(?u32, null), face.substitutionGlyph(substitution, 2));    try std.testing.expectEqual(a, face.substituteGlyph(a));    try std.testing.expectEqual(@as(?GsubSubstitution, null), try face.substitutionAt(0, &glyphs, 1));}test "Face applies GPOS pair adjustments" {    const bytes = try test_font.createWithGposPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const v = face.glyphId('V');    const adjustment = face.gposPairAdjustment(a, v);    try std.testing.expectEqual(@as(i32, -80), adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.right.x_advance);    try std.testing.expect(face.gposPairAdjustment(v, a).isZero());    try std.testing.expect(!face.hasGposSingleAdjustment());    try std.testing.expect(!face.hasGposCursiveAttachment());    try std.testing.expect(!face.hasGposMarkToBase());    try std.testing.expect(!face.hasGposMarkToLigature());    try std.testing.expect(!face.hasGposMarkToMark());}test "Face applies GPOS vertical pair adjustments only for vertical selection" {    const bytes = try test_font.createWithGposVerticalPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const v = face.glyphId('V');    try std.testing.expect(face.gposPairAdjustmentFor(.{}, a, v).isZero());    const vertical = face.gposPairAdjustmentFor(.{ .vertical = true }, a, v);    try std.testing.expectEqual(@as(i32, 0), vertical.left.x_advance);    try std.testing.expectEqual(@as(i32, -80), vertical.left.y_advance);    try std.testing.expectEqual(@as(i32, 0), vertical.right.y_advance);    const disabled = face.gposPairAdjustmentFor(.{        .vertical = true,        .features = &.{.{ .tag = tag("vkrn"), .value = 0 }},    }, a, v);    try std.testing.expect(disabled.isZero());}test "Face applies GPOS pair adjustments across ignored marks" {    const bytes = try test_font.createWithGposPairIgnoreMarks(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{        face.glyphId('A'),        face.glyphId('^'),        face.glyphId('V'),    };    const adjustment = face.gposPairAdjustmentBeforeFor(.{}, &glyphs, 2).?;    try std.testing.expectEqual(@as(usize, 2), adjustment.left_offset);    try std.testing.expectEqual(@as(i32, -80), adjustment.adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.adjustment.right.x_advance);    try std.testing.expectEqual(@as(?GposPairAdjustmentBefore, null), face.gposPairAdjustmentBeforeFor(.{}, &glyphs, 1));}test "Face keeps unfiltered GPOS pair adjustments adjacent" {    const bytes = try test_font.createWithGposPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{        face.glyphId('A'),        face.glyphId('^'),        face.glyphId('V'),    };    try std.testing.expectEqual(@as(?GposPairAdjustmentBefore, null), face.gposPairAdjustmentBeforeFor(.{}, &glyphs, 2));}test "Face applies GPOS contextual pair adjustments" {    const bytes = try test_font.createWithGposContextualPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('V'), face.glyphId('C') };    const mismatch = [_]u32{ face.glyphId('A'), face.glyphId('V'), face.glyphId('!') };    const adjustment = face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 0).?;    try std.testing.expect(face.gposPairAdjustment(face.glyphId('A'), face.glyphId('V')).isZero());    try std.testing.expectEqual(@as(usize, 0), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 1), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, -100), adjustment.adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.adjustment.right.x_advance);    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 1));    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &mismatch, 0));}test "Face applies GPOS simple contextual pair adjustments" {    const bytes = try test_font.createWithGposSimpleContextualPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('V'), face.glyphId('C') };    const mismatch = [_]u32{ face.glyphId('A'), face.glyphId('V'), face.glyphId('!') };    const adjustment = face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 0).?;    try std.testing.expect(face.gposPairAdjustment(face.glyphId('A'), face.glyphId('V')).isZero());    try std.testing.expectEqual(@as(usize, 0), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 1), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, -100), adjustment.adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.adjustment.right.x_advance);    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 1));    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &mismatch, 0));}test "Face applies GPOS class contextual pair adjustments" {    const bytes = try test_font.createWithGposClassContextualPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const mismatch = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const adjustment = face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 0).?;    try std.testing.expect(face.gposPairAdjustment(face.glyphId('A'), face.glyphId('B')).isZero());    try std.testing.expectEqual(@as(usize, 0), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 1), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, -100), adjustment.adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.adjustment.right.x_advance);    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 1));    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &mismatch, 0));}test "Face applies GPOS chained contextual pair adjustments" {    const bytes = try test_font.createWithGposChainedContextualPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('V'), face.glyphId('C'), face.glyphId('!') };    const lookahead_mismatch = [_]u32{ face.glyphId('A'), face.glyphId('V'), face.glyphId('C'), face.glyphId('A') };    const adjustment = face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 1).?;    try std.testing.expect(face.gposPairAdjustment(face.glyphId('V'), face.glyphId('C')).isZero());    try std.testing.expectEqual(@as(usize, 0), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 1), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, -100), adjustment.adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.adjustment.right.x_advance);    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 0));    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &lookahead_mismatch, 1));}test "Face applies GPOS chained simple contextual pair adjustments" {    const bytes = try test_font.createWithGposChainedSimpleContextualPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const missing_backtrack = [_]u32{ face.glyphId('B'), face.glyphId('C'), face.glyphId('!') };    const missing_input = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const adjustment = face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 1).?;    try std.testing.expect(face.gposPairAdjustment(face.glyphId('B'), face.glyphId('C')).isZero());    try std.testing.expectEqual(@as(usize, 0), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 1), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, -100), adjustment.adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.adjustment.right.x_advance);    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 0));    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &missing_backtrack, 0));    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &missing_input, 1));}test "Face applies GPOS chained class contextual pair adjustments" {    const bytes = try test_font.createWithGposChainedClassContextualPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const missing_backtrack = [_]u32{ face.glyphId('B'), face.glyphId('C'), face.glyphId('!') };    const missing_input = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const adjustment = face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 1).?;    try std.testing.expect(face.gposPairAdjustment(face.glyphId('B'), face.glyphId('C')).isZero());    try std.testing.expectEqual(@as(usize, 0), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 1), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, -100), adjustment.adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.adjustment.right.x_advance);    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &glyphs, 0));    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &missing_backtrack, 0));    try std.testing.expectEqual(@as(?GposContextualPairAdjustment, null), face.gposContextualPairAdjustmentAtFor(.{}, &missing_input, 1));}test "Face activates GPOS adjustments for selected script tags" {    const bytes = try test_font.createWithGposPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    try fixture_binary.replaceLayoutScript(bytes, "GPOS", "latn");    const face = try Face.init(bytes);    const a = face.glyphId('A');    const v = face.glyphId('V');    try std.testing.expect(face.gposPairAdjustment(a, v).isZero());    const adjustment = face.gposPairAdjustmentFor(.{ .script = tag("latn") }, a, v);    try std.testing.expectEqual(@as(i32, -80), adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.right.x_advance);    try std.testing.expect(face.gposPairAdjustmentFor(.{ .script = tag("cyrl") }, a, v).isZero());}test "Face resolves GPOS adjustments from ordered script tags" {    const bytes = try test_font.createWithGposPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    try fixture_binary.replaceLayoutScript(bytes, "GPOS", "bng2");    const face = try Face.init(bytes);    const a = face.glyphId('A');    const v = face.glyphId('V');    const script_tags = [_]Tag{ tag("bng3"), tag("bng2"), tag("beng") };    try std.testing.expect(face.gposPairAdjustmentFor(.{ .script = tag("beng") }, a, v).isZero());    const adjustment = face.gposPairAdjustmentFor(.{ .script = tag("beng"), .script_tags = &script_tags }, a, v);    try std.testing.expectEqual(@as(i32, -80), adjustment.left.x_advance);    try std.testing.expectEqual(@as(i32, 0), adjustment.right.x_advance);}test "Face applies GPOS single adjustments" {    const bytes = try test_font.createWithGposSingleAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const b = face.glyphId('B');    const bang = face.glyphId('!');    try std.testing.expect(face.hasGposSingleAdjustment());    const a_adjustment = face.gposSingleAdjustment(a);    try std.testing.expectEqual(@as(i32, 20), a_adjustment.x_placement);    try std.testing.expectEqual(@as(i32, 30), a_adjustment.y_placement);    try std.testing.expectEqual(@as(i32, -40), a_adjustment.x_advance);    const b_adjustment = face.gposSingleAdjustment(b);    try std.testing.expectEqual(@as(i32, -10), b_adjustment.x_placement);    try std.testing.expectEqual(@as(i32, 0), b_adjustment.y_placement);    try std.testing.expectEqual(@as(i32, 0), b_adjustment.x_advance);    try std.testing.expect(face.gposSingleAdjustment(bang).isZero());    const vertical = LayoutSelection{ .vertical = true };    const vertical_enabled = LayoutSelection{ .vertical = true, .features = &.{.{ .tag = tag("dist"), .value = 1 }} };    const glyphs = [_]u32{a};    try std.testing.expect(!face.hasGposSingleAdjustmentFor(vertical));    try std.testing.expect(face.hasGposSingleAdjustmentFor(vertical_enabled));    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(vertical, &glyphs, 0));    try std.testing.expectEqual(@as(i32, 20), face.gposSingleAdjustmentAtFor(vertical_enabled, &glyphs, 0).?.adjustment.x_placement);}test "Face applies GPOS feature variations" {    const bytes = try test_font.createWithGposFeatureVariations(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyph = face.glyphId('A');    const heavy = [_]VariationSetting{.{ .tag = tag("wght"), .value = 900.0 }};    const heavy_selection = LayoutSelection{ .variations = &heavy };    const default_adjustment = face.gposSingleAdjustmentFor(.{}, glyph);    try std.testing.expectEqual(@as(i32, -40), default_adjustment.x_advance);    try std.testing.expectEqual(@as(i32, 0), default_adjustment.x_placement);    const heavy_adjustment = face.gposSingleAdjustmentFor(heavy_selection, glyph);    try std.testing.expect(face.hasGposSingleAdjustmentFor(heavy_selection));    try std.testing.expectEqual(@as(i32, -120), heavy_adjustment.x_advance);    try std.testing.expectEqual(@as(i32, 0), heavy_adjustment.x_placement);}test "Face applies GPOS contextual single adjustments" {    const bytes = try test_font.createWithGposContextualSingleAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const mismatch = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const adjustment = face.gposSingleAdjustmentAtFor(.{}, &glyphs, 0).?;    try std.testing.expect(face.hasGposSingleAdjustment());    try std.testing.expect(face.gposSingleAdjustment(face.glyphId('B')).isZero());    try std.testing.expectEqual(@as(usize, 1), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 3), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, 50), adjustment.adjustment.x_placement);    try std.testing.expectEqual(@as(i32, -100), adjustment.adjustment.x_advance);    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &mismatch, 0));    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &glyphs, 1));}test "Face applies GPOS simple contextual single adjustments" {    const bytes = try test_font.createWithGposSimpleContextualSingleAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const mismatch = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const adjustment = face.gposSingleAdjustmentAtFor(.{}, &glyphs, 0).?;    try std.testing.expect(face.hasGposSingleAdjustment());    try std.testing.expect(face.gposSingleAdjustment(face.glyphId('B')).isZero());    try std.testing.expectEqual(@as(usize, 1), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 3), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, 50), adjustment.adjustment.x_placement);    try std.testing.expectEqual(@as(i32, -100), adjustment.adjustment.x_advance);    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &mismatch, 0));    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &glyphs, 1));}test "Face applies GPOS class contextual single adjustments" {    const bytes = try test_font.createWithGposClassContextualSingleAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const mismatch = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const adjustment = face.gposSingleAdjustmentAtFor(.{}, &glyphs, 0).?;    try std.testing.expect(face.hasGposSingleAdjustment());    try std.testing.expect(face.gposSingleAdjustment(face.glyphId('B')).isZero());    try std.testing.expectEqual(@as(usize, 1), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 3), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, 50), adjustment.adjustment.x_placement);    try std.testing.expectEqual(@as(i32, -100), adjustment.adjustment.x_advance);    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &mismatch, 0));    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &glyphs, 1));}test "Face applies GPOS chained contextual single adjustments" {    const bytes = try test_font.createWithGposChainedContextualSingleAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C'), face.glyphId('!') };    const lookahead_mismatch = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C'), face.glyphId('A') };    const adjustment = face.gposSingleAdjustmentAtFor(.{}, &glyphs, 1).?;    try std.testing.expect(face.hasGposSingleAdjustment());    try std.testing.expect(face.gposSingleAdjustment(face.glyphId('B')).isZero());    try std.testing.expectEqual(@as(usize, 0), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 2), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, 75), adjustment.adjustment.x_placement);    try std.testing.expectEqual(@as(i32, -125), adjustment.adjustment.x_advance);    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &glyphs, 0));    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &lookahead_mismatch, 1));}test "Face applies GPOS chained simple contextual single adjustments" {    const bytes = try test_font.createWithGposChainedSimpleContextualSingleAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const missing_backtrack = [_]u32{ face.glyphId('B'), face.glyphId('C'), face.glyphId('!') };    const missing_lookahead = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const adjustment = face.gposSingleAdjustmentAtFor(.{}, &glyphs, 1).?;    try std.testing.expect(face.hasGposSingleAdjustment());    try std.testing.expect(face.gposSingleAdjustment(face.glyphId('B')).isZero());    try std.testing.expectEqual(@as(usize, 0), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 1), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, 75), adjustment.adjustment.x_placement);    try std.testing.expectEqual(@as(i32, -125), adjustment.adjustment.x_advance);    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &glyphs, 0));    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &missing_backtrack, 0));    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &missing_lookahead, 1));}test "Face applies GPOS chained class contextual single adjustments" {    const bytes = try test_font.createWithGposChainedClassContextualSingleAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const glyphs = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('C') };    const missing_backtrack = [_]u32{ face.glyphId('B'), face.glyphId('C'), face.glyphId('!') };    const missing_lookahead = [_]u32{ face.glyphId('A'), face.glyphId('B'), face.glyphId('!') };    const adjustment = face.gposSingleAdjustmentAtFor(.{}, &glyphs, 1).?;    try std.testing.expect(face.hasGposSingleAdjustment());    try std.testing.expect(face.gposSingleAdjustment(face.glyphId('B')).isZero());    try std.testing.expectEqual(@as(usize, 0), adjustment.target_offset);    try std.testing.expectEqual(@as(usize, 1), adjustment.skip_count);    try std.testing.expectEqual(@as(i32, 75), adjustment.adjustment.x_placement);    try std.testing.expectEqual(@as(i32, -125), adjustment.adjustment.x_advance);    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &glyphs, 0));    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &missing_backtrack, 0));    try std.testing.expectEqual(@as(?GposSingleAdjustment, null), face.gposSingleAdjustmentAtFor(.{}, &missing_lookahead, 1));}test "Face applies GPOS cursive attachments" {    const bytes = try test_font.createWithGposCursiveAttachment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const b = face.glyphId('B');    try std.testing.expect(face.hasGposCursiveAttachment());    const attachment = face.gposCursiveAttachment(a, b).?;    try std.testing.expectEqual(@as(i32, 460), attachment.x_anchor_delta);    try std.testing.expectEqual(@as(i32, 100), attachment.y_anchor_delta);    try std.testing.expect(face.gposCursiveAttachment(b, a) == null);    try std.testing.expect(face.gposCursiveAttachment(a, face.glyphId('!')) == null);    const vertical = LayoutSelection{ .vertical = true };    const vertical_enabled = LayoutSelection{ .vertical = true, .features = &.{.{ .tag = tag("curs"), .value = 1 }} };    try std.testing.expect(!face.hasGposCursiveAttachmentFor(vertical));    try std.testing.expect(face.hasGposCursiveAttachmentFor(vertical_enabled));    try std.testing.expect(face.gposCursiveAttachmentFor(vertical, a, b) == null);    try std.testing.expectEqual(@as(i32, 460), face.gposCursiveAttachmentFor(vertical_enabled, a, b).?.x_anchor_delta);}test "Face applies GPOS mark-to-base attachment" {    const bytes = try test_font.createWithGposMarkToBase(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const a = face.glyphId('A');    const mark = face.glyphId('^');    try std.testing.expect(face.hasGposMarkToBase());    const adjustment = face.gposMarkToBaseAdjustment(a, mark).?;    try std.testing.expectEqual(@as(i32, 150), adjustment.x_placement);    try std.testing.expectEqual(@as(i32, 700), adjustment.y_placement);    try std.testing.expect(face.gposMarkToBaseAdjustment(mark, a) == null);    try std.testing.expect(face.gposMarkToBaseAdjustment(a, face.glyphId('!')) == null);}test "Face applies GPOS above and below-base mark positioning by default" {    const abvm_bytes = try test_font.createWithGposAboveBaseMarkPositioning(std.testing.allocator);    defer std.testing.allocator.free(abvm_bytes);    const blwm_bytes = try test_font.createWithGposBelowBaseMarkPositioning(std.testing.allocator);    defer std.testing.allocator.free(blwm_bytes);    const abvm_face = try Face.init(abvm_bytes);    const blwm_face = try Face.init(blwm_bytes);    const abvm_base = abvm_face.glyphId('A');    const abvm_mark = abvm_face.glyphId('^');    const blwm_base = blwm_face.glyphId('A');    const blwm_mark = blwm_face.glyphId('^');    const disabled_abvm = LayoutSelection{ .features = &.{.{ .tag = tag("abvm"), .value = 0 }} };    const disabled_blwm = LayoutSelection{ .features = &.{.{ .tag = tag("blwm"), .value = 0 }} };    try std.testing.expectEqual(@as(i32, 150), abvm_face.gposMarkToBaseAdjustment(abvm_base, abvm_mark).?.x_placement);    try std.testing.expectEqual(@as(i32, 700), abvm_face.gposMarkToBaseAdjustmentFor(.{ .vertical = true }, abvm_base, abvm_mark).?.y_placement);    try std.testing.expectEqual(@as(i32, 150), blwm_face.gposMarkToBaseAdjustment(blwm_base, blwm_mark).?.x_placement);    try std.testing.expectEqual(@as(i32, 700), blwm_face.gposMarkToBaseAdjustmentFor(.{ .vertical = true }, blwm_base, blwm_mark).?.y_placement);    try std.testing.expect(abvm_face.gposMarkToBaseAdjustmentFor(disabled_abvm, abvm_base, abvm_mark) == null);    try std.testing.expect(blwm_face.gposMarkToBaseAdjustmentFor(disabled_blwm, blwm_base, blwm_mark) == null);}test "Face applies GPOS mark-to-ligature attachment" {    const bytes = try test_font.createWithGposMarkToLigature(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const ligature = @as(u32, 96);    const mark = face.glyphId('^');    try std.testing.expect(face.hasGposMarkToLigature());    const first_component = face.gposMarkToLigatureAdjustment(ligature, mark, 0).?;    try std.testing.expectEqual(@as(i32, 80), first_component.x_placement);    try std.testing.expectEqual(@as(i32, 700), first_component.y_placement);    const second_component = face.gposMarkToLigatureAdjustment(ligature, mark, 1).?;    try std.testing.expectEqual(@as(i32, 230), second_component.x_placement);    try std.testing.expectEqual(@as(i32, 650), second_component.y_placement);    try std.testing.expect(face.gposMarkToLigatureAdjustment(ligature, mark, 2) == null);    try std.testing.expect(face.gposMarkToLigatureAdjustment(mark, ligature, 0) == null);    try std.testing.expect(face.gposMarkToLigatureAdjustment(ligature, face.glyphId('!'), 0) == null);}test "Face applies GPOS mark-to-mark attachment" {    const bytes = try test_font.createWithGposMarkToMark(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const base_mark = face.glyphId('^');    const mark = face.glyphId('_');    try std.testing.expect(face.hasGposMarkToMark());    const adjustment = face.gposMarkToMarkAdjustment(base_mark, mark).?;    try std.testing.expectEqual(@as(i32, 20), adjustment.x_placement);    try std.testing.expectEqual(@as(i32, 300), adjustment.y_placement);    try std.testing.expect(face.gposMarkToMarkAdjustment(mark, base_mark) == null);    try std.testing.expect(face.gposMarkToMarkAdjustment(base_mark, face.glyphId('!')) == null);}test "Face reads GDEF glyph classes" {    const bytes = try test_font.createWithGdefGlyphClasses(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    try std.testing.expectEqual(GlyphClass.base, face.glyphClass(face.glyphId('A')));    try std.testing.expectEqual(GlyphClass.mark, face.glyphClass(face.glyphId('^')));    try std.testing.expectEqual(GlyphClass.component, face.glyphClass(face.glyphId('_')));    try std.testing.expectEqual(GlyphClass.ligature, face.glyphClass(96));    try std.testing.expectEqual(GlyphClass.unknown, face.glyphClass(face.glyphId('!')));}test "Face applies GPOS mark-to-base with matching mark attachment type" {    const bytes = try test_font.createWithGposMarkToBase(std.testing.allocator);    defer std.testing.allocator.free(bytes);    try fixture_binary.setLayoutLookupFlag(bytes, "GPOS", 0, 0x0300);    const gdef_offset = try fixture_binary.tableOffset(bytes, "GDEF");    fixture_binary.writeU16(bytes, gdef_offset + 10, 12);    const face = try Face.init(bytes);    const adjustment = face.gposMarkToBaseAdjustment(face.glyphId('A'), face.glyphId('^')).?;    try std.testing.expectEqual(@as(i32, 150), adjustment.x_placement);    try std.testing.expectEqual(@as(i32, 700), adjustment.y_placement);}test "Face filters GPOS mark-to-base with mismatched mark attachment type" {    const bytes = try test_font.createWithGposMarkToBase(std.testing.allocator);    defer std.testing.allocator.free(bytes);    try fixture_binary.setLayoutLookupFlag(bytes, "GPOS", 0, 0x0200);    const gdef_offset = try fixture_binary.tableOffset(bytes, "GDEF");    fixture_binary.writeU16(bytes, gdef_offset + 10, 12);    const face = try Face.init(bytes);    try std.testing.expect(face.gposMarkToBaseAdjustment(face.glyphId('A'), face.glyphId('^')) == null);}test "Face reads GDEF ligature caret coordinates" {    const bytes = try test_font.createWithGsubLigatureAndGdefCarets(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const caret = face.ligatureCaret(96, 0).?;    try std.testing.expectEqual(@as(u16, 1), face.ligatureCaretCount(96));    try std.testing.expectEqual(@as(i16, 250), caret.coordinate);    try std.testing.expectEqual(false, caret.synthesized);    try std.testing.expect(face.ligatureCaret(96, 1) == null);    try std.testing.expectEqual(@as(u16, 0), face.ligatureCaretCount(face.glyphId('A')));    try std.testing.expect(face.ligatureCaret(face.glyphId('A'), 0) == null);}test "Face exposes horizontal MATH assemblies" {    const bytes = try test_font.createWithMathAssembly(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const arrow = face.glyphId(0x2192);    var assembly = (try face.mathHorizontalAssemblyAlloc(std.testing.allocator, arrow, 1300)).?;    defer assembly.deinit(std.testing.allocator);    try std.testing.expect(arrow != 0);    try std.testing.expect(face.mathHorizontalVariant(arrow, 1300) == null);    try std.testing.expectEqual(@as(u16, 1300), assembly.advance_measurement);    try std.testing.expectEqual(@as(usize, 4), assembly.parts.len);}test "Face exposes MATH top accent attachments" {    const bytes = try test_font.createWithMathAssembly(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const base = face.mathTopAccentAttachment(face.glyphId('A')).?;    const accent = face.mathTopAccentAttachment(face.glyphId('`')).?;    try std.testing.expectEqual(@as(i16, 420), base.value);    try std.testing.expectEqual(@as(i16, 80), accent.value);    try std.testing.expect(face.mathTopAccentAttachment(face.glyphId('B')) == null);}test "Face ignores malformed optional GSUB table" {    const bytes = try test_font.createWithGsubSingleSubstitution(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const gsub_table = try table(bytes, "GSUB");    std.mem.writeInt(u16, bytes[gsub_table.offset..][0..2], 2, .big);    const face = try Face.init(bytes);    const a = face.glyphId('A');    try std.testing.expectEqual(a, face.substituteGlyph(a));}test "Face ignores malformed optional GPOS table" {    const bytes = try test_font.createWithGposPairAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const gpos_table = try table(bytes, "GPOS");    std.mem.writeInt(u16, bytes[gpos_table.offset..][0..2], 2, .big);    const face = try Face.init(bytes);    try std.testing.expect(face.gposPairAdjustment(face.glyphId('A'), face.glyphId('V')).isZero());}test "Face ignores malformed optional GDEF table" {    const bytes = try test_font.createWithGdefGlyphClasses(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const gdef_table = try table(bytes, "GDEF");    std.mem.writeInt(u16, bytes[gdef_table.offset..][0..2], 2, .big);    const face = try Face.init(bytes);    try std.testing.expectEqual(GlyphClass.unknown, face.glyphClass(face.glyphId('A')));}test "Face ignores malformed optional kern table" {    const bytes = try test_font.createWithKern(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const kern_table = try table(bytes, "kern");    std.mem.writeInt(u16, bytes[kern_table.offset + 6 ..][0..2], 2, .big);    const face = try Face.init(bytes);    try std.testing.expectEqual(@as(i16, 0), face.kerning(face.glyphId('A'), face.glyphId('V')));}test "GPOS value records apply GDEF variation deltas" {    const bytes = try test_font.createWithGposSingleVariationAdjustment(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const face = try Face.init(bytes);    const adjustment = face.gposSingleAdjustment(face.glyphId('A'));    try std.testing.expectEqual(@as(i32, 20), adjustment.x_placement);    try std.testing.expectEqual(@as(i32, 20), adjustment.withVariations(face, &.{}).x_placement);    try std.testing.expectEqual(@as(i32, 60), adjustment.withVariations(face, &.{.{ .tag = tag("wght"), .value = 650.0 }}).x_placement);    try std.testing.expectEqual(@as(i32, 100), adjustment.withVariations(face, &.{.{ .tag = tag("wght"), .value = 900.0 }}).x_placement);}test "GDEF reads mark attachment classes and mark glyph sets" {    const bytes = try createGdefMarkFilterFixture(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const gdef = try Gdef.init(bytes, .{ .offset = 0, .len = bytes.len }, null);    try std.testing.expectEqual(GlyphClass.mark, try gdef.glyphClass(bytes, '^' - 31));    try std.testing.expectEqual(@as(u16, 1), try gdef.markAttachmentClass(bytes, '^' - 31));    try std.testing.expectEqual(@as(u16, 2), try gdef.markAttachmentClass(bytes, '_' - 31));    try std.testing.expect(try gdef.markGlyphSetContains(bytes, 0, '^' - 31));    try std.testing.expect(!try gdef.markGlyphSetContains(bytes, 0, '_' - 31));}test "lookup filters use GDEF mark classes and mark glyph sets" {    const bytes = try createGdefMarkFilterFixture(std.testing.allocator);    defer std.testing.allocator.free(bytes);    const gdef = try Gdef.init(bytes, .{ .offset = 0, .len = bytes.len }, null);    try std.testing.expect(!try lookupGlyphIgnored(bytes, gdef, .{ .flags = 0x0100 }, '^' - 31));    try std.testing.expect(try lookupGlyphIgnored(bytes, gdef, .{ .flags = 0x0100 }, '_' - 31));    try std.testing.expect(!try lookupGlyphIgnored(bytes, gdef, .{ .flags = lookup_use_mark_filtering_set, .mark_filtering_set = 0 }, '^' - 31));    try std.testing.expect(try lookupGlyphIgnored(bytes, gdef, .{ .flags = lookup_use_mark_filtering_set, .mark_filtering_set = 0 }, '_' - 31));}fn createGdefMarkFilterFixture(allocator: std.mem.Allocator) ![]u8 {    var out = std.ArrayListUnmanaged(u8).empty;    errdefer out.deinit(allocator);    try fixture_binary.appendU16(allocator, &out, 1);    try fixture_binary.appendU16(allocator, &out, 2);    try fixture_binary.appendU16(allocator, &out, 14);    try fixture_binary.appendU16(allocator, &out, 0);    try fixture_binary.appendU16(allocator, &out, 0);    try fixture_binary.appendU16(allocator, &out, 30);    try fixture_binary.appendU16(allocator, &out, 46);    try fixture_binary.appendU16(allocator, &out, 2);    try fixture_binary.appendU16(allocator, &out, 2);    try fixture_binary.appendU16(allocator, &out, '^' - 31);    try fixture_binary.appendU16(allocator, &out, '^' - 31);    try fixture_binary.appendU16(allocator, &out, 3);    try fixture_binary.appendU16(allocator, &out, '_' - 31);    try fixture_binary.appendU16(allocator, &out, '_' - 31);    try fixture_binary.appendU16(allocator, &out, 3);    try fixture_binary.appendU16(allocator, &out, 2);    try fixture_binary.appendU16(allocator, &out, 2);    try fixture_binary.appendU16(allocator, &out, '^' - 31);    try fixture_binary.appendU16(allocator, &out, '^' - 31);    try fixture_binary.appendU16(allocator, &out, 1);    try fixture_binary.appendU16(allocator, &out, '_' - 31);    try fixture_binary.appendU16(allocator, &out, '_' - 31);    try fixture_binary.appendU16(allocator, &out, 2);    try fixture_binary.appendU16(allocator, &out, 1);    try fixture_binary.appendU16(allocator, &out, 1);    try fixture_binary.appendU32(allocator, &out, 8);    try fixture_binary.appendU16(allocator, &out, 1);    try fixture_binary.appendU16(allocator, &out, 1);    try fixture_binary.appendU16(allocator, &out, '^' - 31);    return out.toOwnedSlice(allocator);}

Source: lib/filigree/src/font/root.zig:6

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

Audit

Definitions1
Public names1
Members0
Version26.7.0
Revisiondaab053ee433