astro-ghostcms/.pnpm-store/v3/files/95/c92965b8342a5185e303903f18a...

252 lines
8.5 KiB
Plaintext

// The `GSUB` table contains ligatures, among other things.
// https://www.microsoft.com/typography/OTSPEC/gsub.htm
import check from '../check';
import { Parser } from '../parse';
const subtableParsers = new Array(9); // subtableParsers[0] is unused
// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS
subtableParsers[1] = function parseLookup1() {
const start = this.offset + this.relativeOffset;
const substFormat = this.parseUShort();
if (substFormat === 1) {
return {
substFormat: 1,
coverage: this.parsePointer(Parser.coverage),
deltaGlyphId: this.parseUShort(),
};
} else if (substFormat === 2) {
return {
substFormat: 2,
coverage: this.parsePointer(Parser.coverage),
substitute: this.parseOffset16List(),
};
}
check.assert(
false,
'0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.'
);
};
// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS
subtableParsers[2] = function parseLookup2() {
const substFormat = this.parseUShort();
check.argument(
substFormat === 1,
'GSUB Multiple Substitution Subtable identifier-format must be 1'
);
return {
substFormat: substFormat,
coverage: this.parsePointer(Parser.coverage),
sequences: this.parseListOfLists(),
};
};
// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS
subtableParsers[3] = function parseLookup3() {
const substFormat = this.parseUShort();
check.argument(
substFormat === 1,
'GSUB Alternate Substitution Subtable identifier-format must be 1'
);
return {
substFormat: substFormat,
coverage: this.parsePointer(Parser.coverage),
alternateSets: this.parseListOfLists(),
};
};
// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS
subtableParsers[4] = function parseLookup4() {
const substFormat = this.parseUShort();
check.argument(
substFormat === 1,
'GSUB ligature table identifier-format must be 1'
);
return {
substFormat: substFormat,
coverage: this.parsePointer(Parser.coverage),
ligatureSets: this.parseListOfLists(function () {
return {
ligGlyph: this.parseUShort(),
components: this.parseUShortList(this.parseUShort() - 1),
};
}),
};
};
const lookupRecordDesc = {
sequenceIndex: Parser.uShort,
lookupListIndex: Parser.uShort,
};
// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF
subtableParsers[5] = function parseLookup5() {
const start = this.offset + this.relativeOffset;
const substFormat = this.parseUShort();
if (substFormat === 1) {
return {
substFormat: substFormat,
coverage: this.parsePointer(Parser.coverage),
ruleSets: this.parseListOfLists(function () {
const glyphCount = this.parseUShort();
const substCount = this.parseUShort();
return {
input: this.parseUShortList(glyphCount - 1),
lookupRecords: this.parseRecordList(
substCount,
lookupRecordDesc
),
};
}),
};
} else if (substFormat === 2) {
return {
substFormat: substFormat,
coverage: this.parsePointer(Parser.coverage),
classDef: this.parsePointer(Parser.classDef),
classSets: this.parseListOfLists(function () {
const glyphCount = this.parseUShort();
const substCount = this.parseUShort();
return {
classes: this.parseUShortList(glyphCount - 1),
lookupRecords: this.parseRecordList(
substCount,
lookupRecordDesc
),
};
}),
};
} else if (substFormat === 3) {
const glyphCount = this.parseUShort();
const substCount = this.parseUShort();
return {
substFormat: substFormat,
coverages: this.parseList(
glyphCount,
Parser.pointer(Parser.coverage)
),
lookupRecords: this.parseRecordList(substCount, lookupRecordDesc),
};
}
check.assert(
false,
'0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.'
);
};
// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC
subtableParsers[6] = function parseLookup6() {
const start = this.offset + this.relativeOffset;
const substFormat = this.parseUShort();
if (substFormat === 1) {
return {
substFormat: 1,
coverage: this.parsePointer(Parser.coverage),
chainRuleSets: this.parseListOfLists(function () {
return {
backtrack: this.parseUShortList(),
input: this.parseUShortList(this.parseShort() - 1),
lookahead: this.parseUShortList(),
lookupRecords: this.parseRecordList(lookupRecordDesc),
};
}),
};
} else if (substFormat === 2) {
return {
substFormat: 2,
coverage: this.parsePointer(Parser.coverage),
backtrackClassDef: this.parsePointer(Parser.classDef),
inputClassDef: this.parsePointer(Parser.classDef),
lookaheadClassDef: this.parsePointer(Parser.classDef),
chainClassSet: this.parseListOfLists(function () {
return {
backtrack: this.parseUShortList(),
input: this.parseUShortList(this.parseShort() - 1),
lookahead: this.parseUShortList(),
lookupRecords: this.parseRecordList(lookupRecordDesc),
};
}),
};
} else if (substFormat === 3) {
return {
substFormat: 3,
backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),
inputCoverage: this.parseList(Parser.pointer(Parser.coverage)),
lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),
lookupRecords: this.parseRecordList(lookupRecordDesc),
};
}
check.assert(
false,
'0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.'
);
};
// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES
subtableParsers[7] = function parseLookup7() {
// Extension Substitution subtable
const substFormat = this.parseUShort();
check.argument(
substFormat === 1,
'GSUB Extension Substitution subtable identifier-format must be 1'
);
const extensionLookupType = this.parseUShort();
const extensionParser = new Parser(
this.data,
this.offset + this.parseULong()
);
return {
substFormat: 1,
lookupType: extensionLookupType,
extension: subtableParsers[extensionLookupType].call(extensionParser),
};
};
// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS
subtableParsers[8] = function parseLookup8() {
const substFormat = this.parseUShort();
check.argument(
substFormat === 1,
'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1'
);
return {
substFormat: substFormat,
coverage: this.parsePointer(Parser.coverage),
backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),
lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),
substitutes: this.parseUShortList(),
};
};
// https://www.microsoft.com/typography/OTSPEC/gsub.htm
function parseGsubTable(data, start) {
start = start || 0;
const p = new Parser(data, start);
const tableVersion = p.parseVersion(1);
check.argument(
tableVersion === 1 || tableVersion === 1.1,
'Unsupported GSUB table version.'
);
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: parseGsubTable };