// Copyright (c) 2022 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.
// Caller has sized the colorRecords array, so we know how much to try and read. bool ParseColorRecordsArray(const ots::Font* font, const uint8_t* data, size_t length,
std::vector<uint32_t>* colorRecords)
{
ots::Buffer subtable(data, length);
for (auto& color : *colorRecords) { if (!subtable.ReadU32(&color)) { return OTS_FAILURE_MSG("Failed to read color record");
}
}
returntrue;
}
// Caller has sized the paletteTypes array, so we know how much to try and read. bool ParsePaletteTypesArray(const ots::Font* font, const uint8_t* data, size_t length,
std::vector<uint32_t>* paletteTypes)
{
ots::Buffer subtable(data, length);
for (auto& type : *paletteTypes) { if (!subtable.ReadU32(&type)) { return OTS_FAILURE_MSG("Failed to read palette type");
} if (type & RESERVED) { // Should we treat this as failure? For now, just a warning; seems unlikely // to be dangerous.
OTS_WARNING("Invalid (reserved) palette type flags %08x", type);
type &= ~RESERVED;
}
}
returntrue;
}
// Caller has sized the labels array, so we know how much to try and read. bool ParseLabelsArray(const ots::Font* font, const uint8_t* data, size_t length,
std::vector<uint16_t>* labels, constchar* labelType)
{
ots::Buffer subtable(data, length);
auto* name = static_cast<ots::OpenTypeNAME*>(font->GetTypedTable(OTS_TAG_NAME)); if (!name) { return OTS_FAILURE_MSG("Required name table missing");
}
for (auto& nameID : *labels) { if (!subtable.ReadU16(&nameID)) { return OTS_FAILURE_MSG("Failed to read %s label ID", labelType);
} if (nameID != 0xffff) { if (!name->IsValidNameId(nameID)) {
OTS_WARNING("Label ID %u for %s missing from name table", nameID, labelType);
nameID = 0xffff;
}
}
}
// Header fields common to versions 0 and 1. These are recomputed // from the array sizes during serialization.
uint16_t numPalettes;
uint16_t numColorRecords;
uint32_t colorRecordsArrayOffset;
if (!table.ReadU16(&this->version) ||
!table.ReadU16(&this->num_palette_entries) ||
!table.ReadU16(&numPalettes) ||
!table.ReadU16(&numColorRecords) ||
!table.ReadU32(&colorRecordsArrayOffset)) { return Error("Failed to read CPAL table header");
}
if (this->version > 1) { return Error("Unknown CPAL table version %u", this->version);
}
if (!this->num_palette_entries || !numPalettes || !numColorRecords) { return Error("Empty CPAL is not valid");
}
if (this->num_palette_entries > numColorRecords) { return Error("Not enough color records for a complete palette");
}
// uint16_t colorRecordIndices[numPalettes]
this->colorRecordIndices.resize(numPalettes); for (auto& colorRecordIndex : this->colorRecordIndices) { if (!table.ReadU16(&colorRecordIndex)) { return Error("Failed to read color record index");
} if (colorRecordIndex > numColorRecords - this->num_palette_entries) { return Error("Palette overflows color records array");
}
}
// The following arrays may occur in any order, as they're independently referenced // by offsets in the header.
if (colorRecordsArrayOffset < headerSize || colorRecordsArrayOffset >= length) { return Error("Bad color records array offset in table header");
}
this->colorRecords.resize(numColorRecords); if (!ParseColorRecordsArray(font, data + colorRecordsArrayOffset, length - colorRecordsArrayOffset,
&this->colorRecords)) { return Error("Failed to parse color records array");
}
if (paletteTypesArrayOffset) { if (paletteTypesArrayOffset < headerSize || paletteTypesArrayOffset >= length) { return Error("Bad palette types array offset in table header");
}
this->paletteTypes.resize(numPalettes); if (!ParsePaletteTypesArray(font, data + paletteTypesArrayOffset, length - paletteTypesArrayOffset,
&this->paletteTypes)) { return Error("Failed to parse palette types array");
}
}
if (paletteLabelsArrayOffset) { if (paletteLabelsArrayOffset < headerSize || paletteLabelsArrayOffset >= length) { return Error("Bad palette labels array offset in table header");
}
this->paletteLabels.resize(numPalettes); if (!ParseLabelsArray(font, data + paletteLabelsArrayOffset, length - paletteLabelsArrayOffset,
&this->paletteLabels, "palette")) { return Error("Failed to parse palette labels array");
}
}
if (paletteEntryLabelsArrayOffset) { if (paletteEntryLabelsArrayOffset < headerSize || paletteEntryLabelsArrayOffset >= length) { return Error("Bad palette entry labels array offset in table header");
}
this->paletteEntryLabels.resize(this->num_palette_entries); if (!ParseLabelsArray(font, data + paletteEntryLabelsArrayOffset, length - paletteEntryLabelsArrayOffset,
&this->paletteEntryLabels, "palette entry")) { return Error("Failed to parse palette entry labels array");
}
}
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.