diff --git a/src/maxp.cc b/src/maxp.cc index 232e4a98..59b98cd7 100644 --- a/src/maxp.cc +++ b/src/maxp.cc @@ -29,6 +29,23 @@ bool OpenTypeMAXP::Parse(const uint8_t *data, size_t length) { return Error("numGlyphs is 0"); } + // Per https://learn.microsoft.com/en-gb/typography/opentype/spec/maxp, + // the only two 'maxp' version numbers are 0.5 (for CFF/CFF2) and 1.0 + // (for TrueType). + if (version == 0x00005000) { + this->version_1 = false; + return true; + } + + if (version != 0x00010000) { + Warning("Unrecognized version %08x, attempting to fix", version); + // If there's at least enough data to read as a version 1.0 table, + // we'll try that. + if (length >= 32) { + version = 0x00010000; + } + } + if (version >> 16 == 1) { this->version_1 = true; if (!table.ReadU16(&this->max_points) || @@ -47,19 +64,15 @@ bool OpenTypeMAXP::Parse(const uint8_t *data, size_t length) { return Error("Failed to read version 1 table data"); } - if (this->max_zones == 0) { + if (this->max_zones < 1) { // workaround for ipa*.ttf Japanese fonts. Warning("Bad maxZones: %u", this->max_zones); this->max_zones = 1; - } else if (this->max_zones == 3) { - // workaround for Ecolier-*.ttf fonts. + } else if (this->max_zones > 2) { + // workaround for Ecolier-*.ttf fonts and bad fonts in some PDFs Warning("Bad maxZones: %u", this->max_zones); this->max_zones = 2; } - - if ((this->max_zones != 1) && (this->max_zones != 2)) { - return Error("Bad maxZones: %u", this->max_zones); - } } else { this->version_1 = false; } diff --git a/src/ots.cc b/src/ots.cc index cefd390a..ed22b8cc 100644 --- a/src/ots.cc +++ b/src/ots.cc @@ -762,12 +762,18 @@ bool ProcessGeneric(ots::FontFile *header, ots::Table *loca = font->GetTable(OTS_TAG_LOCA); ots::Table *cff = font->GetTable(OTS_TAG_CFF); ots::Table *cff2 = font->GetTable(OTS_TAG_CFF2); + ots::OpenTypeMAXP *maxp = static_cast( + font->GetTypedTable(OTS_TAG_MAXP)); if (glyf && loca) { if (font->version != 0x000010000) { OTS_WARNING_MSG_HDR("wrong sfntVersion for glyph data"); font->version = 0x000010000; } + if (!maxp->version_1) { + return OTS_FAILURE_MSG_TAG("wrong maxp version for glyph data", + OTS_TAG_MAXP); + } if (cff) cff->Drop("font contains both CFF and glyf/loca tables"); if (cff2) @@ -781,6 +787,10 @@ bool ProcessGeneric(ots::FontFile *header, glyf->Drop("font contains both CFF and glyf tables"); if (loca) loca->Drop("font contains both CFF and loca tables"); + if (maxp->version_1) { + OTS_WARNING_MSG_HDR("fixing incorrect maxp version for CFF font"); + maxp->version_1 = false; + } } else if (font->GetTable(OTS_TAG('C','B','D','T')) && font->GetTable(OTS_TAG('C','B','L','C'))) { // We don't sanitize bitmap tables, but don’t reject bitmap-only fonts if