Closed Pomax closed 3 years ago
The current code technically gives access to all alternatesets, but it doesn't "pregenerate" them:
class LookupType3 extends LookupType {
constructor(p) {
super(p);
this.alternateSetCount = p.uint16;
this.alternateSetOffsets = [...new Array(this.alternateSetCount)].map(
(_) => p.Offset16
);
}
getAlternateSet(index) {
let p = this.parser;
p.currentPosition = this.start + this.alternateSetOffsets[index];
return new AlternateSetTable(p);
}
}
class AlternateSetTable {
constructor(p) {
this.glyphCount = p.uint16;
this.alternateGlyphIDs = [...new Array(this.glyphCount)].map(
(_) => p.uint16
);
}
}
So the "immediately" option is to go "check which format it is, the know you need to access alternateSetCount
and for-loop your way to the data" but that's kind of crummy, and all GSUB formats should have some kind of same-named function to get the "payloads" that each points to.
I've set up https://github.com/Pomax/Font.js/blob/master/testing/node/athena.ruby.test.js as a convenient file to do Athena Ruby related testing.
Looking at what code would currently be required, we see this:
/**
* Given a script/lang/feature/lookup combination that is type 3:
*/
function lookup3Alternates(font, script, lang, feature, lookupId, lookup) {
if (lookup.lookupType !== 3) return;
// for argument's sake, let's only focus on lookupid=15 used by cv01
if (lookupId !== 15) return;
// get the subtable (we happen to know there's only 1 but we could
// run this iteratively using lookup.subTableCount, too)
const subtable = lookup.getSubTable(0);
// get the first (and only) alternates set and coverage it applies to.
// again, we know there's only 1 but we could run this iteratively
// using subtable.alternateSetCount
const altset = subtable.getAlternateSet(0);
const coverage = subtable.getCoverageTable(0);
console.log(subtable, coverage, altset);
}
This yields:
LookupType3 {
substFormat: 1,
coverageOffset: 64,
alternateSetCount: 1,
alternateSetOffsets: [ 8 ]
}
CoverageTable {
coverageFormat: 1,
glyphCount: 1,
glyphArray: [ 4 ]
}
AlternateSetTable {
glyphCount: 27,
alternateGlyphIDs: [
5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31
]
}
So it's not a matter of "the data is inaccessible", but really more "how low level vs. high level do we make the API"?
Updating the post
table to yield glyph names, the following code in lookup3Alternates
:
const getGlyphName = id => font.opentype.tables.post.getGlyphName(id);
console.log(getGlyphName(coverage.glyphArray[0]), `⇒`, altset.alternateGlyphIDs.map(getGlyphName));
yields
Alpha ⇒ [
'Alpha.1', 'Alpha.2', 'Alpha.3',
'Alpha.4', 'Alpha.5', 'Alpha.6',
'Alpha.7', 'Alpha.8', 'Alpha.9',
'Alpha.10', 'Alpha.11', 'Alpha.12',
'Alpha.13', 'Alpha.14', 'Alpha.15',
'Alpha.16', 'Alpha.17', 'Alpha.18',
'Alpha.19', 'Alpha.20', 'Alpha.21',
'Alpha.22', 'Alpha.23', 'Alpha.24',
'Alpha.25', 'Alpha.26', 'Alpha.27'
]
Awesome work, thanks!
I don't need the individual glyphs for Wakamai Fondue, as its modus operandi is to take the input character and then let the browser show all variants through applying the proper CSS.
Relevant WF PR: https://github.com/Wakamai-Fondue/wakamai-fondue-site/pull/91 Works like advertised, thanks again! My regular test fonts are all shown correctly.
nice, in that case I'll close this but mark it as some code that might work as a recipe.
The snippet above was very helpful, so a great candidate for a recipe!
I grabbed a copy of the font and have stubbed a new test file for it, but if anyone has additional details they want to drop into this issue to make sure the right things come out of that test: please do =)