gdef.cc (12544B)
1 // Copyright (c) 2011-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 "gdef.h" 6 7 #include <limits> 8 #include <vector> 9 10 #include "gpos.h" 11 #include "gsub.h" 12 #include "layout.h" 13 #include "maxp.h" 14 #include "variations.h" 15 16 // GDEF - The Glyph Definition Table 17 // http://www.microsoft.com/typography/otspec/gdef.htm 18 19 namespace { 20 21 // The maximum class value in the glyph class definision table. 22 const uint16_t kMaxGlyphClassDefValue = 4; 23 // The maximum format number of caret value tables. 24 const uint16_t kMaxCaretValueFormat = 3; 25 26 } // namespace 27 28 namespace ots { 29 30 bool OpenTypeGDEF::ParseAttachListTable(const uint8_t *data, size_t length) { 31 ots::Buffer subtable(data, length); 32 33 uint16_t offset_coverage = 0; 34 uint16_t glyph_count = 0; 35 if (!subtable.ReadU16(&offset_coverage) || 36 !subtable.ReadU16(&glyph_count)) { 37 return Error("Failed to read gdef header"); 38 } 39 const unsigned attach_points_end = 40 2 * static_cast<unsigned>(glyph_count) + 4; 41 if (attach_points_end > std::numeric_limits<uint16_t>::max()) { 42 return Error("Bad glyph count in gdef"); 43 } 44 if (offset_coverage == 0 || offset_coverage >= length || 45 offset_coverage < attach_points_end) { 46 return Error("Bad coverage offset %d", offset_coverage); 47 } 48 if (glyph_count > this->m_num_glyphs) { 49 return Error("Bad glyph count %u", glyph_count); 50 } 51 52 std::vector<uint16_t> attach_points; 53 attach_points.resize(glyph_count); 54 for (unsigned i = 0; i < glyph_count; ++i) { 55 if (!subtable.ReadU16(&attach_points[i])) { 56 return Error("Can't read attachment point %d", i); 57 } 58 if (attach_points[i] >= length || 59 attach_points[i] < attach_points_end) { 60 return Error("Bad attachment point %d of %d", i, attach_points[i]); 61 } 62 } 63 64 // Parse coverage table 65 if (!ots::ParseCoverageTable(GetFont(), data + offset_coverage, 66 length - offset_coverage, this->m_num_glyphs)) { 67 return Error("Bad coverage table"); 68 } 69 70 // Parse attach point table 71 for (unsigned i = 0; i < attach_points.size(); ++i) { 72 subtable.set_offset(attach_points[i]); 73 uint16_t point_count = 0; 74 if (!subtable.ReadU16(&point_count)) { 75 return Error("Can't read point count %d", i); 76 } 77 if (point_count == 0) { 78 return Error("zero point count %d", i); 79 } 80 uint16_t last_point_index = 0; 81 uint16_t point_index = 0; 82 for (unsigned j = 0; j < point_count; ++j) { 83 if (!subtable.ReadU16(&point_index)) { 84 return Error("Can't read point index %d in point %d", j, i); 85 } 86 // Contour point indices are in increasing numerical order 87 if (last_point_index != 0 && last_point_index >= point_index) { 88 return Error("bad contour indices: %u >= %u", 89 last_point_index, point_index); 90 } 91 last_point_index = point_index; 92 } 93 } 94 return true; 95 } 96 97 bool OpenTypeGDEF::ParseLigCaretListTable(const uint8_t *data, size_t length) { 98 ots::Buffer subtable(data, length); 99 uint16_t offset_coverage = 0; 100 uint16_t lig_glyph_count = 0; 101 if (!subtable.ReadU16(&offset_coverage) || 102 !subtable.ReadU16(&lig_glyph_count)) { 103 return Error("Can't read caret structure"); 104 } 105 const unsigned lig_glyphs_end = 106 2 * static_cast<unsigned>(lig_glyph_count) + 4; 107 if (lig_glyphs_end > std::numeric_limits<uint16_t>::max()) { 108 return Error("Bad caret structure"); 109 } 110 if (offset_coverage == 0 || offset_coverage >= length || 111 offset_coverage < lig_glyphs_end) { 112 return Error("Bad caret coverate offset %d", offset_coverage); 113 } 114 if (lig_glyph_count > this->m_num_glyphs) { 115 return Error("bad ligature glyph count: %u", lig_glyph_count); 116 } 117 118 std::vector<uint16_t> lig_glyphs; 119 lig_glyphs.resize(lig_glyph_count); 120 for (unsigned i = 0; i < lig_glyph_count; ++i) { 121 if (!subtable.ReadU16(&lig_glyphs[i])) { 122 return Error("Can't read ligature glyph location %d", i); 123 } 124 if (lig_glyphs[i] >= length || lig_glyphs[i] < lig_glyphs_end) { 125 return Error("Bad ligature glyph location %d in glyph %d", lig_glyphs[i], i); 126 } 127 } 128 129 // Parse coverage table 130 if (!ots::ParseCoverageTable(GetFont(), data + offset_coverage, 131 length - offset_coverage, this->m_num_glyphs)) { 132 return Error("Can't parse caret coverage table"); 133 } 134 135 // Parse ligature glyph table 136 for (unsigned i = 0; i < lig_glyphs.size(); ++i) { 137 subtable.set_offset(lig_glyphs[i]); 138 uint16_t caret_count = 0; 139 if (!subtable.ReadU16(&caret_count)) { 140 return Error("Can't read caret count for glyph %d", i); 141 } 142 if (caret_count == 0) { 143 return Error("bad caret value count: %u", caret_count); 144 } 145 146 std::vector<uint16_t> caret_value_offsets; 147 caret_value_offsets.resize(caret_count); 148 unsigned caret_value_offsets_end = 2 * static_cast<unsigned>(caret_count) + 2; 149 for (unsigned j = 0; j < caret_count; ++j) { 150 if (!subtable.ReadU16(&caret_value_offsets[j])) { 151 return Error("Can't read caret offset %d for glyph %d", j, i); 152 } 153 if (caret_value_offsets[j] >= length || caret_value_offsets[j] < caret_value_offsets_end) { 154 return Error("Bad caret offset %d for caret %d glyph %d", caret_value_offsets[j], j, i); 155 } 156 } 157 158 // Parse caret values table 159 for (unsigned j = 0; j < caret_count; ++j) { 160 subtable.set_offset(lig_glyphs[i] + caret_value_offsets[j]); 161 uint16_t caret_format = 0; 162 if (!subtable.ReadU16(&caret_format)) { 163 return Error("Can't read caret values table %d in glyph %d", j, i); 164 } 165 if (caret_format == 0 || caret_format > kMaxCaretValueFormat) { 166 return Error("bad caret value format: %u", caret_format); 167 } 168 // CaretValueFormats contain a 2-byte field which could be 169 // arbitrary value. 170 if (!subtable.Skip(2)) { 171 return Error("Bad caret value table structure %d in glyph %d", j, i); 172 } 173 if (caret_format == 3) { 174 uint16_t offset_device = 0; 175 if (!subtable.ReadU16(&offset_device)) { 176 return Error("Can't read device offset for caret value %d " 177 "in glyph %d", j, i); 178 } 179 size_t absolute_offset = lig_glyphs[i] + caret_value_offsets[j] 180 + offset_device; 181 if (offset_device == 0 || absolute_offset >= length) { 182 return Error("Bad device offset for caret value %d in glyph %d: %d", 183 j, i, offset_device); 184 } 185 if (!ots::ParseDeviceTable(GetFont(), data + absolute_offset, 186 length - absolute_offset)) { 187 return Error("Bad device table for caret value %d in glyph %d", 188 j, i, offset_device); 189 } 190 } 191 } 192 } 193 return true; 194 } 195 196 bool OpenTypeGDEF::ParseMarkGlyphSetsDefTable(const uint8_t *data, size_t length) { 197 ots::Buffer subtable(data, length); 198 uint16_t format = 0; 199 uint16_t mark_set_count = 0; 200 if (!subtable.ReadU16(&format) || 201 !subtable.ReadU16(&mark_set_count)) { 202 return Error("Can' read mark glyph table structure"); 203 } 204 if (format != 1) { 205 return Error("bad mark glyph set table format: %u", format); 206 } 207 208 const unsigned mark_sets_end = 2 * static_cast<unsigned>(mark_set_count) + 4; 209 if (mark_sets_end > std::numeric_limits<uint16_t>::max()) { 210 return Error("Bad mark_set %d", mark_sets_end); 211 } 212 for (unsigned i = 0; i < mark_set_count; ++i) { 213 uint32_t offset_coverage = 0; 214 if (!subtable.ReadU32(&offset_coverage)) { 215 return Error("Can't read covrage location for mark set %d", i); 216 } 217 if (offset_coverage >= length || 218 offset_coverage < mark_sets_end) { 219 return Error("Bad coverage location %d for mark set %d", offset_coverage, i); 220 } 221 if (!ots::ParseCoverageTable(GetFont(), data + offset_coverage, 222 length - offset_coverage, this->m_num_glyphs)) { 223 return Error("Failed to parse coverage table for mark set %d", i); 224 } 225 } 226 this->num_mark_glyph_sets = mark_set_count; 227 return true; 228 } 229 230 bool OpenTypeGDEF::Parse(const uint8_t *data, size_t length) { 231 OpenTypeMAXP *maxp = static_cast<OpenTypeMAXP*>( 232 GetFont()->GetTypedTable(OTS_TAG_MAXP)); 233 234 // Grab the number of glyphs in the font from the maxp table to check 235 // GlyphIDs in GDEF table. 236 if (!maxp) { 237 return Error("No maxp table in font, needed by GDEF"); 238 } 239 this->m_num_glyphs = maxp->num_glyphs; 240 241 Buffer table(data, length); 242 243 uint16_t version_major = 0, version_minor = 0; 244 if (!table.ReadU16(&version_major) || 245 !table.ReadU16(&version_minor)) { 246 return Error("Incomplete table"); 247 } 248 if (version_major != 1 || version_minor == 1) { // there is no v1.1 249 return Error("Bad version"); 250 } 251 252 uint16_t offset_glyph_class_def = 0; 253 uint16_t offset_attach_list = 0; 254 uint16_t offset_lig_caret_list = 0; 255 uint16_t offset_mark_attach_class_def = 0; 256 if (!table.ReadU16(&offset_glyph_class_def) || 257 !table.ReadU16(&offset_attach_list) || 258 !table.ReadU16(&offset_lig_caret_list) || 259 !table.ReadU16(&offset_mark_attach_class_def)) { 260 return Error("Incomplete table"); 261 } 262 uint16_t offset_mark_glyph_sets_def = 0; 263 if (version_minor >= 2) { 264 if (!table.ReadU16(&offset_mark_glyph_sets_def)) { 265 return Error("Incomplete table"); 266 } 267 } 268 uint32_t item_var_store_offset = 0; 269 if (version_minor >= 3) { 270 if (!table.ReadU32(&item_var_store_offset)) { 271 return Error("Incomplete table"); 272 } 273 } 274 275 unsigned gdef_header_end = 4 + 4 * 2; 276 if (version_minor >= 2) 277 gdef_header_end += 2; 278 if (version_minor >= 3) 279 gdef_header_end += 4; 280 281 // Parse subtables 282 if (offset_glyph_class_def) { 283 if (offset_glyph_class_def >= length || 284 offset_glyph_class_def < gdef_header_end) { 285 return Error("Invalid offset to glyph classes"); 286 } 287 if (!ots::ParseClassDefTable(GetFont(), data + offset_glyph_class_def, 288 length - offset_glyph_class_def, 289 this->m_num_glyphs, kMaxGlyphClassDefValue)) { 290 return Error("Invalid glyph classes"); 291 } 292 } 293 294 if (offset_attach_list) { 295 if (offset_attach_list >= length || 296 offset_attach_list < gdef_header_end) { 297 return Error("Invalid offset to attachment list"); 298 } 299 if (!ParseAttachListTable(data + offset_attach_list, 300 length - offset_attach_list)) { 301 return Error("Invalid attachment list"); 302 } 303 } 304 305 if (offset_lig_caret_list) { 306 if (offset_lig_caret_list >= length || 307 offset_lig_caret_list < gdef_header_end) { 308 return Error("Invalid offset to ligature caret list"); 309 } 310 if (!ParseLigCaretListTable(data + offset_lig_caret_list, 311 length - offset_lig_caret_list)) { 312 return Error("Invalid ligature caret list"); 313 } 314 } 315 316 if (offset_mark_attach_class_def) { 317 if (offset_mark_attach_class_def >= length || 318 offset_mark_attach_class_def < gdef_header_end) { 319 return Error("Invalid offset to mark attachment list"); 320 } 321 if (!ots::ParseClassDefTable(GetFont(), 322 data + offset_mark_attach_class_def, 323 length - offset_mark_attach_class_def, 324 this->m_num_glyphs, kMaxClassDefValue)) { 325 return Error("Invalid mark attachment list"); 326 } 327 } 328 329 if (offset_mark_glyph_sets_def) { 330 if (offset_mark_glyph_sets_def >= length || 331 offset_mark_glyph_sets_def < gdef_header_end) { 332 return Error("invalid offset to mark glyph sets"); 333 } 334 if (!ParseMarkGlyphSetsDefTable(data + offset_mark_glyph_sets_def, 335 length - offset_mark_glyph_sets_def)) { 336 return Error("Invalid mark glyph sets"); 337 } 338 } 339 340 if (item_var_store_offset) { 341 if (item_var_store_offset >= length || 342 item_var_store_offset < gdef_header_end) { 343 return Error("invalid offset to item variation store"); 344 } 345 if (!ParseItemVariationStore(GetFont(), data + item_var_store_offset, 346 length - item_var_store_offset)) { 347 return Error("Invalid item variation store"); 348 } 349 } 350 351 this->m_data = data; 352 this->m_length = length; 353 return true; 354 } 355 356 bool OpenTypeGDEF::Serialize(OTSStream *out) { 357 if (!out->Write(this->m_data, this->m_length)) { 358 return Error("Failed to write table"); 359 } 360 361 return true; 362 } 363 364 } // namespace ots