diff --git a/src/features/featureQuery.js b/src/features/featureQuery.js index 4aead842..8c945baa 100644 --- a/src/features/featureQuery.js +++ b/src/features/featureQuery.js @@ -149,15 +149,27 @@ function chainingSubstitutionFormat3(contextParams, subtable) { const lookupListIndex = lookupRecord.lookupListIndex; const lookupTable = this.getLookupByIndex(lookupListIndex); for (let s = 0; s < lookupTable.subtables.length; s++) { - const subtable = lookupTable.subtables[s]; - const lookup = this.getLookupMethod(lookupTable, subtable); - const substitutionType = this.getSubstitutionType(lookupTable, subtable); + let subtable = lookupTable.subtables[s]; + let lookup; + let substitutionType = this.getSubstitutionType(lookupTable, subtable); + + if (substitutionType === '71') { + // This is an extension subtable, so lookup the target subtable + substitutionType = this.getSubstitutionType(subtable, subtable.extension); + lookup = this.getLookupMethod(subtable, subtable.extension); + subtable = subtable.extension; + } else { + lookup = this.getLookupMethod(lookupTable, subtable); + } + if (substitutionType === '12') { for (let n = 0; n < inputLookups.length; n++) { const glyphIndex = contextParams.get(n); const substitution = lookup(glyphIndex); if (substitution) substitutions.push(substitution); } + } else { + throw new Error(`Substitution type ${substitutionType} is not supported in chaining substitution`); } } } @@ -367,9 +379,19 @@ FeatureQuery.prototype.lookupFeature = function (query) { const lookupTable = lookups[l]; const subtables = this.getLookupSubtables(lookupTable); for (let s = 0; s < subtables.length; s++) { - const subtable = subtables[s]; - const substType = this.getSubstitutionType(lookupTable, subtable); - const lookup = this.getLookupMethod(lookupTable, subtable); + let subtable = subtables[s]; + let substType = this.getSubstitutionType(lookupTable, subtable); + let lookup; + + if (substType === '71') { + // This is an extension subtable, so lookup the target subtable + substType = this.getSubstitutionType(subtable, subtable.extension); + lookup = this.getLookupMethod(subtable, subtable.extension); + subtable = subtable.extension; + } else { + lookup = this.getLookupMethod(lookupTable, subtable); + } + let substitution; switch (substType) { case '11': diff --git a/test/tables/gsub.js b/test/tables/gsub.js index a788c5e8..f3ce0fa2 100644 --- a/test/tables/gsub.js +++ b/test/tables/gsub.js @@ -213,7 +213,28 @@ describe('tables/gsub.js', function() { // TODO (no example in the doc from Microsoft) //// Lookup type 7 //////////////////////////////////////////////////////// - // TODO (no example in the doc from Microsoft) + it('can parse lookup7 subtable format 1', function() { + + const data = + '00 01' + // substFormat + '00 01' + // extensionLookupType + '00 00 00 08' + // extensionOffset + '0001 0006 00C0 0002 0001 004E 0058 0000' // data equal to that from the lookup1 substFormat 1 test + ; + const parsed = parseLookup(7, data); + assert.deepEqual(parsed, { + extension: { // object equal to that from the lookup1 substFormat 1 test + substFormat: 1, + coverage: { + format: 2, + ranges: [{ start: 0x4e, end: 0x58, index: 0 }] + }, + deltaGlyphId: 0xc0 + }, + lookupType: 1, + substFormat: 1 + }); + }); //// Lookup type 8 //////////////////////////////////////////////////////// it('can parse lookup8', function() {