147 lines
4.9 KiB
Plaintext
147 lines
4.9 KiB
Plaintext
// The `GPOS` table contains kerning pairs, among other things.
|
|
// https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
|
|
|
|
import check from '../check';
|
|
import { Parser } from '../parse';
|
|
|
|
const subtableParsers = new Array(10); // subtableParsers[0] is unused
|
|
|
|
// https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#lookup-type-1-single-adjustment-positioning-subtable
|
|
// this = Parser instance
|
|
subtableParsers[1] = function parseLookup1() {
|
|
const start = this.offset + this.relativeOffset;
|
|
const posformat = this.parseUShort();
|
|
if (posformat === 1) {
|
|
return {
|
|
posFormat: 1,
|
|
coverage: this.parsePointer(Parser.coverage),
|
|
value: this.parseValueRecord(),
|
|
};
|
|
} else if (posformat === 2) {
|
|
return {
|
|
posFormat: 2,
|
|
coverage: this.parsePointer(Parser.coverage),
|
|
values: this.parseValueRecordList(),
|
|
};
|
|
}
|
|
check.assert(
|
|
false,
|
|
'0x' +
|
|
start.toString(16) +
|
|
': GPOS lookup type 1 format must be 1 or 2.'
|
|
);
|
|
};
|
|
|
|
// https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#lookup-type-2-pair-adjustment-positioning-subtable
|
|
subtableParsers[2] = function parseLookup2() {
|
|
const start = this.offset + this.relativeOffset;
|
|
const posFormat = this.parseUShort();
|
|
check.assert(
|
|
posFormat === 1 || posFormat === 2,
|
|
'0x' +
|
|
start.toString(16) +
|
|
': GPOS lookup type 2 format must be 1 or 2.'
|
|
);
|
|
const coverage = this.parsePointer(Parser.coverage);
|
|
const valueFormat1 = this.parseUShort();
|
|
const valueFormat2 = this.parseUShort();
|
|
if (posFormat === 1) {
|
|
// Adjustments for Glyph Pairs
|
|
return {
|
|
posFormat: posFormat,
|
|
coverage: coverage,
|
|
valueFormat1: valueFormat1,
|
|
valueFormat2: valueFormat2,
|
|
pairSets: this.parseList(
|
|
Parser.pointer(
|
|
Parser.list(function () {
|
|
return {
|
|
// pairValueRecord
|
|
secondGlyph: this.parseUShort(),
|
|
value1: this.parseValueRecord(valueFormat1),
|
|
value2: this.parseValueRecord(valueFormat2),
|
|
};
|
|
})
|
|
)
|
|
),
|
|
};
|
|
} else if (posFormat === 2) {
|
|
const classDef1 = this.parsePointer(Parser.classDef);
|
|
const classDef2 = this.parsePointer(Parser.classDef);
|
|
const class1Count = this.parseUShort();
|
|
const class2Count = this.parseUShort();
|
|
return {
|
|
// Class Pair Adjustment
|
|
posFormat: posFormat,
|
|
coverage: coverage,
|
|
valueFormat1: valueFormat1,
|
|
valueFormat2: valueFormat2,
|
|
classDef1: classDef1,
|
|
classDef2: classDef2,
|
|
class1Count: class1Count,
|
|
class2Count: class2Count,
|
|
classRecords: this.parseList(
|
|
class1Count,
|
|
Parser.list(class2Count, function () {
|
|
return {
|
|
value1: this.parseValueRecord(valueFormat1),
|
|
value2: this.parseValueRecord(valueFormat2),
|
|
};
|
|
})
|
|
),
|
|
};
|
|
}
|
|
};
|
|
|
|
subtableParsers[3] = function parseLookup3() {
|
|
return { error: 'GPOS Lookup 3 not supported' };
|
|
};
|
|
subtableParsers[4] = function parseLookup4() {
|
|
return { error: 'GPOS Lookup 4 not supported' };
|
|
};
|
|
subtableParsers[5] = function parseLookup5() {
|
|
return { error: 'GPOS Lookup 5 not supported' };
|
|
};
|
|
subtableParsers[6] = function parseLookup6() {
|
|
return { error: 'GPOS Lookup 6 not supported' };
|
|
};
|
|
subtableParsers[7] = function parseLookup7() {
|
|
return { error: 'GPOS Lookup 7 not supported' };
|
|
};
|
|
subtableParsers[8] = function parseLookup8() {
|
|
return { error: 'GPOS Lookup 8 not supported' };
|
|
};
|
|
subtableParsers[9] = function parseLookup9() {
|
|
return { error: 'GPOS Lookup 9 not supported' };
|
|
};
|
|
|
|
// https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
|
|
function parseGposTable(data, start) {
|
|
start = start || 0;
|
|
const p = new Parser(data, start);
|
|
const tableVersion = p.parseVersion(1);
|
|
check.argument(
|
|
tableVersion === 1 || tableVersion === 1.1,
|
|
'Unsupported GPOS table version ' + tableVersion
|
|
);
|
|
|
|
if (tableVersion === 1) {
|
|
return {
|
|
version: tableVersion,
|
|
scripts: p.parseScriptList(),
|
|
features: p.parseFeatureList(),
|
|
lookups: p.parseLookupList(subtableParsers),
|
|
};
|
|
} else {
|
|
return {
|
|
version: tableVersion,
|
|
scripts: p.parseScriptList(),
|
|
features: p.parseFeatureList(),
|
|
lookups: p.parseLookupList(subtableParsers),
|
|
variations: p.parseFeatureVariationsList(),
|
|
};
|
|
}
|
|
}
|
|
|
|
export default { parse: parseGposTable };
|