| Index: src/ots.cc
|
| ===================================================================
|
| --- src/ots.cc (revision 99)
|
| +++ src/ots.cc (working copy)
|
| @@ -14,12 +14,15 @@
|
| #include <map>
|
| #include <vector>
|
|
|
| +#include "woff2.h"
|
| +
|
| // The OpenType Font File
|
| // http://www.microsoft.com/typography/otspec/cmap.htm
|
|
|
| namespace {
|
|
|
| bool g_debug_output = true;
|
| +bool g_enable_woff2 = false;
|
|
|
| struct OpenTypeTable {
|
| uint32_t tag;
|
| @@ -29,15 +32,6 @@
|
| uint32_t uncompressed_length;
|
| };
|
|
|
| -// Round a value up to the nearest multiple of 4. Don't round the value in the
|
| -// case that rounding up overflows.
|
| -template<typename T> T Round4(T value) {
|
| - if (std::numeric_limits<T>::max() - value < 3) {
|
| - return value;
|
| - }
|
| - return (value + 3) & ~3;
|
| -}
|
| -
|
| bool CheckTag(uint32_t tag_value) {
|
| for (unsigned i = 0; i < 4; ++i) {
|
| const uint32_t check = tag_value & 0xff;
|
| @@ -151,15 +145,6 @@
|
| { 0, NULL, NULL, NULL, NULL, false },
|
| };
|
|
|
| -bool IsValidVersionTag(uint32_t tag) {
|
| - return tag == Tag("\x00\x01\x00\x00") ||
|
| - // OpenType fonts with CFF data have 'OTTO' tag.
|
| - tag == Tag("OTTO") ||
|
| - // Older Mac fonts might have 'true' or 'typ1' tag.
|
| - tag == Tag("true") ||
|
| - tag == Tag("typ1");
|
| -}
|
| -
|
| bool ProcessGeneric(ots::OpenTypeFile *header,
|
| uint32_t signature,
|
| ots::OTSStream *output,
|
| @@ -179,7 +164,7 @@
|
| if (!file.ReadTag(&header->version)) {
|
| return OTS_FAILURE();
|
| }
|
| - if (!IsValidVersionTag(header->version)) {
|
| + if (!ots::IsValidVersionTag(header->version)) {
|
| return OTS_FAILURE();
|
| }
|
|
|
| @@ -265,7 +250,7 @@
|
| if (!file.ReadTag(&header->version)) {
|
| return OTS_FAILURE();
|
| }
|
| - if (!IsValidVersionTag(header->version)) {
|
| + if (!ots::IsValidVersionTag(header->version)) {
|
| return OTS_FAILURE();
|
| }
|
|
|
| @@ -343,7 +328,7 @@
|
| return OTS_FAILURE();
|
| }
|
|
|
| - total_sfnt_size += Round4(table.uncompressed_length);
|
| + total_sfnt_size += ots::Round4(table.uncompressed_length);
|
| if (total_sfnt_size > std::numeric_limits<uint32_t>::max()) {
|
| return OTS_FAILURE();
|
| }
|
| @@ -359,7 +344,7 @@
|
| }
|
|
|
| // Table data must follow immediately after the header.
|
| - if (tables[first_index].offset != Round4(file.offset())) {
|
| + if (tables[first_index].offset != ots::Round4(file.offset())) {
|
| return OTS_FAILURE();
|
| }
|
|
|
| @@ -369,7 +354,7 @@
|
| }
|
| // Blocks must follow immediately after the previous block.
|
| // (Except for padding with a maximum of three null bytes)
|
| - uint64_t block_end = Round4(
|
| + uint64_t block_end = ots::Round4(
|
| static_cast<uint64_t>(tables[last_index].offset) +
|
| static_cast<uint64_t>(tables[last_index].length));
|
| if (block_end > std::numeric_limits<uint32_t>::max()) {
|
| @@ -379,8 +364,8 @@
|
| if (block_end != meta_offset) {
|
| return OTS_FAILURE();
|
| }
|
| - block_end = Round4(static_cast<uint64_t>(meta_offset) +
|
| - static_cast<uint64_t>(meta_length));
|
| + block_end = ots::Round4(static_cast<uint64_t>(meta_offset) +
|
| + static_cast<uint64_t>(meta_length));
|
| if (block_end > std::numeric_limits<uint32_t>::max()) {
|
| return OTS_FAILURE();
|
| }
|
| @@ -389,19 +374,38 @@
|
| if (block_end != priv_offset) {
|
| return OTS_FAILURE();
|
| }
|
| - block_end = Round4(static_cast<uint64_t>(priv_offset) +
|
| - static_cast<uint64_t>(priv_length));
|
| + block_end = ots::Round4(static_cast<uint64_t>(priv_offset) +
|
| + static_cast<uint64_t>(priv_length));
|
| if (block_end > std::numeric_limits<uint32_t>::max()) {
|
| return OTS_FAILURE();
|
| }
|
| }
|
| - if (block_end != Round4(length)) {
|
| + if (block_end != ots::Round4(length)) {
|
| return OTS_FAILURE();
|
| }
|
|
|
| return ProcessGeneric(header, woff_tag, output, data, length, tables, file);
|
| }
|
|
|
| +bool ProcessWOFF2(ots::OpenTypeFile *header,
|
| + ots::OTSStream *output, const uint8_t *data, size_t length) {
|
| + size_t decompressed_size = ots::ComputeWOFF2FinalSize(data, length);
|
| + if (decompressed_size == 0) {
|
| + return OTS_FAILURE();
|
| + }
|
| + // decompressed font must be <= 30MB
|
| + if (decompressed_size > 30 * 1024 * 1024) {
|
| + return OTS_FAILURE();
|
| + }
|
| +
|
| + std::vector<uint8_t> decompressed_buffer(decompressed_size);
|
| + if (!ots::ConvertWOFF2ToTTF(&decompressed_buffer[0], decompressed_size,
|
| + data, length)) {
|
| + return OTS_FAILURE();
|
| + }
|
| + return ProcessTTF(header, output, &decompressed_buffer[0], decompressed_size);
|
| +}
|
| +
|
| bool ProcessGeneric(ots::OpenTypeFile *header, uint32_t signature,
|
| ots::OTSStream *output,
|
| const uint8_t *data, size_t length,
|
| @@ -467,7 +471,7 @@
|
| uint32_t end_byte = tables[i].offset + tables[i].length;
|
| // Tables in the WOFF file must be aligned 4-byte boundary.
|
| if (signature == Tag("wOFF")) {
|
| - end_byte = Round4(end_byte);
|
| + end_byte = ots::Round4(end_byte);
|
| }
|
| if (!end_byte || end_byte > length) {
|
| return OTS_FAILURE();
|
| @@ -679,10 +683,23 @@
|
|
|
| namespace ots {
|
|
|
| +bool IsValidVersionTag(uint32_t tag) {
|
| + return tag == Tag("\x00\x01\x00\x00") ||
|
| + // OpenType fonts with CFF data have 'OTTO' tag.
|
| + tag == Tag("OTTO") ||
|
| + // Older Mac fonts might have 'true' or 'typ1' tag.
|
| + tag == Tag("true") ||
|
| + tag == Tag("typ1");
|
| +}
|
| +
|
| void DisableDebugOutput() {
|
| g_debug_output = false;
|
| }
|
|
|
| +void EnableWOFF2() {
|
| + g_enable_woff2 = true;
|
| +}
|
| +
|
| bool Process(OTSStream *output, const uint8_t *data, size_t length) {
|
| OpenTypeFile header;
|
| if (length < 4) {
|
| @@ -692,6 +709,10 @@
|
| bool result;
|
| if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F') {
|
| result = ProcessWOFF(&header, output, data, length);
|
| + } else if (g_enable_woff2 &&
|
| + data[0] == 'w' && data[1] == 'O' && data[2] == 'F' &&
|
| + data[3] == '2') {
|
| + result = ProcessWOFF2(&header, output, data, length);
|
| } else {
|
| result = ProcessTTF(&header, output, data, length);
|
| }
|
|
|