glat.cc (15304B)
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 "glat.h" 6 7 #include "gloc.h" 8 #include "mozilla/Compression.h" 9 #include <list> 10 #include <memory> 11 12 namespace ots { 13 14 // ----------------------------------------------------------------------------- 15 // OpenTypeGLAT_v1 16 // ----------------------------------------------------------------------------- 17 18 bool OpenTypeGLAT_v1::Parse(const uint8_t* data, size_t length) { 19 Buffer table(data, length); 20 OpenTypeGLOC* gloc = static_cast<OpenTypeGLOC*>( 21 GetFont()->GetTypedTable(OTS_TAG_GLOC)); 22 if (!gloc) { 23 return DropGraphite("Required Gloc table is missing"); 24 } 25 26 if (!table.ReadU32(&this->version) || this->version >> 16 != 1) { 27 return DropGraphite("Failed to read version"); 28 } 29 30 const std::vector<uint32_t>& locations = gloc->GetLocations(); 31 if (locations.empty()) { 32 return DropGraphite("No locations from Gloc table"); 33 } 34 std::list<uint32_t> unverified(locations.begin(), locations.end()); 35 while (table.remaining()) { 36 GlatEntry entry(this); 37 if (table.offset() > unverified.front()) { 38 return DropGraphite("Offset check failed for a GlatEntry"); 39 } 40 if (table.offset() == unverified.front()) { 41 unverified.pop_front(); 42 } 43 if (unverified.empty()) { 44 return DropGraphite("Expected more locations"); 45 } 46 if (!entry.ParsePart(table)) { 47 return DropGraphite("Failed to read a GlatEntry"); 48 } 49 this->entries.push_back(entry); 50 } 51 52 if (unverified.size() != 1 || unverified.front() != table.offset()) { 53 return DropGraphite("%zu location(s) could not be verified", unverified.size()); 54 } 55 if (table.remaining()) { 56 return Warning("%zu bytes unparsed", table.remaining()); 57 } 58 return true; 59 } 60 61 bool OpenTypeGLAT_v1::Serialize(OTSStream* out) { 62 assert(ShouldSerialize()); 63 if (!out->WriteU32(this->version) || 64 !SerializeParts(this->entries, out)) { 65 return Error("Failed to write table"); 66 } 67 return true; 68 } 69 70 bool OpenTypeGLAT_v1::GlatEntry::ParsePart(Buffer& table) { 71 if (!table.ReadU8(&this->attNum)) { 72 return parent->Error("GlatEntry: Failed to read attNum"); 73 } 74 if (!table.ReadU8(&this->num)) { 75 return parent->Error("GlatEntry: Failed to read num"); 76 } 77 78 //this->attributes.resize(this->num); 79 for (int i = 0; i < this->num; ++i) { 80 this->attributes.emplace_back(); 81 if (!table.ReadS16(&this->attributes[i])) { 82 return parent->Error("GlatEntry: Failed to read attribute %u", i); 83 } 84 } 85 return true; 86 } 87 88 bool OpenTypeGLAT_v1::GlatEntry::SerializePart(OTSStream* out) const { 89 if (!out->WriteU8(this->attNum) || 90 !out->WriteU8(this->num) || 91 !SerializeParts(this->attributes, out)) { 92 return parent->Error("GlatEntry: Failed to write"); 93 } 94 return true; 95 } 96 97 // ----------------------------------------------------------------------------- 98 // OpenTypeGLAT_v2 99 // ----------------------------------------------------------------------------- 100 101 bool OpenTypeGLAT_v2::Parse(const uint8_t* data, size_t length) { 102 Buffer table(data, length); 103 OpenTypeGLOC* gloc = static_cast<OpenTypeGLOC*>( 104 GetFont()->GetTypedTable(OTS_TAG_GLOC)); 105 if (!gloc) { 106 return DropGraphite("Required Gloc table is missing"); 107 } 108 109 if (!table.ReadU32(&this->version) || this->version >> 16 != 1) { 110 return DropGraphite("Failed to read version"); 111 } 112 113 const std::vector<uint32_t>& locations = gloc->GetLocations(); 114 if (locations.empty()) { 115 return DropGraphite("No locations from Gloc table"); 116 } 117 std::list<uint32_t> unverified(locations.begin(), locations.end()); 118 while (table.remaining()) { 119 GlatEntry entry(this); 120 if (table.offset() > unverified.front()) { 121 return DropGraphite("Offset check failed for a GlatEntry"); 122 } 123 if (table.offset() == unverified.front()) { 124 unverified.pop_front(); 125 } 126 if (unverified.empty()) { 127 return DropGraphite("Expected more locations"); 128 } 129 if (!entry.ParsePart(table)) { 130 return DropGraphite("Failed to read a GlatEntry"); 131 } 132 this->entries.push_back(entry); 133 } 134 135 if (unverified.size() != 1 || unverified.front() != table.offset()) { 136 return DropGraphite("%zu location(s) could not be verified", unverified.size()); 137 } 138 if (table.remaining()) { 139 return Warning("%zu bytes unparsed", table.remaining()); 140 } 141 return true; 142 } 143 144 bool OpenTypeGLAT_v2::Serialize(OTSStream* out) { 145 assert(ShouldSerialize()); 146 if (!out->WriteU32(this->version) || 147 !SerializeParts(this->entries, out)) { 148 return Error("Failed to write table"); 149 } 150 return true; 151 } 152 153 bool OpenTypeGLAT_v2::GlatEntry::ParsePart(Buffer& table) { 154 if (!table.ReadS16(&this->attNum)) { 155 return parent->Error("GlatEntry: Failed to read attNum"); 156 } 157 if (!table.ReadS16(&this->num) || this->num < 0) { 158 return parent->Error("GlatEntry: Failed to read valid num"); 159 } 160 161 //this->attributes.resize(this->num); 162 for (int i = 0; i < this->num; ++i) { 163 this->attributes.emplace_back(); 164 if (!table.ReadS16(&this->attributes[i])) { 165 return parent->Error("GlatEntry: Failed to read attribute %u", i); 166 } 167 } 168 return true; 169 } 170 171 bool OpenTypeGLAT_v2::GlatEntry::SerializePart(OTSStream* out) const { 172 if (!out->WriteS16(this->attNum) || 173 !out->WriteS16(this->num) || 174 !SerializeParts(this->attributes, out)) { 175 return parent->Error("GlatEntry: Failed to write"); 176 } 177 return true; 178 } 179 180 // ----------------------------------------------------------------------------- 181 // OpenTypeGLAT_v3 182 // ----------------------------------------------------------------------------- 183 184 bool OpenTypeGLAT_v3::Parse(const uint8_t* data, size_t length, 185 bool prevent_decompression) { 186 Buffer table(data, length); 187 OpenTypeGLOC* gloc = static_cast<OpenTypeGLOC*>( 188 GetFont()->GetTypedTable(OTS_TAG_GLOC)); 189 if (!gloc) { 190 return DropGraphite("Required Gloc table is missing"); 191 } 192 193 if (!table.ReadU32(&this->version) || this->version >> 16 != 3) { 194 return DropGraphite("Failed to read version"); 195 } 196 if (!table.ReadU32(&this->compHead)) { 197 return DropGraphite("Failed to read compression header"); 198 } 199 switch ((this->compHead & SCHEME) >> 27) { 200 case 0: // uncompressed 201 break; 202 case 1: { // lz4 203 if (prevent_decompression) { 204 return DropGraphite("Illegal nested compression"); 205 } 206 size_t decompressed_size = this->compHead & FULL_SIZE; 207 if (decompressed_size < length) { 208 return DropGraphite("Decompressed size is less than compressed size"); 209 } 210 if (decompressed_size == 0) { 211 return DropGraphite("Decompressed size is set to 0"); 212 } 213 // decompressed table must be <= OTS_MAX_DECOMPRESSED_TABLE_SIZE 214 if (decompressed_size > OTS_MAX_DECOMPRESSED_TABLE_SIZE) { 215 return DropGraphite("Decompressed size exceeds %gMB: %gMB", 216 OTS_MAX_DECOMPRESSED_TABLE_SIZE / (1024.0 * 1024.0), 217 decompressed_size / (1024.0 * 1024.0)); 218 } 219 std::unique_ptr<uint8_t> decompressed(new uint8_t[decompressed_size]()); 220 size_t outputSize = 0; 221 bool ret = mozilla::Compression::LZ4::decompressPartial( 222 reinterpret_cast<const char*>(data + table.offset()), 223 table.remaining(), // input buffer size (input size + padding) 224 reinterpret_cast<char*>(decompressed.get()), 225 decompressed_size, // target output size 226 &outputSize); // return output size 227 if (!ret || outputSize != decompressed_size) { 228 return DropGraphite("Decompression failed"); 229 } 230 return this->Parse(decompressed.get(), decompressed_size, true); 231 } 232 default: 233 return DropGraphite("Unknown compression scheme"); 234 } 235 if (this->compHead & RESERVED) { 236 Warning("Nonzero reserved"); 237 } 238 239 const std::vector<uint32_t>& locations = gloc->GetLocations(); 240 if (locations.empty()) { 241 return DropGraphite("No locations from Gloc table"); 242 } 243 std::list<uint32_t> unverified(locations.begin(), locations.end()); 244 //this->entries.resize(locations.size() - 1, this); 245 for (size_t i = 0; i < locations.size() - 1; ++i) { 246 this->entries.emplace_back(this); 247 if (table.offset() != unverified.front()) { 248 return DropGraphite("Offset check failed for a GlyphAttrs"); 249 } 250 unverified.pop_front(); 251 if (!this->entries[i].ParsePart(table, 252 unverified.front() - table.offset())) { 253 // unverified.front() is guaranteed to exist because of the number of 254 // iterations of this loop 255 return DropGraphite("Failed to read a GlyphAttrs"); 256 } 257 } 258 259 if (unverified.size() != 1 || unverified.front() != table.offset()) { 260 return DropGraphite("%zu location(s) could not be verified", unverified.size()); 261 } 262 if (table.remaining()) { 263 return Warning("%zu bytes unparsed", table.remaining()); 264 } 265 return true; 266 } 267 268 bool OpenTypeGLAT_v3::Serialize(OTSStream* out) { 269 assert(ShouldSerialize()); 270 if (!out->WriteU32(this->version) || 271 !out->WriteU32(this->compHead) || 272 !SerializeParts(this->entries, out)) { 273 return Error("Failed to write table"); 274 } 275 return true; 276 } 277 278 bool OpenTypeGLAT_v3::GlyphAttrs::ParsePart(Buffer& table, const size_t size) { 279 size_t init_offset = table.offset(); 280 if (parent->compHead & OCTABOXES && !octabox.ParsePart(table)) { 281 // parent->flags & 0b1: octaboxes are present flag 282 return parent->Error("GlyphAttrs: Failed to read octabox"); 283 } 284 285 while (table.offset() < init_offset + size) { 286 GlatEntry entry(parent); 287 if (!entry.ParsePart(table)) { 288 return parent->Error("GlyphAttrs: Failed to read a GlatEntry"); 289 } 290 this->entries.push_back(entry); 291 } 292 return true; 293 } 294 295 bool OpenTypeGLAT_v3::GlyphAttrs::SerializePart(OTSStream* out) const { 296 if ((parent->compHead & OCTABOXES && !octabox.SerializePart(out)) || 297 !SerializeParts(this->entries, out)) { 298 return parent->Error("GlyphAttrs: Failed to write"); 299 } 300 return true; 301 } 302 303 bool OpenTypeGLAT_v3::GlyphAttrs:: 304 OctaboxMetrics::ParsePart(Buffer& table) { 305 if (!table.ReadU16(&this->subbox_bitmap)) { 306 return parent->Error("OctaboxMetrics: Failed to read subbox_bitmap"); 307 } 308 if (!table.ReadU8(&this->diag_neg_min)) { 309 return parent->Error("OctaboxMetrics: Failed to read diag_neg_min"); 310 } 311 if (!table.ReadU8(&this->diag_neg_max) || 312 this->diag_neg_max < this->diag_neg_min) { 313 return parent->Error("OctaboxMetrics: Failed to read valid diag_neg_max"); 314 } 315 if (!table.ReadU8(&this->diag_pos_min)) { 316 return parent->Error("OctaboxMetrics: Failed to read diag_pos_min"); 317 } 318 if (!table.ReadU8(&this->diag_pos_max) || 319 this->diag_pos_max < this->diag_pos_min) { 320 return parent->Error("OctaboxMetrics: Failed to read valid diag_pos_max"); 321 } 322 323 unsigned subboxes_len = 0; // count of 1's in this->subbox_bitmap 324 for (uint16_t i = this->subbox_bitmap; i; i >>= 1) { 325 if (i & 0b1) { 326 ++subboxes_len; 327 } 328 } 329 //this->subboxes.resize(subboxes_len, parent); 330 for (unsigned i = 0; i < subboxes_len; i++) { 331 this->subboxes.emplace_back(parent); 332 if (!this->subboxes[i].ParsePart(table)) { 333 return parent->Error("OctaboxMetrics: Failed to read subbox[%u]", i); 334 } 335 } 336 return true; 337 } 338 339 bool OpenTypeGLAT_v3::GlyphAttrs:: 340 OctaboxMetrics::SerializePart(OTSStream* out) const { 341 if (!out->WriteU16(this->subbox_bitmap) || 342 !out->WriteU8(this->diag_neg_min) || 343 !out->WriteU8(this->diag_neg_max) || 344 !out->WriteU8(this->diag_pos_min) || 345 !out->WriteU8(this->diag_pos_max) || 346 !SerializeParts(this->subboxes, out)) { 347 return parent->Error("OctaboxMetrics: Failed to write"); 348 } 349 return true; 350 } 351 352 bool OpenTypeGLAT_v3::GlyphAttrs::OctaboxMetrics:: 353 SubboxEntry::ParsePart(Buffer& table) { 354 if (!table.ReadU8(&this->left)) { 355 return parent->Error("SubboxEntry: Failed to read left"); 356 } 357 if (!table.ReadU8(&this->right) || this->right < this->left) { 358 return parent->Error("SubboxEntry: Failed to read valid right"); 359 } 360 if (!table.ReadU8(&this->bottom)) { 361 return parent->Error("SubboxEntry: Failed to read bottom"); 362 } 363 if (!table.ReadU8(&this->top) || this->top < this->bottom) { 364 return parent->Error("SubboxEntry: Failed to read valid top"); 365 } 366 if (!table.ReadU8(&this->diag_pos_min)) { 367 return parent->Error("SubboxEntry: Failed to read diag_pos_min"); 368 } 369 if (!table.ReadU8(&this->diag_pos_max) || 370 this->diag_pos_max < this->diag_pos_min) { 371 return parent->Error("SubboxEntry: Failed to read valid diag_pos_max"); 372 } 373 if (!table.ReadU8(&this->diag_neg_min)) { 374 return parent->Error("SubboxEntry: Failed to read diag_neg_min"); 375 } 376 if (!table.ReadU8(&this->diag_neg_max) || 377 this->diag_neg_max < this->diag_neg_min) { 378 return parent->Error("SubboxEntry: Failed to read valid diag_neg_max"); 379 } 380 return true; 381 } 382 383 bool OpenTypeGLAT_v3::GlyphAttrs::OctaboxMetrics:: 384 SubboxEntry::SerializePart(OTSStream* out) const { 385 if (!out->WriteU8(this->left) || 386 !out->WriteU8(this->right) || 387 !out->WriteU8(this->bottom) || 388 !out->WriteU8(this->top) || 389 !out->WriteU8(this->diag_pos_min) || 390 !out->WriteU8(this->diag_pos_max) || 391 !out->WriteU8(this->diag_neg_min) || 392 !out->WriteU8(this->diag_neg_max)) { 393 return parent->Error("SubboxEntry: Failed to write"); 394 } 395 return true; 396 } 397 398 bool OpenTypeGLAT_v3::GlyphAttrs:: 399 GlatEntry::ParsePart(Buffer& table) { 400 if (!table.ReadS16(&this->attNum)) { 401 return parent->Error("GlatEntry: Failed to read attNum"); 402 } 403 if (!table.ReadS16(&this->num) || this->num < 0) { 404 return parent->Error("GlatEntry: Failed to read valid num"); 405 } 406 407 //this->attributes.resize(this->num); 408 for (int i = 0; i < this->num; ++i) { 409 this->attributes.emplace_back(); 410 if (!table.ReadS16(&this->attributes[i])) { 411 return parent->Error("GlatEntry: Failed to read attribute %u", i); 412 } 413 } 414 return true; 415 } 416 417 bool OpenTypeGLAT_v3::GlyphAttrs:: 418 GlatEntry::SerializePart(OTSStream* out) const { 419 if (!out->WriteS16(this->attNum) || 420 !out->WriteS16(this->num) || 421 !SerializeParts(this->attributes, out)) { 422 return parent->Error("GlatEntry: Failed to write"); 423 } 424 return true; 425 } 426 427 // ----------------------------------------------------------------------------- 428 // OpenTypeGLAT 429 // ----------------------------------------------------------------------------- 430 431 bool OpenTypeGLAT::Parse(const uint8_t* data, size_t length) { 432 Buffer table(data, length); 433 uint32_t version; 434 if (!table.ReadU32(&version)) { 435 return DropGraphite("Failed to read version"); 436 } 437 switch (version >> 16) { 438 case 1: 439 this->handler = new OpenTypeGLAT_v1(this->font, this->tag); 440 break; 441 case 2: 442 this->handler = new OpenTypeGLAT_v2(this->font, this->tag); 443 break; 444 case 3: { 445 this->handler = new OpenTypeGLAT_v3(this->font, this->tag); 446 break; 447 } 448 default: 449 return DropGraphite("Unsupported table version: %u", version >> 16); 450 } 451 return this->handler->Parse(data, length); 452 } 453 454 bool OpenTypeGLAT::Serialize(OTSStream* out) { 455 if (!this->handler) { 456 return Error("No Glat table parsed"); 457 } 458 return this->handler->Serialize(out); 459 } 460 461 } // namespace ots