// Copyright (c) 2009-2017 The OTS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.
bool OpenTypeSILF::SILSub::ParsePart(Buffer& table) {
size_t init_offset = table.offset(); if (parent->version >> 16 >= 3) { if (!table.ReadU32(&this->ruleVersion)) { return parent->Error("SILSub: Failed to read ruleVersion");
} if (!table.ReadU16(&this->passOffset)) { return parent->Error("SILSub: Failed to read passOffset");
} if (!table.ReadU16(&this->pseudosOffset)) { return parent->Error("SILSub: Failed to read pseudosOffset");
}
} if (!table.ReadU16(&this->maxGlyphID)) { return parent->Error("SILSub: Failed to read maxGlyphID");
} if (!table.ReadS16(&this->extraAscent)) { return parent->Error("SILSub: Failed to read extraAscent");
} if (!table.ReadS16(&this->extraDescent)) { return parent->Error("SILSub: Failed to read extraDescent");
} if (!table.ReadU8(&this->numPasses)) { return parent->Error("SILSub: Failed to read numPasses");
} if (!table.ReadU8(&this->iSubst) || this->iSubst > this->numPasses) { return parent->Error("SILSub: Failed to read valid iSubst");
} if (!table.ReadU8(&this->iPos) || this->iPos > this->numPasses) { return parent->Error("SILSub: Failed to read valid iPos");
} if (!table.ReadU8(&this->iJust) || this->iJust > this->numPasses) { return parent->Error("SILSub: Failed to read valid iJust");
} if (!table.ReadU8(&this->iBidi) ||
!(iBidi == 0xFF || this->iBidi <= this->iPos)) { return parent->Error("SILSub: Failed to read valid iBidi");
} if (!table.ReadU8(&this->flags)) { return parent->Error("SILSub: Failed to read flags"); // checks omitted
} if (!table.ReadU8(&this->maxPreContext)) { return parent->Error("SILSub: Failed to read maxPreContext");
} if (!table.ReadU8(&this->maxPostContext)) { return parent->Error("SILSub: Failed to read maxPostContext");
} if (!table.ReadU8(&this->attrPseudo)) { return parent->Error("SILSub: Failed to read attrPseudo");
} if (!table.ReadU8(&this->attrBreakWeight)) { return parent->Error("SILSub: Failed to read attrBreakWeight");
} if (!table.ReadU8(&this->attrDirectionality)) { return parent->Error("SILSub: Failed to read attrDirectionality");
} if (parent->version >> 16 >= 2) { if (!table.ReadU8(&this->attrMirroring)) { return parent->Error("SILSub: Failed to read attrMirroring");
} if (!table.ReadU8(&this->attrSkipPasses)) { return parent->Error("SILSub: Failed to read attrSkipPasses");
}
if (!table.ReadU8(&this->numJLevels)) { return parent->Error("SILSub: Failed to read numJLevels");
} //this->jLevels.resize(this->numJLevels, parent); for (unsigned i = 0; i < this->numJLevels; ++i) {
this->jLevels.emplace_back(parent); if (!this->jLevels[i].ParsePart(table)) { return parent->Error("SILSub: Failed to read jLevels[%u]", i);
}
}
}
if (!table.ReadU16(&this->numLigComp)) { return parent->Error("SILSub: Failed to read numLigComp");
} if (!table.ReadU8(&this->numUserDefn)) { return parent->Error("SILSub: Failed to read numUserDefn");
} if (!table.ReadU8(&this->maxCompPerLig)) { return parent->Error("SILSub: Failed to read maxCompPerLig");
} if (!table.ReadU8(&this->direction)) { return parent->Error("SILSub: Failed to read direction");
} if (!table.ReadU8(&this->attrCollisions)) { return parent->Error("SILSub: Failed to read attrCollisions");
} if (parent->version < 0x40001 && this->attrCollisions != 0) {
parent->Warning("SILSub: Nonzero attrCollisions (reserved before v4.1)");
} if (!table.ReadU8(&this->reserved4)) { return parent->Error("SILSub: Failed to read reserved4");
} if (this->reserved4 != 0) {
parent->Warning("SILSub: Nonzero reserved4");
} if (!table.ReadU8(&this->reserved5)) { return parent->Error("SILSub: Failed to read reserved5");
} if (this->reserved5 != 0) {
parent->Warning("SILSub: Nonzero reserved5");
} if (parent->version >> 16 >= 2) { if (!table.ReadU8(&this->reserved6)) { return parent->Error("SILSub: Failed to read reserved6");
} if (this->reserved6 != 0) {
parent->Warning("SILSub: Nonzero reserved6");
}
if (!table.ReadU8(&this->numCritFeatures)) { return parent->Error("SILSub: Failed to read numCritFeatures");
} //this->critFeatures.resize(this->numCritFeatures); for (unsigned i = 0; i < this->numCritFeatures; ++i) {
this->critFeatures.emplace_back(); if (!table.ReadU16(&this->critFeatures[i])) { return parent->Error("SILSub: Failed to read critFeatures[%u]", i);
}
}
if (!table.ReadU8(&this->reserved7)) { return parent->Error("SILSub: Failed to read reserved7");
} if (this->reserved7 != 0) {
parent->Warning("SILSub: Nonzero reserved7");
}
}
if (!table.ReadU8(&this->numScriptTag)) { return parent->Error("SILSub: Failed to read numScriptTag");
} //this->scriptTag.resize(this->numScriptTag); for (unsigned i = 0; i < this->numScriptTag; ++i) {
this->scriptTag.emplace_back(); if (!table.ReadU32(&this->scriptTag[i])) { return parent->Error("SILSub: Failed to read scriptTag[%u]", i);
}
}
if (!table.ReadU16(&this->lbGID)) { return parent->Error("SILSub: Failed to read lbGID");
} if (this->lbGID > this->maxGlyphID) {
parent->Warning("SILSub: lbGID %u outside range 0..%u, replaced with 0",
this->lbGID, this->maxGlyphID);
this->lbGID = 0;
}
if (parent->version >> 16 >= 3 &&
table.offset() != init_offset + this->passOffset) { return parent->Error("SILSub: passOffset check failed");
} unsignedlong last_oPass = 0; //this->oPasses.resize(static_cast<unsigned>(this->numPasses) + 1); for (unsigned i = 0; i <= this->numPasses; ++i) {
this->oPasses.emplace_back(); if (!table.ReadU32(&this->oPasses[i]) || this->oPasses[i] < last_oPass) { returnfalse;
}
last_oPass = this->oPasses[i];
}
if (parent->version >> 16 >= 3 &&
table.offset() != init_offset + this->pseudosOffset) { return parent->Error("SILSub: pseudosOffset check failed");
} if (!table.ReadU16(&this->numPseudo)) { return parent->Error("SILSub: Failed to read numPseudo");
}
// The following three fields are deprecated and ignored. We fix them up here // just for internal consistency, but the Graphite engine doesn't care. if (!table.ReadU16(&this->searchPseudo) ||
!table.ReadU16(&this->pseudoSelector) ||
!table.ReadU16(&this->pseudoShift)) { return parent->Error("SILSub: Failed to read searchPseudo..pseudoShift");
} if (this->numPseudo == 0) { if (this->searchPseudo != 0 || this->pseudoSelector != 0 || this->pseudoShift != 0) {
this->searchPseudo = this->pseudoSelector = this->pseudoShift = 0;
}
} else { unsigned floorLog2 = std::floor(std::log2(this->numPseudo)); if (this->searchPseudo != 6 * (unsigned)std::pow(2, floorLog2) ||
this->pseudoSelector != floorLog2 ||
this->pseudoShift != 6 * this->numPseudo - this->searchPseudo) {
this->searchPseudo = 6 * (unsigned)std::pow(2, floorLog2);
this->pseudoSelector = floorLog2;
this->pseudoShift = 6 * this->numPseudo - this->searchPseudo;
}
}
//this->pMaps.resize(this->numPseudo, parent); for (unsigned i = 0; i < numPseudo; i++) {
this->pMaps.emplace_back(parent); if (!this->pMaps[i].ParsePart(table)) { return parent->Error("SILSub: Failed to read pMaps[%u]", i);
}
}
if (!this->classes.ParsePart(table)) { return parent->Error("SILSub: Failed to read classes");
}
//this->passes.resize(this->numPasses, parent); for (unsigned i = 0; i < this->numPasses; ++i) {
this->passes.emplace_back(parent); if (table.offset() != init_offset + this->oPasses[i]) { return parent->Error("SILSub: Offset check failed for passes[%u]", i);
} if (!this->passes[i].ParsePart(table, init_offset, this->oPasses[i+1])) { return parent->Error("SILSub: Failed to read passes[%u]", i);
}
} returntrue;
}
bool OpenTypeSILF::SILSub::ClassMap::LookupClass::
LookupPair::ParsePart(Buffer& table) { if (!table.ReadU16(&this->glyphId)) { return parent->Error("LookupPair: Failed to read glyphId");
} if (!table.ReadU16(&this->index)) { return parent->Error("LookupPair: Failed to read index");
} returntrue;
}
bool OpenTypeSILF::SILSub::ClassMap::LookupClass::
LookupPair::SerializePart(OTSStream* out) const { if (!out->WriteU16(this->glyphId) ||
!out->WriteU16(this->index)) { return parent->Error("LookupPair: Failed to write");
} returntrue;
}
bool OpenTypeSILF::SILSub::
SILPass::ParsePart(Buffer& table, const size_t SILSub_init_offset, const size_t next_pass_offset) {
size_t init_offset = table.offset(); if (!table.ReadU8(&this->flags)) { return parent->Error("SILPass: Failed to read flags"); // checks omitted
} if (!table.ReadU8(&this->maxRuleLoop)) { return parent->Error("SILPass: Failed to read valid maxRuleLoop");
} if (!table.ReadU8(&this->maxRuleContext)) { return parent->Error("SILPass: Failed to read maxRuleContext");
} if (!table.ReadU8(&this->maxBackup)) { return parent->Error("SILPass: Failed to read maxBackup");
} if (!table.ReadU16(&this->numRules)) { return parent->Error("SILPass: Failed to read numRules");
} if (parent->version >> 16 >= 2) { if (!table.ReadU16(&this->fsmOffset)) { return parent->Error("SILPass: Failed to read fsmOffset");
} if (!table.ReadU32(&this->pcCode) ||
(parent->version >= 3 && this->pcCode < this->fsmOffset)) { return parent->Error("SILPass: Failed to read pcCode");
}
} if (!table.ReadU32(&this->rcCode) ||
(parent->version >> 16 >= 2 && this->rcCode < this->pcCode)) { return parent->Error("SILPass: Failed to read valid rcCode");
} if (!table.ReadU32(&this->aCode) || this->aCode < this->rcCode) { return parent->Error("SILPass: Failed to read valid aCode");
} if (!table.ReadU32(&this->oDebug) ||
(this->oDebug && this->oDebug < this->aCode)) { return parent->Error("SILPass: Failed to read valid oDebug");
} if (parent->version >> 16 >= 3 &&
table.offset() != init_offset + this->fsmOffset) { return parent->Error("SILPass: fsmOffset check failed");
} if (!table.ReadU16(&this->numRows) ||
(this->oDebug && this->numRows < this->numRules)) { return parent->Error("SILPass: Failed to read valid numRows");
} if (!table.ReadU16(&this->numTransitional)) { return parent->Error("SILPass: Failed to read numTransitional");
} if (!table.ReadU16(&this->numSuccess)) { return parent->Error("SILPass: Failed to read numSuccess");
} if (!table.ReadU16(&this->numColumns)) { return parent->Error("SILPass: Failed to read numColumns");
} if (!table.ReadU16(&this->numRange)) { return parent->Error("SILPass: Failed to read numRange");
}
// The following three fields are deprecated and ignored. We fix them up here // just for internal consistency, but the Graphite engine doesn't care. if (!table.ReadU16(&this->searchRange) ||
!table.ReadU16(&this->entrySelector) ||
!table.ReadU16(&this->rangeShift)) { return parent->Error("SILPass: Failed to read searchRange..rangeShift");
} if (this->numRange == 0) { if (this->searchRange != 0 || this->entrySelector != 0 || this->rangeShift != 0) {
this->searchRange = this->entrySelector = this->rangeShift = 0;
}
} else { unsigned floorLog2 = std::floor(std::log2(this->numRange)); if (this->searchRange != 6 * (unsigned)std::pow(2, floorLog2) ||
this->entrySelector != floorLog2 ||
this->rangeShift != 6 * this->numRange - this->searchRange) {
this->searchRange = 6 * (unsigned)std::pow(2, floorLog2);
this->entrySelector = floorLog2;
this->rangeShift = 6 * this->numRange - this->searchRange;
}
}
//this->ranges.resize(this->numRange, parent); for (unsigned i = 0 ; i < this->numRange; ++i) {
this->ranges.emplace_back(parent); if (!this->ranges[i].ParsePart(table)) { return parent->Error("SILPass: Failed to read ranges[%u]", i);
}
} unsigned ruleMap_len = 0; // maximum value in oRuleMap //this->oRuleMap.resize(static_cast<unsigned long>(this->numSuccess) + 1); for (unsignedlong i = 0; i <= this->numSuccess; ++i) {
this->oRuleMap.emplace_back(); if (!table.ReadU16(&this->oRuleMap[i])) { return parent->Error("SILPass: Failed to read oRuleMap[%u]", i);
} if (oRuleMap[i] > ruleMap_len) {
ruleMap_len = oRuleMap[i];
}
}
//this->ruleMap.resize(ruleMap_len); for (unsigned i = 0; i < ruleMap_len; ++i) {
this->ruleMap.emplace_back(); if (!table.ReadU16(&this->ruleMap[i])) { return parent->Error("SILPass: Failed to read ruleMap[%u]", i);
}
}
if (!table.ReadU8(&this->minRulePreContext)) { return parent->Error("SILPass: Failed to read minRulePreContext");
} if (!table.ReadU8(&this->maxRulePreContext) ||
this->maxRulePreContext < this->minRulePreContext) { return parent->Error("SILPass: Failed to read valid maxRulePreContext");
}
unsigned startStates_len = this->maxRulePreContext - this->minRulePreContext
+ 1; // this->minRulePreContext <= this->maxRulePreContext //this->startStates.resize(startStates_len); for (unsigned i = 0; i < startStates_len; ++i) {
this->startStates.emplace_back(); if (!table.ReadS16(&this->startStates[i])) { return parent->Error("SILPass: Failed to read startStates[%u]", i);
}
}
//this->ruleSortKeys.resize(this->numRules); for (unsigned i = 0; i < this->numRules; ++i) {
this->ruleSortKeys.emplace_back(); if (!table.ReadU16(&this->ruleSortKeys[i])) { return parent->Error("SILPass: Failed to read ruleSortKeys[%u]", i);
}
}
//this->rulePreContext.resize(this->numRules); for (unsigned i = 0; i < this->numRules; ++i) {
this->rulePreContext.emplace_back(); if (!table.ReadU8(&this->rulePreContext[i])) { return parent->Error("SILPass: Failed to read rulePreContext[%u]", i);
}
}
if (parent->version >> 16 >= 2) { if (!table.ReadU8(&this->collisionThreshold)) { return parent->Error("SILPass: Failed to read collisionThreshold");
} if (!table.ReadU16(&this->pConstraint)) { return parent->Error("SILPass: Failed to read pConstraint");
}
}
unsignedlong ruleConstraints_len = this->aCode - this->rcCode; // this->rcCode <= this->aCode //this->oConstraints.resize(static_cast<unsigned long>(this->numRules) + 1); for (unsignedlong i = 0; i <= this->numRules; ++i) {
this->oConstraints.emplace_back(); if (!table.ReadU16(&this->oConstraints[i]) ||
this->oConstraints[i] > ruleConstraints_len) { return parent->Error("SILPass: Failed to read valid oConstraints[%lu]",
i);
}
}
if (!this->oDebug && this->aCode > next_pass_offset) { return parent->Error("SILPass: Failed to calculate length of actions");
} unsignedlong actions_len = this->oDebug ? this->oDebug - this->aCode :
next_pass_offset - this->aCode; // if this->oDebug, then this->aCode <= this->oDebug //this->oActions.resize(static_cast<unsigned long>(this->numRules) + 1); for (unsignedlong i = 0; i <= this->numRules; ++i) {
this->oActions.emplace_back(); if (!table.ReadU16(&this->oActions[i]) ||
(this->oActions[i] > actions_len)) { return parent->Error("SILPass: Failed to read valid oActions[%lu]", i);
}
}
//this->stateTrans.resize(this->numTransitional); for (unsigned i = 0; i < this->numTransitional; ++i) {
this->stateTrans.emplace_back(); //this->stateTrans[i].resize(this->numColumns); for (unsigned j = 0; j < this->numColumns; ++j) {
this->stateTrans[i].emplace_back(); if (!table.ReadU16(&stateTrans[i][j])) { return parent->Error("SILPass: Failed to read stateTrans[%u][%u]",
i, j);
}
}
}
if (parent->version >> 16 >= 2) { if (!table.ReadU8(&this->reserved2)) { return parent->Error("SILPass: Failed to read reserved2");
} if (this->reserved2 != 0) {
parent->Warning("SILPass: Nonzero reserved2");
}
if (table.offset() != SILSub_init_offset + this->pcCode) { return parent->Error("SILPass: pcCode check failed");
} //this->passConstraints.resize(this->pConstraint); for (unsigned i = 0; i < this->pConstraint; ++i) {
this->passConstraints.emplace_back(); if (!table.ReadU8(&this->passConstraints[i])) { return parent->Error("SILPass: Failed to read passConstraints[%u]", i);
}
}
}
if (table.offset() != SILSub_init_offset + this->rcCode) { return parent->Error("SILPass: rcCode check failed");
} //this->ruleConstraints.resize(ruleConstraints_len); // calculated above for (unsignedlong i = 0; i < ruleConstraints_len; ++i) {
this->ruleConstraints.emplace_back(); if (!table.ReadU8(&this->ruleConstraints[i])) { return parent->Error("SILPass: Failed to read ruleConstraints[%u]", i);
}
}
if (table.offset() != SILSub_init_offset + this->aCode) { return parent->Error("SILPass: aCode check failed");
} //this->actions.resize(actions_len); // calculated above for (unsignedlong i = 0; i < actions_len; ++i) {
this->actions.emplace_back(); if (!table.ReadU8(&this->actions[i])) { return parent->Error("SILPass: Failed to read actions[%u]", i);
}
}
if (this->oDebug) {
OpenTypeNAME* name = static_cast<OpenTypeNAME*>(
parent->GetFont()->GetTypedTable(OTS_TAG_NAME)); if (!name) { return parent->Error("SILPass: Required name table is missing");
}
if (table.offset() != SILSub_init_offset + this->oDebug) { return parent->Error("SILPass: oDebug check failed");
} //this->dActions.resize(this->numRules); for (unsigned i = 0; i < this->numRules; ++i) {
this->dActions.emplace_back(); if (!table.ReadU16(&this->dActions[i]) ||
!name->IsValidNameId(this->dActions[i])) { return parent->Error("SILPass: Failed to read valid dActions[%u]", i);
}
}
unsigned dStates_len = this->numRows - this->numRules; // this->numRules <= this->numRows //this->dStates.resize(dStates_len); for (unsigned i = 0; i < dStates_len; ++i) {
this->dStates.emplace_back(); if (!table.ReadU16(&this->dStates[i]) ||
!name->IsValidNameId(this->dStates[i])) { return parent->Error("SILPass: Failed to read valid dStates[%u]", i);
}
}
//this->dCols.resize(this->numRules); for (unsigned i = 0; i < this->numRules; ++i) {
this->dCols.emplace_back(); if (!table.ReadU16(&this->dCols[i]) ||
!name->IsValidNameId(this->dCols[i])) { return parent->Error("SILPass: Failed to read valid dCols[%u]");
}
}
} returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.