Added Brotli compress/decompress utilities and makefiles
diff --git a/woff2/normalize.cc b/woff2/normalize.cc
new file mode 100644
index 0000000..ef9f158
--- /dev/null
+++ b/woff2/normalize.cc
@@ -0,0 +1,194 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Glyph normalization
+
+#include "./normalize.h"
+
+#include <inttypes.h>
+#include <stddef.h>
+
+#include "./ots.h"
+#include "./port.h"
+#include "./font.h"
+#include "./glyph.h"
+#include "./round.h"
+#include "./store_bytes.h"
+
+namespace woff2 {
+
+namespace {
+
+void StoreLoca(int index_fmt, uint32_t value, size_t* offset, uint8_t* dst) {
+ if (index_fmt == 0) {
+ Store16(value >> 1, offset, dst);
+ } else {
+ StoreU32(value, offset, dst);
+ }
+}
+
+void NormalizeSimpleGlyphBoundingBox(Glyph* glyph) {
+ if (glyph->contours.empty() || glyph->contours[0].empty()) {
+ return;
+ }
+ int16_t x_min = glyph->contours[0][0].x;
+ int16_t y_min = glyph->contours[0][0].y;
+ int16_t x_max = x_min;
+ int16_t y_max = y_min;
+ for (const auto& contour : glyph->contours) {
+ for (const auto& point : contour) {
+ if (point.x < x_min) x_min = point.x;
+ if (point.x > x_max) x_max = point.x;
+ if (point.y < y_min) y_min = point.y;
+ if (point.y > y_max) y_max = point.y;
+ }
+ }
+ glyph->x_min = x_min;
+ glyph->y_min = y_min;
+ glyph->x_max = x_max;
+ glyph->y_max = y_max;
+}
+
+} // namespace
+
+bool NormalizeGlyphs(Font* font) {
+ Font::Table* head_table = font->FindTable(kHeadTableTag);
+ Font::Table* glyf_table = font->FindTable(kGlyfTableTag);
+ Font::Table* loca_table = font->FindTable(kLocaTableTag);
+ if (head_table == NULL || loca_table == NULL || glyf_table == NULL) {
+ return OTS_FAILURE();
+ }
+ int index_fmt = head_table->data[51];
+ int num_glyphs = NumGlyphs(*font);
+
+ // We need to allocate a bit more than its original length for the normalized
+ // glyf table, since it can happen that the glyphs in the original table are
+ // 2-byte aligned, while in the normalized table they are 4-byte aligned.
+ // That gives a maximum of 2 bytes increase per glyph. However, there is no
+ // theoretical guarantee that the total size of the flags plus the coordinates
+ // is the smallest possible in the normalized version, so we have to allow
+ // some general overhead.
+ // TODO(user) Figure out some more precise upper bound on the size of
+ // the overhead.
+ size_t max_normalized_glyf_size = 1.1 * glyf_table->length + 2 * num_glyphs;
+
+ glyf_table->buffer.resize(max_normalized_glyf_size);
+ loca_table->buffer.resize(Round4(loca_table->length));
+ uint8_t* glyf_dst = &glyf_table->buffer[0];
+ uint8_t* loca_dst = &loca_table->buffer[0];
+ uint32_t glyf_offset = 0;
+ size_t loca_offset = 0;
+
+ for (int i = 0; i < num_glyphs; ++i) {
+ StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst);
+ Glyph glyph;
+ const uint8_t* glyph_data;
+ size_t glyph_size;
+ if (!GetGlyphData(*font, i, &glyph_data, &glyph_size) ||
+ (glyph_size > 0 && !ReadGlyph(glyph_data, glyph_size, &glyph))) {
+ return OTS_FAILURE();
+ }
+ NormalizeSimpleGlyphBoundingBox(&glyph);
+ size_t glyf_dst_size = glyf_table->buffer.size() - glyf_offset;
+ if (!StoreGlyph(glyph, glyf_dst + glyf_offset, &glyf_dst_size)) {
+ return OTS_FAILURE();
+ }
+ glyf_dst_size = Round4(glyf_dst_size);
+ if (glyf_dst_size > std::numeric_limits<uint32_t>::max() ||
+ glyf_offset + static_cast<uint32_t>(glyf_dst_size) < glyf_offset ||
+ (index_fmt == 0 && glyf_offset + glyf_dst_size >= (1UL << 17))) {
+ return OTS_FAILURE();
+ }
+ glyf_offset += glyf_dst_size;
+ }
+ StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst);
+
+ glyf_table->buffer.resize(glyf_offset);
+ glyf_table->data = &glyf_table->buffer[0];
+ glyf_table->length = glyf_offset;
+ loca_table->data = &loca_table->buffer[0];
+
+ return true;
+}
+
+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);
+ }
+ 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;
+ uint16_t search_range = max_pow2 ? 1 << (max_pow2 + 4) : 0;
+ uint16_t range_shift = (font.num_tables << 4) - search_range;
+ checksum += (font.num_tables << 16 | search_range);
+ checksum += (max_pow2 << 16 | range_shift);
+ for (const auto& i : font.tables) {
+ checksum += i.second.tag;
+ checksum += i.second.checksum;
+ checksum += i.second.offset;
+ checksum += i.second.length;
+ }
+ return checksum;
+}
+
+} // namespace
+
+bool FixChecksums(Font* font) {
+ Font::Table* head_table = font->FindTable(kHeadTableTag);
+ if (head_table == NULL || head_table->length < 12) {
+ return OTS_FAILURE();
+ }
+ head_table->buffer.resize(Round4(head_table->length));
+ uint8_t* head_buf = &head_table->buffer[0];
+ memcpy(head_buf, head_table->data, Round4(head_table->length));
+ head_table->data = head_buf;
+ size_t offset = 8;
+ StoreU32(0, &offset, head_buf);
+ uint32_t file_checksum = 0;
+ for (auto& i : font->tables) {
+ Font::Table* table = &i.second;
+ table->checksum = ComputeChecksum(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) {
+ return (NormalizeGlyphs(font) &&
+ NormalizeOffsets(font) &&
+ FixChecksums(font));
+}
+
+} // namespace woff2