-
-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lookuptype 6 tests #105
Comments
substFormat 3 doesn't have additional function, it already parses everything in the constructor, as per https://github.com/Pomax/Font.js/blob/master/src/opentype/tables/advanced/shared/subtables/gsub.js#L281-L297, you can directly consult However, there is no coverage format 3. Only versions 1 and 2 exist, so that looks like a genuine bug. |
Ah, I was thinking this referred to the Chained Sequence Context Format |
Time to figure out why the CoverageTable format is so very wrong. Step one: does |
Updating your code to include the lookup number and subtable format: ...
lookupIDs.forEach((id) => {
const lookup = GSUB.getLookup(id);
// Only dump lookup type 6 for DFLT/dflt
if (lookup.lookupType === 6 && lang === "dflt") {
console.log(`--- lookup type 6 in dflt, lookup ${id}`);
for (let i = 0; i < lookup.subTableCount; i++) {
const subtable = lookup.getSubTable(i);
console.log(` - subtable ${subtable.substFormat}`)
const coverage = subtable.getCoverageTable();
console.log(` `, coverage);
}
}
});
});
});
});
};
so let's look at whether or not https://github.com/Pomax/lib-font/blob/master/src/opentype/tables/advanced/shared/subtables/gsub.js#L281-L299 is doing the right thing: if (this.substFormat === 3) {
this.backtrackGlyphCount = p.uint16;
this.backtrackCoverageOffsets = [
...new Array(this.backtrackGlyphCount),
].map((_) => p.Offset16);
this.inputGlyphCount = p.uint16;
this.inputCoverageOffsets = [...new Array(this.inputGlyphCount)].map(
(_) => p.Offset16
);
this.lookaheadGlyphCount = p.uint16;
this.lookaheadCoverageOffsets = [
...new Array(this.lookaheadGlyphCount),
].map((_) => p.Offset16);
this.substitutionCount = p.uint16;
this.substLookupRecords = [...new Array(this.substitutionCount)].map(
(_) => new SubstLookupRecord(p)
);
} This should match https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chseqctxt3:
The class LookupType extends ParsedData {
constructor(p) {
super(p);
this.substFormat = p.uint16;
this.coverageOffset = p.Offset16;
}
getCoverageTable() {
let p = this.parser;
p.currentPosition = this.start + this.coverageOffset;
return new CoverageTable(p);
}
} But we actually see this reading too much data. For substformat 3, the near universal LookupType 5, subtable format 3 is the only other data structure that does this, and has code in place to correct for reading ahead by two bytes, but LookupType 6 subtable format 3 does not: let's fix that. Adding the same correction: p.currentPosition -= 2;
delete this.coverageOffset; now yields:
So that looks pretty good @RoelN |
This seems to report |
Further updating: the 6.3 code was not complete, so I've updated that in 2ae18d9 and I've updated my test run code to: import { Font } from "./lib-font.js";
const font = new Font("boink");
font.src = `./fonts/Recursive_VF_1.064.ttf`;
// font.src = `./fonts/MehrNastaliqWeb-Regular.ttf`;
font.onload = (evt) => {
let font = evt.detail.font;
const { GSUB } = font.opentype.tables;
let scripts = GSUB.getSupportedScripts();
scripts.forEach((script) => {
let langsys = GSUB.getSupportedLangSys(script);
langsys.forEach((lang) => {
let langSysTable = GSUB.getLangSysTable(script, lang);
let features = GSUB.getFeatures(langSysTable);
features.forEach((feature) => {
const lookupIDs = feature.lookupListIndices;
lookupIDs.forEach((id) => {
const lookup = GSUB.getLookup(id);
// Only dump lookup type 6 for DFLT/dflt
if (lookup.lookupType === 6 && lang === "dflt") {
for(let i=0; i<lookup.subTableCount; i++) {
let subtable = lookup.getSubTable(i);
console.log(`=====================================================`);
console.log(`lookup type 6 in dflt, lookup ${id}, subtable ${i}`);
console.log(`=====================================================`);
if (subtable.backtrackGlyphCount > 0)
subtable.backtrackCoverageOffsets.forEach((offset, id) => {
let coverage = subtable.getCoverageFromOffset(offset);
console.log(`backtrack coverage ${id+1}:`, coverage);
});
if (subtable.lookaheadGlyphCount > 0)
subtable.lookaheadCoverageOffsets.forEach((offset, id) => {
let coverage = subtable.getCoverageFromOffset(offset);
console.log(`lookahead coverage ${id+1}:`, coverage);
});
subtable.seqLookupRecords.forEach(slRecord => {
console.log(`sequence lookup record:`, slRecord);
});
}
}
});
});
});
});
}; Which yields an insane amount of data, but of the form:
Which looks more in line with what the data should look like. the first backtrack rule maps to:
Which anecdotally feels like things make more sense now =) Confirming with TTX shows: <Lookup index="1">
<LookupType value="6"/>
<LookupFlag value="0"/>
<!-- SubTableCount=23 -->
<ChainContextSubst index="0" Format="3">
<!-- BacktrackGlyphCount=11 -->
<BacktrackCoverage index="0" Format="2">
<Glyph value="zero"/>
<Glyph value="one"/>
<Glyph value="two"/>
<Glyph value="three"/>
<Glyph value="four"/>
<Glyph value="five"/>
<Glyph value="six"/>
<Glyph value="seven"/>
<Glyph value="eight"/>
<Glyph value="nine"/>
<Glyph value="zero.sans"/>
</BacktrackCoverage>
<BacktrackCoverage index="1" Format="2">
<Glyph value="zero"/>
<Glyph value="one"/>
<Glyph value="two"/>
<Glyph value="three"/>
<Glyph value="four"/>
<Glyph value="five"/>
<Glyph value="six"/>
<Glyph value="seven"/>
<Glyph value="eight"/>
<Glyph value="nine"/>
<Glyph value="zero.sans"/>
</BacktrackCoverage> |
This is fantastic! Thanks a lot, @Pomax! For the record, I'm also logging the input coverage, so you have a complete picture of what goes "in" the substitution: if (subtable.inputGlyphCount > 0)
subtable.inputCoverageOffsets.forEach((offset, id) => {
let coverage = subtable.getCoverageFromOffset(offset);
console.log(`input coverage ${id+1}:`, coverage);
console.log("\n");
}); |
I'm testing as follows:
For Recusive, this outputs stuff like:
Which seems wrong.
If I understand https://github.com/Pomax/Font.js/blob/master/src/opentype/tables/advanced/shared/subtables/gsub.js#L301 correctly there's only getters for
substFormat
1 and 2, while most fonts I test with have asubstFormat
of 3.Dumping the subtable appears to provide valid data, if these offsets are supposed to jump around this much (from 1 to 1410, to 1, to 20, etc.)
Getting
backtrackCoverage
,inputCoverage
andlookaheadCoverage
with a list of glyphs sounds like what I could use for Wakamai Fondue. Is there a way to get to that?The text was updated successfully, but these errors were encountered: