import { ClassDefTable } from '../tables'; /** * Get the number of the class to which the glyph belongs, or null if it doesn't * belong to any of them. * * @param table JSON representation of the class def table * @param glyphId Index of the glyph to look for */ export default function getGlyphClass(table: ClassDefTable, glyphId: number | [number, number]): Map { switch (table.format) { // https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2 case 2: if (Array.isArray(glyphId)) { return getRangeGlyphClass(table, glyphId); } else { return new Map([[ glyphId, getIndividualGlyphClass(table, glyphId) ]]); } // https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-1 default: return new Map([[glyphId, null]]); } } function getRangeGlyphClass(table: ClassDefTable.Format2, glyphId: [number, number]): Map { let classStart: number = glyphId[0]; let currentClass: number | null = getIndividualGlyphClass(table, classStart); let search: number = glyphId[0] + 1; const result = new Map<[number, number] | number, number | null>(); while (search < glyphId[1]) { const clazz = getIndividualGlyphClass(table, search); if (clazz !== currentClass) { if (search - classStart <= 1) { result.set(classStart, currentClass); } else { result.set([classStart, search], currentClass); } } search++; } if (search - classStart <= 1) { result.set(classStart, currentClass); } else { result.set([classStart, search], currentClass); } return result; } function getIndividualGlyphClass(table: ClassDefTable.Format2, glyphId: number): number | null { for (const range of table.ranges) { if (range.start <= glyphId && range.end >= glyphId) { return range.classId; } } return null; } export function listClassGlyphs(table: ClassDefTable, index: number): (number | [number, number])[] { switch (table.format) { case 2: const results: (number | [number, number])[] = []; for (const range of table.ranges) { if (range.classId !== index) { continue; } if (range.end === range.start) { results.push(range.start); } else { results.push([range.start, range.end + 1]); } } return results; default: return []; } }