Mark as transformed. Correct how table records were used by font.cc when writing collections.

This commit is contained in:
Rod Sheeter
2015-04-09 07:47:55 -07:00
parent 804d3b93a7
commit 90603761c7
2 changed files with 62 additions and 13 deletions
+21 -8
View File
@@ -223,20 +223,33 @@ bool WriteFont(const Font& font, uint8_t* dst, size_t dst_size) {
return WriteFont(font, &offset, dst, dst_size); return WriteFont(font, &offset, dst, dst_size);
} }
bool WriteTableRecord(const Font::Table* table, size_t* offset, uint8_t* dst,
size_t dst_size) {
if (dst_size < *offset + kSfntEntrySize) {
return FONT_COMPRESSION_FAILURE();
}
if (table->IsReused()) {
table = table->reuse_of;
}
StoreU32(table->tag, offset, dst);
StoreU32(table->checksum, offset, dst);
StoreU32(table->offset, offset, dst);
StoreU32(table->length, offset, dst);
return true;
}
bool WriteTable(const Font::Table& table, size_t* offset, uint8_t* dst, bool WriteTable(const Font::Table& table, size_t* offset, uint8_t* dst,
size_t dst_size) { size_t dst_size) {
StoreU32(table.tag, offset, dst); if (!WriteTableRecord(&table, offset, dst, dst_size)) {
StoreU32(table.checksum, offset, dst); return false;
StoreU32(table.offset, offset, dst);
StoreU32(table.length, offset, dst);
if (table.offset + table.length < table.offset ||
dst_size < table.offset + table.length) {
return FONT_COMPRESSION_FAILURE();
} }
// Write the actual table data if it's the first time we've seen it // Write the actual table data if it's the first time we've seen it
if (!table.IsReused()) { if (!table.IsReused()) {
if (table.offset + table.length < table.offset ||
dst_size < table.offset + table.length) {
return FONT_COMPRESSION_FAILURE();
}
memcpy(dst + table.offset, table.data, table.length); memcpy(dst + table.offset, table.data, table.length);
size_t padding_size = (4 - (table.length & 3)) & 3; size_t padding_size = (4 - (table.length & 3)) & 3;
if (table.offset + table.length + padding_size < padding_size || if (table.offset + table.length + padding_size < padding_size ||
+41 -5
View File
@@ -215,10 +215,14 @@ uint32_t ComputeHeaderChecksum(const Font& font) {
checksum += (font.num_tables << 16 | search_range); checksum += (font.num_tables << 16 | search_range);
checksum += (max_pow2 << 16 | range_shift); checksum += (max_pow2 << 16 | range_shift);
for (const auto& i : font.tables) { for (const auto& i : font.tables) {
checksum += i.second.tag; const Font::Table* table = &i.second;
checksum += i.second.checksum; if (table->IsReused()) {
checksum += i.second.offset; table = table->reuse_of;
checksum += i.second.length; }
checksum += table->tag;
checksum += table->checksum;
checksum += table->offset;
checksum += table->length;
} }
return checksum; return checksum;
} }
@@ -227,16 +231,21 @@ uint32_t ComputeHeaderChecksum(const Font& font) {
bool FixChecksums(Font* font) { bool FixChecksums(Font* font) {
Font::Table* head_table = font->FindTable(kHeadTableTag); Font::Table* head_table = font->FindTable(kHeadTableTag);
if (head_table == NULL) {
return FONT_COMPRESSION_FAILURE();
}
if (head_table->reuse_of != NULL) { if (head_table->reuse_of != NULL) {
head_table = head_table->reuse_of; head_table = head_table->reuse_of;
} }
if (head_table == NULL || head_table->length < 12) { if (head_table->length < 12) {
return FONT_COMPRESSION_FAILURE(); return FONT_COMPRESSION_FAILURE();
} }
uint8_t* head_buf = &head_table->buffer[0]; uint8_t* head_buf = &head_table->buffer[0];
size_t offset = 8; size_t offset = 8;
StoreU32(0, &offset, head_buf); StoreU32(0, &offset, head_buf);
uint32_t file_checksum = 0; uint32_t file_checksum = 0;
uint32_t head_checksum = 0;
for (auto& i : font->tables) { for (auto& i : font->tables) {
Font::Table* table = &i.second; Font::Table* table = &i.second;
if (table->IsReused()) { if (table->IsReused()) {
@@ -244,17 +253,44 @@ bool FixChecksums(Font* font) {
} }
table->checksum = ComputeULongSum(table->data, table->length); table->checksum = ComputeULongSum(table->data, table->length);
file_checksum += table->checksum; file_checksum += table->checksum;
if (table->tag == kHeadTableTag) {
head_checksum = table->checksum;
}
} }
file_checksum += ComputeHeaderChecksum(*font); file_checksum += ComputeHeaderChecksum(*font);
offset = 8; offset = 8;
StoreU32(0xb1b0afba - file_checksum, &offset, head_buf); StoreU32(0xb1b0afba - file_checksum, &offset, head_buf);
return true; return true;
} }
namespace {
bool MarkTransformed(Font* font) {
Font::Table* head_table = font->FindTable(kHeadTableTag);
if (head_table == NULL) {
return FONT_COMPRESSION_FAILURE();
}
if (head_table->reuse_of != NULL) {
head_table = head_table->reuse_of;
}
if (head_table->length < 17) {
return FONT_COMPRESSION_FAILURE();
}
// set bit 11 of head table 'flags' to indicate that font has undergone
// lossless modifying transform
int head_flags = head_table->data[16];
head_table->buffer[16] = head_flags | 0x08;
return true;
}
} // namespace
bool NormalizeWithoutFixingChecksums(Font* font) { bool NormalizeWithoutFixingChecksums(Font* font) {
return (MakeEditableBuffer(font, kHeadTableTag) && return (MakeEditableBuffer(font, kHeadTableTag) &&
RemoveDigitalSignature(font) && RemoveDigitalSignature(font) &&
MarkTransformed(font) &&
NormalizeGlyphs(font) && NormalizeGlyphs(font) &&
NormalizeOffsets(font)); NormalizeOffsets(font));
} }