Adding TTC support, take 1

This commit is contained in:
Rod Sheeter
2015-02-24 13:53:35 -08:00
parent 445f541996
commit 1c975530b9
11 changed files with 1040 additions and 279 deletions
+70 -17
View File
@@ -26,6 +26,7 @@
#include "./round.h"
#include "./store_bytes.h"
#include "./table_tags.h"
#include "./woff2_common.h"
namespace woff2 {
@@ -123,6 +124,9 @@ bool MakeEditableBuffer(Font* font, int tableTag) {
if (table == NULL) {
return FONT_COMPRESSION_FAILURE();
}
if (table->IsReused()) {
return true;
}
int sz = Round4(table->length);
table->buffer.resize(sz);
uint8_t* buf = &table->buffer[0];
@@ -148,6 +152,15 @@ bool NormalizeGlyphs(Font* font) {
if (loca_table == NULL || glyf_table == NULL) {
return FONT_COMPRESSION_FAILURE();
}
// Must share neither or both loca & glyf
if (loca_table->IsReused() != glyf_table->IsReused()) {
return FONT_COMPRESSION_FAILURE();
}
if (loca_table->IsReused()) {
return true;
}
int index_fmt = head_table->data[51];
int num_glyphs = NumGlyphs(*font);
@@ -184,26 +197,16 @@ bool NormalizeGlyphs(Font* font) {
bool NormalizeOffsets(Font* font) {
uint32_t offset = 12 + 16 * font->num_tables;
for (auto& i : font->tables) {
i.second.offset = offset;
offset += Round4(i.second.length);
for (auto tag : font->OutputOrderedTags()) {
auto& table = font->tables[tag];
table.offset = offset;
offset += Round4(table.length);
}
return true;
}
namespace {
uint32_t ComputeChecksum(const uint8_t* buf, size_t size) {
uint32_t checksum = 0;
for (size_t i = 0; i < size; i += 4) {
checksum += ((buf[i] << 24) |
(buf[i + 1] << 16) |
(buf[i + 2] << 8) |
buf[i + 3]);
}
return checksum;
}
uint32_t ComputeHeaderChecksum(const Font& font) {
uint32_t checksum = font.flavor;
uint16_t max_pow2 = font.num_tables ? Log2Floor(font.num_tables) : 0;
@@ -224,6 +227,9 @@ uint32_t ComputeHeaderChecksum(const Font& font) {
bool FixChecksums(Font* font) {
Font::Table* head_table = font->FindTable(kHeadTableTag);
if (head_table->reuse_of != NULL) {
head_table = head_table->reuse_of;
}
if (head_table == NULL || head_table->length < 12) {
return FONT_COMPRESSION_FAILURE();
}
@@ -233,21 +239,68 @@ bool FixChecksums(Font* font) {
uint32_t file_checksum = 0;
for (auto& i : font->tables) {
Font::Table* table = &i.second;
table->checksum = ComputeChecksum(table->data, table->length);
if (table->IsReused()) {
table = table->reuse_of;
}
table->checksum = ComputeULongSum(table->data, table->length);
file_checksum += table->checksum;
}
file_checksum += ComputeHeaderChecksum(*font);
offset = 8;
StoreU32(0xb1b0afba - file_checksum, &offset, head_buf);
return true;
}
bool NormalizeFont(Font* font) {
bool NormalizeWithoutFixingChecksums(Font* font) {
return (MakeEditableBuffer(font, kHeadTableTag) &&
RemoveDigitalSignature(font) &&
NormalizeGlyphs(font) &&
NormalizeOffsets(font) &&
NormalizeOffsets(font));
}
bool NormalizeFont(Font* font) {
return (NormalizeWithoutFixingChecksums(font) &&
FixChecksums(font));
}
bool NormalizeFontCollection(FontCollection* font_collection) {
if (font_collection->fonts.size() == 1) {
return NormalizeFont(&font_collection->fonts[0]);
}
uint32_t offset = CollectionHeaderSize(font_collection->header_version,
font_collection->fonts.size());
for (auto& font : font_collection->fonts) {
if (!NormalizeWithoutFixingChecksums(&font)) {
fprintf(stderr, "Font normalization failed.\n");
return false;
}
offset += kSfntHeaderSize + kSfntEntrySize * font.num_tables;
}
// Start table offsets after TTC Header and Sfnt Headers
for (auto& font : font_collection->fonts) {
for (auto tag : font.OutputOrderedTags()) {
Font::Table& table = font.tables[tag];
if (table.IsReused()) {
table.offset = table.reuse_of->offset;
} else {
table.offset = offset;
offset += Round4(table.length);
}
}
}
// Now we can fix the checksums
for (auto& font : font_collection->fonts) {
if (!FixChecksums(&font)) {
fprintf(stderr, "Failed to fix checksums\n");
return false;
}
}
return true;
}
} // namespace woff2