silf.cc (35589B)
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 "silf.h" 6 7 #include "name.h" 8 #include "mozilla/Compression.h" 9 #include <cmath> 10 #include <memory> 11 12 namespace ots { 13 14 bool OpenTypeSILF::Parse(const uint8_t* data, size_t length, 15 bool prevent_decompression) { 16 Buffer table(data, length); 17 18 if (!table.ReadU32(&this->version)) { 19 return DropGraphite("Failed to read version"); 20 } 21 if (this->version >> 16 != 1 && 22 this->version >> 16 != 2 && 23 this->version >> 16 != 3 && 24 this->version >> 16 != 4 && 25 this->version >> 16 != 5) { 26 return DropGraphite("Unsupported table version: %u", this->version >> 16); 27 } 28 if (this->version >> 16 >= 3 && !table.ReadU32(&this->compHead)) { 29 return DropGraphite("Failed to read compHead"); 30 } 31 if (this->version >> 16 >= 5) { 32 switch ((this->compHead & SCHEME) >> 27) { 33 case 0: // uncompressed 34 break; 35 case 1: { // lz4 36 if (prevent_decompression) { 37 return DropGraphite("Illegal nested compression"); 38 } 39 size_t decompressed_size = this->compHead & FULL_SIZE; 40 if (decompressed_size < length) { 41 return DropGraphite("Decompressed size is less than compressed size"); 42 } 43 if (decompressed_size == 0) { 44 return DropGraphite("Decompressed size is set to 0"); 45 } 46 // decompressed table must be <= OTS_MAX_DECOMPRESSED_TABLE_SIZE 47 if (decompressed_size > OTS_MAX_DECOMPRESSED_TABLE_SIZE) { 48 return DropGraphite("Decompressed size exceeds %gMB: %gMB", 49 OTS_MAX_DECOMPRESSED_TABLE_SIZE / (1024.0 * 1024.0), 50 decompressed_size / (1024.0 * 1024.0)); 51 } 52 std::unique_ptr<uint8_t> decompressed(new uint8_t[decompressed_size]()); 53 size_t outputSize = 0; 54 bool ret = mozilla::Compression::LZ4::decompressPartial( 55 reinterpret_cast<const char*>(data + table.offset()), 56 table.remaining(), // input buffer size (input size + padding) 57 reinterpret_cast<char*>(decompressed.get()), 58 decompressed_size, // target output size 59 &outputSize); // return output size 60 if (!ret || outputSize != decompressed_size) { 61 return DropGraphite("Decompression failed"); 62 } 63 return this->Parse(decompressed.get(), decompressed_size, true); 64 } 65 default: 66 return DropGraphite("Unknown compression scheme"); 67 } 68 } 69 if (!table.ReadU16(&this->numSub)) { 70 return DropGraphite("Failed to read numSub"); 71 } 72 if (this->version >> 16 >= 2 && !table.ReadU16(&this->reserved)) { 73 return DropGraphite("Failed to read reserved"); 74 } 75 if (this->version >> 16 >= 2 && this->reserved != 0) { 76 Warning("Nonzero reserved"); 77 } 78 79 unsigned long last_offset = 0; 80 //this->offset.resize(this->numSub); 81 for (unsigned i = 0; i < this->numSub; ++i) { 82 this->offset.emplace_back(); 83 if (!table.ReadU32(&this->offset[i]) || this->offset[i] < last_offset) { 84 return DropGraphite("Failed to read offset[%u]", i); 85 } 86 last_offset = this->offset[i]; 87 } 88 89 for (unsigned i = 0; i < this->numSub; ++i) { 90 if (table.offset() != this->offset[i]) { 91 return DropGraphite("Offset check failed for tables[%lu]", i); 92 } 93 SILSub subtable(this); 94 if (!subtable.ParsePart(table)) { 95 return DropGraphite("Failed to read tables[%u]", i); 96 } 97 tables.push_back(subtable); 98 } 99 100 if (table.remaining()) { 101 return Warning("%zu bytes unparsed", table.remaining()); 102 } 103 return true; 104 } 105 106 bool OpenTypeSILF::Serialize(OTSStream* out) { 107 if (!out->WriteU32(this->version) || 108 (this->version >> 16 >= 3 && !out->WriteU32(this->compHead)) || 109 !out->WriteU16(this->numSub) || 110 (this->version >> 16 >= 2 && !out->WriteU16(this->reserved)) || 111 !SerializeParts(this->offset, out) || 112 !SerializeParts(this->tables, out)) { 113 return Error("Failed to write table"); 114 } 115 return true; 116 } 117 118 bool OpenTypeSILF::SILSub::ParsePart(Buffer& table) { 119 size_t init_offset = table.offset(); 120 if (parent->version >> 16 >= 3) { 121 if (!table.ReadU32(&this->ruleVersion)) { 122 return parent->Error("SILSub: Failed to read ruleVersion"); 123 } 124 if (!table.ReadU16(&this->passOffset)) { 125 return parent->Error("SILSub: Failed to read passOffset"); 126 } 127 if (!table.ReadU16(&this->pseudosOffset)) { 128 return parent->Error("SILSub: Failed to read pseudosOffset"); 129 } 130 } 131 if (!table.ReadU16(&this->maxGlyphID)) { 132 return parent->Error("SILSub: Failed to read maxGlyphID"); 133 } 134 if (!table.ReadS16(&this->extraAscent)) { 135 return parent->Error("SILSub: Failed to read extraAscent"); 136 } 137 if (!table.ReadS16(&this->extraDescent)) { 138 return parent->Error("SILSub: Failed to read extraDescent"); 139 } 140 if (!table.ReadU8(&this->numPasses)) { 141 return parent->Error("SILSub: Failed to read numPasses"); 142 } 143 if (!table.ReadU8(&this->iSubst) || this->iSubst > this->numPasses) { 144 return parent->Error("SILSub: Failed to read valid iSubst"); 145 } 146 if (!table.ReadU8(&this->iPos) || this->iPos > this->numPasses) { 147 return parent->Error("SILSub: Failed to read valid iPos"); 148 } 149 if (!table.ReadU8(&this->iJust) || this->iJust > this->numPasses) { 150 return parent->Error("SILSub: Failed to read valid iJust"); 151 } 152 if (!table.ReadU8(&this->iBidi) || 153 !(iBidi == 0xFF || this->iBidi <= this->iPos)) { 154 return parent->Error("SILSub: Failed to read valid iBidi"); 155 } 156 if (!table.ReadU8(&this->flags)) { 157 return parent->Error("SILSub: Failed to read flags"); 158 // checks omitted 159 } 160 if (!table.ReadU8(&this->maxPreContext)) { 161 return parent->Error("SILSub: Failed to read maxPreContext"); 162 } 163 if (!table.ReadU8(&this->maxPostContext)) { 164 return parent->Error("SILSub: Failed to read maxPostContext"); 165 } 166 if (!table.ReadU8(&this->attrPseudo)) { 167 return parent->Error("SILSub: Failed to read attrPseudo"); 168 } 169 if (!table.ReadU8(&this->attrBreakWeight)) { 170 return parent->Error("SILSub: Failed to read attrBreakWeight"); 171 } 172 if (!table.ReadU8(&this->attrDirectionality)) { 173 return parent->Error("SILSub: Failed to read attrDirectionality"); 174 } 175 if (parent->version >> 16 >= 2) { 176 if (!table.ReadU8(&this->attrMirroring)) { 177 return parent->Error("SILSub: Failed to read attrMirroring"); 178 } 179 if (!table.ReadU8(&this->attrSkipPasses)) { 180 return parent->Error("SILSub: Failed to read attrSkipPasses"); 181 } 182 183 if (!table.ReadU8(&this->numJLevels)) { 184 return parent->Error("SILSub: Failed to read numJLevels"); 185 } 186 //this->jLevels.resize(this->numJLevels, parent); 187 for (unsigned i = 0; i < this->numJLevels; ++i) { 188 this->jLevels.emplace_back(parent); 189 if (!this->jLevels[i].ParsePart(table)) { 190 return parent->Error("SILSub: Failed to read jLevels[%u]", i); 191 } 192 } 193 } 194 195 if (!table.ReadU16(&this->numLigComp)) { 196 return parent->Error("SILSub: Failed to read numLigComp"); 197 } 198 if (!table.ReadU8(&this->numUserDefn)) { 199 return parent->Error("SILSub: Failed to read numUserDefn"); 200 } 201 if (!table.ReadU8(&this->maxCompPerLig)) { 202 return parent->Error("SILSub: Failed to read maxCompPerLig"); 203 } 204 if (!table.ReadU8(&this->direction)) { 205 return parent->Error("SILSub: Failed to read direction"); 206 } 207 if (!table.ReadU8(&this->attrCollisions)) { 208 return parent->Error("SILSub: Failed to read attrCollisions"); 209 } 210 if (parent->version < 0x40001 && this->attrCollisions != 0) { 211 parent->Warning("SILSub: Nonzero attrCollisions (reserved before v4.1)"); 212 } 213 if (!table.ReadU8(&this->reserved4)) { 214 return parent->Error("SILSub: Failed to read reserved4"); 215 } 216 if (this->reserved4 != 0) { 217 parent->Warning("SILSub: Nonzero reserved4"); 218 } 219 if (!table.ReadU8(&this->reserved5)) { 220 return parent->Error("SILSub: Failed to read reserved5"); 221 } 222 if (this->reserved5 != 0) { 223 parent->Warning("SILSub: Nonzero reserved5"); 224 } 225 if (parent->version >> 16 >= 2) { 226 if (!table.ReadU8(&this->reserved6)) { 227 return parent->Error("SILSub: Failed to read reserved6"); 228 } 229 if (this->reserved6 != 0) { 230 parent->Warning("SILSub: Nonzero reserved6"); 231 } 232 233 if (!table.ReadU8(&this->numCritFeatures)) { 234 return parent->Error("SILSub: Failed to read numCritFeatures"); 235 } 236 //this->critFeatures.resize(this->numCritFeatures); 237 for (unsigned i = 0; i < this->numCritFeatures; ++i) { 238 this->critFeatures.emplace_back(); 239 if (!table.ReadU16(&this->critFeatures[i])) { 240 return parent->Error("SILSub: Failed to read critFeatures[%u]", i); 241 } 242 } 243 244 if (!table.ReadU8(&this->reserved7)) { 245 return parent->Error("SILSub: Failed to read reserved7"); 246 } 247 if (this->reserved7 != 0) { 248 parent->Warning("SILSub: Nonzero reserved7"); 249 } 250 } 251 252 if (!table.ReadU8(&this->numScriptTag)) { 253 return parent->Error("SILSub: Failed to read numScriptTag"); 254 } 255 //this->scriptTag.resize(this->numScriptTag); 256 for (unsigned i = 0; i < this->numScriptTag; ++i) { 257 this->scriptTag.emplace_back(); 258 if (!table.ReadU32(&this->scriptTag[i])) { 259 return parent->Error("SILSub: Failed to read scriptTag[%u]", i); 260 } 261 } 262 263 if (!table.ReadU16(&this->lbGID)) { 264 return parent->Error("SILSub: Failed to read lbGID"); 265 } 266 if (this->lbGID > this->maxGlyphID) { 267 parent->Warning("SILSub: lbGID %u outside range 0..%u, replaced with 0", 268 this->lbGID, this->maxGlyphID); 269 this->lbGID = 0; 270 } 271 272 if (parent->version >> 16 >= 3 && 273 table.offset() != init_offset + this->passOffset) { 274 return parent->Error("SILSub: passOffset check failed"); 275 } 276 unsigned long last_oPass = 0; 277 //this->oPasses.resize(static_cast<unsigned>(this->numPasses) + 1); 278 for (unsigned i = 0; i <= this->numPasses; ++i) { 279 this->oPasses.emplace_back(); 280 if (!table.ReadU32(&this->oPasses[i]) || this->oPasses[i] < last_oPass) { 281 return false; 282 } 283 last_oPass = this->oPasses[i]; 284 } 285 286 if (parent->version >> 16 >= 3 && 287 table.offset() != init_offset + this->pseudosOffset) { 288 return parent->Error("SILSub: pseudosOffset check failed"); 289 } 290 if (!table.ReadU16(&this->numPseudo)) { 291 return parent->Error("SILSub: Failed to read numPseudo"); 292 } 293 294 // The following three fields are deprecated and ignored. We fix them up here 295 // just for internal consistency, but the Graphite engine doesn't care. 296 if (!table.ReadU16(&this->searchPseudo) || 297 !table.ReadU16(&this->pseudoSelector) || 298 !table.ReadU16(&this->pseudoShift)) { 299 return parent->Error("SILSub: Failed to read searchPseudo..pseudoShift"); 300 } 301 if (this->numPseudo == 0) { 302 if (this->searchPseudo != 0 || this->pseudoSelector != 0 || this->pseudoShift != 0) { 303 this->searchPseudo = this->pseudoSelector = this->pseudoShift = 0; 304 } 305 } else { 306 unsigned floorLog2 = std::floor(std::log2(this->numPseudo)); 307 if (this->searchPseudo != 6 * (unsigned)std::pow(2, floorLog2) || 308 this->pseudoSelector != floorLog2 || 309 this->pseudoShift != 6 * this->numPseudo - this->searchPseudo) { 310 this->searchPseudo = 6 * (unsigned)std::pow(2, floorLog2); 311 this->pseudoSelector = floorLog2; 312 this->pseudoShift = 6 * this->numPseudo - this->searchPseudo; 313 } 314 } 315 316 //this->pMaps.resize(this->numPseudo, parent); 317 for (unsigned i = 0; i < numPseudo; i++) { 318 this->pMaps.emplace_back(parent); 319 if (!this->pMaps[i].ParsePart(table)) { 320 return parent->Error("SILSub: Failed to read pMaps[%u]", i); 321 } 322 } 323 324 if (!this->classes.ParsePart(table)) { 325 return parent->Error("SILSub: Failed to read classes"); 326 } 327 328 //this->passes.resize(this->numPasses, parent); 329 for (unsigned i = 0; i < this->numPasses; ++i) { 330 this->passes.emplace_back(parent); 331 if (table.offset() != init_offset + this->oPasses[i]) { 332 return parent->Error("SILSub: Offset check failed for passes[%u]", i); 333 } 334 if (!this->passes[i].ParsePart(table, init_offset, this->oPasses[i+1])) { 335 return parent->Error("SILSub: Failed to read passes[%u]", i); 336 } 337 } 338 return true; 339 } 340 341 bool OpenTypeSILF::SILSub::SerializePart(OTSStream* out) const { 342 if ((parent->version >> 16 >= 3 && 343 (!out->WriteU32(this->ruleVersion) || 344 !out->WriteU16(this->passOffset) || 345 !out->WriteU16(this->pseudosOffset))) || 346 !out->WriteU16(this->maxGlyphID) || 347 !out->WriteS16(this->extraAscent) || 348 !out->WriteS16(this->extraDescent) || 349 !out->WriteU8(this->numPasses) || 350 !out->WriteU8(this->iSubst) || 351 !out->WriteU8(this->iPos) || 352 !out->WriteU8(this->iJust) || 353 !out->WriteU8(this->iBidi) || 354 !out->WriteU8(this->flags) || 355 !out->WriteU8(this->maxPreContext) || 356 !out->WriteU8(this->maxPostContext) || 357 !out->WriteU8(this->attrPseudo) || 358 !out->WriteU8(this->attrBreakWeight) || 359 !out->WriteU8(this->attrDirectionality) || 360 (parent->version >> 16 >= 2 && 361 (!out->WriteU8(this->attrMirroring) || 362 !out->WriteU8(this->attrSkipPasses) || 363 !out->WriteU8(this->numJLevels) || 364 !SerializeParts(this->jLevels, out))) || 365 !out->WriteU16(this->numLigComp) || 366 !out->WriteU8(this->numUserDefn) || 367 !out->WriteU8(this->maxCompPerLig) || 368 !out->WriteU8(this->direction) || 369 !out->WriteU8(this->attrCollisions) || 370 !out->WriteU8(this->reserved4) || 371 !out->WriteU8(this->reserved5) || 372 (parent->version >> 16 >= 2 && 373 (!out->WriteU8(this->reserved6) || 374 !out->WriteU8(this->numCritFeatures) || 375 !SerializeParts(this->critFeatures, out) || 376 !out->WriteU8(this->reserved7))) || 377 !out->WriteU8(this->numScriptTag) || 378 !SerializeParts(this->scriptTag, out) || 379 !out->WriteU16(this->lbGID) || 380 !SerializeParts(this->oPasses, out) || 381 !out->WriteU16(this->numPseudo) || 382 !out->WriteU16(this->searchPseudo) || 383 !out->WriteU16(this->pseudoSelector) || 384 !out->WriteU16(this->pseudoShift) || 385 !SerializeParts(this->pMaps, out) || 386 !this->classes.SerializePart(out) || 387 !SerializeParts(this->passes, out)) { 388 return parent->Error("SILSub: Failed to write"); 389 } 390 return true; 391 } 392 393 bool OpenTypeSILF::SILSub:: 394 JustificationLevel::ParsePart(Buffer& table) { 395 if (!table.ReadU8(&this->attrStretch)) { 396 return parent->Error("JustificationLevel: Failed to read attrStretch"); 397 } 398 if (!table.ReadU8(&this->attrShrink)) { 399 return parent->Error("JustificationLevel: Failed to read attrShrink"); 400 } 401 if (!table.ReadU8(&this->attrStep)) { 402 return parent->Error("JustificationLevel: Failed to read attrStep"); 403 } 404 if (!table.ReadU8(&this->attrWeight)) { 405 return parent->Error("JustificationLevel: Failed to read attrWeight"); 406 } 407 if (!table.ReadU8(&this->runto)) { 408 return parent->Error("JustificationLevel: Failed to read runto"); 409 } 410 if (!table.ReadU8(&this->reserved)) { 411 return parent->Error("JustificationLevel: Failed to read reserved"); 412 } 413 if (this->reserved != 0) { 414 parent->Warning("JustificationLevel: Nonzero reserved"); 415 } 416 if (!table.ReadU8(&this->reserved2)) { 417 return parent->Error("JustificationLevel: Failed to read reserved2"); 418 } 419 if (this->reserved2 != 0) { 420 parent->Warning("JustificationLevel: Nonzero reserved2"); 421 } 422 if (!table.ReadU8(&this->reserved3)) { 423 return parent->Error("JustificationLevel: Failed to read reserved3"); 424 } 425 if (this->reserved3 != 0) { 426 parent->Warning("JustificationLevel: Nonzero reserved3"); 427 } 428 return true; 429 } 430 431 bool OpenTypeSILF::SILSub:: 432 JustificationLevel::SerializePart(OTSStream* out) const { 433 if (!out->WriteU8(this->attrStretch) || 434 !out->WriteU8(this->attrShrink) || 435 !out->WriteU8(this->attrStep) || 436 !out->WriteU8(this->attrWeight) || 437 !out->WriteU8(this->runto) || 438 !out->WriteU8(this->reserved) || 439 !out->WriteU8(this->reserved2) || 440 !out->WriteU8(this->reserved3)) { 441 return parent->Error("JustificationLevel: Failed to write"); 442 } 443 return true; 444 } 445 446 bool OpenTypeSILF::SILSub:: 447 PseudoMap::ParsePart(Buffer& table) { 448 if (parent->version >> 16 >= 2 && !table.ReadU32(&this->unicode)) { 449 return parent->Error("PseudoMap: Failed to read unicode"); 450 } 451 if (parent->version >> 16 == 1) { 452 uint16_t unicode; 453 if (!table.ReadU16(&unicode)) { 454 return parent->Error("PseudoMap: Failed to read unicode"); 455 } 456 this->unicode = unicode; 457 } 458 if (!table.ReadU16(&this->nPseudo)) { 459 return parent->Error("PseudoMap: Failed to read nPseudo"); 460 } 461 return true; 462 } 463 464 bool OpenTypeSILF::SILSub:: 465 PseudoMap::SerializePart(OTSStream* out) const { 466 if ((parent->version >> 16 >= 2 && !out->WriteU32(this->unicode)) || 467 (parent->version >> 16 == 1 && 468 !out->WriteU16(static_cast<uint16_t>(this->unicode))) || 469 !out->WriteU16(this->nPseudo)) { 470 return parent->Error("PseudoMap: Failed to write"); 471 } 472 return true; 473 } 474 475 bool OpenTypeSILF::SILSub:: 476 ClassMap::ParsePart(Buffer& table) { 477 size_t init_offset = table.offset(); 478 if (!table.ReadU16(&this->numClass)) { 479 return parent->Error("ClassMap: Failed to read numClass"); 480 } 481 if (!table.ReadU16(&this->numLinear) || this->numLinear > this->numClass) { 482 return parent->Error("ClassMap: Failed to read valid numLinear"); 483 } 484 485 //this->oClass.resize(static_cast<unsigned long>(this->numClass) + 1); 486 if (parent->version >> 16 >= 4) { 487 unsigned long last_oClass = 0; 488 for (unsigned long i = 0; i <= this->numClass; ++i) { 489 this->oClass.emplace_back(); 490 if (!table.ReadU32(&this->oClass[i]) || this->oClass[i] < last_oClass) { 491 return parent->Error("ClassMap: Failed to read oClass[%lu]", i); 492 } 493 last_oClass = this->oClass[i]; 494 } 495 } 496 if (parent->version >> 16 < 4) { 497 unsigned last_oClass = 0; 498 for (unsigned long i = 0; i <= this->numClass; ++i) { 499 uint16_t offset; 500 if (!table.ReadU16(&offset) || offset < last_oClass) { 501 return parent->Error("ClassMap: Failed to read oClass[%lu]", i); 502 } 503 last_oClass = offset; 504 this->oClass.push_back(static_cast<uint32_t>(offset)); 505 } 506 } 507 508 if (table.offset() - init_offset > this->oClass[this->numLinear]) { 509 return parent->Error("ClassMap: Failed to calculate length of glyphs"); 510 } 511 unsigned long glyphs_len = (this->oClass[this->numLinear] - 512 (table.offset() - init_offset))/2; 513 //this->glyphs.resize(glyphs_len); 514 for (unsigned long i = 0; i < glyphs_len; ++i) { 515 this->glyphs.emplace_back(); 516 if (!table.ReadU16(&this->glyphs[i])) { 517 return parent->Error("ClassMap: Failed to read glyphs[%lu]", i); 518 } 519 } 520 521 unsigned lookups_len = this->numClass - this->numLinear; 522 // this->numLinear <= this->numClass 523 //this->lookups.resize(lookups_len, parent); 524 for (unsigned i = 0; i < lookups_len; ++i) { 525 this->lookups.emplace_back(parent); 526 if (table.offset() != init_offset + oClass[this->numLinear + i]) { 527 return parent->Error("ClassMap: Offset check failed for lookups[%u]", i); 528 } 529 if (!this->lookups[i].ParsePart(table)) { 530 return parent->Error("ClassMap: Failed to read lookups[%u]", i); 531 } 532 } 533 return true; 534 } 535 536 bool OpenTypeSILF::SILSub:: 537 ClassMap::SerializePart(OTSStream* out) const { 538 if (!out->WriteU16(this->numClass) || 539 !out->WriteU16(this->numLinear) || 540 (parent->version >> 16 >= 4 && !SerializeParts(this->oClass, out)) || 541 (parent->version >> 16 < 4 && 542 ![&] { 543 for (uint32_t offset : this->oClass) { 544 if (!out->WriteU16(static_cast<uint16_t>(offset))) { 545 return false; 546 } 547 } 548 return true; 549 }()) || 550 !SerializeParts(this->glyphs, out) || 551 !SerializeParts(this->lookups, out)) { 552 return parent->Error("ClassMap: Failed to write"); 553 } 554 return true; 555 } 556 557 bool OpenTypeSILF::SILSub::ClassMap:: 558 LookupClass::ParsePart(Buffer& table) { 559 if (!table.ReadU16(&this->numIDs)) { 560 return parent->Error("LookupClass: Failed to read numIDs"); 561 } 562 if (!table.ReadU16(&this->searchRange) || 563 !table.ReadU16(&this->entrySelector) || 564 !table.ReadU16(&this->rangeShift)) { 565 return parent->Error("LookupClass: Failed to read searchRange..rangeShift"); 566 } 567 if (this->numIDs == 0) { 568 if (this->searchRange != 0 || this->entrySelector != 0 || this->rangeShift != 0) { 569 parent->Warning("LookupClass: Correcting binary-search header for zero-length LookupPair list"); 570 this->searchRange = this->entrySelector = this->rangeShift = 0; 571 } 572 } else { 573 unsigned floorLog2 = std::floor(std::log2(this->numIDs)); 574 if (this->searchRange != (unsigned)std::pow(2, floorLog2) || 575 this->entrySelector != floorLog2 || 576 this->rangeShift != this->numIDs - this->searchRange) { 577 parent->Warning("LookupClass: Correcting binary-search header for LookupPair list"); 578 this->searchRange = (unsigned)std::pow(2, floorLog2); 579 this->entrySelector = floorLog2; 580 this->rangeShift = this->numIDs - this->searchRange; 581 } 582 } 583 584 //this->lookups.resize(this->numIDs, parent); 585 for (unsigned i = 0; i < numIDs; ++i) { 586 this->lookups.emplace_back(parent); 587 if (!this->lookups[i].ParsePart(table)) { 588 return parent->Error("LookupClass: Failed to read lookups[%u]", i); 589 } 590 } 591 return true; 592 } 593 594 bool OpenTypeSILF::SILSub::ClassMap:: 595 LookupClass::SerializePart(OTSStream* out) const { 596 if (!out->WriteU16(this->numIDs) || 597 !out->WriteU16(this->searchRange) || 598 !out->WriteU16(this->entrySelector) || 599 !out->WriteU16(this->rangeShift) || 600 !SerializeParts(this->lookups, out)) { 601 return parent->Error("LookupClass: Failed to write"); 602 } 603 return true; 604 } 605 606 bool OpenTypeSILF::SILSub::ClassMap::LookupClass:: 607 LookupPair::ParsePart(Buffer& table) { 608 if (!table.ReadU16(&this->glyphId)) { 609 return parent->Error("LookupPair: Failed to read glyphId"); 610 } 611 if (!table.ReadU16(&this->index)) { 612 return parent->Error("LookupPair: Failed to read index"); 613 } 614 return true; 615 } 616 617 bool OpenTypeSILF::SILSub::ClassMap::LookupClass:: 618 LookupPair::SerializePart(OTSStream* out) const { 619 if (!out->WriteU16(this->glyphId) || 620 !out->WriteU16(this->index)) { 621 return parent->Error("LookupPair: Failed to write"); 622 } 623 return true; 624 } 625 626 bool OpenTypeSILF::SILSub:: 627 SILPass::ParsePart(Buffer& table, const size_t SILSub_init_offset, 628 const size_t next_pass_offset) { 629 size_t init_offset = table.offset(); 630 if (!table.ReadU8(&this->flags)) { 631 return parent->Error("SILPass: Failed to read flags"); 632 // checks omitted 633 } 634 if (!table.ReadU8(&this->maxRuleLoop)) { 635 return parent->Error("SILPass: Failed to read valid maxRuleLoop"); 636 } 637 if (!table.ReadU8(&this->maxRuleContext)) { 638 return parent->Error("SILPass: Failed to read maxRuleContext"); 639 } 640 if (!table.ReadU8(&this->maxBackup)) { 641 return parent->Error("SILPass: Failed to read maxBackup"); 642 } 643 if (!table.ReadU16(&this->numRules)) { 644 return parent->Error("SILPass: Failed to read numRules"); 645 } 646 if (parent->version >> 16 >= 2) { 647 if (!table.ReadU16(&this->fsmOffset)) { 648 return parent->Error("SILPass: Failed to read fsmOffset"); 649 } 650 if (!table.ReadU32(&this->pcCode) || 651 (parent->version >= 3 && this->pcCode < this->fsmOffset)) { 652 return parent->Error("SILPass: Failed to read pcCode"); 653 } 654 } 655 if (!table.ReadU32(&this->rcCode) || 656 (parent->version >> 16 >= 2 && this->rcCode < this->pcCode)) { 657 return parent->Error("SILPass: Failed to read valid rcCode"); 658 } 659 if (!table.ReadU32(&this->aCode) || this->aCode < this->rcCode) { 660 return parent->Error("SILPass: Failed to read valid aCode"); 661 } 662 if (!table.ReadU32(&this->oDebug) || 663 (this->oDebug && this->oDebug < this->aCode)) { 664 return parent->Error("SILPass: Failed to read valid oDebug"); 665 } 666 if (parent->version >> 16 >= 3 && 667 table.offset() != init_offset + this->fsmOffset) { 668 return parent->Error("SILPass: fsmOffset check failed"); 669 } 670 if (!table.ReadU16(&this->numRows) || 671 (this->oDebug && this->numRows < this->numRules)) { 672 return parent->Error("SILPass: Failed to read valid numRows"); 673 } 674 if (!table.ReadU16(&this->numTransitional)) { 675 return parent->Error("SILPass: Failed to read numTransitional"); 676 } 677 if (!table.ReadU16(&this->numSuccess)) { 678 return parent->Error("SILPass: Failed to read numSuccess"); 679 } 680 if (!table.ReadU16(&this->numColumns)) { 681 return parent->Error("SILPass: Failed to read numColumns"); 682 } 683 if (!table.ReadU16(&this->numRange)) { 684 return parent->Error("SILPass: Failed to read numRange"); 685 } 686 687 // The following three fields are deprecated and ignored. We fix them up here 688 // just for internal consistency, but the Graphite engine doesn't care. 689 if (!table.ReadU16(&this->searchRange) || 690 !table.ReadU16(&this->entrySelector) || 691 !table.ReadU16(&this->rangeShift)) { 692 return parent->Error("SILPass: Failed to read searchRange..rangeShift"); 693 } 694 if (this->numRange == 0) { 695 if (this->searchRange != 0 || this->entrySelector != 0 || this->rangeShift != 0) { 696 this->searchRange = this->entrySelector = this->rangeShift = 0; 697 } 698 } else { 699 unsigned floorLog2 = std::floor(std::log2(this->numRange)); 700 if (this->searchRange != 6 * (unsigned)std::pow(2, floorLog2) || 701 this->entrySelector != floorLog2 || 702 this->rangeShift != 6 * this->numRange - this->searchRange) { 703 this->searchRange = 6 * (unsigned)std::pow(2, floorLog2); 704 this->entrySelector = floorLog2; 705 this->rangeShift = 6 * this->numRange - this->searchRange; 706 } 707 } 708 709 //this->ranges.resize(this->numRange, parent); 710 for (unsigned i = 0 ; i < this->numRange; ++i) { 711 this->ranges.emplace_back(parent); 712 if (!this->ranges[i].ParsePart(table)) { 713 return parent->Error("SILPass: Failed to read ranges[%u]", i); 714 } 715 } 716 unsigned ruleMap_len = 0; // maximum value in oRuleMap 717 //this->oRuleMap.resize(static_cast<unsigned long>(this->numSuccess) + 1); 718 for (unsigned long i = 0; i <= this->numSuccess; ++i) { 719 this->oRuleMap.emplace_back(); 720 if (!table.ReadU16(&this->oRuleMap[i])) { 721 return parent->Error("SILPass: Failed to read oRuleMap[%u]", i); 722 } 723 if (oRuleMap[i] > ruleMap_len) { 724 ruleMap_len = oRuleMap[i]; 725 } 726 } 727 728 //this->ruleMap.resize(ruleMap_len); 729 for (unsigned i = 0; i < ruleMap_len; ++i) { 730 this->ruleMap.emplace_back(); 731 if (!table.ReadU16(&this->ruleMap[i])) { 732 return parent->Error("SILPass: Failed to read ruleMap[%u]", i); 733 } 734 } 735 736 if (!table.ReadU8(&this->minRulePreContext)) { 737 return parent->Error("SILPass: Failed to read minRulePreContext"); 738 } 739 if (!table.ReadU8(&this->maxRulePreContext) || 740 this->maxRulePreContext < this->minRulePreContext) { 741 return parent->Error("SILPass: Failed to read valid maxRulePreContext"); 742 } 743 744 unsigned startStates_len = this->maxRulePreContext - this->minRulePreContext 745 + 1; 746 // this->minRulePreContext <= this->maxRulePreContext 747 //this->startStates.resize(startStates_len); 748 for (unsigned i = 0; i < startStates_len; ++i) { 749 this->startStates.emplace_back(); 750 if (!table.ReadS16(&this->startStates[i])) { 751 return parent->Error("SILPass: Failed to read startStates[%u]", i); 752 } 753 } 754 755 //this->ruleSortKeys.resize(this->numRules); 756 for (unsigned i = 0; i < this->numRules; ++i) { 757 this->ruleSortKeys.emplace_back(); 758 if (!table.ReadU16(&this->ruleSortKeys[i])) { 759 return parent->Error("SILPass: Failed to read ruleSortKeys[%u]", i); 760 } 761 } 762 763 //this->rulePreContext.resize(this->numRules); 764 for (unsigned i = 0; i < this->numRules; ++i) { 765 this->rulePreContext.emplace_back(); 766 if (!table.ReadU8(&this->rulePreContext[i])) { 767 return parent->Error("SILPass: Failed to read rulePreContext[%u]", i); 768 } 769 } 770 771 if (parent->version >> 16 >= 2) { 772 if (!table.ReadU8(&this->collisionThreshold)) { 773 return parent->Error("SILPass: Failed to read collisionThreshold"); 774 } 775 if (!table.ReadU16(&this->pConstraint)) { 776 return parent->Error("SILPass: Failed to read pConstraint"); 777 } 778 } 779 780 unsigned long ruleConstraints_len = this->aCode - this->rcCode; 781 // this->rcCode <= this->aCode 782 //this->oConstraints.resize(static_cast<unsigned long>(this->numRules) + 1); 783 for (unsigned long i = 0; i <= this->numRules; ++i) { 784 this->oConstraints.emplace_back(); 785 if (!table.ReadU16(&this->oConstraints[i]) || 786 this->oConstraints[i] > ruleConstraints_len) { 787 return parent->Error("SILPass: Failed to read valid oConstraints[%lu]", 788 i); 789 } 790 } 791 792 if (!this->oDebug && this->aCode > next_pass_offset) { 793 return parent->Error("SILPass: Failed to calculate length of actions"); 794 } 795 unsigned long actions_len = this->oDebug ? this->oDebug - this->aCode : 796 next_pass_offset - this->aCode; 797 // if this->oDebug, then this->aCode <= this->oDebug 798 //this->oActions.resize(static_cast<unsigned long>(this->numRules) + 1); 799 for (unsigned long i = 0; i <= this->numRules; ++i) { 800 this->oActions.emplace_back(); 801 if (!table.ReadU16(&this->oActions[i]) || 802 (this->oActions[i] > actions_len)) { 803 return parent->Error("SILPass: Failed to read valid oActions[%lu]", i); 804 } 805 } 806 807 //this->stateTrans.resize(this->numTransitional); 808 for (unsigned i = 0; i < this->numTransitional; ++i) { 809 this->stateTrans.emplace_back(); 810 //this->stateTrans[i].resize(this->numColumns); 811 for (unsigned j = 0; j < this->numColumns; ++j) { 812 this->stateTrans[i].emplace_back(); 813 if (!table.ReadU16(&stateTrans[i][j])) { 814 return parent->Error("SILPass: Failed to read stateTrans[%u][%u]", 815 i, j); 816 } 817 } 818 } 819 820 if (parent->version >> 16 >= 2) { 821 if (!table.ReadU8(&this->reserved2)) { 822 return parent->Error("SILPass: Failed to read reserved2"); 823 } 824 if (this->reserved2 != 0) { 825 parent->Warning("SILPass: Nonzero reserved2"); 826 } 827 828 if (table.offset() != SILSub_init_offset + this->pcCode) { 829 return parent->Error("SILPass: pcCode check failed"); 830 } 831 //this->passConstraints.resize(this->pConstraint); 832 for (unsigned i = 0; i < this->pConstraint; ++i) { 833 this->passConstraints.emplace_back(); 834 if (!table.ReadU8(&this->passConstraints[i])) { 835 return parent->Error("SILPass: Failed to read passConstraints[%u]", i); 836 } 837 } 838 } 839 840 if (table.offset() != SILSub_init_offset + this->rcCode) { 841 return parent->Error("SILPass: rcCode check failed"); 842 } 843 //this->ruleConstraints.resize(ruleConstraints_len); // calculated above 844 for (unsigned long i = 0; i < ruleConstraints_len; ++i) { 845 this->ruleConstraints.emplace_back(); 846 if (!table.ReadU8(&this->ruleConstraints[i])) { 847 return parent->Error("SILPass: Failed to read ruleConstraints[%u]", i); 848 } 849 } 850 851 if (table.offset() != SILSub_init_offset + this->aCode) { 852 return parent->Error("SILPass: aCode check failed"); 853 } 854 //this->actions.resize(actions_len); // calculated above 855 for (unsigned long i = 0; i < actions_len; ++i) { 856 this->actions.emplace_back(); 857 if (!table.ReadU8(&this->actions[i])) { 858 return parent->Error("SILPass: Failed to read actions[%u]", i); 859 } 860 } 861 862 if (this->oDebug) { 863 OpenTypeNAME* name = static_cast<OpenTypeNAME*>( 864 parent->GetFont()->GetTypedTable(OTS_TAG_NAME)); 865 if (!name) { 866 return parent->Error("SILPass: Required name table is missing"); 867 } 868 869 if (table.offset() != SILSub_init_offset + this->oDebug) { 870 return parent->Error("SILPass: oDebug check failed"); 871 } 872 //this->dActions.resize(this->numRules); 873 for (unsigned i = 0; i < this->numRules; ++i) { 874 this->dActions.emplace_back(); 875 if (!table.ReadU16(&this->dActions[i]) || 876 !name->IsValidNameId(this->dActions[i])) { 877 return parent->Error("SILPass: Failed to read valid dActions[%u]", i); 878 } 879 } 880 881 unsigned dStates_len = this->numRows - this->numRules; 882 // this->numRules <= this->numRows 883 //this->dStates.resize(dStates_len); 884 for (unsigned i = 0; i < dStates_len; ++i) { 885 this->dStates.emplace_back(); 886 if (!table.ReadU16(&this->dStates[i]) || 887 !name->IsValidNameId(this->dStates[i])) { 888 return parent->Error("SILPass: Failed to read valid dStates[%u]", i); 889 } 890 } 891 892 //this->dCols.resize(this->numRules); 893 for (unsigned i = 0; i < this->numRules; ++i) { 894 this->dCols.emplace_back(); 895 if (!table.ReadU16(&this->dCols[i]) || 896 !name->IsValidNameId(this->dCols[i])) { 897 return parent->Error("SILPass: Failed to read valid dCols[%u]"); 898 } 899 } 900 } 901 return true; 902 } 903 904 bool OpenTypeSILF::SILSub:: 905 SILPass::SerializePart(OTSStream* out) const { 906 if (!out->WriteU8(this->flags) || 907 !out->WriteU8(this->maxRuleLoop) || 908 !out->WriteU8(this->maxRuleContext) || 909 !out->WriteU8(this->maxBackup) || 910 !out->WriteU16(this->numRules) || 911 (parent->version >> 16 >= 2 && 912 (!out->WriteU16(this->fsmOffset) || 913 !out->WriteU32(this->pcCode))) || 914 !out->WriteU32(this->rcCode) || 915 !out->WriteU32(this->aCode) || 916 !out->WriteU32(this->oDebug) || 917 !out->WriteU16(this->numRows) || 918 !out->WriteU16(this->numTransitional) || 919 !out->WriteU16(this->numSuccess) || 920 !out->WriteU16(this->numColumns) || 921 !out->WriteU16(this->numRange) || 922 !out->WriteU16(this->searchRange) || 923 !out->WriteU16(this->entrySelector) || 924 !out->WriteU16(this->rangeShift) || 925 !SerializeParts(this->ranges, out) || 926 !SerializeParts(this->oRuleMap, out) || 927 !SerializeParts(this->ruleMap, out) || 928 !out->WriteU8(this->minRulePreContext) || 929 !out->WriteU8(this->maxRulePreContext) || 930 !SerializeParts(this->startStates, out) || 931 !SerializeParts(this->ruleSortKeys, out) || 932 !SerializeParts(this->rulePreContext, out) || 933 (parent->version >> 16 >= 2 && 934 (!out->WriteU8(this->collisionThreshold) || 935 !out->WriteU16(this->pConstraint))) || 936 !SerializeParts(this->oConstraints, out) || 937 !SerializeParts(this->oActions, out) || 938 !SerializeParts(this->stateTrans, out) || 939 (parent->version >> 16 >= 2 && 940 (!out->WriteU8(this->reserved2) || 941 !SerializeParts(this->passConstraints, out))) || 942 !SerializeParts(this->ruleConstraints, out) || 943 !SerializeParts(this->actions, out) || 944 !SerializeParts(this->dActions, out) || 945 !SerializeParts(this->dStates, out) || 946 !SerializeParts(this->dCols, out)) { 947 return parent->Error("SILPass: Failed to write"); 948 } 949 return true; 950 } 951 952 bool OpenTypeSILF::SILSub::SILPass:: 953 PassRange::ParsePart(Buffer& table) { 954 if (!table.ReadU16(&this->firstId)) { 955 return parent->Error("PassRange: Failed to read firstId"); 956 } 957 if (!table.ReadU16(&this->lastId)) { 958 return parent->Error("PassRange: Failed to read lastId"); 959 } 960 if (!table.ReadU16(&this->colId)) { 961 return parent->Error("PassRange: Failed to read colId"); 962 } 963 return true; 964 } 965 966 bool OpenTypeSILF::SILSub::SILPass:: 967 PassRange::SerializePart(OTSStream* out) const { 968 if (!out->WriteU16(this->firstId) || 969 !out->WriteU16(this->lastId) || 970 !out->WriteU16(this->colId)) { 971 return parent->Error("PassRange: Failed to write"); 972 } 973 return true; 974 } 975 976 } // namespace ots