head.cc (3526B)
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 "head.h" 6 7 #include <cstring> 8 9 // head - Font Header 10 // http://www.microsoft.com/typography/otspec/head.htm 11 12 namespace ots { 13 14 bool OpenTypeHEAD::Parse(const uint8_t *data, size_t length) { 15 Buffer table(data, length); 16 17 uint32_t version = 0; 18 if (!table.ReadU32(&version) || 19 !table.ReadU32(&this->revision)) { 20 return Error("Failed to read table header"); 21 } 22 23 if (version >> 16 != 1) { 24 return Error("Unsupported majorVersion: %d", version >> 16); 25 } 26 27 // Skip the checksum adjustment 28 if (!table.Skip(4)) { 29 return Error("Failed to read checksum"); 30 } 31 32 uint32_t magic; 33 if (!table.ReadU32(&magic) || magic != 0x5F0F3CF5) { 34 return Error("Failed to read or incorrect magicNumber"); 35 } 36 37 if (!table.ReadU16(&this->flags)) { 38 return Error("Failed to read flags"); 39 } 40 41 // We allow bits 0..4, 11..13 42 this->flags &= 0x381f; 43 44 if (!table.ReadU16(&this->upem)) { 45 return Error("Failed to read unitsPerEm"); 46 } 47 48 // upem must be in range 49 if (this->upem < 16 || 50 this->upem > 16384) { 51 return Error("unitsPerEm on in the range [16, 16384]: %d", this->upem); 52 } 53 54 if (!table.ReadR64(&this->created) || 55 !table.ReadR64(&this->modified)) { 56 return Error("Can't read font dates"); 57 } 58 59 if (!table.ReadS16(&this->xmin) || 60 !table.ReadS16(&this->ymin) || 61 !table.ReadS16(&this->xmax) || 62 !table.ReadS16(&this->ymax)) { 63 return Error("Failed to read font bounding box"); 64 } 65 66 if (this->xmin > this->xmax) { 67 return Error("Bad x dimension in the font bounding box (%d, %d)", 68 this->xmin, this->xmax); 69 } 70 if (this->ymin > this->ymax) { 71 return Error("Bad y dimension in the font bounding box (%d, %d)", 72 this->ymin, this->ymax); 73 } 74 75 if (!table.ReadU16(&this->mac_style)) { 76 return Error("Failed to read macStyle"); 77 } 78 79 // We allow bits 0..6 80 this->mac_style &= 0x7f; 81 82 if (!table.ReadU16(&this->min_ppem)) { 83 return Error("Failed to read lowestRecPPEM"); 84 } 85 86 // We don't care about the font direction hint 87 if (!table.Skip(2)) { 88 return Error("Failed to read fontDirectionHint"); 89 } 90 91 if (!table.ReadS16(&this->index_to_loc_format)) { 92 return Error("Failed to read indexToLocFormat"); 93 } 94 if (this->index_to_loc_format < 0 || 95 this->index_to_loc_format > 1) { 96 return Error("Bad indexToLocFormat %d", this->index_to_loc_format); 97 } 98 99 int16_t glyph_data_format; 100 if (!table.ReadS16(&glyph_data_format) || 101 glyph_data_format) { 102 return Error("Failed to read or bad glyphDataFormat"); 103 } 104 105 return true; 106 } 107 108 bool OpenTypeHEAD::Serialize(OTSStream *out) { 109 if (!out->WriteU32(0x00010000) || 110 !out->WriteU32(this->revision) || 111 !out->WriteU32(0) || // check sum not filled in yet 112 !out->WriteU32(0x5F0F3CF5) || 113 !out->WriteU16(this->flags) || 114 !out->WriteU16(this->upem) || 115 !out->WriteR64(this->created) || 116 !out->WriteR64(this->modified) || 117 !out->WriteS16(this->xmin) || 118 !out->WriteS16(this->ymin) || 119 !out->WriteS16(this->xmax) || 120 !out->WriteS16(this->ymax) || 121 !out->WriteU16(this->mac_style) || 122 !out->WriteU16(this->min_ppem) || 123 !out->WriteS16(2) || 124 !out->WriteS16(this->index_to_loc_format) || 125 !out->WriteS16(0)) { 126 return Error("Failed to write table"); 127 } 128 129 return true; 130 } 131 132 } // namespace