Skip to documentation
SLOP

tiny.filigree.font.cmap

Reference tiny.filigree font cmap

Defined in font.

API (4)

Actions

Public operations.

Types and contracts

Public types and contracts.

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

Source

Called byCallstest sourcelib.filigree.src.font.cmaptest: Cmap maps supplementary codepoi...private sourcelib.filigree.src.font.faceinitDirectoryImplprivate sourcelib.filigree.src.font.cmapscoreSubtableprivate sourcelib.filigree.src.font.cmapvalidateFormat12private sourcelib.filigree.src.font.cmapvalidateFormat14private sourcelib.filigree.src.font.cmapvalidateFormat4font.cmap.Cmapinit
Static calls · unresolved targets: 2 · external targets: 0.
Called byCallstest sourcelib.filigree.src.font.cmaptest: Cmap maps supplementary codepoi...private sourcelib.filigree.src.font.cmapmapFormat12private sourcelib.filigree.src.font.cmapmapFormat4font.cmap.Cmapmap
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.filigree.src.font.cmapmapFormat14font.cmap.CmapmapVariation
Static calls · unresolved targets: 0 · external targets: 0.

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

zig
const std = @import("std");const binary = @import("binary.zig");const model = @import("model.zig");const FontError = model.FontError;const Table = binary.Table;const readU16 = binary.readU16;const readU24 = binary.readU24;const readU32 = binary.readU32;const CmapFormat = enum {    format_4,    format_12,};pub const Cmap = struct {    offset: usize,    len: usize,    format: CmapFormat,    variation: ?Table = null,    pub fn init(data: []const u8, cmap_table: Table) FontError!Cmap {        if (cmap_table.len < 4) return error.InvalidCmap;        const count = try readU16(data, cmap_table.offset + 2);        if (4 + @as(usize, count) * 8 > cmap_table.len) return error.InvalidCmap;        var best_score: u16 = 0;        var best: ?Cmap = null;        var variation: ?Table = null;        for (0..count) |i| {            const record = cmap_table.offset + 4 + i * 8;            const platform = try readU16(data, record);            const encoding = try readU16(data, record + 2);            const sub_offset = try readU32(data, record + 4);            if (sub_offset >= cmap_table.len) continue;            const absolute = cmap_table.offset + @as(usize, @intCast(sub_offset));            if (absolute + 2 > data.len) continue;            const format = try readU16(data, absolute);            if (format == 14 and platform == 0 and encoding == 5) {                variation = validateFormat14(data, absolute) catch variation;                continue;            }            const candidate = switch (format) {                4 => validateFormat4(data, absolute) catch continue,                12 => validateFormat12(data, absolute) catch continue,                else => continue,            };            const score = scoreSubtable(platform, encoding, candidate.format);            if (score > best_score) {                best_score = score;                best = candidate;            }        }        var selected = best orelse return error.UnsupportedCmap;        selected.variation = variation;        return selected;    }    pub fn map(self: Cmap, data: []const u8, codepoint: u32) FontError!u32 {        return switch (self.format) {            .format_4 => mapFormat4(self, data, codepoint),            .format_12 => mapFormat12(self, data, codepoint),        };    }    pub fn mapVariation(self: Cmap, data: []const u8, codepoint: u32, variation_selector: u32) FontError!?u32 {        const variation = self.variation orelse return null;        return try mapFormat14(self, data, variation, codepoint, variation_selector);    }};fn validateFormat4(data: []const u8, offset: usize) FontError!Cmap {    if (offset > data.len or data.len - offset < 16) return error.InvalidCmap;    const len: usize = try readU16(data, offset + 2);    if (len < 16 or len > data.len - offset) return error.InvalidCmap;    const seg_count_x2 = try readU16(data, offset + 6);    if (seg_count_x2 == 0 or seg_count_x2 % 2 != 0) return error.InvalidCmap;    const seg_count = @as(usize, seg_count_x2 / 2);    const arrays_end = 14 + seg_count * 8;    if (arrays_end > len) return error.InvalidCmap;    return .{ .offset = offset, .len = len, .format = .format_4 };}fn validateFormat12(data: []const u8, offset: usize) FontError!Cmap {    if (offset > data.len or data.len - offset < 16) return error.InvalidCmap;    const len_u32 = try readU32(data, offset + 4);    if (@as(u64, len_u32) > @as(u64, std.math.maxInt(usize))) return error.InvalidCmap;    const len: usize = @intCast(len_u32);    if (len < 16 or len > data.len - offset) return error.InvalidCmap;    const groups = try readU32(data, offset + 12);    const records_len = @as(u64, groups) * 12;    if (records_len > std.math.maxInt(usize)) return error.InvalidCmap;    if (records_len > @as(u64, len - 16)) return error.InvalidCmap;    return .{ .offset = offset, .len = len, .format = .format_12 };}fn validateFormat14(data: []const u8, offset: usize) FontError!Table {    if (offset > data.len or data.len - offset < 10) return error.InvalidCmap;    const len_u32 = try readU32(data, offset + 2);    if (@as(u64, len_u32) > @as(u64, std.math.maxInt(usize))) return error.InvalidCmap;    const len: usize = @intCast(len_u32);    if (len < 10 or len > data.len - offset) return error.InvalidCmap;    const selector_count = try readU32(data, offset + 6);    if (@as(u64, selector_count) * 11 > @as(u64, len - 10)) return error.InvalidCmap;    const subtable = Table{ .offset = offset, .len = len };    for (0..selector_count) |i| {        const record = offset + 10 + i * 11;        _ = try readU24(data, record);        const default_offset = try readU32(data, record + 3);        const non_default_offset = try readU32(data, record + 7);        if (default_offset != 0) {            const default_table = try format14ChildOffset(subtable, default_offset, 4);            const range_count = try readU32(data, default_table);            if (@as(u64, range_count) * 4 > @as(u64, offset + len - default_table - 4)) return error.InvalidCmap;        }        if (non_default_offset != 0) {            const non_default_table = try format14ChildOffset(subtable, non_default_offset, 4);            const mapping_count = try readU32(data, non_default_table);            if (@as(u64, mapping_count) * 5 > @as(u64, offset + len - non_default_table - 4)) return error.InvalidCmap;        }    }    return subtable;}fn mapFormat4(cmap: Cmap, data: []const u8, codepoint: u32) FontError!u32 {    if (codepoint > 0xffff) return 0;    const cp: u16 = @intCast(codepoint);    const seg_count = @as(usize, (try readU16(data, cmap.offset + 6)) / 2);    const end_codes = cmap.offset + 14;    const start_codes = end_codes + seg_count * 2 + 2;    const id_deltas = start_codes + seg_count * 2;    const id_range_offsets = id_deltas + seg_count * 2;    for (0..seg_count) |i| {        const end = try readU16(data, end_codes + i * 2);        if (cp > end) continue;        const start = try readU16(data, start_codes + i * 2);        if (cp < start) return 0;        const delta = try readU16(data, id_deltas + i * 2);        const range_offset_pos = id_range_offsets + i * 2;        const range_offset = try readU16(data, range_offset_pos);        if (range_offset == 0) {            return @as(u16, @truncate(@as(u32, cp) + @as(u32, delta)));        }        const glyph_offset = range_offset_pos + @as(usize, range_offset) + (@as(usize, cp - start) * 2);        if (glyph_offset + 2 > cmap.offset + cmap.len) return error.InvalidCmap;        const glyph = try readU16(data, glyph_offset);        if (glyph == 0) return 0;        return @as(u16, @truncate(@as(u32, glyph) + @as(u32, delta)));    }    return 0;}fn mapFormat12(cmap: Cmap, data: []const u8, codepoint: u32) FontError!u32 {    const groups = try readU32(data, cmap.offset + 12);    var left: usize = 0;    var right: usize = @intCast(groups);    while (left < right) {        const mid = left + (right - left) / 2;        const record = cmap.offset + 16 + mid * 12;        const start = try readU32(data, record);        const end = try readU32(data, record + 4);        if (codepoint < start) {            right = mid;        } else if (codepoint > end) {            left = mid + 1;        } else {            const glyph_start = try readU32(data, record + 8);            const delta = codepoint - start;            if (glyph_start > std.math.maxInt(u32) - delta) return error.InvalidCmap;            return glyph_start + delta;        }    }    return 0;}fn mapFormat14(cmap: Cmap, data: []const u8, variation: Table, codepoint: u32, variation_selector: u32) FontError!?u32 {    const selector_count = try readU32(data, variation.offset + 6);    var left: usize = 0;    var right: usize = @intCast(selector_count);    while (left < right) {        const mid = left + (right - left) / 2;        const record = variation.offset + 10 + mid * 11;        const selector = try readU24(data, record);        if (variation_selector < selector) {            right = mid;        } else if (variation_selector > selector) {            left = mid + 1;        } else {            const default_offset = try readU32(data, record + 3);            const non_default_offset = try readU32(data, record + 7);            if (non_default_offset != 0) {                if (try mapFormat14NonDefault(data, variation, non_default_offset, codepoint)) |glyph| return glyph;            }            if (default_offset != 0 and try mapFormat14Default(data, variation, default_offset, codepoint)) {                return try cmap.map(data, codepoint);            }            return null;        }    }    return null;}fn mapFormat14Default(data: []const u8, variation: Table, relative_offset: u32, codepoint: u32) FontError!bool {    const table_offset = try format14ChildOffset(variation, relative_offset, 4);    const range_count = try readU32(data, table_offset);    var left: usize = 0;    var right: usize = @intCast(range_count);    while (left < right) {        const mid = left + (right - left) / 2;        const record = table_offset + 4 + mid * 4;        const start = try readU24(data, record);        const additional_count = data[record + 3];        const end = start + additional_count;        if (codepoint < start) {            right = mid;        } else if (codepoint > end) {            left = mid + 1;        } else {            return true;        }    }    return false;}fn mapFormat14NonDefault(data: []const u8, variation: Table, relative_offset: u32, codepoint: u32) FontError!?u32 {    const table_offset = try format14ChildOffset(variation, relative_offset, 4);    const mapping_count = try readU32(data, table_offset);    var left: usize = 0;    var right: usize = @intCast(mapping_count);    while (left < right) {        const mid = left + (right - left) / 2;        const record = table_offset + 4 + mid * 5;        const value = try readU24(data, record);        if (codepoint < value) {            right = mid;        } else if (codepoint > value) {            left = mid + 1;        } else {            return try readU16(data, record + 3);        }    }    return null;}fn format14ChildOffset(subtable: Table, relative_offset: u32, min_len: usize) FontError!usize {    if (relative_offset == 0) return error.InvalidCmap;    if (relative_offset > std.math.maxInt(usize)) return error.InvalidCmap;    const relative: usize = @intCast(relative_offset);    if (relative > subtable.len or min_len > subtable.len - relative) return error.InvalidCmap;    return subtable.offset + relative;}fn scoreSubtable(platform: u16, encoding: u16, format: CmapFormat) u16 {    return switch (format) {        .format_12 => if (platform == 3 and encoding == 10) 600 else if (platform == 0) 500 else 100,        .format_4 => if (platform == 3 and encoding == 1) 400 else if (platform == 3 and encoding == 0) 350 else if (platform == 0) 300 else 50,    };}test "Cmap maps supplementary codepoints through format 12" {    var bytes = @as([40]u8, @splat(0));    std.mem.writeInt(u16, bytes[0..2], 0, .big);    std.mem.writeInt(u16, bytes[2..4], 1, .big);    std.mem.writeInt(u16, bytes[4..6], 3, .big);    std.mem.writeInt(u16, bytes[6..8], 10, .big);    std.mem.writeInt(u32, bytes[8..12], 12, .big);    std.mem.writeInt(u16, bytes[12..14], 12, .big);    std.mem.writeInt(u16, bytes[14..16], 0, .big);    std.mem.writeInt(u32, bytes[16..20], 28, .big);    std.mem.writeInt(u32, bytes[20..24], 0, .big);    std.mem.writeInt(u32, bytes[24..28], 1, .big);    std.mem.writeInt(u32, bytes[28..32], 0x1f600, .big);    std.mem.writeInt(u32, bytes[32..36], 0x1f600, .big);    std.mem.writeInt(u32, bytes[36..40], 77, .big);    const mapped = try Cmap.init(&bytes, .{ .offset = 0, .len = bytes.len });    try std.testing.expectEqual(@as(u32, 77), try mapped.map(&bytes, 0x1f600));    try std.testing.expectEqual(@as(u32, 0), try mapped.map(&bytes, 'A'));}

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

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

Audit

Definitions5
Public names5
Members4
Version26.7.0
Revisiondaab053ee433