diff --git a/src/cff.cc b/src/cff.cc index af54a4a1..af6d1eb8 100644 --- a/src/cff.cc +++ b/src/cff.cc @@ -1250,6 +1250,11 @@ bool OpenTypeCFF::Parse(const uint8_t *data, size_t length) { if (!maxp) { return Error("Required maxp table missing"); } + if (maxp->version_1) { + Warning("Fixing incorrect maxp version for CFF font"); + maxp->version_1 = false; + } + const uint16_t num_glyphs = maxp->num_glyphs; const size_t sid_max = string_index.count + kNStdString; // string_index.count == 0 is allowed. 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; }