85 lines
2.5 KiB
TypeScript
85 lines
2.5 KiB
TypeScript
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<number | [number, number], number | null> {
|
|
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);
|
|
}
|
|
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.IFormat2, glyphId: [number, number]): Map<number | [number, number], number | null> {
|
|
const classStart: number = glyphId[0];
|
|
const 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.IFormat2, 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 [];
|
|
}
|
|
}
|