1 // Copyright (c) 2009 The Chromium 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 "os2.h" 6 7 #include "head.h" 8 9 // OS/2 - OS/2 and Windows Metrics 10 // http://www.microsoft.com/opentype/otspec/os2.htm 11 12 namespace ots { 13 14 bool ots_os2_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 15 Buffer table(data, length); 16 17 OpenTypeOS2 *os2 = new OpenTypeOS2; 18 file->os2 = os2; 19 20 if (!table.ReadU16(&os2->version) || 21 !table.ReadS16(&os2->avg_char_width) || 22 !table.ReadU16(&os2->weight_class) || 23 !table.ReadU16(&os2->width_class) || 24 !table.ReadU16(&os2->type) || 25 !table.ReadS16(&os2->subscript_x_size) || 26 !table.ReadS16(&os2->subscript_y_size) || 27 !table.ReadS16(&os2->subscript_x_offset) || 28 !table.ReadS16(&os2->subscript_y_offset) || 29 !table.ReadS16(&os2->superscript_x_size) || 30 !table.ReadS16(&os2->superscript_y_size) || 31 !table.ReadS16(&os2->superscript_x_offset) || 32 !table.ReadS16(&os2->superscript_y_offset) || 33 !table.ReadS16(&os2->strikeout_size) || 34 !table.ReadS16(&os2->strikeout_position) || 35 !table.ReadS16(&os2->family_class)) { 36 return OTS_FAILURE(); 37 } 38 39 if (os2->version > 4) { 40 return OTS_FAILURE(); 41 } 42 43 // Some linux fonts (e.g., Kedage-t.ttf and LucidaSansDemiOblique.ttf) have 44 // weird weight/width classes. Overwrite them with FW_NORMAL/1/9. 45 if (os2->weight_class < 100 || 46 os2->weight_class > 900 || 47 os2->weight_class % 100) { 48 OTS_WARNING("bad weight: %u", os2->weight_class); 49 os2->weight_class = 400; // FW_NORMAL 50 } 51 if (os2->width_class < 1) { 52 OTS_WARNING("bad width: %u", os2->width_class); 53 os2->width_class = 1; 54 } else if (os2->width_class > 9) { 55 OTS_WARNING("bad width: %u", os2->width_class); 56 os2->width_class = 9; 57 } 58 59 // lowest 3 bits of fsType are exclusive. 60 if (os2->type & 0x2) { 61 // mask bits 2 & 3. 62 os2->type &= 0xfff3u; 63 } else if (os2->type & 0x4) { 64 // mask bits 1 & 3. 65 os2->type &= 0xfff4u; 66 } else if (os2->type & 0x8) { 67 // mask bits 1 & 2. 68 os2->type &= 0xfff9u; 69 } 70 71 // mask reserved bits. use only 0..3, 8, 9 bits. 72 os2->type &= 0x30f; 73 74 if (os2->subscript_x_size < 0) { 75 OTS_WARNING("bad subscript_x_size: %d", os2->subscript_x_size); 76 os2->subscript_x_size = 0; 77 } 78 if (os2->subscript_y_size < 0) { 79 OTS_WARNING("bad subscript_y_size: %d", os2->subscript_y_size); 80 os2->subscript_y_size = 0; 81 } 82 if (os2->superscript_x_size < 0) { 83 OTS_WARNING("bad superscript_x_size: %d", os2->superscript_x_size); 84 os2->superscript_x_size = 0; 85 } 86 if (os2->superscript_y_size < 0) { 87 OTS_WARNING("bad superscript_y_size: %d", os2->superscript_y_size); 88 os2->superscript_y_size = 0; 89 } 90 if (os2->strikeout_size < 0) { 91 OTS_WARNING("bad strikeout_size: %d", os2->strikeout_size); 92 os2->strikeout_size = 0; 93 } 94 95 for (unsigned i = 0; i < 10; ++i) { 96 if (!table.ReadU8(&os2->panose[i])) { 97 return OTS_FAILURE(); 98 } 99 } 100 101 if (!table.ReadU32(&os2->unicode_range_1) || 102 !table.ReadU32(&os2->unicode_range_2) || 103 !table.ReadU32(&os2->unicode_range_3) || 104 !table.ReadU32(&os2->unicode_range_4) || 105 !table.ReadU32(&os2->vendor_id) || 106 !table.ReadU16(&os2->selection) || 107 !table.ReadU16(&os2->first_char_index) || 108 !table.ReadU16(&os2->last_char_index) || 109 !table.ReadS16(&os2->typo_ascender) || 110 !table.ReadS16(&os2->typo_descender) || 111 !table.ReadS16(&os2->typo_linegap) || 112 !table.ReadU16(&os2->win_ascent) || 113 !table.ReadU16(&os2->win_descent)) { 114 return OTS_FAILURE(); 115 } 116 117 // If bit 6 is set, then bits 0 and 5 must be clear. 118 if (os2->selection & 0x40) { 119 os2->selection &= 0xffdeu; 120 } 121 122 // the settings of bits 0 and 1 must be reflected in the macStyle bits 123 // in the 'head' table. 124 if (!file->head) { 125 return OTS_FAILURE(); 126 } 127 if ((os2->selection & 0x1) && 128 !(file->head->mac_style & 0x2)) { 129 OTS_WARNING("adjusting Mac style (italic)"); 130 file->head->mac_style |= 0x2; 131 } 132 if ((os2->selection & 0x2) && 133 !(file->head->mac_style & 0x4)) { 134 OTS_WARNING("adjusting Mac style (underscore)"); 135 file->head->mac_style |= 0x4; 136 } 137 138 // While bit 6 on implies that bits 0 and 1 of macStyle are clear, 139 // the reverse is not true. 140 if ((os2->selection & 0x40) && 141 (file->head->mac_style & 0x3)) { 142 OTS_WARNING("adjusting Mac style (regular)"); 143 file->head->mac_style &= 0xfffcu; 144 } 145 146 if ((os2->version < 4) && 147 (os2->selection & 0x300)) { 148 // bit 8 and 9 must be unset in OS/2 table versions less than 4. 149 return OTS_FAILURE(); 150 } 151 152 // mask reserved bits. use only 0..9 bits. 153 os2->selection &= 0x3ff; 154 155 if (os2->first_char_index > os2->last_char_index) { 156 return OTS_FAILURE(); 157 } 158 if (os2->typo_linegap < 0) { 159 OTS_WARNING("bad linegap: %d", os2->typo_linegap); 160 os2->typo_linegap = 0; 161 } 162 163 if (os2->version < 1) { 164 // http://www.microsoft.com/typography/otspec/os2ver0.htm 165 return true; 166 } 167 168 if (length < offsetof(OpenTypeOS2, code_page_range_2)) { 169 OTS_WARNING("bad version number: %u", os2->version); 170 // Some fonts (e.g., kredit1.ttf and quinquef.ttf) have weird version 171 // numbers. Fix them. 172 os2->version = 0; 173 return true; 174 } 175 176 if (!table.ReadU32(&os2->code_page_range_1) || 177 !table.ReadU32(&os2->code_page_range_2)) { 178 return OTS_FAILURE(); 179 } 180 181 if (os2->version < 2) { 182 // http://www.microsoft.com/typography/otspec/os2ver1.htm 183 return true; 184 } 185 186 if (length < offsetof(OpenTypeOS2, max_context)) { 187 OTS_WARNING("bad version number: %u", os2->version); 188 // some Japanese fonts (e.g., mona.ttf) have weird version number. 189 // fix them. 190 os2->version = 1; 191 return true; 192 } 193 194 if (!table.ReadS16(&os2->x_height) || 195 !table.ReadS16(&os2->cap_height) || 196 !table.ReadU16(&os2->default_char) || 197 !table.ReadU16(&os2->break_char) || 198 !table.ReadU16(&os2->max_context)) { 199 return OTS_FAILURE(); 200 } 201 202 if (os2->x_height < 0) { 203 OTS_WARNING("bad x_height: %d", os2->x_height); 204 os2->x_height = 0; 205 } 206 if (os2->cap_height < 0) { 207 OTS_WARNING("bad cap_height: %d", os2->cap_height); 208 os2->cap_height = 0; 209 } 210 211 return true; 212 } 213 214 bool ots_os2_should_serialise(OpenTypeFile *file) { 215 return file->os2 != NULL; 216 } 217 218 bool ots_os2_serialise(OTSStream *out, OpenTypeFile *file) { 219 const OpenTypeOS2 *os2 = file->os2; 220 221 if (!out->WriteU16(os2->version) || 222 !out->WriteS16(os2->avg_char_width) || 223 !out->WriteU16(os2->weight_class) || 224 !out->WriteU16(os2->width_class) || 225 !out->WriteU16(os2->type) || 226 !out->WriteS16(os2->subscript_x_size) || 227 !out->WriteS16(os2->subscript_y_size) || 228 !out->WriteS16(os2->subscript_x_offset) || 229 !out->WriteS16(os2->subscript_y_offset) || 230 !out->WriteS16(os2->superscript_x_size) || 231 !out->WriteS16(os2->superscript_y_size) || 232 !out->WriteS16(os2->superscript_x_offset) || 233 !out->WriteS16(os2->superscript_y_offset) || 234 !out->WriteS16(os2->strikeout_size) || 235 !out->WriteS16(os2->strikeout_position) || 236 !out->WriteS16(os2->family_class)) { 237 return OTS_FAILURE(); 238 } 239 240 for (unsigned i = 0; i < 10; ++i) { 241 if (!out->Write(&os2->panose[i], 1)) { 242 return OTS_FAILURE(); 243 } 244 } 245 246 if (!out->WriteU32(os2->unicode_range_1) || 247 !out->WriteU32(os2->unicode_range_2) || 248 !out->WriteU32(os2->unicode_range_3) || 249 !out->WriteU32(os2->unicode_range_4) || 250 !out->WriteU32(os2->vendor_id) || 251 !out->WriteU16(os2->selection) || 252 !out->WriteU16(os2->first_char_index) || 253 !out->WriteU16(os2->last_char_index) || 254 !out->WriteS16(os2->typo_ascender) || 255 !out->WriteS16(os2->typo_descender) || 256 !out->WriteS16(os2->typo_linegap) || 257 !out->WriteU16(os2->win_ascent) || 258 !out->WriteU16(os2->win_descent)) { 259 return OTS_FAILURE(); 260 } 261 262 if (os2->version < 1) { 263 return true; 264 } 265 266 if (!out->WriteU32(os2->code_page_range_1) || 267 !out->WriteU32(os2->code_page_range_2)) { 268 return OTS_FAILURE(); 269 } 270 271 if (os2->version < 2) { 272 return true; 273 } 274 275 if (!out->WriteS16(os2->x_height) || 276 !out->WriteS16(os2->cap_height) || 277 !out->WriteU16(os2->default_char) || 278 !out->WriteU16(os2->break_char) || 279 !out->WriteU16(os2->max_context)) { 280 return OTS_FAILURE(); 281 } 282 283 return true; 284 } 285 286 void ots_os2_free(OpenTypeFile *file) { 287 delete file->os2; 288 } 289 290 } // namespace ots 291