70 lines
2.1 KiB
TypeScript
70 lines
2.1 KiB
TypeScript
import { IReverseChainingContextualSingleSubstitutionTable } from '../tables';
|
|
import { ILookupTree, ILookupTreeEntry } from '../types';
|
|
|
|
import { listGlyphsByIndex } from './coverage';
|
|
import { processLookaheadPosition, processBacktrackPosition, IEntryMeta } from './helper';
|
|
|
|
/**
|
|
* Build lookup tree for GSUB lookup table 8, format 1.
|
|
* https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#81-reverse-chaining-contextual-single-substitution-format-1-coverage-based-glyph-contexts
|
|
*
|
|
* @param table JSON representation of the table
|
|
* @param tableIndex Index of this table in the overall lookup
|
|
*/
|
|
export default function buildTree(table: IReverseChainingContextualSingleSubstitutionTable, tableIndex: number): ILookupTree {
|
|
const result: ILookupTree = {
|
|
individual: {},
|
|
range: []
|
|
};
|
|
|
|
const glyphs = listGlyphsByIndex(table.coverage);
|
|
|
|
for (const { glyphId, index } of glyphs) {
|
|
const initialEntry: ILookupTreeEntry = {};
|
|
if (Array.isArray(glyphId)) {
|
|
result.range.push({
|
|
entry: initialEntry,
|
|
range: glyphId
|
|
});
|
|
} else {
|
|
result.individual[glyphId] = initialEntry;
|
|
}
|
|
|
|
let currentEntries: IEntryMeta[] = [{
|
|
entry: initialEntry,
|
|
substitutions: [table.substitutes[index]]
|
|
}];
|
|
|
|
// We walk forward, then backward
|
|
for (const coverage of table.lookaheadCoverage) {
|
|
currentEntries = processLookaheadPosition(
|
|
listGlyphsByIndex(coverage).map(glyph => glyph.glyphId),
|
|
currentEntries
|
|
);
|
|
}
|
|
|
|
for (const coverage of table.backtrackCoverage) {
|
|
currentEntries = processBacktrackPosition(
|
|
listGlyphsByIndex(coverage).map(glyph => glyph.glyphId),
|
|
currentEntries
|
|
);
|
|
}
|
|
|
|
// When we get to the end, insert the lookup information
|
|
for (const { entry, substitutions } of currentEntries) {
|
|
entry.lookup = {
|
|
substitutions,
|
|
index: tableIndex,
|
|
subIndex: 0,
|
|
length: 1,
|
|
contextRange: [
|
|
-1 * table.backtrackCoverage.length,
|
|
1 + table.lookaheadCoverage.length
|
|
]
|
|
};
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|