maxp.cc (3337B)
1 // Copyright (c) 2009-2017 The OTS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "maxp.h" 6 7 // maxp - Maximum Profile 8 // http://www.microsoft.com/typography/otspec/maxp.htm 9 10 namespace ots { 11 12 bool OpenTypeMAXP::Parse(const uint8_t *data, size_t length) { 13 Buffer table(data, length); 14 15 uint32_t version = 0; 16 if (!table.ReadU32(&version)) { 17 return Error("Failed to read table version"); 18 } 19 20 if (version >> 16 > 1) { 21 return Error("Unsupported table version 0x%x", version); 22 } 23 24 if (!table.ReadU16(&this->num_glyphs)) { 25 return Error("Failed to read numGlyphs"); 26 } 27 28 if (!this->num_glyphs) { 29 return Error("numGlyphs is 0"); 30 } 31 32 this->version_1 = false; 33 34 // Per https://learn.microsoft.com/en-gb/typography/opentype/spec/maxp, 35 // the only two 'maxp' version numbers are 0.5 (for CFF/CFF2) and 1.0 36 // (for TrueType). 37 // If it's version 0.5, there is nothing more to read. 38 if (version == 0x00005000) { 39 return true; 40 } 41 42 if (version != 0x00010000) { 43 Warning("Unexpected version 0x%08x; attempting to read as version 1.0", 44 version); 45 } 46 47 // Otherwise, try to read the version 1.0 fields: 48 if (!table.ReadU16(&this->max_points) || 49 !table.ReadU16(&this->max_contours) || 50 !table.ReadU16(&this->max_c_points) || 51 !table.ReadU16(&this->max_c_contours) || 52 !table.ReadU16(&this->max_zones) || 53 !table.ReadU16(&this->max_t_points) || 54 !table.ReadU16(&this->max_storage) || 55 !table.ReadU16(&this->max_fdefs) || 56 !table.ReadU16(&this->max_idefs) || 57 !table.ReadU16(&this->max_stack) || 58 !table.ReadU16(&this->max_size_glyf_instructions) || 59 !table.ReadU16(&this->max_c_components) || 60 !table.ReadU16(&this->max_c_depth)) { 61 Warning("Failed to read version 1.0 fields, downgrading to version 0.5"); 62 return true; 63 } 64 65 this->version_1 = true; 66 67 if (this->max_zones < 1) { 68 // workaround for ipa*.ttf Japanese fonts. 69 Warning("Bad maxZones: %u", this->max_zones); 70 this->max_zones = 1; 71 } else if (this->max_zones > 2) { 72 // workaround for Ecolier-*.ttf fonts and bad fonts in some PDFs 73 Warning("Bad maxZones: %u", this->max_zones); 74 this->max_zones = 2; 75 } 76 77 return true; 78 } 79 80 bool OpenTypeMAXP::Serialize(OTSStream *out) { 81 if (!out->WriteU32(this->version_1 ? 0x00010000 : 0x00005000) || 82 !out->WriteU16(this->num_glyphs)) { 83 return Error("Failed to write version or numGlyphs"); 84 } 85 86 if (!this->version_1) return true; 87 88 if (!out->WriteU16(this->max_points) || 89 !out->WriteU16(this->max_contours) || 90 !out->WriteU16(this->max_c_points) || 91 !out->WriteU16(this->max_c_contours)) { 92 return Error("Failed to write maxp"); 93 } 94 95 if (!out->WriteU16(this->max_zones) || 96 !out->WriteU16(this->max_t_points) || 97 !out->WriteU16(this->max_storage) || 98 !out->WriteU16(this->max_fdefs) || 99 !out->WriteU16(this->max_idefs) || 100 !out->WriteU16(this->max_stack) || 101 !out->WriteU16(this->max_size_glyf_instructions)) { 102 return Error("Failed to write more maxp"); 103 } 104 105 if (!out->WriteU16(this->max_c_components) || 106 !out->WriteU16(this->max_c_depth)) { 107 return Error("Failed to write yet more maxp"); 108 } 109 110 return true; 111 } 112 113 } // namespace ots