diff --git a/WORKSPACE b/WORKSPACE index aa239bbd939f..5f36dc210523 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -6,27 +6,6 @@ workspace(name = "carbon") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -############################################################################### -# Example conversion repositories -############################################################################### - -local_repository( - name = "brotli", - path = "third_party/examples/brotli/original", -) - -new_local_repository( - name = "woff2", - build_file = "third_party/examples/woff2/BUILD.original", - path = "third_party/examples/woff2/original", - workspace_file = "third_party/examples/woff2/WORKSPACE.original", -) - -local_repository( - name = "woff2_carbon", - path = "third_party/examples/woff2/carbon", -) - ############################################################################### # Treesitter rules ############################################################################### diff --git a/third_party/examples/woff2/BUILD.original b/third_party/examples/woff2/BUILD.original deleted file mode 100644 index 13aa377d1153..000000000000 --- a/third_party/examples/woff2/BUILD.original +++ /dev/null @@ -1,106 +0,0 @@ -# Part of the Carbon Language project, under the Apache License v2.0 with LLVM -# Exceptions. See /LICENSE for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -# Rules are adapted from CMakeLists.txt. - -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") - -package( - default_visibility = ["//visibility:public"], -) - -# Common part used by decoder and encoder -cc_library( - name = "woff2common", - srcs = [ - "src/table_tags.cc", - "src/variable_length.cc", - "src/woff2_common.cc", - ], - hdrs = [ - "src/buffer.h", - "src/file.h", - "src/port.h", - "src/round.h", - "src/store_bytes.h", - "src/table_tags.h", - "src/variable_length.h", - "src/woff2_common.h", - ], - strip_include_prefix = "src/", -) - -# WOFF2 Decoder -cc_library( - name = "woff2dec", - srcs = [ - "src/woff2_dec.cc", - "src/woff2_out.cc", - ], - hdrs = [ - "include/woff2/decode.h", - "include/woff2/output.h", - ], - copts = [ - "-Wno-unused-variable", - "-Wno-unused-const-variable", - ], - strip_include_prefix = "include/", - deps = [ - ":woff2common", - "@brotli//:brotlidec", - ], -) - -cc_binary( - name = "woff2_decompress", - srcs = ["src/woff2_decompress.cc"], - deps = [":woff2dec"], -) - -# WOFF2 Encoder -cc_library( - name = "woff2enc", - srcs = [ - "src/font.cc", - "src/font.h", - "src/glyph.cc", - "src/glyph.h", - "src/normalize.cc", - "src/normalize.h", - "src/transform.cc", - "src/transform.h", - "src/woff2_enc.cc", - ], - hdrs = [ - "include/woff2/encode.h", - ], - copts = [ - "-Wno-unused-variable", - "-Wno-unused-const-variable", - "-Wno-sign-compare", - ], - strip_include_prefix = "include/", - deps = [ - ":woff2common", - "@brotli//:brotlienc", - ], -) - -cc_binary( - name = "woff2_compress", - srcs = ["src/woff2_compress.cc"], - deps = [":woff2enc"], -) - -# WOFF2 info -cc_binary( - name = "woff2_info", - srcs = [ - "src/font.h", - "src/woff2_info.cc", - ], - copts = ["-Wno-sign-compare"], - deps = [":woff2common"], -) diff --git a/third_party/examples/woff2/WORKSPACE.original b/third_party/examples/woff2/WORKSPACE.original deleted file mode 100644 index d2fc05bde52f..000000000000 --- a/third_party/examples/woff2/WORKSPACE.original +++ /dev/null @@ -1,5 +0,0 @@ -# Part of the Carbon Language project, under the Apache License v2.0 with LLVM -# Exceptions. See /LICENSE for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -workspace(name = "woff2") diff --git a/third_party/examples/woff2/carbon/BUILD b/third_party/examples/woff2/carbon/BUILD deleted file mode 100644 index 13aa377d1153..000000000000 --- a/third_party/examples/woff2/carbon/BUILD +++ /dev/null @@ -1,106 +0,0 @@ -# Part of the Carbon Language project, under the Apache License v2.0 with LLVM -# Exceptions. See /LICENSE for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -# Rules are adapted from CMakeLists.txt. - -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") - -package( - default_visibility = ["//visibility:public"], -) - -# Common part used by decoder and encoder -cc_library( - name = "woff2common", - srcs = [ - "src/table_tags.cc", - "src/variable_length.cc", - "src/woff2_common.cc", - ], - hdrs = [ - "src/buffer.h", - "src/file.h", - "src/port.h", - "src/round.h", - "src/store_bytes.h", - "src/table_tags.h", - "src/variable_length.h", - "src/woff2_common.h", - ], - strip_include_prefix = "src/", -) - -# WOFF2 Decoder -cc_library( - name = "woff2dec", - srcs = [ - "src/woff2_dec.cc", - "src/woff2_out.cc", - ], - hdrs = [ - "include/woff2/decode.h", - "include/woff2/output.h", - ], - copts = [ - "-Wno-unused-variable", - "-Wno-unused-const-variable", - ], - strip_include_prefix = "include/", - deps = [ - ":woff2common", - "@brotli//:brotlidec", - ], -) - -cc_binary( - name = "woff2_decompress", - srcs = ["src/woff2_decompress.cc"], - deps = [":woff2dec"], -) - -# WOFF2 Encoder -cc_library( - name = "woff2enc", - srcs = [ - "src/font.cc", - "src/font.h", - "src/glyph.cc", - "src/glyph.h", - "src/normalize.cc", - "src/normalize.h", - "src/transform.cc", - "src/transform.h", - "src/woff2_enc.cc", - ], - hdrs = [ - "include/woff2/encode.h", - ], - copts = [ - "-Wno-unused-variable", - "-Wno-unused-const-variable", - "-Wno-sign-compare", - ], - strip_include_prefix = "include/", - deps = [ - ":woff2common", - "@brotli//:brotlienc", - ], -) - -cc_binary( - name = "woff2_compress", - srcs = ["src/woff2_compress.cc"], - deps = [":woff2enc"], -) - -# WOFF2 info -cc_binary( - name = "woff2_info", - srcs = [ - "src/font.h", - "src/woff2_info.cc", - ], - copts = ["-Wno-sign-compare"], - deps = [":woff2common"], -) diff --git a/third_party/examples/woff2/carbon/LICENSE b/third_party/examples/woff2/carbon/LICENSE deleted file mode 100644 index 4f9441b6e1b9..000000000000 --- a/third_party/examples/woff2/carbon/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013-2017 by the WOFF2 Authors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/third_party/examples/woff2/carbon/WORKSPACE b/third_party/examples/woff2/carbon/WORKSPACE deleted file mode 100644 index d2fc05bde52f..000000000000 --- a/third_party/examples/woff2/carbon/WORKSPACE +++ /dev/null @@ -1,5 +0,0 @@ -# Part of the Carbon Language project, under the Apache License v2.0 with LLVM -# Exceptions. See /LICENSE for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -workspace(name = "woff2") diff --git a/third_party/examples/woff2/carbon/include/woff2/decode.carbon b/third_party/examples/woff2/carbon/include/woff2/decode.carbon deleted file mode 100644 index 6d350dcd9b48..000000000000 --- a/third_party/examples/woff2/carbon/include/woff2/decode.carbon +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Library for converting WOFF2 format font files to their TTF versions. */ - -#ifndef WOFF2_WOFF2_DEC_H_ -#define WOFF2_WOFF2_DEC_H_ - -#include - -#include -#include - -namespace woff2 { - -// Compute the size of the final uncompressed font, or 0 on error. -fn ComputeWOFF2FinalSize(data: const uint8_t*, length: size_t) -> size_t; - -// Decompresses the font into the target buffer. The result_length should -// be the same as determined by ComputeFinalSize(). Returns true on successful -// decompression. -// DEPRECATED; please prefer the version that takes a WOFF2Out* -fn ConvertWOFF2ToTTF(result: uint8_t*, result_length: size_t, - data: const uint8_t*, length: size_t) -> bool; - -// Decompresses the font into out. Returns true on success. -// Works even if WOFF2Header totalSfntSize is wrong. -// Please prefer this API. -fn ConvertWOFF2ToTTF(data: const uint8_t*, length: size_t, - out: WOFF2Out*) -> bool; - -} // namespace woff2 - -#endif // WOFF2_WOFF2_DEC_H_ diff --git a/third_party/examples/woff2/carbon/include/woff2/encode.carbon b/third_party/examples/woff2/carbon/include/woff2/encode.carbon deleted file mode 100644 index 93a45ae3132a..000000000000 --- a/third_party/examples/woff2/carbon/include/woff2/encode.carbon +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Library for converting WOFF2 format font files to their TTF versions. */ - -#ifndef WOFF2_WOFF2_ENC_H_ -#define WOFF2_WOFF2_ENC_H_ - -#include -#include -#include - -namespace woff2 { - -struct WOFF2Params { - WOFF2Params() : extended_metadata("") - {} - - std::string extended_metadata; - int brotli_quality{11}; - bool allow_transforms{true}; -}; - -// Returns an upper bound on the size of the compressed file. -fn MaxWOFF2CompressedSize(data: const uint8_t*, length: size_t) -> size_t; -fn MaxWOFF2CompressedSize(data: const uint8_t*, length: size_t, - extended_metadata: const std::string&) -> size_t; - -// Compresses the font into the target buffer. *result_length should be at least -// the value returned by MaxWOFF2CompressedSize(), upon return, it is set to the -// actual compressed size. Returns true on successful compression. -fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t, - result: uint8_t*, result_length: size_t*) -> bool; -fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t, - result: uint8_t*, result_length: size_t*, - params: const WOFF2Params&) -> bool; - -} // namespace woff2 - -#endif // WOFF2_WOFF2_ENC_H_ diff --git a/third_party/examples/woff2/carbon/include/woff2/output.carbon b/third_party/examples/woff2/carbon/include/woff2/output.carbon deleted file mode 100644 index b2852d667e31..000000000000 --- a/third_party/examples/woff2/carbon/include/woff2/output.carbon +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright 2016 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Output buffer for WOFF2 decompression. */ - -#ifndef WOFF2_WOFF2_OUT_H_ -#define WOFF2_WOFF2_OUT_H_ - -#include -#include -#include -#include - -namespace woff2 { - -// Suggested max size for output. -let kDefaultMaxSize: const size_t = 30 * 1024 * 1024; - -/** - * Output interface for the woff2 decoding. - * - * Writes to arbitrary offsets are supported to facilitate updating offset - * table and checksums after tables are ready. Reading the current size is - * supported so a 'loca' table can be built up while writing glyphs. - * - * By default limits size to kDefaultMaxSize. - */ -class WOFF2Out { - public: - virtual ~WOFF2Out() = default; - - // Append n bytes of data from buf. - // Return true if all written, false otherwise. - fn virtual Write(buf: const void*, n: size_t) -> bool = 0; - - // Write n bytes of data from buf at offset. - // Return true if all written, false otherwise. - fn virtual Write(buf: const void*, offset: size_t, n: size_t) -> bool = 0; - - fn virtual Size() -> size_t = 0; -}; - -/** - * Expanding memory block for woff2 out. By default limited to kDefaultMaxSize. - */ -class WOFF2StringOut : public WOFF2Out { - public: - // Create a writer that writes its data to buf. - // buf->size() will grow to at most max_size - // buf may be sized (e.g. using EstimateWOFF2FinalSize) or empty. - explicit WOFF2StringOut(buf: std::string*); - - fn Write(buf: const void*, n: size_t) -> bool override; - fn Write(buf: const void*, offset: size_t, n: size_t) -> bool override; - fn Size() -> size_t override { return offset_; } - fn MaxSize() -> size_t { return max_size_; } - fn SetMaxSize(max_size: size_t); - private: - std::string* buf_; - size_t max_size_; - size_t offset_; -}; - -/** - * Fixed memory block for woff2 out. - */ -class WOFF2MemoryOut : public WOFF2Out { - public: - // Create a writer that writes its data to buf. - WOFF2MemoryOut(buf: uint8_t*, buf_size: size_t); - - fn Write(buf: const void*, n: size_t) -> bool override; - fn Write(buf: const void*, offset: size_t, n: size_t) -> bool override; - fn Size() -> size_t override { return offset_; } - private: - uint8_t* buf_; - size_t buf_size_; - size_t offset_; -}; - -} // namespace woff2 - -#endif // WOFF2_WOFF2_OUT_H_ diff --git a/third_party/examples/woff2/carbon/src/buffer.carbon b/third_party/examples/woff2/carbon/src/buffer.carbon deleted file mode 100644 index a72e71fc5d25..000000000000 --- a/third_party/examples/woff2/carbon/src/buffer.carbon +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* The parts of ots.h & opentype-sanitiser.h that we need, taken from the - https://code.google.com/p/ots/ project. */ - -#ifndef WOFF2_BUFFER_H_ -#define WOFF2_BUFFER_H_ - -#if defined(_WIN32) -#include -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#define ntohl(x) _byteswap_ulong (x) -#define ntohs(x) _byteswap_ushort (x) -#define htonl(x) _byteswap_ulong (x) -#define htons(x) _byteswap_ushort (x) -#else -#include - -#include -#endif - -#include -#include -#include -#include - -namespace woff2 { - -#if defined(_MSC_VER) || !defined(FONT_COMPRESSION_DEBUG) -#define FONT_COMPRESSION_FAILURE() false -#else -#define FONT_COMPRESSION_FAILURE() \ - woff2::Failure(__FILE__, __LINE__, __PRETTY_FUNCTION__) -inline bool Failure(const char *f, int l, const char *fn) { - fprintf(stderr, "ERROR at %s:%d (%s)\n", f, l, fn); - fflush(stderr); - return false; -} -#endif - -// ----------------------------------------------------------------------------- -// Buffer helper class -// -// This class perform some trival buffer operations while checking for -// out-of-bounds errors. As a family they return false if anything is amiss, -// updating the current offset otherwise. -// ----------------------------------------------------------------------------- -class Buffer { - public: - Buffer(data: const uint8_t*, len: size_t) - : buffer_(data), - length_(len), - offset_(0) { } - - fn Skip(n_bytes: size_t) -> bool { - return Read(nullptr, n_bytes); - } - - fn Read(data: uint8_t*, n_bytes: size_t) -> bool { - if (n_bytes > 1024 * 1024 * 1024) { - return FONT_COMPRESSION_FAILURE(); - } - if ((offset_ + n_bytes > length_) || - (offset_ > length_ - n_bytes)) { - return FONT_COMPRESSION_FAILURE(); - } - if (data) { - std::memcpy(data, buffer_ + offset_, n_bytes); - } - offset_ += n_bytes; - return true; - } - - fn inline ReadU8(value: uint8_t*) -> bool { - if (offset_ + 1 > length_) { - return FONT_COMPRESSION_FAILURE(); - } - *value = buffer_[offset_]; - ++offset_; - return true; - } - - fn ReadU16(value: uint16_t*) -> bool { - if (offset_ + 2 > length_) { - return FONT_COMPRESSION_FAILURE(); - } - std::memcpy(value, buffer_ + offset_, sizeof(uint16_t)); - *value = ntohs(*value); - offset_ += 2; - return true; - } - - fn ReadS16(value: int16_t*) -> bool { - return ReadU16(reinterpret_cast(value)); - } - - fn ReadU24(value: uint32_t*) -> bool { - if (offset_ + 3 > length_) { - return FONT_COMPRESSION_FAILURE(); - } - *value = static_cast(buffer_[offset_]) << 16 | - static_cast(buffer_[offset_ + 1]) << 8 | - static_cast(buffer_[offset_ + 2]); - offset_ += 3; - return true; - } - - fn ReadU32(value: uint32_t*) -> bool { - if (offset_ + 4 > length_) { - return FONT_COMPRESSION_FAILURE(); - } - std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); - *value = ntohl(*value); - offset_ += 4; - return true; - } - - fn ReadS32(value: int32_t*) -> bool { - return ReadU32(reinterpret_cast(value)); - } - - fn ReadTag(value: uint32_t*) -> bool { - if (offset_ + 4 > length_) { - return FONT_COMPRESSION_FAILURE(); - } - std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); - offset_ += 4; - return true; - } - - fn ReadR64(value: uint64_t*) -> bool { - if (offset_ + 8 > length_) { - return FONT_COMPRESSION_FAILURE(); - } - std::memcpy(value, buffer_ + offset_, sizeof(uint64_t)); - offset_ += 8; - return true; - } - - [[nodiscard]] fn buffer() const -> const uint8_t * { return buffer_; } - [[nodiscard]] fn offset() const -> size_t { return offset_; } - [[nodiscard]] fn length() const -> size_t { return length_; } - - fn set_offset(newoffset: size_t) { offset_ = newoffset; } - - private: - const uint8_t * const buffer_; - const size_t length_; - size_t offset_; -}; - -} // namespace woff2 - -#endif // WOFF2_BUFFER_H_ diff --git a/third_party/examples/woff2/carbon/src/convert_woff2ttf_fuzzer.impl.carbon b/third_party/examples/woff2/carbon/src/convert_woff2ttf_fuzzer.impl.carbon deleted file mode 100644 index c555dfb7235e..000000000000 --- a/third_party/examples/woff2/carbon/src/convert_woff2ttf_fuzzer.impl.carbon +++ /dev/null @@ -1,13 +0,0 @@ -#include - -#include -#include - -// Entry point for LibFuzzer. -extern "C" fn LLVMFuzzerTestOneInput(data: const uint8_t*, size: size_t) -> int { - var buf: std::string; - var out: woff2::WOFF2StringOut(&buf); - out.SetMaxSize(30 * 1024 * 1024); - woff2::ConvertWOFF2ToTTF(data, size, &out); - return 0; -} diff --git a/third_party/examples/woff2/carbon/src/convert_woff2ttf_fuzzer_new_entry.impl.carbon b/third_party/examples/woff2/carbon/src/convert_woff2ttf_fuzzer_new_entry.impl.carbon deleted file mode 100644 index 65114d0bf20c..000000000000 --- a/third_party/examples/woff2/carbon/src/convert_woff2ttf_fuzzer_new_entry.impl.carbon +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -extern "C" fn LLVMFuzzerTestOneInput(data: const uint8_t*, data_size: size_t) -> int { - // Decode using newer entry pattern. - // Same pattern as woff2_decompress. - var output: std::string(std::min(woff2::ComputeWOFF2FinalSize(data, data_size), - woff2::kDefaultMaxSize), 0); - var out: woff2::WOFF2StringOut(&output); - woff2::ConvertWOFF2ToTTF(data, data_size, &out); - return 0; -} diff --git a/third_party/examples/woff2/carbon/src/file.carbon b/third_party/examples/woff2/carbon/src/file.carbon deleted file mode 100644 index bebf76b2b493..000000000000 --- a/third_party/examples/woff2/carbon/src/file.carbon +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* File IO helpers. */ - -#ifndef WOFF2_FILE_H_ -#define WOFF2_FILE_H_ - -#include -#include - -namespace woff2 { - -using std::string; - - -fn inline GetFileContent(filename: const string&) -> string { - var ifs: std::ifstream(filename.c_str(), std::ios::binary); - return string( - std::istreambuf_iterator(ifs.rdbuf()), - std::istreambuf_iterator()); -} - -fn inline SetFileContents(filename: const string&, start: string::iterator, - end: string::iterator) { - var ofs: std::ofstream(filename.c_str(), std::ios::binary); - std::copy(start, end, std::ostream_iterator(ofs)); -} - -} // namespace woff2 -#endif // WOFF2_FILE_H_ diff --git a/third_party/examples/woff2/carbon/src/font.carbon b/third_party/examples/woff2/carbon/src/font.carbon deleted file mode 100644 index 76f129a908cf..000000000000 --- a/third_party/examples/woff2/carbon/src/font.carbon +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Data model for a font file in sfnt format, reading and writing functions and - accessors for the glyph data. */ - -#ifndef WOFF2_FONT_H_ -#define WOFF2_FONT_H_ - -#include -#include -#include -#include - -namespace woff2 { - -// Represents an sfnt font file. Only the table directory is parsed, for the -// table data we only store a raw pointer, therefore a font object is valid only -// as long the data from which it was parsed is around. -struct Font { - uint32_t flavor; - uint16_t num_tables; - - struct Table { - uint32_t tag; - uint32_t checksum; - uint32_t offset; - uint32_t length; - const uint8_t* data; - - // Buffer used to mutate the data before writing out. - std::vector buffer; - - // If we've seen this tag/offset before, pointer to the first time we saw it - // If this is the first time we've seen this table, NULL - // Intended use is to bypass re-processing tables - Font::Table* reuse_of; - - uint8_t flag_byte; - - // Is this table reused by a TTC - [[nodiscard]] fn IsReused() const -> bool; - }; - std::map tables; - [[nodiscard]] fn OutputOrderedTags() const -> std::vector; - - fn FindTable(tag: uint32_t) -> Table*; - [[nodiscard]] fn FindTable(tag: uint32_t) const -> const Table*; -}; - -// Accommodates both singular (OTF, TTF) and collection (TTC) fonts -struct FontCollection { - uint32_t flavor; - uint32_t header_version; - // (offset, first use of table*) pairs - std::map tables; - std::vector fonts; -}; - -// Parses the font from the given data. Returns false on parsing failure or -// buffer overflow. The font is valid only so long the input data pointer is -// valid. Does NOT support collections. -fn ReadFont(data: const uint8_t*, len: size_t, font: Font*) -> bool; - -// Parses the font from the given data. Returns false on parsing failure or -// buffer overflow. The font is valid only so long the input data pointer is -// valid. Supports collections. -fn ReadFontCollection(data: const uint8_t*, len: size_t, fonts: FontCollection*) -> bool; - -// Returns the file size of the font. -fn FontFileSize(font: const Font&) -> size_t; -fn FontCollectionFileSize(font: const FontCollection&) -> size_t; - -// Writes the font into the specified dst buffer. The dst_size should be the -// same as returned by FontFileSize(). Returns false upon buffer overflow (which -// should not happen if dst_size was computed by FontFileSize()). -fn WriteFont(font: const Font&, dst: uint8_t*, dst_size: size_t) -> bool; -// Write the font at a specific offset -fn WriteFont(font: const Font&, offset: size_t*, dst: uint8_t*, dst_size: size_t) -> bool; - -fn WriteFontCollection(font_collection: const FontCollection&, dst: uint8_t*, - dst_size: size_t) -> bool; - -// Returns the number of glyphs in the font. -// NOTE: Currently this works only for TrueType-flavored fonts, will return -// zero for CFF-flavored fonts. -fn NumGlyphs(font: const Font&) -> int; - -// Returns the index format of the font -fn IndexFormat(font: const Font&) -> int; - -// Sets *glyph_data and *glyph_size to point to the location of the glyph data -// with the given index. Returns false if the glyph is not found. -fn GetGlyphData(font: const Font&, glyph_index: int, - glyph_data: const uint8_t**, glyph_size: size_t*) -> bool; - -// Removes the digital signature (DSIG) table -fn RemoveDigitalSignature(font: Font*) -> bool; - -} // namespace woff2 - -#endif // WOFF2_FONT_H_ diff --git a/third_party/examples/woff2/carbon/src/font.impl.carbon b/third_party/examples/woff2/carbon/src/font.impl.carbon deleted file mode 100644 index 21573db93e19..000000000000 --- a/third_party/examples/woff2/carbon/src/font.impl.carbon +++ /dev/null @@ -1,399 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Font management utilities */ - -#include "./font.h" - -#include - -#include "./buffer.h" -#include "./port.h" -#include "./store_bytes.h" -#include "./table_tags.h" -#include "./woff2_common.h" - -namespace woff2 { - -fn Font::FindTable(tag: uint32_t) -> Font::Table* { - var it: auto = tables.find(tag); - return it == tables.end() ? nullptr : &it->second; -} - -fn Font::FindTable(tag: uint32_t) const -> const Font::Table* { - var it: auto = tables.find(tag); - return it == tables.end() ? nullptr : &it->second; -} - -fn Font::OutputOrderedTags() const -> std::vector { - var output_order: std::vector; - - for (const auto& i in tables) { - var table: const Font::Table& = i.second; - // This is a transformed table, we will write it together with the - // original version. - if (table.tag & 0x80808080) { - continue; - } - output_order.push_back(table.tag); - } - - // Alphabetize then put loca immediately after glyf - var glyf_loc: auto = std::find(output_order.begin(), output_order.end(), - kGlyfTableTag); - var loca_loc: auto = std::find(output_order.begin(), output_order.end(), - kLocaTableTag); - if (glyf_loc != output_order.end() && loca_loc != output_order.end()) { - output_order.erase(loca_loc); - output_order.insert(std::find(output_order.begin(), output_order.end(), - kGlyfTableTag) + 1, kLocaTableTag); - } - - return output_order; -} - -fn ReadTrueTypeFont(file: Buffer*, data: const uint8_t*, len: size_t, - font: Font*) -> bool { - // We don't care about the search_range, entry_selector and range_shift - // fields, they will always be computed upon writing the font. - if (!file->ReadU16(&font->num_tables) || - !file->Skip(6)) { - return FONT_COMPRESSION_FAILURE(); - } - - var intervals: std::map; - for (var i: uint16_t = 0; i < font->num_tables; ++i) { - var table: Font::Table; - table.flag_byte = 0; - table.reuse_of = nullptr; - if (!file->ReadU32(&table.tag) || - !file->ReadU32(&table.checksum) || - !file->ReadU32(&table.offset) || - !file->ReadU32(&table.length)) { - return FONT_COMPRESSION_FAILURE(); - } - if ((table.offset & 3) != 0 || - table.length > len || - len - table.length < table.offset) { - return FONT_COMPRESSION_FAILURE(); - } - intervals[table.offset] = table.length; - table.data = data + table.offset; - if (font->tables.find(table.tag) != font->tables.end()) { - return FONT_COMPRESSION_FAILURE(); - } - font->tables[table.tag] = table; - } - - // Check that tables are non-overlapping. - var last_offset: uint32_t = 12UL + 16UL * font->num_tables; - for (const auto& i in intervals) { - if (i.first < last_offset || i.first + i.second < i.first) { - return FONT_COMPRESSION_FAILURE(); - } - last_offset = i.first + i.second; - } - - // Sanity check key tables - var head_table: const Font::Table* = font->FindTable(kHeadTableTag); - if (head_table != nullptr && head_table->length < 52) { - return FONT_COMPRESSION_FAILURE(); - } - - return true; -} - -fn ReadCollectionFont(file: Buffer*, data: const uint8_t*, len: size_t, - font: Font*, - all_tables: std::map*) -> bool { - if (!file->ReadU32(&font->flavor)) { - return FONT_COMPRESSION_FAILURE(); - } - if (!ReadTrueTypeFont(file, data, len, font)) { - return FONT_COMPRESSION_FAILURE(); - } - - for (auto& entry in font->tables) { - var table: Font::Table& = entry.second; - - if (all_tables->find(table.offset) == all_tables->end()) { - (*all_tables)[table.offset] = font->FindTable(table.tag); - } else { - table.reuse_of = (*all_tables)[table.offset]; - if (table.tag != table.reuse_of->tag) { - return FONT_COMPRESSION_FAILURE(); - } - } - - } - return true; -} - -fn ReadTrueTypeCollection(file: Buffer*, data: const uint8_t*, len: size_t, - font_collection: FontCollection*) -> bool { - var num_fonts: uint32_t; - - if (!file->ReadU32(&font_collection->header_version) || - !file->ReadU32(&num_fonts)) { - return FONT_COMPRESSION_FAILURE(); - } - - var offsets: std::vector; - for (var i: size_t = 0; i < num_fonts; i++) { - var offset: uint32_t; - if (!file->ReadU32(&offset)) { - return FONT_COMPRESSION_FAILURE(); - } - offsets.push_back(offset); - } - - font_collection->fonts.resize(offsets.size()); - var font_it: auto = font_collection->fonts.begin(); - - var all_tables: std::map; - for (const auto offset in offsets) { - file->set_offset(offset); - var font: Font& = *font_it++; - if (!ReadCollectionFont(file, data, len, &font, &all_tables)) { - return FONT_COMPRESSION_FAILURE(); - } - } - - return true; -} - -fn ReadFont(data: const uint8_t*, len: size_t, font: Font*) -> bool { - var file: Buffer(data, len); - - if (!file.ReadU32(&font->flavor)) { - return FONT_COMPRESSION_FAILURE(); - } - - if (font->flavor == kTtcFontFlavor) { - return FONT_COMPRESSION_FAILURE(); - } - return ReadTrueTypeFont(&file, data, len, font); -} - -fn ReadFontCollection(data: const uint8_t*, len: size_t, - font_collection: FontCollection*) -> bool { - var file: Buffer(data, len); - - if (!file.ReadU32(&font_collection->flavor)) { - return FONT_COMPRESSION_FAILURE(); - } - - if (font_collection->flavor != kTtcFontFlavor) { - font_collection->fonts.resize(1); - var font: Font& = font_collection->fonts[0]; - font.flavor = font_collection->flavor; - return ReadTrueTypeFont(&file, data, len, &font); - } - return ReadTrueTypeCollection(&file, data, len, font_collection); -} - -fn FontFileSize(font: const Font&) -> size_t { - var max_offset: size_t = 12ULL + 16ULL * font.num_tables; - for (const auto& i in font.tables) { - var table: const Font::Table& = i.second; - var padding_size: size_t = (4 - (table.length & 3)) & 3; - var end_offset: size_t = (padding_size + table.offset) + table.length; - max_offset = std::max(max_offset, end_offset); - } - return max_offset; -} - -fn FontCollectionFileSize(font_collection: const FontCollection&) -> size_t { - var max_offset: size_t = 0; - for (auto& font in font_collection.fonts) { - // font file size actually just finds max offset - max_offset = std::max(max_offset, FontFileSize(font)); - } - return max_offset; -} - -fn WriteFont(font: const Font&, dst: uint8_t*, dst_size: size_t) -> bool { - var offset: size_t = 0; - return WriteFont(font, &offset, dst, dst_size); -} - -fn WriteTableRecord(table: const Font::Table*, offset: size_t*, dst: uint8_t*, - dst_size: size_t) -> bool { - 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; -} - -fn WriteTable(table: const Font::Table&, offset: size_t*, dst: uint8_t*, - dst_size: size_t) -> bool { - if (!WriteTableRecord(&table, offset, dst, dst_size)) { - return false; - } - - // Write the actual table data if it's the first time we've seen it - 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); - var padding_size: size_t = (4 - (table.length & 3)) & 3; - if (table.offset + table.length + padding_size < padding_size || - dst_size < table.offset + table.length + padding_size) { - return FONT_COMPRESSION_FAILURE(); - } - memset(dst + table.offset + table.length, 0, padding_size); - } - return true; -} - -fn WriteFont(font: const Font&, offset: size_t*, dst: uint8_t*, - dst_size: size_t) -> bool { - if (dst_size < 12ULL + 16ULL * font.num_tables) { - return FONT_COMPRESSION_FAILURE(); - } - StoreU32(font.flavor, offset, dst); - Store16(font.num_tables, offset, dst); - var max_pow2: uint16_t = font.num_tables ? Log2Floor(font.num_tables) : 0; - var search_range: uint16_t = max_pow2 ? 1 << (max_pow2 + 4) : 0; - var range_shift: uint16_t = (font.num_tables << 4) - search_range; - Store16(search_range, offset, dst); - Store16(max_pow2, offset, dst); - Store16(range_shift, offset, dst); - - for (const auto& i in font.tables) { - if (!WriteTable(i.second, offset, dst, dst_size)) { - return false; - } - } - - return true; -} - -fn WriteFontCollection(font_collection: const FontCollection&, dst: uint8_t*, - dst_size: size_t) -> bool { - var offset: size_t = 0; - - // It's simpler if this just a simple sfnt - if (font_collection.flavor != kTtcFontFlavor) { - return WriteFont(font_collection.fonts[0], &offset, dst, dst_size); - } - - // Write TTC header - StoreU32(kTtcFontFlavor, &offset, dst); - StoreU32(font_collection.header_version, &offset, dst); - StoreU32(font_collection.fonts.size(), &offset, dst); - - // Offset Table, zeroed for now - var offset_table: size_t = offset; // where to write offsets later - for (var i: size_t = 0; i < font_collection.fonts.size(); i++) { - StoreU32(0, &offset, dst); - } - - if (font_collection.header_version == 0x00020000) { - StoreU32(0, &offset, dst); // ulDsigTag - StoreU32(0, &offset, dst); // ulDsigLength - StoreU32(0, &offset, dst); // ulDsigOffset - } - - // Write fonts and their offsets. - for (const auto & font in font_collection.fonts) { - StoreU32(offset, &offset_table, dst); - if (!WriteFont(font, &offset, dst, dst_size)) { - return false; - } - } - - return true; -} - -fn NumGlyphs(font: const Font&) -> int { - var head_table: const Font::Table* = font.FindTable(kHeadTableTag); - var loca_table: const Font::Table* = font.FindTable(kLocaTableTag); - if (head_table == nullptr || loca_table == nullptr || head_table->length < 52) { - return 0; - } - var index_fmt: int = IndexFormat(font); - var loca_record_size: int = (index_fmt == 0 ? 2 : 4); - if (loca_table->length < loca_record_size) { - return 0; - } - return (loca_table->length / loca_record_size) - 1; -} - -fn IndexFormat(font: const Font&) -> int { - var head_table: const Font::Table* = font.FindTable(kHeadTableTag); - if (head_table == nullptr) { - return 0; - } - return head_table->data[51]; -} - -fn Font::Table::IsReused() const -> bool { - return this->reuse_of != nullptr; -} - -fn GetGlyphData(font: const Font&, glyph_index: int, - glyph_data: const uint8_t**, glyph_size: size_t*) -> bool { - if (glyph_index < 0) { - return FONT_COMPRESSION_FAILURE(); - } - var head_table: const Font::Table* = font.FindTable(kHeadTableTag); - var loca_table: const Font::Table* = font.FindTable(kLocaTableTag); - var glyf_table: const Font::Table* = font.FindTable(kGlyfTableTag); - if (head_table == nullptr || loca_table == nullptr || glyf_table == nullptr || - head_table->length < 52) { - return FONT_COMPRESSION_FAILURE(); - } - - var index_fmt: int = IndexFormat(font); - - var loca_buf: Buffer(loca_table->data, loca_table->length); - if (index_fmt == 0) { - var offset1: uint16_t, var offset2: uint16_t; - if (!loca_buf.Skip(2 * glyph_index) || - !loca_buf.ReadU16(&offset1) || - !loca_buf.ReadU16(&offset2) || - offset2 < offset1 || - 2 * offset2 > glyf_table->length) { - return FONT_COMPRESSION_FAILURE(); - } - *glyph_data = glyf_table->data + 2 * offset1; - *glyph_size = 2 * (offset2 - offset1); - } else { - var offset1: uint32_t, var offset2: uint32_t; - if (!loca_buf.Skip(4 * glyph_index) || - !loca_buf.ReadU32(&offset1) || - !loca_buf.ReadU32(&offset2) || - offset2 < offset1 || - offset2 > glyf_table->length) { - return FONT_COMPRESSION_FAILURE(); - } - *glyph_data = glyf_table->data + offset1; - *glyph_size = offset2 - offset1; - } - return true; -} - -fn RemoveDigitalSignature(font: Font*) -> bool { - var it: auto = - font->tables.find(kDsigTableTag); - if (it != font->tables.end()) { - font->tables.erase(it); - font->num_tables = font->tables.size(); - } - return true; -} - -} // namespace woff2 diff --git a/third_party/examples/woff2/carbon/src/glyph.carbon b/third_party/examples/woff2/carbon/src/glyph.carbon deleted file mode 100644 index 89dc3cedfb67..000000000000 --- a/third_party/examples/woff2/carbon/src/glyph.carbon +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Data model and I/O for glyph data within sfnt format files for the purpose of - performing the preprocessing step of the WOFF 2.0 conversion. */ - -#ifndef WOFF2_GLYPH_H_ -#define WOFF2_GLYPH_H_ - -#include -#include -#include - -namespace woff2 { - -// Represents a parsed simple or composite glyph. The composite glyph data and -// instructions are un-parsed and we keep only pointers to the raw data, -// therefore the glyph is valid only so long the data from which it was parsed -// is around. -class Glyph { - public: - Glyph() {} - - // Bounding box. - int16_t x_min; - int16_t x_max; - int16_t y_min; - int16_t y_max; - - // Instructions. - uint16_t instructions_size{0}; - const uint8_t* instructions_data; - - // Data model for simple glyphs. - struct Point { - int x; - int y; - bool on_curve; - }; - std::vector > contours; - - // Data for composite glyphs. - const uint8_t* composite_data; - uint32_t composite_data_size{0}; - bool have_instructions; -}; - -// Parses the glyph from the given data. Returns false on parsing failure or -// buffer overflow. The glyph is valid only so long the input data pointer is -// valid. -fn ReadGlyph(data: const uint8_t*, len: size_t, glyph: Glyph*) -> bool; - -// Stores the glyph into the specified dst buffer. The *dst_size is the buffer -// size on entry and is set to the actual (unpadded) stored size on exit. -// Returns false on buffer overflow. -fn StoreGlyph(glyph: const Glyph&, dst: uint8_t*, dst_size: size_t*) -> bool; - -} // namespace woff2 - -#endif // WOFF2_GLYPH_H_ diff --git a/third_party/examples/woff2/carbon/src/glyph.impl.carbon b/third_party/examples/woff2/carbon/src/glyph.impl.carbon deleted file mode 100644 index e60f6a1b42ec..000000000000 --- a/third_party/examples/woff2/carbon/src/glyph.impl.carbon +++ /dev/null @@ -1,375 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Glyph manipulation */ - -#include "./glyph.h" - -#include -#include - -#include "./buffer.h" -#include "./store_bytes.h" - -namespace woff2 { - -let kFLAG_ONCURVE: const int32_t = 1; -let kFLAG_XSHORT: const int32_t = 1 << 1; -let kFLAG_YSHORT: const int32_t = 1 << 2; -let kFLAG_REPEAT: const int32_t = 1 << 3; -let kFLAG_XREPEATSIGN: const int32_t = 1 << 4; -let kFLAG_YREPEATSIGN: const int32_t = 1 << 5; -let kFLAG_ARG_1_AND_2_ARE_WORDS: const int32_t = 1 << 0; -let kFLAG_WE_HAVE_A_SCALE: const int32_t = 1 << 3; -let kFLAG_MORE_COMPONENTS: const int32_t = 1 << 5; -let kFLAG_WE_HAVE_AN_X_AND_Y_SCALE: const int32_t = 1 << 6; -let kFLAG_WE_HAVE_A_TWO_BY_TWO: const int32_t = 1 << 7; -let kFLAG_WE_HAVE_INSTRUCTIONS: const int32_t = 1 << 8; - -fn ReadCompositeGlyphData(buffer: Buffer*, glyph: Glyph*) -> bool { - glyph->have_instructions = false; - glyph->composite_data = buffer->buffer() + buffer->offset(); - var start_offset: size_t = buffer->offset(); - var flags: uint16_t = kFLAG_MORE_COMPONENTS; - while (flags & kFLAG_MORE_COMPONENTS) { - if (!buffer->ReadU16(&flags)) { - return FONT_COMPRESSION_FAILURE(); - } - glyph->have_instructions |= (flags & kFLAG_WE_HAVE_INSTRUCTIONS) != 0; - var arg_size: size_t = 2; // glyph index - if (flags & kFLAG_ARG_1_AND_2_ARE_WORDS) { - arg_size += 4; - } else { - arg_size += 2; - } - if (flags & kFLAG_WE_HAVE_A_SCALE) { - arg_size += 2; - } else if (flags & kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) { - arg_size += 4; - } else if (flags & kFLAG_WE_HAVE_A_TWO_BY_TWO) { - arg_size += 8; - } - if (!buffer->Skip(arg_size)) { - return FONT_COMPRESSION_FAILURE(); - } - } - if (buffer->offset() - start_offset > std::numeric_limits::max()) { - return FONT_COMPRESSION_FAILURE(); - } - glyph->composite_data_size = buffer->offset() - start_offset; - return true; -} - -fn ReadGlyph(data: const uint8_t*, len: size_t, glyph: Glyph*) -> bool { - var buffer: Buffer(data, len); - - var num_contours: int16_t; - if (!buffer.ReadS16(&num_contours)) { - return FONT_COMPRESSION_FAILURE(); - } - - // Read the bounding box. - if (!buffer.ReadS16(&glyph->x_min) || - !buffer.ReadS16(&glyph->y_min) || - !buffer.ReadS16(&glyph->x_max) || - !buffer.ReadS16(&glyph->y_max)) { - return FONT_COMPRESSION_FAILURE(); - } - - if (num_contours == 0) { - // Empty glyph. - return true; - } - - if (num_contours > 0) { - // Simple glyph. - glyph->contours.resize(num_contours); - - // Read the number of points per contour. - var last_point_index: uint16_t = 0; - for (var i: int = 0; i < num_contours; ++i) { - var point_index: uint16_t; - if (!buffer.ReadU16(&point_index)) { - return FONT_COMPRESSION_FAILURE(); - } - var num_points: uint16_t = point_index - last_point_index + (i == 0 ? 1 : 0); - glyph->contours[i].resize(num_points); - last_point_index = point_index; - } - - // Read the instructions. - if (!buffer.ReadU16(&glyph->instructions_size)) { - return FONT_COMPRESSION_FAILURE(); - } - glyph->instructions_data = data + buffer.offset(); - if (!buffer.Skip(glyph->instructions_size)) { - return FONT_COMPRESSION_FAILURE(); - } - - // Read the run-length coded flags. - var flags: std::vector >(num_contours); - { - var flag: uint8_t = 0; - var flag_repeat: uint8_t = 0; - for (var i: int = 0; i < num_contours; ++i) { - flags[i].resize(glyph->contours[i].size()); - for (var j: size_t = 0; j < glyph->contours[i].size(); ++j) { - if (flag_repeat == 0) { - if (!buffer.ReadU8(&flag)) { - return FONT_COMPRESSION_FAILURE(); - } - if (flag & kFLAG_REPEAT) { - if (!buffer.ReadU8(&flag_repeat)) { - return FONT_COMPRESSION_FAILURE(); - } - } - } else { - flag_repeat--; - } - flags[i][j] = flag; - glyph->contours[i][j].on_curve = flag & kFLAG_ONCURVE; - } - } - } - - // Read the x coordinates. - var prev_x: int = 0; - for (var i: int = 0; i < num_contours; ++i) { - for (var j: size_t = 0; j < glyph->contours[i].size(); ++j) { - var flag: uint8_t = flags[i][j]; - if (flag & kFLAG_XSHORT) { - // single byte x-delta coord value - var x_delta: uint8_t; - if (!buffer.ReadU8(&x_delta)) { - return FONT_COMPRESSION_FAILURE(); - } - var sign: int = (flag & kFLAG_XREPEATSIGN) ? 1 : -1; - glyph->contours[i][j].x = prev_x + sign * x_delta; - } else { - // double byte x-delta coord value - var x_delta: int16_t = 0; - if (!(flag & kFLAG_XREPEATSIGN)) { - if (!buffer.ReadS16(&x_delta)) { - return FONT_COMPRESSION_FAILURE(); - } - } - glyph->contours[i][j].x = prev_x + x_delta; - } - prev_x = glyph->contours[i][j].x; - } - } - - // Read the y coordinates. - var prev_y: int = 0; - for (var i: int = 0; i < num_contours; ++i) { - for (var j: size_t = 0; j < glyph->contours[i].size(); ++j) { - var flag: uint8_t = flags[i][j]; - if (flag & kFLAG_YSHORT) { - // single byte y-delta coord value - var y_delta: uint8_t; - if (!buffer.ReadU8(&y_delta)) { - return FONT_COMPRESSION_FAILURE(); - } - var sign: int = (flag & kFLAG_YREPEATSIGN) ? 1 : -1; - glyph->contours[i][j].y = prev_y + sign * y_delta; - } else { - // double byte y-delta coord value - var y_delta: int16_t = 0; - if (!(flag & kFLAG_YREPEATSIGN)) { - if (!buffer.ReadS16(&y_delta)) { - return FONT_COMPRESSION_FAILURE(); - } - } - glyph->contours[i][j].y = prev_y + y_delta; - } - prev_y = glyph->contours[i][j].y; - } - } - } else if (num_contours == -1) { - // Composite glyph. - if (!ReadCompositeGlyphData(&buffer, glyph)) { - return FONT_COMPRESSION_FAILURE(); - } - // Read the instructions. - if (glyph->have_instructions) { - if (!buffer.ReadU16(&glyph->instructions_size)) { - return FONT_COMPRESSION_FAILURE(); - } - glyph->instructions_data = data + buffer.offset(); - if (!buffer.Skip(glyph->instructions_size)) { - return FONT_COMPRESSION_FAILURE(); - } - } else { - glyph->instructions_size = 0; - } - } else { - return FONT_COMPRESSION_FAILURE(); - } - return true; -} - -namespace { - -fn StoreBbox(glyph: const Glyph&, offset: size_t*, dst: uint8_t*) { - Store16(glyph.x_min, offset, dst); - Store16(glyph.y_min, offset, dst); - Store16(glyph.x_max, offset, dst); - Store16(glyph.y_max, offset, dst); -} - -fn StoreInstructions(glyph: const Glyph&, offset: size_t*, dst: uint8_t*) { - Store16(glyph.instructions_size, offset, dst); - StoreBytes(glyph.instructions_data, glyph.instructions_size, offset, dst); -} - -fn StoreEndPtsOfContours(glyph: const Glyph&, offset: size_t*, dst: uint8_t*) -> bool { - var end_point: int = -1; - for (const auto& contour in glyph.contours) { - end_point += contour.size(); - if (contour.size() > std::numeric_limits::max() || - end_point > std::numeric_limits::max()) { - return FONT_COMPRESSION_FAILURE(); - } - Store16(end_point, offset, dst); - } - return true; -} - -fn StorePoints(glyph: const Glyph&, offset: size_t*, - dst: uint8_t*, dst_size: size_t) -> bool { - var last_flag: int = -1; - var repeat_count: int = 0; - var last_x: int = 0; - var last_y: int = 0; - var x_bytes: size_t = 0; - var y_bytes: size_t = 0; - - // Store the flags and calculate the total size of the x and y coordinates. - for (const auto& contour in glyph.contours) { - for (const auto& point in contour) { - var flag: int = point.on_curve ? kFLAG_ONCURVE : 0; - var dx: int = point.x - last_x; - var dy: int = point.y - last_y; - if (dx == 0) { - flag |= kFLAG_XREPEATSIGN; - } else if (dx > -256 && dx < 256) { - flag |= kFLAG_XSHORT | (dx > 0 ? kFLAG_XREPEATSIGN : 0); - x_bytes += 1; - } else { - x_bytes += 2; - } - if (dy == 0) { - flag |= kFLAG_YREPEATSIGN; - } else if (dy > -256 && dy < 256) { - flag |= kFLAG_YSHORT | (dy > 0 ? kFLAG_YREPEATSIGN : 0); - y_bytes += 1; - } else { - y_bytes += 2; - } - if (flag == last_flag && repeat_count != 255) { - dst[*offset - 1] |= kFLAG_REPEAT; - repeat_count++; - } else { - if (repeat_count != 0) { - if (*offset >= dst_size) { - return FONT_COMPRESSION_FAILURE(); - } - dst[(*offset)++] = repeat_count; - } - if (*offset >= dst_size) { - return FONT_COMPRESSION_FAILURE(); - } - dst[(*offset)++] = flag; - repeat_count = 0; - } - last_x = point.x; - last_y = point.y; - last_flag = flag; - } - } - if (repeat_count != 0) { - if (*offset >= dst_size) { - return FONT_COMPRESSION_FAILURE(); - } - dst[(*offset)++] = repeat_count; - } - - if (*offset + x_bytes + y_bytes > dst_size) { - return FONT_COMPRESSION_FAILURE(); - } - - // Store the x and y coordinates. - var x_offset: size_t = *offset; - var y_offset: size_t = *offset + x_bytes; - last_x = 0; - last_y = 0; - for (const auto& contour in glyph.contours) { - for (const auto& point in contour) { - var dx: int = point.x - last_x; - var dy: int = point.y - last_y; - if (dx == 0) { - // pass - } else if (dx > -256 && dx < 256) { - dst[x_offset++] = std::abs(dx); - } else { - Store16(dx, &x_offset, dst); - } - if (dy == 0) { - // pass - } else if (dy > -256 && dy < 256) { - dst[y_offset++] = std::abs(dy); - } else { - Store16(dy, &y_offset, dst); - } - last_x += dx; - last_y += dy; - } - } - *offset = y_offset; - return true; -} - -} // namespace - -fn StoreGlyph(glyph: const Glyph&, dst: uint8_t*, dst_size: size_t*) -> bool { - var offset: size_t = 0; - if (glyph.composite_data_size > 0) { - // Composite glyph. - if (*dst_size < ((10ULL + glyph.composite_data_size) + - ((glyph.have_instructions ? 2ULL : 0) + - glyph.instructions_size))) { - return FONT_COMPRESSION_FAILURE(); - } - Store16(-1, &offset, dst); - StoreBbox(glyph, &offset, dst); - StoreBytes(glyph.composite_data, glyph.composite_data_size, &offset, dst); - if (glyph.have_instructions) { - StoreInstructions(glyph, &offset, dst); - } - } else if (glyph.contours.size() > 0) { - // Simple glyph. - if (glyph.contours.size() > std::numeric_limits::max()) { - return FONT_COMPRESSION_FAILURE(); - } - if (*dst_size < ((12ULL + 2 * glyph.contours.size()) + - glyph.instructions_size)) { - return FONT_COMPRESSION_FAILURE(); - } - Store16(glyph.contours.size(), &offset, dst); - StoreBbox(glyph, &offset, dst); - if (!StoreEndPtsOfContours(glyph, &offset, dst)) { - return FONT_COMPRESSION_FAILURE(); - } - StoreInstructions(glyph, &offset, dst); - if (!StorePoints(glyph, &offset, dst, *dst_size)) { - return FONT_COMPRESSION_FAILURE(); - } - } - *dst_size = offset; - return true; -} - -} // namespace woff2 diff --git a/third_party/examples/woff2/carbon/src/normalize.carbon b/third_party/examples/woff2/carbon/src/normalize.carbon deleted file mode 100644 index d153ec4b1ee4..000000000000 --- a/third_party/examples/woff2/carbon/src/normalize.carbon +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Functions for normalizing fonts. Since the WOFF 2.0 decoder creates font - files in normalized form, the WOFF 2.0 conversion is guaranteed to be - lossless (in a bitwise sense) only for normalized font files. */ - -#ifndef WOFF2_NORMALIZE_H_ -#define WOFF2_NORMALIZE_H_ - -namespace woff2 { - -struct Font; -struct FontCollection; - -// Changes the offset fields of the table headers so that the data for the -// tables will be written in order of increasing tag values, without any gaps -// other than the 4-byte padding. -fn NormalizeOffsets(font: Font*) -> bool; - -// Changes the checksum fields of the table headers and the checksum field of -// the head table so that it matches the current data. -fn FixChecksums(font: Font*) -> bool; - -// Parses each of the glyphs in the font and writes them again to the glyf -// table in normalized form, as defined by the StoreGlyph() function. Changes -// the loca table accordingly. -fn NormalizeGlyphs(font: Font*) -> bool; - -// Performs all of the normalization steps above. -fn NormalizeFont(font: Font*) -> bool; -fn NormalizeFontCollection(font_collection: FontCollection*) -> bool; - -} // namespace woff2 - -#endif // WOFF2_NORMALIZE_H_ diff --git a/third_party/examples/woff2/carbon/src/normalize.impl.carbon b/third_party/examples/woff2/carbon/src/normalize.impl.carbon deleted file mode 100644 index a1407462731f..000000000000 --- a/third_party/examples/woff2/carbon/src/normalize.impl.carbon +++ /dev/null @@ -1,314 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Glyph normalization */ - -#include "./normalize.h" - -#include -#include - -#include "./buffer.h" -#include "./font.h" -#include "./glyph.h" -#include "./port.h" -#include "./round.h" -#include "./store_bytes.h" -#include "./table_tags.h" -#include "./woff2_common.h" - -namespace woff2 { - -namespace { - -fn StoreLoca(index_fmt: int, value: uint32_t, offset: size_t*, dst: uint8_t*) { - if (index_fmt == 0) { - Store16(value >> 1, offset, dst); - } else { - StoreU32(value, offset, dst); - } -} - -} // namespace - -namespace { - -fn WriteNormalizedLoca(index_fmt: int, num_glyphs: int, font: Font*) -> bool { - var glyf_table: Font::Table* = font->FindTable(kGlyfTableTag); - var loca_table: Font::Table* = font->FindTable(kLocaTableTag); - - var glyph_sz: int = index_fmt == 0 ? 2 : 4; - loca_table->buffer.resize(Round4(num_glyphs + 1) * glyph_sz); - loca_table->length = (num_glyphs + 1) * glyph_sz; - - var glyf_dst: uint8_t* = num_glyphs ? &glyf_table->buffer[0] : nullptr; - var loca_dst: uint8_t* = &loca_table->buffer[0]; - var glyf_offset: uint32_t = 0; - var loca_offset: size_t = 0; - - for (var i: int = 0; i < num_glyphs; ++i) { - StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst); - var glyph: Glyph; - var glyph_data: const uint8_t*; - var glyph_size: size_t; - if (!GetGlyphData(*font, i, &glyph_data, &glyph_size) || - (glyph_size > 0 && !ReadGlyph(glyph_data, glyph_size, &glyph))) { - return FONT_COMPRESSION_FAILURE(); - } - var glyf_dst_size: size_t = glyf_table->buffer.size() - glyf_offset; - if (!StoreGlyph(glyph, glyf_dst + glyf_offset, &glyf_dst_size)) { - return FONT_COMPRESSION_FAILURE(); - } - glyf_dst_size = Round4(glyf_dst_size); - if (glyf_dst_size > std::numeric_limits::max() || - glyf_offset + static_cast(glyf_dst_size) < glyf_offset || - (index_fmt == 0 && glyf_offset + glyf_dst_size >= (1UL << 17))) { - return FONT_COMPRESSION_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_offset ? &glyf_table->buffer[0] : nullptr; - glyf_table->length = glyf_offset; - loca_table->data = loca_offset ? &loca_table->buffer[0] : nullptr; - - return true; -} - -} // namespace - -namespace { - -fn MakeEditableBuffer(font: Font*, tableTag: int) -> bool { - var table: Font::Table* = font->FindTable(tableTag); - if (table == nullptr) { - return FONT_COMPRESSION_FAILURE(); - } - if (table->IsReused()) { - return true; - } - var sz: int = Round4(table->length); - table->buffer.resize(sz); - var buf: uint8_t* = &table->buffer[0]; - memcpy(buf, table->data, table->length); - if (PREDICT_FALSE(sz > table->length)) { - memset(buf + table->length, 0, sz - table->length); - } - table->data = buf; - return true; -} - -} // namespace - -fn NormalizeGlyphs(font: Font*) -> bool { - var head_table: Font::Table* = font->FindTable(kHeadTableTag); - var glyf_table: Font::Table* = font->FindTable(kGlyfTableTag); - var loca_table: Font::Table* = font->FindTable(kLocaTableTag); - if (head_table == nullptr) { - return FONT_COMPRESSION_FAILURE(); - } - // If you don't have glyf/loca this transform isn't very interesting - if (loca_table == nullptr && glyf_table == nullptr) { - return true; - } - // It would be best if you didn't have just one of glyf/loca - if ((glyf_table == nullptr) != (loca_table == nullptr)) { - 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; - } - - var index_fmt: int = head_table->data[51]; - var num_glyphs: int = 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. - var max_normalized_glyf_size: size_t = 1.1 * glyf_table->length + 2 * num_glyphs; - - glyf_table->buffer.resize(max_normalized_glyf_size); - - // if we can't write a loca using short's (index_fmt 0) - // try again using longs (index_fmt 1) - if (!WriteNormalizedLoca(index_fmt, num_glyphs, font)) { - if (index_fmt != 0) { - return FONT_COMPRESSION_FAILURE(); - } - - // Rewrite loca with 4-byte entries & update head to match - index_fmt = 1; - if (!WriteNormalizedLoca(index_fmt, num_glyphs, font)) { - return FONT_COMPRESSION_FAILURE(); - } - head_table->buffer[51] = 1; - } - - return true; -} - -fn NormalizeOffsets(font: Font*) -> bool { - var offset: uint32_t = 12 + 16 * font->num_tables; - for (auto tag in font->OutputOrderedTags()) { - var table: auto& = font->tables[tag]; - table.offset = offset; - offset += Round4(table.length); - } - return true; -} - -namespace { - -fn ComputeHeaderChecksum(font: const Font&) -> uint32_t { - var checksum: uint32_t = font.flavor; - var max_pow2: uint16_t = font.num_tables ? Log2Floor(font.num_tables) : 0; - var search_range: uint16_t = max_pow2 ? 1 << (max_pow2 + 4) : 0; - var range_shift: uint16_t = (font.num_tables << 4) - search_range; - checksum += (font.num_tables << 16 | search_range); - checksum += (max_pow2 << 16 | range_shift); - for (const auto& i in font.tables) { - var table: const Font::Table* = &i.second; - if (table->IsReused()) { - table = table->reuse_of; - } - checksum += table->tag; - checksum += table->checksum; - checksum += table->offset; - checksum += table->length; - } - return checksum; -} - -} // namespace - -fn FixChecksums(font: Font*) -> bool { - var head_table: Font::Table* = font->FindTable(kHeadTableTag); - if (head_table == nullptr) { - return FONT_COMPRESSION_FAILURE(); - } - if (head_table->reuse_of != nullptr) { - head_table = head_table->reuse_of; - } - if (head_table->length < 12) { - return FONT_COMPRESSION_FAILURE(); - } - - var head_buf: uint8_t* = &head_table->buffer[0]; - var offset: size_t = 8; - StoreU32(0, &offset, head_buf); - var file_checksum: uint32_t = 0; - var head_checksum: uint32_t = 0; - for (auto& i in font->tables) { - var table: Font::Table* = &i.second; - if (table->IsReused()) { - table = table->reuse_of; - } - table->checksum = ComputeULongSum(table->data, table->length); - file_checksum += table->checksum; - - if (table->tag == kHeadTableTag) { - head_checksum = table->checksum; - } - } - - file_checksum += ComputeHeaderChecksum(*font); - offset = 8; - StoreU32(0xb1b0afba - file_checksum, &offset, head_buf); - - return true; -} - -namespace { -fn MarkTransformed(font: Font*) -> bool { - var head_table: Font::Table* = font->FindTable(kHeadTableTag); - if (head_table == nullptr) { - return FONT_COMPRESSION_FAILURE(); - } - if (head_table->reuse_of != nullptr) { - 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 - var head_flags: int = head_table->data[16]; - head_table->buffer[16] = head_flags | 0x08; - return true; -} -} // namespace - - -fn NormalizeWithoutFixingChecksums(font: Font*) -> bool { - return (MakeEditableBuffer(font, kHeadTableTag) && - RemoveDigitalSignature(font) && - MarkTransformed(font) && - NormalizeGlyphs(font) && - NormalizeOffsets(font)); -} - -fn NormalizeFont(font: Font*) -> bool { - return (NormalizeWithoutFixingChecksums(font) && - FixChecksums(font)); -} - -fn NormalizeFontCollection(font_collection: FontCollection*) -> bool { - if (font_collection->fonts.size() == 1) { - return NormalizeFont(&font_collection->fonts[0]); - } - - var offset: uint32_t = CollectionHeaderSize(font_collection->header_version, - font_collection->fonts.size()); - for (auto& font in font_collection->fonts) { - if (!NormalizeWithoutFixingChecksums(&font)) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Font normalization failed.\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - offset += kSfntHeaderSize + kSfntEntrySize * font.num_tables; - } - - // Start table offsets after TTC Header and Sfnt Headers - for (auto& font in font_collection->fonts) { - for (auto tag in font.OutputOrderedTags()) { - var table: Font::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 in font_collection->fonts) { - if (!FixChecksums(&font)) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Failed to fix checksums\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - } - - return true; -} - -} // namespace woff2 diff --git a/third_party/examples/woff2/carbon/src/port.carbon b/third_party/examples/woff2/carbon/src/port.carbon deleted file mode 100644 index dafcae037310..000000000000 --- a/third_party/examples/woff2/carbon/src/port.carbon +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Helper function for bit twiddling and macros for branch prediction. */ - -#ifndef WOFF2_PORT_H_ -#define WOFF2_PORT_H_ - -#include - -namespace woff2 { - -using uint32 = unsigned int; - -fn inline Log2Floor(n: uint32) -> int { -#if defined(__GNUC__) - return n == 0 ? -1 : 31 ^ __builtin_clz(n); -#else - if (n == 0) - return -1; - int log = 0; - uint32 value = n; - for (int i = 4; i >= 0; --i) { - int shift = (1 << i); - uint32 x = value >> shift; - if (x != 0) { - value = x; - log += shift; - } - } - assert(value == 1); - return log; -#endif -} - -} // namespace woff2 - -/* Compatibility with non-clang compilers. */ -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - -#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || \ - (defined(__llvm__) && __has_builtin(__builtin_expect)) -#define PREDICT_FALSE(x) (__builtin_expect(x, 0)) -#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) -#else -#define PREDICT_FALSE(x) (x) -#define PREDICT_TRUE(x) (x) -#endif - -#if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \ - (defined(M_ARM) && (M_ARM == 7)) || \ - defined(__aarch64__) || defined(__ARM64_ARCH_8__) || defined(__i386) || \ - defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) -#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#define WOFF_LITTLE_ENDIAN -#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -#define WOFF_BIG_ENDIAN -#endif /* endianness */ -#endif /* CPU whitelist */ - -#endif // WOFF2_PORT_H_ diff --git a/third_party/examples/woff2/carbon/src/round.carbon b/third_party/examples/woff2/carbon/src/round.carbon deleted file mode 100644 index ad58321dcfef..000000000000 --- a/third_party/examples/woff2/carbon/src/round.carbon +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Helper for rounding */ - -#ifndef WOFF2_ROUND_H_ -#define WOFF2_ROUND_H_ - -#include - -namespace woff2 { - -// Round a value up to the nearest multiple of 4. Don't round the value in the -// case that rounding up overflows. -template fn Round4(value: T) -> T { - if (std::numeric_limits::max() - value < 3) { - return value; - } - return (value + 3) & ~3; -} - -} // namespace woff2 - -#endif // WOFF2_ROUND_H_ diff --git a/third_party/examples/woff2/carbon/src/store_bytes.carbon b/third_party/examples/woff2/carbon/src/store_bytes.carbon deleted file mode 100644 index a78b5f35f7c6..000000000000 --- a/third_party/examples/woff2/carbon/src/store_bytes.carbon +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Helper functions for storing integer values into byte streams. - No bounds checking is performed, that is the responsibility of the caller. */ - -#ifndef WOFF2_STORE_BYTES_H_ -#define WOFF2_STORE_BYTES_H_ - -#include -#include -#include - -#include "./port.h" - -namespace woff2 { - -fn inline StoreU32(dst: uint8_t*, offset: size_t, x: uint32_t) -> size_t { - dst[offset] = x >> 24; - dst[offset + 1] = x >> 16; - dst[offset + 2] = x >> 8; - dst[offset + 3] = x; - return offset + 4; -} - -fn inline Store16(dst: uint8_t*, offset: size_t, x: int) -> size_t { -#if defined(WOFF_LITTLE_ENDIAN) - *reinterpret_cast(dst + offset) = - ((x & 0xFF) << 8) | ((x & 0xFF00) >> 8); -#elif defined(WOFF_BIG_ENDIAN) - *reinterpret_cast(dst + offset) = static_cast(x); -#else - dst[offset] = x >> 8; - dst[offset + 1] = x; -#endif - return offset + 2; -} - -fn inline StoreU32(val: uint32_t, offset: size_t*, dst: uint8_t*) { - dst[(*offset)++] = val >> 24; - dst[(*offset)++] = val >> 16; - dst[(*offset)++] = val >> 8; - dst[(*offset)++] = val; -} - -fn inline Store16(val: int, offset: size_t*, dst: uint8_t*) { -#if defined(WOFF_LITTLE_ENDIAN) - *reinterpret_cast(dst + *offset) = - ((val & 0xFF) << 8) | ((val & 0xFF00) >> 8); - *offset += 2; -#elif defined(WOFF_BIG_ENDIAN) - *reinterpret_cast(dst + *offset) = static_cast(val); - *offset += 2; -#else - dst[(*offset)++] = val >> 8; - dst[(*offset)++] = val; -#endif -} - -fn inline StoreBytes(data: const uint8_t*, len: size_t, - offset: size_t*, dst: uint8_t*) { - memcpy(&dst[*offset], data, len); - *offset += len; -} - -} // namespace woff2 - -#endif // WOFF2_STORE_BYTES_H_ diff --git a/third_party/examples/woff2/carbon/src/table_tags.carbon b/third_party/examples/woff2/carbon/src/table_tags.carbon deleted file mode 100644 index 9740aa7791df..000000000000 --- a/third_party/examples/woff2/carbon/src/table_tags.carbon +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Font table tags */ - -#ifndef WOFF2_TABLE_TAGS_H_ -#define WOFF2_TABLE_TAGS_H_ - -#include - -namespace woff2 { - -// Tags of popular tables. -let kGlyfTableTag: const uint32_t = 0x676c7966; -let kHeadTableTag: const uint32_t = 0x68656164; -let kLocaTableTag: const uint32_t = 0x6c6f6361; -let kDsigTableTag: const uint32_t = 0x44534947; -let kCffTableTag: const uint32_t = 0x43464620; -let kHmtxTableTag: const uint32_t = 0x686d7478; -let kHheaTableTag: const uint32_t = 0x68686561; -let kMaxpTableTag: const uint32_t = 0x6d617870; - -let kKnownTags: const uint32_t[]; - -} // namespace woff2 - -#endif // WOFF2_TABLE_TAGS_H_ diff --git a/third_party/examples/woff2/carbon/src/table_tags.impl.carbon b/third_party/examples/woff2/carbon/src/table_tags.impl.carbon deleted file mode 100644 index 54f0accc4dd8..000000000000 --- a/third_party/examples/woff2/carbon/src/table_tags.impl.carbon +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Font table tags */ - -#include "./table_tags.h" - -namespace woff2 { - -// Note that the byte order is big-endian, not the same as ots.cc -#define TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) - -let kKnownTags: const uint32_t[63] = { - TAG('c', 'm', 'a', 'p'), // 0 - TAG('h', 'e', 'a', 'd'), // 1 - TAG('h', 'h', 'e', 'a'), // 2 - TAG('h', 'm', 't', 'x'), // 3 - TAG('m', 'a', 'x', 'p'), // 4 - TAG('n', 'a', 'm', 'e'), // 5 - TAG('O', 'S', '/', '2'), // 6 - TAG('p', 'o', 's', 't'), // 7 - TAG('c', 'v', 't', ' '), // 8 - TAG('f', 'p', 'g', 'm'), // 9 - TAG('g', 'l', 'y', 'f'), // 10 - TAG('l', 'o', 'c', 'a'), // 11 - TAG('p', 'r', 'e', 'p'), // 12 - TAG('C', 'F', 'F', ' '), // 13 - TAG('V', 'O', 'R', 'G'), // 14 - TAG('E', 'B', 'D', 'T'), // 15 - TAG('E', 'B', 'L', 'C'), // 16 - TAG('g', 'a', 's', 'p'), // 17 - TAG('h', 'd', 'm', 'x'), // 18 - TAG('k', 'e', 'r', 'n'), // 19 - TAG('L', 'T', 'S', 'H'), // 20 - TAG('P', 'C', 'L', 'T'), // 21 - TAG('V', 'D', 'M', 'X'), // 22 - TAG('v', 'h', 'e', 'a'), // 23 - TAG('v', 'm', 't', 'x'), // 24 - TAG('B', 'A', 'S', 'E'), // 25 - TAG('G', 'D', 'E', 'F'), // 26 - TAG('G', 'P', 'O', 'S'), // 27 - TAG('G', 'S', 'U', 'B'), // 28 - TAG('E', 'B', 'S', 'C'), // 29 - TAG('J', 'S', 'T', 'F'), // 30 - TAG('M', 'A', 'T', 'H'), // 31 - TAG('C', 'B', 'D', 'T'), // 32 - TAG('C', 'B', 'L', 'C'), // 33 - TAG('C', 'O', 'L', 'R'), // 34 - TAG('C', 'P', 'A', 'L'), // 35 - TAG('S', 'V', 'G', ' '), // 36 - TAG('s', 'b', 'i', 'x'), // 37 - TAG('a', 'c', 'n', 't'), // 38 - TAG('a', 'v', 'a', 'r'), // 39 - TAG('b', 'd', 'a', 't'), // 40 - TAG('b', 'l', 'o', 'c'), // 41 - TAG('b', 's', 'l', 'n'), // 42 - TAG('c', 'v', 'a', 'r'), // 43 - TAG('f', 'd', 's', 'c'), // 44 - TAG('f', 'e', 'a', 't'), // 45 - TAG('f', 'm', 't', 'x'), // 46 - TAG('f', 'v', 'a', 'r'), // 47 - TAG('g', 'v', 'a', 'r'), // 48 - TAG('h', 's', 't', 'y'), // 49 - TAG('j', 'u', 's', 't'), // 50 - TAG('l', 'c', 'a', 'r'), // 51 - TAG('m', 'o', 'r', 't'), // 52 - TAG('m', 'o', 'r', 'x'), // 53 - TAG('o', 'p', 'b', 'd'), // 54 - TAG('p', 'r', 'o', 'p'), // 55 - TAG('t', 'r', 'a', 'k'), // 56 - TAG('Z', 'a', 'p', 'f'), // 57 - TAG('S', 'i', 'l', 'f'), // 58 - TAG('G', 'l', 'a', 't'), // 59 - TAG('G', 'l', 'o', 'c'), // 60 - TAG('F', 'e', 'a', 't'), // 61 - TAG('S', 'i', 'l', 'l'), // 62 -}; - -} // namespace woff2 diff --git a/third_party/examples/woff2/carbon/src/transform.carbon b/third_party/examples/woff2/carbon/src/transform.carbon deleted file mode 100644 index 19d6c48f1403..000000000000 --- a/third_party/examples/woff2/carbon/src/transform.carbon +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Library for preprocessing fonts as part of the WOFF 2.0 conversion. */ - -#ifndef WOFF2_TRANSFORM_H_ -#define WOFF2_TRANSFORM_H_ - -#include "./font.h" - -namespace woff2 { - -// Adds the transformed versions of the glyf and loca tables to the font. The -// transformed loca table has zero length. The tag of the transformed tables is -// derived from the original tag by flipping the MSBs of every byte. -fn TransformGlyfAndLocaTables(font: Font*) -> bool; - -// Apply transformation to hmtx table if applicable for this font. -fn TransformHmtxTable(font: Font*) -> bool; - -} // namespace woff2 - -#endif // WOFF2_TRANSFORM_H_ diff --git a/third_party/examples/woff2/carbon/src/transform.impl.carbon b/third_party/examples/woff2/carbon/src/transform.impl.carbon deleted file mode 100644 index 3235d08323d0..000000000000 --- a/third_party/examples/woff2/carbon/src/transform.impl.carbon +++ /dev/null @@ -1,421 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Library for preprocessing fonts as part of the WOFF 2.0 conversion. */ - -#include "./transform.h" - -#include // for std::abs - -#include "./buffer.h" -#include "./font.h" -#include "./glyph.h" -#include "./table_tags.h" -#include "./variable_length.h" - -namespace woff2 { - -namespace { - -let FLAG_ARG_1_AND_2_ARE_WORDS: const int = 1 << 0; -let FLAG_WE_HAVE_INSTRUCTIONS: const int = 1 << 8; - -fn WriteBytes(out: std::vector*, data: const uint8_t*, len: size_t) { - if (len == 0) { return; -} - var offset: size_t = out->size(); - out->resize(offset + len); - memcpy(&(*out)[offset], data, len); -} - -fn WriteBytes(out: std::vector*, in: const std::vector&) { - for (unsigned char i in in) { - out->push_back(i); - } -} - -fn WriteUShort(out: std::vector*, value: int) { - out->push_back(value >> 8); - out->push_back(value & 255); -} - -fn WriteLong(out: std::vector*, value: int) { - out->push_back((value >> 24) & 255); - out->push_back((value >> 16) & 255); - out->push_back((value >> 8) & 255); - out->push_back(value & 255); -} - -// Glyf table preprocessing, based on -// GlyfEncoder.java -class GlyfEncoder { - public: - explicit GlyfEncoder(num_glyphs: int) - : n_glyphs_(num_glyphs) { - bbox_bitmap_.resize(((num_glyphs + 31) >> 5) << 2); - } - - fn Encode(glyph_id: int, glyph: const Glyph&) -> bool { - if (glyph.composite_data_size > 0) { - WriteCompositeGlyph(glyph_id, glyph); - } else if (glyph.contours.size() > 0) { - WriteSimpleGlyph(glyph_id, glyph); - } else { - WriteUShort(&n_contour_stream_, 0); - } - return true; - } - - fn GetTransformedGlyfBytes(result: std::vector*) { - WriteLong(result, 0); // version - WriteUShort(result, n_glyphs_); - WriteUShort(result, 0); // index_format, will be set later - WriteLong(result, n_contour_stream_.size()); - WriteLong(result, n_points_stream_.size()); - WriteLong(result, flag_byte_stream_.size()); - WriteLong(result, glyph_stream_.size()); - WriteLong(result, composite_stream_.size()); - WriteLong(result, bbox_bitmap_.size() + bbox_stream_.size()); - WriteLong(result, instruction_stream_.size()); - WriteBytes(result, n_contour_stream_); - WriteBytes(result, n_points_stream_); - WriteBytes(result, flag_byte_stream_); - WriteBytes(result, glyph_stream_); - WriteBytes(result, composite_stream_); - WriteBytes(result, bbox_bitmap_); - WriteBytes(result, bbox_stream_); - WriteBytes(result, instruction_stream_); - } - - private: - fn WriteInstructions(glyph: const Glyph&) { - Write255UShort(&glyph_stream_, glyph.instructions_size); - WriteBytes(&instruction_stream_, - glyph.instructions_data, glyph.instructions_size); - } - - fn ShouldWriteSimpleGlyphBbox(glyph: const Glyph&) -> bool { - if (glyph.contours.empty() || glyph.contours[0].empty()) { - return glyph.x_min || glyph.y_min || glyph.x_max || glyph.y_max; - } - - var x_min: int16_t = glyph.contours[0][0].x; - var y_min: int16_t = glyph.contours[0][0].y; - var x_max: int16_t = x_min; - var y_max: int16_t = y_min; - for (const auto& contour in glyph.contours) { - for (const auto& point in 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; -} - } - } - - if (glyph.x_min != x_min) { - return true; -} - if (glyph.y_min != y_min) { - return true; -} - if (glyph.x_max != x_max) { - return true; -} - if (glyph.y_max != y_max) { - return true; -} - - return false; - } - - fn WriteSimpleGlyph(glyph_id: int, glyph: const Glyph&) { - var num_contours: int = glyph.contours.size(); - WriteUShort(&n_contour_stream_, num_contours); - if (ShouldWriteSimpleGlyphBbox(glyph)) { - WriteBbox(glyph_id, glyph); - } - for (var i: int = 0; i < num_contours; i++) { - Write255UShort(&n_points_stream_, glyph.contours[i].size()); - } - var lastX: int = 0; - var lastY: int = 0; - for (var i: int = 0; i < num_contours; i++) { - var num_points: int = glyph.contours[i].size(); - for (var j: int = 0; j < num_points; j++) { - var x: int = glyph.contours[i][j].x; - var y: int = glyph.contours[i][j].y; - var dx: int = x - lastX; - var dy: int = y - lastY; - WriteTriplet(glyph.contours[i][j].on_curve, dx, dy); - lastX = x; - lastY = y; - } - } - if (num_contours > 0) { - WriteInstructions(glyph); - } - } - - fn WriteCompositeGlyph(glyph_id: int, glyph: const Glyph&) { - WriteUShort(&n_contour_stream_, -1); - WriteBbox(glyph_id, glyph); - WriteBytes(&composite_stream_, - glyph.composite_data, - glyph.composite_data_size); - if (glyph.have_instructions) { - WriteInstructions(glyph); - } - } - - fn WriteBbox(glyph_id: int, glyph: const Glyph&) { - bbox_bitmap_[glyph_id >> 3] |= 0x80 >> (glyph_id & 7); - WriteUShort(&bbox_stream_, glyph.x_min); - WriteUShort(&bbox_stream_, glyph.y_min); - WriteUShort(&bbox_stream_, glyph.x_max); - WriteUShort(&bbox_stream_, glyph.y_max); - } - - fn WriteTriplet(on_curve: bool, x: int, y: int) { - var abs_x: int = std::abs(x); - var abs_y: int = std::abs(y); - var on_curve_bit: int = on_curve ? 0 : 128; - var x_sign_bit: int = (x < 0) ? 0 : 1; - var y_sign_bit: int = (y < 0) ? 0 : 1; - var xy_sign_bits: int = x_sign_bit + 2 * y_sign_bit; - if (x == 0 && abs_y < 1280) { - flag_byte_stream_.push_back(on_curve_bit + - ((abs_y & 0xf00) >> 7) + y_sign_bit); - glyph_stream_.push_back(abs_y & 0xff); - } else if (y == 0 && abs_x < 1280) { - flag_byte_stream_.push_back(on_curve_bit + 10 + - ((abs_x & 0xf00) >> 7) + x_sign_bit); - glyph_stream_.push_back(abs_x & 0xff); - } else if (abs_x < 65 && abs_y < 65) { - flag_byte_stream_.push_back(on_curve_bit + 20 + - ((abs_x - 1) & 0x30) + - (((abs_y - 1) & 0x30) >> 2) + - xy_sign_bits); - glyph_stream_.push_back((((abs_x - 1) & 0xf) << 4) | ((abs_y - 1) & 0xf)); - } else if (abs_x < 769 && abs_y < 769) { - flag_byte_stream_.push_back(on_curve_bit + 84 + - 12 * (((abs_x - 1) & 0x300) >> 8) + - (((abs_y - 1) & 0x300) >> 6) + xy_sign_bits); - glyph_stream_.push_back((abs_x - 1) & 0xff); - glyph_stream_.push_back((abs_y - 1) & 0xff); - } else if (abs_x < 4096 && abs_y < 4096) { - flag_byte_stream_.push_back(on_curve_bit + 120 + xy_sign_bits); - glyph_stream_.push_back(abs_x >> 4); - glyph_stream_.push_back(((abs_x & 0xf) << 4) | (abs_y >> 8)); - glyph_stream_.push_back(abs_y & 0xff); - } else { - flag_byte_stream_.push_back(on_curve_bit + 124 + xy_sign_bits); - glyph_stream_.push_back(abs_x >> 8); - glyph_stream_.push_back(abs_x & 0xff); - glyph_stream_.push_back(abs_y >> 8); - glyph_stream_.push_back(abs_y & 0xff); - } - } - - std::vector n_contour_stream_; - std::vector n_points_stream_; - std::vector flag_byte_stream_; - std::vector composite_stream_; - std::vector bbox_bitmap_; - std::vector bbox_stream_; - std::vector glyph_stream_; - std::vector instruction_stream_; - int n_glyphs_; -}; - -} // namespace - -fn TransformGlyfAndLocaTables(font: Font*) -> bool { - // no transform for CFF - var glyf_table: const Font::Table* = font->FindTable(kGlyfTableTag); - var loca_table: const Font::Table* = font->FindTable(kLocaTableTag); - - // If you don't have glyf/loca this transform isn't very interesting - if (loca_table == nullptr && glyf_table == nullptr) { - return true; - } - // It would be best if you didn't have just one of glyf/loca - if ((glyf_table == nullptr) != (loca_table == nullptr)) { - 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; - } - - var transformed_glyf: Font::Table* = &font->tables[kGlyfTableTag ^ 0x80808080]; - var transformed_loca: Font::Table* = &font->tables[kLocaTableTag ^ 0x80808080]; - - var num_glyphs: int = NumGlyphs(*font); - var encoder: GlyfEncoder(num_glyphs); - for (var i: int = 0; i < num_glyphs; ++i) { - var glyph: Glyph; - var glyph_data: const uint8_t*; - var glyph_size: size_t; - if (!GetGlyphData(*font, i, &glyph_data, &glyph_size) || - (glyph_size > 0 && !ReadGlyph(glyph_data, glyph_size, &glyph))) { - return FONT_COMPRESSION_FAILURE(); - } - encoder.Encode(i, glyph); - } - encoder.GetTransformedGlyfBytes(&transformed_glyf->buffer); - - var head_table: const Font::Table* = font->FindTable(kHeadTableTag); - if (head_table == nullptr || head_table->length < 52) { - return FONT_COMPRESSION_FAILURE(); - } - transformed_glyf->buffer[7] = head_table->data[51]; // index_format - - transformed_glyf->tag = kGlyfTableTag ^ 0x80808080; - transformed_glyf->length = transformed_glyf->buffer.size(); - transformed_glyf->data = transformed_glyf->buffer.data(); - - transformed_loca->tag = kLocaTableTag ^ 0x80808080; - transformed_loca->length = 0; - transformed_loca->data = nullptr; - - return true; -} - -// See https://www.microsoft.com/typography/otspec/hmtx.htm -// See WOFF2 spec, 5.4. Transformed hmtx table format -fn TransformHmtxTable(font: Font*) -> bool { - var glyf_table: const Font::Table* = font->FindTable(kGlyfTableTag); - var hmtx_table: const Font::Table* = font->FindTable(kHmtxTableTag); - var hhea_table: const Font::Table* = font->FindTable(kHheaTableTag); - - // If you don't have hmtx or a glyf not much is going to happen here - if (hmtx_table == nullptr || glyf_table == nullptr) { - return true; - } - - // hmtx without hhea doesn't make sense - if (hhea_table == nullptr) { - return FONT_COMPRESSION_FAILURE(); - } - - // Skip 34 to reach 'hhea' numberOfHMetrics - var hhea_buf: Buffer(hhea_table->data, hhea_table->length); - var num_hmetrics: uint16_t; - if (!hhea_buf.Skip(34) || !hhea_buf.ReadU16(&num_hmetrics)) { - return FONT_COMPRESSION_FAILURE(); - } - - // Must have at least one hMetric - if (num_hmetrics < 1) { - return FONT_COMPRESSION_FAILURE(); - } - - var num_glyphs: int = NumGlyphs(*font); - - // Most fonts can be transformed; assume it's a go until proven otherwise - var advance_widths: std::vector; - var proportional_lsbs: std::vector; - var monospace_lsbs: std::vector; - - var remove_proportional_lsb: bool = true; - var remove_monospace_lsb: bool = (num_glyphs - num_hmetrics) > 0; - - var hmtx_buf: Buffer(hmtx_table->data, hmtx_table->length); - for (var i: int = 0; i < num_glyphs; i++) { - var glyph: Glyph; - var glyph_data: const uint8_t*; - var glyph_size: size_t; - if (!GetGlyphData(*font, i, &glyph_data, &glyph_size) || - (glyph_size > 0 && !ReadGlyph(glyph_data, glyph_size, &glyph))) { - return FONT_COMPRESSION_FAILURE(); - } - - var advance_width: uint16_t = 0; - var lsb: int16_t = 0; - - if (i < num_hmetrics) { - // [0, num_hmetrics) are proportional hMetrics - if (!hmtx_buf.ReadU16(&advance_width)) { - return FONT_COMPRESSION_FAILURE(); - } - - if (!hmtx_buf.ReadS16(&lsb)) { - return FONT_COMPRESSION_FAILURE(); - } - - if (glyph_size > 0 && glyph.x_min != lsb) { - remove_proportional_lsb = false; - } - - advance_widths.push_back(advance_width); - proportional_lsbs.push_back(lsb); - } else { - // [num_hmetrics, num_glyphs) are monospace leftSideBearing's - if (!hmtx_buf.ReadS16(&lsb)) { - return FONT_COMPRESSION_FAILURE(); - } - if (glyph_size > 0 && glyph.x_min != lsb) { - remove_monospace_lsb = false; - } - monospace_lsbs.push_back(lsb); - } - - // If we know we can't optimize, bail out completely - if (!remove_proportional_lsb && !remove_monospace_lsb) { - return true; - } - } - - var transformed_hmtx: Font::Table* = &font->tables[kHmtxTableTag ^ 0x80808080]; - - var flags: uint8_t = 0; - var transformed_size: size_t = 1 + 2 * advance_widths.size(); - if (remove_proportional_lsb) { - flags |= 1; - } else { - transformed_size += 2 * proportional_lsbs.size(); - } - if (remove_monospace_lsb) { - flags |= 1 << 1; - } else { - transformed_size += 2 * monospace_lsbs.size(); - } - - transformed_hmtx->buffer.reserve(transformed_size); - var out: std::vector* = &transformed_hmtx->buffer; - WriteBytes(out, &flags, 1); - for (uint16_t advance_width in advance_widths) { - WriteUShort(out, advance_width); - } - - if (!remove_proportional_lsb) { - for (int16_t lsb in proportional_lsbs) { - WriteUShort(out, lsb); - } - } - if (!remove_monospace_lsb) { - for (int16_t lsb in monospace_lsbs) { - WriteUShort(out, lsb); - } - } - - transformed_hmtx->tag = kHmtxTableTag ^ 0x80808080; - transformed_hmtx->flag_byte = 1 << 6; - transformed_hmtx->length = transformed_hmtx->buffer.size(); - transformed_hmtx->data = transformed_hmtx->buffer.data(); - - - return true; -} - -} // namespace woff2 diff --git a/third_party/examples/woff2/carbon/src/variable_length.carbon b/third_party/examples/woff2/carbon/src/variable_length.carbon deleted file mode 100644 index 603347b8d2ab..000000000000 --- a/third_party/examples/woff2/carbon/src/variable_length.carbon +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright 2015 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Helper functions for woff2 variable length types: 255UInt16 and UIntBase128 */ - -#ifndef WOFF2_VARIABLE_LENGTH_H_ -#define WOFF2_VARIABLE_LENGTH_H_ - -#include -#include - -#include "./buffer.h" - -namespace woff2 { - -fn Size255UShort(value: uint16_t) -> size_t; -fn Read255UShort(buf: Buffer*, value: unsigned int*) -> bool; -fn Write255UShort(out: std::vector*, value: int); -fn Store255UShort(val: int, offset: size_t*, dst: uint8_t*); - -fn Base128Size(n: size_t) -> size_t; -fn ReadBase128(buf: Buffer*, value: uint32_t*) -> bool; -fn StoreBase128(len: size_t, offset: size_t*, dst: uint8_t*); - -} // namespace woff2 - -#endif // WOFF2_VARIABLE_LENGTH_H_ - diff --git a/third_party/examples/woff2/carbon/src/variable_length.impl.carbon b/third_party/examples/woff2/carbon/src/variable_length.impl.carbon deleted file mode 100644 index 77c6c98f3a8b..000000000000 --- a/third_party/examples/woff2/carbon/src/variable_length.impl.carbon +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright 2015 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Helper functions for woff2 variable length types: 255UInt16 and UIntBase128 */ - -#include "./variable_length.h" - -namespace woff2 { - -fn Size255UShort(value: uint16_t) -> size_t { - var result: size_t = 3; - if (value < 253) { - result = 1; - } else if (value < 762) { - result = 2; - } else { - result = 3; - } - return result; -} - -fn Write255UShort(out: std::vector*, value: int) { - if (value < 253) { - out->push_back(value); - } else if (value < 506) { - out->push_back(255); - out->push_back(value - 253); - } else if (value < 762) { - out->push_back(254); - out->push_back(value - 506); - } else { - out->push_back(253); - out->push_back(value >> 8); - out->push_back(value & 0xff); - } -} - -fn Store255UShort(val: int, offset: size_t*, dst: uint8_t*) { - var packed: std::vector; - Write255UShort(&packed, val); - for (uint8_t packed_byte in packed) { - dst[(*offset)++] = packed_byte; - } -} - -// Based on section 6.1.1 of MicroType Express draft spec -fn Read255UShort(buf: Buffer*, value: unsigned int*) -> bool { - let kWordCode: const int = 253; - let kOneMoreByteCode2: const int = 254; - let kOneMoreByteCode1: const int = 255; - let kLowestUCode: const int = 253; - var code: uint8_t = 0; - if (!buf->ReadU8(&code)) { - return FONT_COMPRESSION_FAILURE(); - } - if (code == kWordCode) { - var result: uint16_t = 0; - if (!buf->ReadU16(&result)) { - return FONT_COMPRESSION_FAILURE(); - } - *value = result; - return true; - } else if (code == kOneMoreByteCode1) { - var result: uint8_t = 0; - if (!buf->ReadU8(&result)) { - return FONT_COMPRESSION_FAILURE(); - } - *value = result + kLowestUCode; - return true; - } else if (code == kOneMoreByteCode2) { - var result: uint8_t = 0; - if (!buf->ReadU8(&result)) { - return FONT_COMPRESSION_FAILURE(); - } - *value = result + kLowestUCode * 2; - return true; - } else { - *value = code; - return true; - } -} - -fn ReadBase128(buf: Buffer*, value: uint32_t*) -> bool { - var result: uint32_t = 0; - for (var i: size_t = 0; i < 5; ++i) { - var code: uint8_t = 0; - if (!buf->ReadU8(&code)) { - return FONT_COMPRESSION_FAILURE(); - } - // Leading zeros are invalid. - if (i == 0 && code == 0x80) { - return FONT_COMPRESSION_FAILURE(); - } - // If any of the top seven bits are set then we're about to overflow. - if (result & 0xfe000000) { - return FONT_COMPRESSION_FAILURE(); - } - result = (result << 7) | (code & 0x7f); - if ((code & 0x80) == 0) { - *value = result; - return true; - } - } - // Make sure not to exceed the size bound - return FONT_COMPRESSION_FAILURE(); -} - -fn Base128Size(n: size_t) -> size_t { - var size: size_t = 1; - for (; n >= 128; n >>= 7) { ++size; -} - return size; -} - -fn StoreBase128(len: size_t, offset: size_t*, dst: uint8_t*) { - var size: size_t = Base128Size(len); - for (var i: size_t = 0; i < size; ++i) { - var b: int = static_cast((len >> (7 * (size - i - 1))) & 0x7f); - if (i < size - 1) { - b |= 0x80; - } - dst[(*offset)++] = b; - } -} - -} // namespace woff2 - diff --git a/third_party/examples/woff2/carbon/src/woff2_common.carbon b/third_party/examples/woff2/carbon/src/woff2_common.carbon deleted file mode 100644 index d4798d1f17fa..000000000000 --- a/third_party/examples/woff2/carbon/src/woff2_common.carbon +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Common definition for WOFF2 encoding/decoding */ - -#ifndef WOFF2_WOFF2_COMMON_H_ -#define WOFF2_WOFF2_COMMON_H_ - -#include -#include -#include - -namespace woff2 { - -let kWoff2Signature: const uint32_t = 0x774f4632; // "wOF2" - -// Leave the first byte open to store flag_byte -let kWoff2FlagsTransform: const unsigned int = 1 << 8; - -// TrueType Collection ID string: 'ttcf' -let kTtcFontFlavor: const uint32_t = 0x74746366; - -let kSfntHeaderSize: const size_t = 12; -let kSfntEntrySize: const size_t = 16; - -struct Point { - int x; - int y; - bool on_curve; -}; - -struct Table { - uint32_t tag; - uint32_t flags; - uint32_t src_offset; - uint32_t src_length; - - uint32_t transform_length; - - uint32_t dst_offset; - uint32_t dst_length; - const uint8_t* dst_data; - - fn operator<(other: const Table&) const -> bool { - return tag < other.tag; - } -}; - - -// Size of the collection header. 0 if version indicates this isn't a -// collection. Ref http://www.microsoft.com/typography/otspec/otff.htm, -// True Type Collections -fn CollectionHeaderSize(header_version: uint32_t, num_fonts: uint32_t) -> size_t; - -// Compute checksum over size bytes of buf -fn ComputeULongSum(buf: const uint8_t*, size: size_t) -> uint32_t; - -} // namespace woff2 - -#endif // WOFF2_WOFF2_COMMON_H_ diff --git a/third_party/examples/woff2/carbon/src/woff2_common.impl.carbon b/third_party/examples/woff2/carbon/src/woff2_common.impl.carbon deleted file mode 100644 index 3aeb6527bedc..000000000000 --- a/third_party/examples/woff2/carbon/src/woff2_common.impl.carbon +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Helpers common across multiple parts of woff2 */ - -#include - -#include "./woff2_common.h" - -#include "./port.h" - -namespace woff2 { - - -fn ComputeULongSum(buf: const uint8_t*, size: size_t) -> uint32_t { - var checksum: uint32_t = 0; - var aligned_size: size_t = size & ~3; - for (var i: size_t = 0; i < aligned_size; i += 4) { -#if defined(WOFF_LITTLE_ENDIAN) - var v: uint32_t = *reinterpret_cast(buf + i); - checksum += (((v & 0xFF) << 24) | ((v & 0xFF00) << 8) | - ((v & 0xFF0000) >> 8) | ((v & 0xFF000000) >> 24)); -#elif defined(WOFF_BIG_ENDIAN) - checksum += *reinterpret_cast(buf + i); -#else - checksum += (buf[i] << 24) | (buf[i + 1] << 16) | - (buf[i + 2] << 8) | buf[i + 3]; -#endif - } - - // treat size not aligned on 4 as if it were padded to 4 with 0's - if (size != aligned_size) { - var v: uint32_t = 0; - for (var i: size_t = aligned_size; i < size; ++i) { - v |= buf[i] << (24 - 8 * (i & 3)); - } - checksum += v; - } - - return checksum; -} - -fn CollectionHeaderSize(header_version: uint32_t, num_fonts: uint32_t) -> size_t { - var size: size_t = 0; - if (header_version == 0x00020000) { - size += 12; // ulDsig{Tag,Length,Offset} - } - if (header_version == 0x00010000 || header_version == 0x00020000) { - size += 12 // TTCTag, Version, numFonts - + 4 * num_fonts; // OffsetTable[numFonts] - } - return size; -} - -} // namespace woff2 diff --git a/third_party/examples/woff2/carbon/src/woff2_compress.impl.carbon b/third_party/examples/woff2/carbon/src/woff2_compress.impl.carbon deleted file mode 100644 index e9cd7a4f3fcb..000000000000 --- a/third_party/examples/woff2/carbon/src/woff2_compress.impl.carbon +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* A commandline tool for compressing ttf format files to woff2. */ - -#include - -#include "file.h" -#include - - -fn main(argc: int, argv: char**) -> int { - using std::string; - - if (argc != 2) { - fprintf(stderr, "One argument, the input filename, must be provided.\n"); - return 1; - } - - var filename: string(argv[1]); - var outfilename: string = filename.substr(0, filename.find_last_of('.')) + ".woff2"; - fprintf(stdout, "Processing %s => %s\n", - filename.c_str(), outfilename.c_str()); - var input: string = woff2::GetFileContent(filename); - - var input_data: const auto* = reinterpret_cast(input.data()); - var output_size: size_t = woff2::MaxWOFF2CompressedSize(input_data, input.size()); - var output: string(output_size, 0); - var output_data: auto* = reinterpret_cast(&output[0]); - - var params: woff2::WOFF2Params; - if (!woff2::ConvertTTFToWOFF2(input_data, input.size(), - output_data, &output_size, params)) { - fprintf(stderr, "Compression failed.\n"); - return 1; - } - output.resize(output_size); - - woff2::SetFileContents(outfilename, output.begin(), output.end()); - - return 0; -} diff --git a/third_party/examples/woff2/carbon/src/woff2_dec.impl.carbon b/third_party/examples/woff2/carbon/src/woff2_dec.impl.carbon deleted file mode 100644 index a9ab3d09cf03..000000000000 --- a/third_party/examples/woff2/carbon/src/woff2_dec.impl.carbon +++ /dev/null @@ -1,1370 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Library for converting WOFF2 format font files to their TTF versions. */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "./buffer.h" -#include "./port.h" -#include "./round.h" -#include "./store_bytes.h" -#include "./table_tags.h" -#include "./variable_length.h" -#include "./woff2_common.h" - -namespace woff2 { - -namespace { - -using std::string; -using std::vector; - - -// simple glyph flags -let kGlyfOnCurve: const int = 1 << 0; -let kGlyfXShort: const int = 1 << 1; -let kGlyfYShort: const int = 1 << 2; -let kGlyfRepeat: const int = 1 << 3; -let kGlyfThisXIsSame: const int = 1 << 4; -let kGlyfThisYIsSame: const int = 1 << 5; - -// composite glyph flags -// See CompositeGlyph.java in sfntly for full definitions -let FLAG_ARG_1_AND_2_ARE_WORDS: const int = 1 << 0; -let FLAG_WE_HAVE_A_SCALE: const int = 1 << 3; -let FLAG_MORE_COMPONENTS: const int = 1 << 5; -let FLAG_WE_HAVE_AN_X_AND_Y_SCALE: const int = 1 << 6; -let FLAG_WE_HAVE_A_TWO_BY_TWO: const int = 1 << 7; -let FLAG_WE_HAVE_INSTRUCTIONS: const int = 1 << 8; - -let kCheckSumAdjustmentOffset: const size_t = 8; - -let kEndPtsOfContoursOffset: const size_t = 10; -let kCompositeGlyphBegin: const size_t = 10; - -// 98% of Google Fonts have no glyph above 5k bytes -// Largest glyph ever observed was 72k bytes -let kDefaultGlyphBuf: const size_t = 5120; - -// Over 14k test fonts the max compression ratio seen to date was ~20. -// >100 suggests you wrote a bad uncompressed size. -let kMaxPlausibleCompressionRatio: const float = 100.0; - -// metadata for a TTC font entry -struct TtcFont { - uint32_t flavor; - uint32_t dst_offset; - uint32_t header_checksum; - std::vector table_indices; -}; - -struct WOFF2Header { - uint32_t flavor; - uint32_t header_version; - uint16_t num_tables; - uint64_t compressed_offset; - uint32_t compressed_length; - uint32_t uncompressed_size; - std::vector tables; // num_tables unique tables - std::vector ttc_fonts; // metadata to help rebuild font -}; - -/** - * Accumulates data we may need to reconstruct a single font. One per font - * created for a TTC. - */ -struct WOFF2FontInfo { - uint16_t num_glyphs; - uint16_t index_format; - uint16_t num_hmetrics; - std::vector x_mins; - std::map table_entry_by_tag; -}; - -// Accumulates metadata as we rebuild the font -struct RebuildMetadata { - uint32_t header_checksum; // set by WriteHeaders - std::vector font_infos; - // checksums for tables that have been written. - // (tag, src_offset) => checksum. Need both because 0-length loca. - std::map, uint32_t> checksums; -}; - -fn WithSign(flag: int, baseval: int) -> int { - // Precondition: 0 <= baseval < 65536 (to avoid integer overflow) - return (flag & 1) ? baseval : -baseval; -} - -fn _SafeIntAddition(a: int, b: int, result: int*) -> bool { - if (PREDICT_FALSE( - ((a > 0) && (b > std::numeric_limits::max() - a)) || - ((a < 0) && (b < std::numeric_limits::min() - a)))) { - return false; - } - *result = a + b; - return true; -} - -fn TripletDecode(flags_in: const uint8_t*, in: const uint8_t*, in_size: size_t, - n_points: unsigned int, result: Point*, in_bytes_consumed: size_t*) -> bool { - var x: int = 0; - var y: int = 0; - - if (PREDICT_FALSE(n_points > in_size)) { - return FONT_COMPRESSION_FAILURE(); - } - var triplet_index: unsigned int = 0; - - for (var i: unsigned int = 0; i < n_points; ++i) { - var flag: uint8_t = flags_in[i]; - var on_curve: bool = !(flag >> 7); - flag &= 0x7f; - var n_data_bytes: unsigned int; - if (flag < 84) { - n_data_bytes = 1; - } else if (flag < 120) { - n_data_bytes = 2; - } else if (flag < 124) { - n_data_bytes = 3; - } else { - n_data_bytes = 4; - } - if (PREDICT_FALSE(triplet_index + n_data_bytes > in_size || - triplet_index + n_data_bytes < triplet_index)) { - return FONT_COMPRESSION_FAILURE(); - } - var dx: int, var dy: int; - if (flag < 10) { - dx = 0; - dy = WithSign(flag, ((flag & 14) << 7) + in[triplet_index]); - } else if (flag < 20) { - dx = WithSign(flag, (((flag - 10) & 14) << 7) + in[triplet_index]); - dy = 0; - } else if (flag < 84) { - var b0: int = flag - 20; - var b1: int = in[triplet_index]; - dx = WithSign(flag, 1 + (b0 & 0x30) + (b1 >> 4)); - dy = WithSign(flag >> 1, 1 + ((b0 & 0x0c) << 2) + (b1 & 0x0f)); - } else if (flag < 120) { - var b0: int = flag - 84; - dx = WithSign(flag, 1 + ((b0 / 12) << 8) + in[triplet_index]); - dy = WithSign(flag >> 1, - 1 + (((b0 % 12) >> 2) << 8) + in[triplet_index + 1]); - } else if (flag < 124) { - var b2: int = in[triplet_index + 1]; - dx = WithSign(flag, (in[triplet_index] << 4) + (b2 >> 4)); - dy = WithSign(flag >> 1, ((b2 & 0x0f) << 8) + in[triplet_index + 2]); - } else { - dx = WithSign(flag, (in[triplet_index] << 8) + in[triplet_index + 1]); - dy = WithSign(flag >> 1, - (in[triplet_index + 2] << 8) + in[triplet_index + 3]); - } - triplet_index += n_data_bytes; - if (!_SafeIntAddition(x, dx, &x)) { - return false; - } - if (!_SafeIntAddition(y, dy, &y)) { - return false; - } - *result++ = {x, y, on_curve}; - } - *in_bytes_consumed = triplet_index; - return true; -} - -// This function stores just the point data. On entry, dst points to the -// beginning of a simple glyph. Returns true on success. -fn StorePoints(n_points: unsigned int, points: const Point*, - n_contours: unsigned int, instruction_length: unsigned int, - dst: uint8_t*, dst_size: size_t, glyph_size: size_t*) -> bool { - // I believe that n_contours < 65536, in which case this is safe. However, a - // comment and/or an assert would be good. - var flag_offset: unsigned int = kEndPtsOfContoursOffset + 2 * n_contours + 2 + - instruction_length; - var last_flag: int = -1; - var repeat_count: int = 0; - var last_x: int = 0; - var last_y: int = 0; - var x_bytes: unsigned int = 0; - var y_bytes: unsigned int = 0; - - for (var i: unsigned int = 0; i < n_points; ++i) { - var point: const Point& = points[i]; - var flag: int = point.on_curve ? kGlyfOnCurve : 0; - var dx: int = point.x - last_x; - var dy: int = point.y - last_y; - if (dx == 0) { - flag |= kGlyfThisXIsSame; - } else if (dx > -256 && dx < 256) { - flag |= kGlyfXShort | (dx > 0 ? kGlyfThisXIsSame : 0); - x_bytes += 1; - } else { - x_bytes += 2; - } - if (dy == 0) { - flag |= kGlyfThisYIsSame; - } else if (dy > -256 && dy < 256) { - flag |= kGlyfYShort | (dy > 0 ? kGlyfThisYIsSame : 0); - y_bytes += 1; - } else { - y_bytes += 2; - } - - if (flag == last_flag && repeat_count != 255) { - dst[flag_offset - 1] |= kGlyfRepeat; - repeat_count++; - } else { - if (repeat_count != 0) { - if (PREDICT_FALSE(flag_offset >= dst_size)) { - return FONT_COMPRESSION_FAILURE(); - } - dst[flag_offset++] = repeat_count; - } - if (PREDICT_FALSE(flag_offset >= dst_size)) { - return FONT_COMPRESSION_FAILURE(); - } - dst[flag_offset++] = flag; - repeat_count = 0; - } - last_x = point.x; - last_y = point.y; - last_flag = flag; - } - - if (repeat_count != 0) { - if (PREDICT_FALSE(flag_offset >= dst_size)) { - return FONT_COMPRESSION_FAILURE(); - } - dst[flag_offset++] = repeat_count; - } - var xy_bytes: unsigned int = x_bytes + y_bytes; - if (PREDICT_FALSE(xy_bytes < x_bytes || - flag_offset + xy_bytes < flag_offset || - flag_offset + xy_bytes > dst_size)) { - return FONT_COMPRESSION_FAILURE(); - } - - var x_offset: int = flag_offset; - var y_offset: int = flag_offset + x_bytes; - last_x = 0; - last_y = 0; - for (var i: unsigned int = 0; i < n_points; ++i) { - var dx: int = points[i].x - last_x; - if (dx == 0) { - // pass - } else if (dx > -256 && dx < 256) { - dst[x_offset++] = std::abs(dx); - } else { - // will always fit for valid input, but overflow is harmless - x_offset = Store16(dst, x_offset, dx); - } - last_x += dx; - var dy: int = points[i].y - last_y; - if (dy == 0) { - // pass - } else if (dy > -256 && dy < 256) { - dst[y_offset++] = std::abs(dy); - } else { - y_offset = Store16(dst, y_offset, dy); - } - last_y += dy; - } - *glyph_size = y_offset; - return true; -} - -// Compute the bounding box of the coordinates, and store into a glyf buffer. -// A precondition is that there are at least 10 bytes available. -// dst should point to the beginning of a 'glyf' record. -fn ComputeBbox(n_points: unsigned int, points: const Point*, dst: uint8_t*) { - var x_min: int = 0; - var y_min: int = 0; - var x_max: int = 0; - var y_max: int = 0; - - if (n_points > 0) { - x_min = points[0].x; - x_max = points[0].x; - y_min = points[0].y; - y_max = points[0].y; - } - for (var i: unsigned int = 1; i < n_points; ++i) { - var x: int = points[i].x; - var y: int = points[i].y; - x_min = std::min(x, x_min); - x_max = std::max(x, x_max); - y_min = std::min(y, y_min); - y_max = std::max(y, y_max); - } - var offset: size_t = 2; - offset = Store16(dst, offset, x_min); - offset = Store16(dst, offset, y_min); - offset = Store16(dst, offset, x_max); - offset = Store16(dst, offset, y_max); -} - - -fn SizeOfComposite(composite_stream: Buffer, size: size_t*, - have_instructions: bool*) -> bool { - var start_offset: size_t = composite_stream.offset(); - var we_have_instructions: bool = false; - - var flags: uint16_t = FLAG_MORE_COMPONENTS; - while (flags & FLAG_MORE_COMPONENTS) { - if (PREDICT_FALSE(!composite_stream.ReadU16(&flags))) { - return FONT_COMPRESSION_FAILURE(); - } - we_have_instructions |= (flags & FLAG_WE_HAVE_INSTRUCTIONS) != 0; - var arg_size: size_t = 2; // glyph index - if (flags & FLAG_ARG_1_AND_2_ARE_WORDS) { - arg_size += 4; - } else { - arg_size += 2; - } - if (flags & FLAG_WE_HAVE_A_SCALE) { - arg_size += 2; - } else if (flags & FLAG_WE_HAVE_AN_X_AND_Y_SCALE) { - arg_size += 4; - } else if (flags & FLAG_WE_HAVE_A_TWO_BY_TWO) { - arg_size += 8; - } - if (PREDICT_FALSE(!composite_stream.Skip(arg_size))) { - return FONT_COMPRESSION_FAILURE(); - } - } - - *size = composite_stream.offset() - start_offset; - *have_instructions = we_have_instructions; - - return true; -} - -fn Pad4(out: WOFF2Out*) -> bool { - var zeroes: uint8_t[] = {0, 0, 0}; - if (PREDICT_FALSE(out->Size() + 3 < out->Size())) { - return FONT_COMPRESSION_FAILURE(); - } - var pad_bytes: uint32_t = Round4(out->Size()) - out->Size(); - if (pad_bytes > 0) { - if (PREDICT_FALSE(!out->Write(&zeroes, pad_bytes))) { - return FONT_COMPRESSION_FAILURE(); - } - } - return true; -} - -// Build TrueType loca table -fn StoreLoca(loca_values: const std::vector&, index_format: int, - checksum: uint32_t*, out: WOFF2Out*) -> bool { - // TODO(user) figure out what index format to use based on whether max - // offset fits into uint16_t or not - let loca_size: const uint64_t = loca_values.size(); - let offset_size: const uint64_t = index_format ? 4 : 2; - if (PREDICT_FALSE((loca_size << 2) >> 2 != loca_size)) { - return FONT_COMPRESSION_FAILURE(); - } - var loca_content: std::vector(loca_size * offset_size); - var dst: uint8_t* = &loca_content[0]; - var offset: size_t = 0; - for (unsigned int value in loca_values) { - if (index_format) { - offset = StoreU32(dst, offset, value); - } else { - offset = Store16(dst, offset, value >> 1); - } - } - *checksum = ComputeULongSum(&loca_content[0], loca_content.size()); - if (PREDICT_FALSE(!out->Write(&loca_content[0], loca_content.size()))) { - return FONT_COMPRESSION_FAILURE(); - } - return true; -} - -// Reconstruct entire glyf table based on transformed original -fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*, - glyf_checksum: uint32_t*, loca_table: Table*, - loca_checksum: uint32_t*, info: WOFF2FontInfo*, - out: WOFF2Out*) -> bool { - let kNumSubStreams: const int = 7; - var file: Buffer(data, glyf_table->transform_length); - var version: uint32_t; - var substreams: std::vector >(kNumSubStreams); - let glyf_start: const size_t = out->Size(); - - if (PREDICT_FALSE(!file.ReadU32(&version))) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(!file.ReadU16(&info->num_glyphs) || - !file.ReadU16(&info->index_format))) { - return FONT_COMPRESSION_FAILURE(); - } - - // https://dev.w3.org/webfonts/WOFF2/spec/#conform-mustRejectLoca - // dst_length here is origLength in the spec - var expected_loca_dst_length: uint32_t = (info->index_format ? 4 : 2) - * (static_cast(info->num_glyphs) + 1); - if (PREDICT_FALSE(loca_table->dst_length != expected_loca_dst_length)) { - return FONT_COMPRESSION_FAILURE(); - } - - var offset: unsigned int = (2 + kNumSubStreams) * 4; - if (PREDICT_FALSE(offset > glyf_table->transform_length)) { - return FONT_COMPRESSION_FAILURE(); - } - // Invariant from here on: data_size >= offset - for (var i: int = 0; i < kNumSubStreams; ++i) { - var substream_size: uint32_t; - if (PREDICT_FALSE(!file.ReadU32(&substream_size))) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(substream_size > glyf_table->transform_length - offset)) { - return FONT_COMPRESSION_FAILURE(); - } - substreams[i] = std::make_pair(data + offset, substream_size); - offset += substream_size; - } - var n_contour_stream: Buffer(substreams[0].first, substreams[0].second); - var n_points_stream: Buffer(substreams[1].first, substreams[1].second); - var flag_stream: Buffer(substreams[2].first, substreams[2].second); - var glyph_stream: Buffer(substreams[3].first, substreams[3].second); - var composite_stream: Buffer(substreams[4].first, substreams[4].second); - var bbox_stream: Buffer(substreams[5].first, substreams[5].second); - var instruction_stream: Buffer(substreams[6].first, substreams[6].second); - - var loca_values: std::vector(info->num_glyphs + 1); - var n_points_vec: std::vector; - var points: std::unique_ptr; - var points_size: size_t = 0; - var bbox_bitmap: const uint8_t* = bbox_stream.buffer(); - // Safe because num_glyphs is bounded - var bitmap_length: unsigned int = ((info->num_glyphs + 31) >> 5) << 2; - if (!bbox_stream.Skip(bitmap_length)) { - return FONT_COMPRESSION_FAILURE(); - } - - // Temp buffer for glyph's. - var glyph_buf_size: size_t = kDefaultGlyphBuf; - var glyph_buf: std::unique_ptr(new uint8_t[glyph_buf_size]); - - info->x_mins.resize(info->num_glyphs); - for (var i: unsigned int = 0; i < info->num_glyphs; ++i) { - var glyph_size: size_t = 0; - var n_contours: uint16_t = 0; - var have_bbox: bool = false; - if (bbox_bitmap[i >> 3] & (0x80 >> (i & 7))) { - have_bbox = true; - } - if (PREDICT_FALSE(!n_contour_stream.ReadU16(&n_contours))) { - return FONT_COMPRESSION_FAILURE(); - } - - if (n_contours == 0xffff) { - // composite glyph - var have_instructions: bool = false; - var instruction_size: unsigned int = 0; - if (PREDICT_FALSE(!have_bbox)) { - // composite glyphs must have an explicit bbox - return FONT_COMPRESSION_FAILURE(); - } - - var composite_size: size_t; - if (PREDICT_FALSE(!SizeOfComposite(composite_stream, &composite_size, - &have_instructions))) { - return FONT_COMPRESSION_FAILURE(); - } - if (have_instructions) { - if (PREDICT_FALSE(!Read255UShort(&glyph_stream, &instruction_size))) { - return FONT_COMPRESSION_FAILURE(); - } - } - - var size_needed: size_t = 12 + composite_size + instruction_size; - if (PREDICT_FALSE(glyph_buf_size < size_needed)) { - glyph_buf.reset(new uint8_t[size_needed]); - glyph_buf_size = size_needed; - } - - glyph_size = Store16(glyph_buf.get(), glyph_size, n_contours); - if (PREDICT_FALSE(!bbox_stream.Read(glyph_buf.get() + glyph_size, 8))) { - return FONT_COMPRESSION_FAILURE(); - } - glyph_size += 8; - - if (PREDICT_FALSE(!composite_stream.Read(glyph_buf.get() + glyph_size, - composite_size))) { - return FONT_COMPRESSION_FAILURE(); - } - glyph_size += composite_size; - if (have_instructions) { - glyph_size = Store16(glyph_buf.get(), glyph_size, instruction_size); - if (PREDICT_FALSE(!instruction_stream.Read(glyph_buf.get() + glyph_size, - instruction_size))) { - return FONT_COMPRESSION_FAILURE(); - } - glyph_size += instruction_size; - } - } else if (n_contours > 0) { - // simple glyph - n_points_vec.clear(); - var total_n_points: unsigned int = 0; - var n_points_contour: unsigned int; - for (var j: unsigned int = 0; j < n_contours; ++j) { - if (PREDICT_FALSE( - !Read255UShort(&n_points_stream, &n_points_contour))) { - return FONT_COMPRESSION_FAILURE(); - } - n_points_vec.push_back(n_points_contour); - if (PREDICT_FALSE(total_n_points + n_points_contour < total_n_points)) { - return FONT_COMPRESSION_FAILURE(); - } - total_n_points += n_points_contour; - } - var flag_size: unsigned int = total_n_points; - if (PREDICT_FALSE( - flag_size > flag_stream.length() - flag_stream.offset())) { - return FONT_COMPRESSION_FAILURE(); - } - var flags_buf: const uint8_t* = flag_stream.buffer() + flag_stream.offset(); - var triplet_buf: const uint8_t* = glyph_stream.buffer() + - glyph_stream.offset(); - var triplet_size: size_t = glyph_stream.length() - glyph_stream.offset(); - var triplet_bytes_consumed: size_t = 0; - if (points_size < total_n_points) { - points_size = total_n_points; - points = std::make_unique(points_size); - } - if (PREDICT_FALSE(!TripletDecode(flags_buf, triplet_buf, triplet_size, - total_n_points, points.get(), &triplet_bytes_consumed))) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(!flag_stream.Skip(flag_size))) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(!glyph_stream.Skip(triplet_bytes_consumed))) { - return FONT_COMPRESSION_FAILURE(); - } - var instruction_size: unsigned int; - if (PREDICT_FALSE(!Read255UShort(&glyph_stream, &instruction_size))) { - return FONT_COMPRESSION_FAILURE(); - } - - if (PREDICT_FALSE(total_n_points >= (1 << 27) - || instruction_size >= (1 << 30))) { - return FONT_COMPRESSION_FAILURE(); - } - var size_needed: size_t = 12 + 2 * n_contours + 5 * total_n_points - + instruction_size; - if (PREDICT_FALSE(glyph_buf_size < size_needed)) { - glyph_buf.reset(new uint8_t[size_needed]); - glyph_buf_size = size_needed; - } - - glyph_size = Store16(glyph_buf.get(), glyph_size, n_contours); - if (have_bbox) { - if (PREDICT_FALSE(!bbox_stream.Read(glyph_buf.get() + glyph_size, 8))) { - return FONT_COMPRESSION_FAILURE(); - } - } else { - ComputeBbox(total_n_points, points.get(), glyph_buf.get()); - } - glyph_size = kEndPtsOfContoursOffset; - var end_point: int = -1; - for (var contour_ix: unsigned int = 0; contour_ix < n_contours; ++contour_ix) { - end_point += n_points_vec[contour_ix]; - if (PREDICT_FALSE(end_point >= 65536)) { - return FONT_COMPRESSION_FAILURE(); - } - glyph_size = Store16(glyph_buf.get(), glyph_size, end_point); - } - - glyph_size = Store16(glyph_buf.get(), glyph_size, instruction_size); - if (PREDICT_FALSE(!instruction_stream.Read(glyph_buf.get() + glyph_size, - instruction_size))) { - return FONT_COMPRESSION_FAILURE(); - } - glyph_size += instruction_size; - - if (PREDICT_FALSE(!StorePoints(total_n_points, points.get(), n_contours, - instruction_size, glyph_buf.get(), glyph_buf_size, &glyph_size))) { - return FONT_COMPRESSION_FAILURE(); - } - } else { - // n_contours == 0; empty glyph. Must NOT have a bbox. - if (PREDICT_FALSE(have_bbox)) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Empty glyph has a bbox\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - } - - loca_values[i] = out->Size() - glyf_start; - if (PREDICT_FALSE(!out->Write(glyph_buf.get(), glyph_size))) { - return FONT_COMPRESSION_FAILURE(); - } - - // TODO(user) Old code aligned glyphs ... but do we actually need to? - if (PREDICT_FALSE(!Pad4(out))) { - return FONT_COMPRESSION_FAILURE(); - } - - *glyf_checksum += ComputeULongSum(glyph_buf.get(), glyph_size); - - // We may need x_min to reconstruct 'hmtx' - if (n_contours > 0) { - var x_min_buf: Buffer(glyph_buf.get() + 2, 2); - if (PREDICT_FALSE(!x_min_buf.ReadS16(&info->x_mins[i]))) { - return FONT_COMPRESSION_FAILURE(); - } - } - } - - // glyf_table dst_offset was set by ReconstructFont - glyf_table->dst_length = out->Size() - glyf_table->dst_offset; - loca_table->dst_offset = out->Size(); - // loca[n] will be equal the length of the glyph data ('glyf') table - loca_values[info->num_glyphs] = glyf_table->dst_length; - if (PREDICT_FALSE(!StoreLoca(loca_values, info->index_format, loca_checksum, - out))) { - return FONT_COMPRESSION_FAILURE(); - } - loca_table->dst_length = out->Size() - loca_table->dst_offset; - - return true; -} - -fn FindTable(tables: std::vector*, tag: uint32_t) -> Table* { - for (Table* table in *tables) { - if (table->tag == tag) { - return table; - } - } - return nullptr; -} - -// Get numberOfHMetrics, https://www.microsoft.com/typography/otspec/hhea.htm -fn ReadNumHMetrics(data: const uint8_t*, data_size: size_t, - num_hmetrics: uint16_t*) -> bool { - // Skip 34 to reach 'hhea' numberOfHMetrics - var buffer: Buffer(data, data_size); - if (PREDICT_FALSE(!buffer.Skip(34) || !buffer.ReadU16(num_hmetrics))) { - return FONT_COMPRESSION_FAILURE(); - } - return true; -} - -// http://dev.w3.org/webfonts/WOFF2/spec/Overview.html#hmtx_table_format -fn ReconstructTransformedHmtx(transformed_buf: const uint8_t*, - transformed_size: size_t, - num_glyphs: uint16_t, - num_hmetrics: uint16_t, - x_mins: const std::vector&, - checksum: uint32_t*, - out: WOFF2Out*) -> bool { - var hmtx_buff_in: Buffer(transformed_buf, transformed_size); - - var hmtx_flags: uint8_t; - if (PREDICT_FALSE(!hmtx_buff_in.ReadU8(&hmtx_flags))) { - return FONT_COMPRESSION_FAILURE(); - } - - var advance_widths: std::vector; - var lsbs: std::vector; - var has_proportional_lsbs: bool = (hmtx_flags & 1) == 0; - var has_monospace_lsbs: bool = (hmtx_flags & 2) == 0; - - // Bits 2-7 are reserved and MUST be zero. - if ((hmtx_flags & 0xFC) != 0) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Illegal hmtx flags; bits 2-7 must be 0\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - - // you say you transformed but there is little evidence of it - if (has_proportional_lsbs && has_monospace_lsbs) { - return FONT_COMPRESSION_FAILURE(); - } - - assert(x_mins.size() == num_glyphs); - - // num_glyphs 0 is OK if there is no 'glyf' but cannot then xform 'hmtx'. - if (PREDICT_FALSE(num_hmetrics > num_glyphs)) { - return FONT_COMPRESSION_FAILURE(); - } - - // https://www.microsoft.com/typography/otspec/hmtx.htm - // "...only one entry need be in the array, but that entry is required." - if (PREDICT_FALSE(num_hmetrics < 1)) { - return FONT_COMPRESSION_FAILURE(); - } - - for (var i: uint16_t = 0; i < num_hmetrics; i++) { - var advance_width: uint16_t; - if (PREDICT_FALSE(!hmtx_buff_in.ReadU16(&advance_width))) { - return FONT_COMPRESSION_FAILURE(); - } - advance_widths.push_back(advance_width); - } - - for (var i: uint16_t = 0; i < num_hmetrics; i++) { - var lsb: int16_t; - if (has_proportional_lsbs) { - if (PREDICT_FALSE(!hmtx_buff_in.ReadS16(&lsb))) { - return FONT_COMPRESSION_FAILURE(); - } - } else { - lsb = x_mins[i]; - } - lsbs.push_back(lsb); - } - - for (var i: uint16_t = num_hmetrics; i < num_glyphs; i++) { - var lsb: int16_t; - if (has_monospace_lsbs) { - if (PREDICT_FALSE(!hmtx_buff_in.ReadS16(&lsb))) { - return FONT_COMPRESSION_FAILURE(); - } - } else { - lsb = x_mins[i]; - } - lsbs.push_back(lsb); - } - - // bake me a shiny new hmtx table - var hmtx_output_size: uint32_t = 2 * num_glyphs + 2 * num_hmetrics; - var hmtx_table: std::vector(hmtx_output_size); - var dst: uint8_t* = &hmtx_table[0]; - var dst_offset: size_t = 0; - for (var i: uint32_t = 0; i < num_glyphs; i++) { - if (i < num_hmetrics) { - Store16(advance_widths[i], &dst_offset, dst); - } - Store16(lsbs[i], &dst_offset, dst); - } - - *checksum = ComputeULongSum(&hmtx_table[0], hmtx_output_size); - if (PREDICT_FALSE(!out->Write(&hmtx_table[0], hmtx_output_size))) { - return FONT_COMPRESSION_FAILURE(); - } - - return true; -} - -fn Woff2Uncompress(dst_buf: uint8_t*, dst_size: size_t, - src_buf: const uint8_t*, src_size: size_t) -> bool { - var uncompressed_size: size_t = dst_size; - var result: BrotliDecoderResult = BrotliDecoderDecompress( - src_size, src_buf, &uncompressed_size, dst_buf); - if (PREDICT_FALSE(result != BROTLI_DECODER_RESULT_SUCCESS || - uncompressed_size != dst_size)) { - return FONT_COMPRESSION_FAILURE(); - } - return true; -} - -fn ReadTableDirectory(file: Buffer*, tables: std::vector
*, - num_tables: size_t) -> bool { - var src_offset: uint32_t = 0; - for (var i: size_t = 0; i < num_tables; ++i) { - var table: Table* = &(*tables)[i]; - var flag_byte: uint8_t; - if (PREDICT_FALSE(!file->ReadU8(&flag_byte))) { - return FONT_COMPRESSION_FAILURE(); - } - var tag: uint32_t; - if ((flag_byte & 0x3f) == 0x3f) { - if (PREDICT_FALSE(!file->ReadU32(&tag))) { - return FONT_COMPRESSION_FAILURE(); - } - } else { - tag = kKnownTags[flag_byte & 0x3f]; - } - var flags: uint32_t = 0; - var xform_version: uint8_t = (flag_byte >> 6) & 0x03; - - // 0 means xform for glyph/loca, non-0 for others - if (tag == kGlyfTableTag || tag == kLocaTableTag) { - if (xform_version == 0) { - flags |= kWoff2FlagsTransform; - } - } else if (xform_version != 0) { - flags |= kWoff2FlagsTransform; - } - flags |= xform_version; - - var dst_length: uint32_t; - if (PREDICT_FALSE(!ReadBase128(file, &dst_length))) { - return FONT_COMPRESSION_FAILURE(); - } - var transform_length: uint32_t = dst_length; - if ((flags & kWoff2FlagsTransform) != 0) { - if (PREDICT_FALSE(!ReadBase128(file, &transform_length))) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(tag == kLocaTableTag && transform_length)) { - return FONT_COMPRESSION_FAILURE(); - } - } - if (PREDICT_FALSE(src_offset + transform_length < src_offset)) { - return FONT_COMPRESSION_FAILURE(); - } - table->src_offset = src_offset; - table->src_length = transform_length; - src_offset += transform_length; - - table->tag = tag; - table->flags = flags; - table->transform_length = transform_length; - table->dst_length = dst_length; - } - return true; -} - -// Writes a single Offset Table entry -fn StoreOffsetTable(result: uint8_t*, offset: size_t, flavor: uint32_t, - num_tables: uint16_t) -> size_t { - offset = StoreU32(result, offset, flavor); // sfnt version - offset = Store16(result, offset, num_tables); // num_tables - var max_pow2: unsigned = 0; - while (1u << (max_pow2 + 1) <= num_tables) { - max_pow2++; - } - let output_search_range: const uint16_t = (1u << max_pow2) << 4; - offset = Store16(result, offset, output_search_range); // searchRange - offset = Store16(result, offset, max_pow2); // entrySelector - // rangeShift - offset = Store16(result, offset, (num_tables << 4) - output_search_range); - return offset; -} - -fn StoreTableEntry(result: uint8_t*, offset: uint32_t, tag: uint32_t) -> size_t { - offset = StoreU32(result, offset, tag); - offset = StoreU32(result, offset, 0); - offset = StoreU32(result, offset, 0); - offset = StoreU32(result, offset, 0); - return offset; -} - -// First table goes after all the headers, table directory, etc -fn ComputeOffsetToFirstTable(hdr: const WOFF2Header&) -> uint64_t { - var offset: uint64_t = kSfntHeaderSize + - kSfntEntrySize * static_cast(hdr.num_tables); - if (hdr.header_version) { - offset = CollectionHeaderSize(hdr.header_version, hdr.ttc_fonts.size()) - + kSfntHeaderSize * hdr.ttc_fonts.size(); - for (const auto& ttc_font in hdr.ttc_fonts) { - offset += kSfntEntrySize * ttc_font.table_indices.size(); - } - } - return offset; -} - -fn Tables(hdr: WOFF2Header*, font_index: size_t) -> std::vector { - var tables: std::vector; - if (PREDICT_FALSE(hdr->header_version)) { - for (auto index in hdr->ttc_fonts[font_index].table_indices) { - tables.push_back(&hdr->tables[index]); - } - } else { - for (auto& table in hdr->tables) { - tables.push_back(&table); - } - } - return tables; -} - -// Offset tables assumed to have been written in with 0's initially. -// WOFF2Header isn't const so we can use [] instead of at() (which upsets FF) -fn ReconstructFont(transformed_buf: uint8_t*, - let transformed_buf_size: const uint32_t, - metadata: RebuildMetadata*, - hdr: WOFF2Header*, - font_index: size_t, - out: WOFF2Out*) -> bool { - var dest_offset: size_t = out->Size(); - var table_entry: uint8_t[12]; - var info: WOFF2FontInfo* = &metadata->font_infos[font_index]; - var tables: std::vector = Tables(hdr, font_index); - - // 'glyf' without 'loca' doesn't make sense - var glyf_table: const Table* = FindTable(&tables, kGlyfTableTag); - var loca_table: const Table* = FindTable(&tables, kLocaTableTag); - if (PREDICT_FALSE(static_cast(glyf_table) != - static_cast(loca_table))) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Cannot have just one of glyf/loca\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - - if (glyf_table != nullptr) { - if (PREDICT_FALSE((glyf_table->flags & kWoff2FlagsTransform) - != (loca_table->flags & kWoff2FlagsTransform))) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Cannot transform just one of glyf/loca\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - } - - var font_checksum: uint32_t = metadata->header_checksum; - if (hdr->header_version) { - font_checksum = hdr->ttc_fonts[font_index].header_checksum; - } - - var loca_checksum: uint32_t = 0; - for (var i: size_t = 0; i < tables.size(); i++) { - var table: Table& = *tables[i]; - - var checksum_key: std::pair = {table.tag, table.src_offset}; - var reused: bool = metadata->checksums.find(checksum_key) - != metadata->checksums.end(); - if (PREDICT_FALSE(font_index == 0 && reused)) { - return FONT_COMPRESSION_FAILURE(); - } - - // TODO(user) a collection with optimized hmtx that reused glyf/loca - // would fail. We don't optimize hmtx for collections yet. - if (PREDICT_FALSE(static_cast(table.src_offset) + table.src_length - > transformed_buf_size)) { - return FONT_COMPRESSION_FAILURE(); - } - - if (table.tag == kHheaTableTag) { - if (!ReadNumHMetrics(transformed_buf + table.src_offset, - table.src_length, &info->num_hmetrics)) { - return FONT_COMPRESSION_FAILURE(); - } - } - - var checksum: uint32_t = 0; - if (!reused) { - if ((table.flags & kWoff2FlagsTransform) != kWoff2FlagsTransform) { - if (table.tag == kHeadTableTag) { - if (PREDICT_FALSE(table.src_length < 12)) { - return FONT_COMPRESSION_FAILURE(); - } - // checkSumAdjustment = 0 - StoreU32(transformed_buf + table.src_offset, 8, 0); - } - table.dst_offset = dest_offset; - checksum = ComputeULongSum(transformed_buf + table.src_offset, - table.src_length); - if (PREDICT_FALSE(!out->Write(transformed_buf + table.src_offset, - table.src_length))) { - return FONT_COMPRESSION_FAILURE(); - } - } else { - if (table.tag == kGlyfTableTag) { - table.dst_offset = dest_offset; - - var loca_table: Table* = FindTable(&tables, kLocaTableTag); - if (PREDICT_FALSE(!ReconstructGlyf(transformed_buf + table.src_offset, - &table, &checksum, loca_table, &loca_checksum, info, out))) { - return FONT_COMPRESSION_FAILURE(); - } - } else if (table.tag == kLocaTableTag) { - // All the work was done by ReconstructGlyf. We already know checksum. - checksum = loca_checksum; - } else if (table.tag == kHmtxTableTag) { - table.dst_offset = dest_offset; - // Tables are sorted so all the info we need has been gathered. - if (PREDICT_FALSE(!ReconstructTransformedHmtx( - transformed_buf + table.src_offset, table.src_length, - info->num_glyphs, info->num_hmetrics, info->x_mins, &checksum, - out))) { - return FONT_COMPRESSION_FAILURE(); - } - } else { - return FONT_COMPRESSION_FAILURE(); // transform unknown - } - } - metadata->checksums[checksum_key] = checksum; - } else { - checksum = metadata->checksums[checksum_key]; - } - font_checksum += checksum; - - // update the table entry with real values. - StoreU32(table_entry, 0, checksum); - StoreU32(table_entry, 4, table.dst_offset); - StoreU32(table_entry, 8, table.dst_length); - if (PREDICT_FALSE(!out->Write(table_entry, - info->table_entry_by_tag[table.tag] + 4, 12))) { - return FONT_COMPRESSION_FAILURE(); - } - - // We replaced 0's. Update overall checksum. - font_checksum += ComputeULongSum(table_entry, 12); - - if (PREDICT_FALSE(!Pad4(out))) { - return FONT_COMPRESSION_FAILURE(); - } - - if (PREDICT_FALSE(static_cast(table.dst_offset + table.dst_length) - > out->Size())) { - return FONT_COMPRESSION_FAILURE(); - } - dest_offset = out->Size(); - } - - // Update 'head' checkSumAdjustment. We already set it to 0 and summed font. - var head_table: Table* = FindTable(&tables, kHeadTableTag); - if (head_table) { - if (PREDICT_FALSE(head_table->dst_length < 12)) { - return FONT_COMPRESSION_FAILURE(); - } - var checksum_adjustment: uint8_t[4]; - StoreU32(checksum_adjustment, 0, 0xB1B0AFBA - font_checksum); - if (PREDICT_FALSE(!out->Write(checksum_adjustment, - head_table->dst_offset + 8, 4))) { - return FONT_COMPRESSION_FAILURE(); - } - } - - return true; -} - -fn ReadWOFF2Header(data: const uint8_t*, length: size_t, hdr: WOFF2Header*) -> bool { - var file: Buffer(data, length); - - var signature: uint32_t; - if (PREDICT_FALSE(!file.ReadU32(&signature) || signature != kWoff2Signature || - !file.ReadU32(&hdr->flavor))) { - return FONT_COMPRESSION_FAILURE(); - } - - // TODO(user): Should call IsValidVersionTag() here. - - var reported_length: uint32_t; - if (PREDICT_FALSE( - !file.ReadU32(&reported_length) || length != reported_length)) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(!file.ReadU16(&hdr->num_tables) || !hdr->num_tables)) { - return FONT_COMPRESSION_FAILURE(); - } - - // We don't care about these fields of the header: - // uint16_t reserved - // uint32_t total_sfnt_size, we don't believe this, will compute later - if (PREDICT_FALSE(!file.Skip(6))) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(!file.ReadU32(&hdr->compressed_length))) { - return FONT_COMPRESSION_FAILURE(); - } - // We don't care about these fields of the header: - // uint16_t major_version, minor_version - if (PREDICT_FALSE(!file.Skip(2 * 2))) { - return FONT_COMPRESSION_FAILURE(); - } - var meta_offset: uint32_t; - var meta_length: uint32_t; - var meta_length_orig: uint32_t; - if (PREDICT_FALSE(!file.ReadU32(&meta_offset) || - !file.ReadU32(&meta_length) || - !file.ReadU32(&meta_length_orig))) { - return FONT_COMPRESSION_FAILURE(); - } - if (meta_offset) { - if (PREDICT_FALSE( - meta_offset >= length || length - meta_offset < meta_length)) { - return FONT_COMPRESSION_FAILURE(); - } - } - var priv_offset: uint32_t; - var priv_length: uint32_t; - if (PREDICT_FALSE(!file.ReadU32(&priv_offset) || - !file.ReadU32(&priv_length))) { - return FONT_COMPRESSION_FAILURE(); - } - if (priv_offset) { - if (PREDICT_FALSE( - priv_offset >= length || length - priv_offset < priv_length)) { - return FONT_COMPRESSION_FAILURE(); - } - } - hdr->tables.resize(hdr->num_tables); - if (PREDICT_FALSE(!ReadTableDirectory( - &file, &hdr->tables, hdr->num_tables))) { - return FONT_COMPRESSION_FAILURE(); - } - - // Before we sort for output the last table end is the uncompressed size. - var last_table: Table& = hdr->tables.back(); - hdr->uncompressed_size = last_table.src_offset + last_table.src_length; - if (PREDICT_FALSE(hdr->uncompressed_size < last_table.src_offset)) { - return FONT_COMPRESSION_FAILURE(); - } - - hdr->header_version = 0; - - if (hdr->flavor == kTtcFontFlavor) { - if (PREDICT_FALSE(!file.ReadU32(&hdr->header_version))) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(hdr->header_version != 0x00010000 - && hdr->header_version != 0x00020000)) { - return FONT_COMPRESSION_FAILURE(); - } - var num_fonts: uint32_t; - if (PREDICT_FALSE(!Read255UShort(&file, &num_fonts) || !num_fonts)) { - return FONT_COMPRESSION_FAILURE(); - } - hdr->ttc_fonts.resize(num_fonts); - - for (var i: uint32_t = 0; i < num_fonts; i++) { - var ttc_font: TtcFont& = hdr->ttc_fonts[i]; - var num_tables: uint32_t; - if (PREDICT_FALSE(!Read255UShort(&file, &num_tables) || !num_tables)) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(!file.ReadU32(&ttc_font.flavor))) { - return FONT_COMPRESSION_FAILURE(); - } - - ttc_font.table_indices.resize(num_tables); - - - var glyf_idx: unsigned int = 0; - var loca_idx: unsigned int = 0; - - for (var j: uint32_t = 0; j < num_tables; j++) { - var table_idx: unsigned int; - if (PREDICT_FALSE(!Read255UShort(&file, &table_idx)) || - table_idx >= hdr->tables.size()) { - return FONT_COMPRESSION_FAILURE(); - } - ttc_font.table_indices[j] = table_idx; - - var table: const Table& = hdr->tables[table_idx]; - if (table.tag == kLocaTableTag) { - loca_idx = table_idx; - } - if (table.tag == kGlyfTableTag) { - glyf_idx = table_idx; - } - - } - - // if we have both glyf and loca make sure they are consecutive - // if we have just one we'll reject the font elsewhere - if (glyf_idx > 0 || loca_idx > 0) { - if (PREDICT_FALSE(glyf_idx > loca_idx || loca_idx - glyf_idx != 1)) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "TTC font %d has non-consecutive glyf/loca\n", i); -#endif - return FONT_COMPRESSION_FAILURE(); - } - } - } - } - - let first_table_offset: const uint64_t = ComputeOffsetToFirstTable(*hdr); - - hdr->compressed_offset = file.offset(); - if (PREDICT_FALSE(hdr->compressed_offset > - std::numeric_limits::max())) { - return FONT_COMPRESSION_FAILURE(); - } - var src_offset: uint64_t = Round4(hdr->compressed_offset + hdr->compressed_length); - var dst_offset: uint64_t = first_table_offset; - - - if (PREDICT_FALSE(src_offset > length)) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "offset fail; src_offset %" PRIu64 " length %lu " - "dst_offset %" PRIu64 "\n", - src_offset, length, dst_offset); -#endif - return FONT_COMPRESSION_FAILURE(); - } - if (meta_offset) { - if (PREDICT_FALSE(src_offset != meta_offset)) { - return FONT_COMPRESSION_FAILURE(); - } - src_offset = Round4(meta_offset + meta_length); - if (PREDICT_FALSE(src_offset > std::numeric_limits::max())) { - return FONT_COMPRESSION_FAILURE(); - } - } - - if (priv_offset) { - if (PREDICT_FALSE(src_offset != priv_offset)) { - return FONT_COMPRESSION_FAILURE(); - } - src_offset = Round4(priv_offset + priv_length); - if (PREDICT_FALSE(src_offset > std::numeric_limits::max())) { - return FONT_COMPRESSION_FAILURE(); - } - } - - if (PREDICT_FALSE(src_offset != Round4(length))) { - return FONT_COMPRESSION_FAILURE(); - } - - return true; -} - -// Write everything before the actual table data -fn WriteHeaders(metadata: RebuildMetadata*, - hdr: WOFF2Header*, out: WOFF2Out*) -> bool { - var output: std::vector(ComputeOffsetToFirstTable(*hdr), 0); - - // Re-order tables in output (OTSpec) order - var sorted_tables: std::vector
(hdr->tables); - if (hdr->header_version) { - // collection; we have to sort the table offset vector in each font - for (auto& ttc_font in hdr->ttc_fonts) { - var sorted_index_by_tag: std::map; - for (auto table_index in ttc_font.table_indices) { - sorted_index_by_tag[hdr->tables[table_index].tag] = table_index; - } - var index: uint16_t = 0; - for (auto& i in sorted_index_by_tag) { - ttc_font.table_indices[index++] = i.second; - } - } - } else { - // non-collection; we can just sort the tables - std::sort(sorted_tables.begin(), sorted_tables.end()); - } - - // Start building the font - var result: uint8_t* = &output[0]; - var offset: size_t = 0; - if (hdr->header_version) { - // TTC header - offset = StoreU32(result, offset, hdr->flavor); // TAG TTCTag - offset = StoreU32(result, offset, hdr->header_version); // FIXED Version - offset = StoreU32(result, offset, hdr->ttc_fonts.size()); // ULONG numFonts - // Space for ULONG OffsetTable[numFonts] (zeroed initially) - var offset_table: size_t = offset; // keep start of offset table for later - for (var i: size_t = 0; i < hdr->ttc_fonts.size(); i++) { - offset = StoreU32(result, offset, 0); // will fill real values in later - } - // space for DSIG fields for header v2 - if (hdr->header_version == 0x00020000) { - offset = StoreU32(result, offset, 0); // ULONG ulDsigTag - offset = StoreU32(result, offset, 0); // ULONG ulDsigLength - offset = StoreU32(result, offset, 0); // ULONG ulDsigOffset - } - - // write Offset Tables and store the location of each in TTC Header - metadata->font_infos.resize(hdr->ttc_fonts.size()); - for (var i: size_t = 0; i < hdr->ttc_fonts.size(); i++) { - var ttc_font: TtcFont& = hdr->ttc_fonts[i]; - - // write Offset Table location into TTC Header - offset_table = StoreU32(result, offset_table, offset); - - // write the actual offset table so our header doesn't lie - ttc_font.dst_offset = offset; - offset = StoreOffsetTable(result, offset, ttc_font.flavor, - ttc_font.table_indices.size()); - - for (const auto table_index in ttc_font.table_indices) { - var tag: uint32_t = hdr->tables[table_index].tag; - metadata->font_infos[i].table_entry_by_tag[tag] = offset; - offset = StoreTableEntry(result, offset, tag); - } - - ttc_font.header_checksum = ComputeULongSum(&output[ttc_font.dst_offset], - offset - ttc_font.dst_offset); - } - } else { - metadata->font_infos.resize(1); - offset = StoreOffsetTable(result, offset, hdr->flavor, hdr->num_tables); - for (var i: uint16_t = 0; i < hdr->num_tables; ++i) { - metadata->font_infos[0].table_entry_by_tag[sorted_tables[i].tag] = offset; - offset = StoreTableEntry(result, offset, sorted_tables[i].tag); - } - } - - if (PREDICT_FALSE(!out->Write(&output[0], output.size()))) { - return FONT_COMPRESSION_FAILURE(); - } - metadata->header_checksum = ComputeULongSum(&output[0], output.size()); - return true; -} - -} // namespace - -fn ComputeWOFF2FinalSize(data: const uint8_t*, length: size_t) -> size_t { - var file: Buffer(data, length); - var total_length: uint32_t; - - if (!file.Skip(16) || - !file.ReadU32(&total_length)) { - return 0; - } - return total_length; -} - -fn ConvertWOFF2ToTTF(result: uint8_t*, result_length: size_t, - data: const uint8_t*, length: size_t) -> bool { - var out: WOFF2MemoryOut(result, result_length); - return ConvertWOFF2ToTTF(data, length, &out); -} - -fn ConvertWOFF2ToTTF(data: const uint8_t*, length: size_t, - out: WOFF2Out*) -> bool { - var metadata: RebuildMetadata; - var hdr: WOFF2Header; - if (!ReadWOFF2Header(data, length, &hdr)) { - return FONT_COMPRESSION_FAILURE(); - } - - if (!WriteHeaders(&metadata, &hdr, out)) { - return FONT_COMPRESSION_FAILURE(); - } - - let compression_ratio: const float = static_cast(hdr.uncompressed_size) / length; - if (compression_ratio > kMaxPlausibleCompressionRatio) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Implausible compression ratio %.01f\n", compression_ratio); -#endif - return FONT_COMPRESSION_FAILURE(); - } - - var src_buf: const uint8_t* = data + hdr.compressed_offset; - var uncompressed_buf: std::vector(hdr.uncompressed_size); - if (PREDICT_FALSE(hdr.uncompressed_size < 1)) { - return FONT_COMPRESSION_FAILURE(); - } - if (PREDICT_FALSE(!Woff2Uncompress(&uncompressed_buf[0], - hdr.uncompressed_size, src_buf, - hdr.compressed_length))) { - return FONT_COMPRESSION_FAILURE(); - } - - for (var i: size_t = 0; i < metadata.font_infos.size(); i++) { - if (PREDICT_FALSE(!ReconstructFont(&uncompressed_buf[0], - hdr.uncompressed_size, - &metadata, &hdr, i, out))) { - return FONT_COMPRESSION_FAILURE(); - } - } - - return true; -} - -} // namespace woff2 diff --git a/third_party/examples/woff2/carbon/src/woff2_decompress.impl.carbon b/third_party/examples/woff2/carbon/src/woff2_decompress.impl.carbon deleted file mode 100644 index 2898d37992f1..000000000000 --- a/third_party/examples/woff2/carbon/src/woff2_decompress.impl.carbon +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* A very simple commandline tool for decompressing woff2 format files to true - type font files. */ - -#include - -#include "./file.h" -#include - - -fn main(argc: int, argv: char**) -> int { - using std::string; - - if (argc != 2) { - fprintf(stderr, "One argument, the input filename, must be provided.\n"); - return 1; - } - - var filename: string(argv[1]); - var outfilename: string = filename.substr(0, filename.find_last_of('.')) + ".ttf"; - - // Note: update woff2_dec_fuzzer_new_entry.cc if this pattern changes. - var input: string = woff2::GetFileContent(filename); - var raw_input: const auto* = reinterpret_cast(input.data()); - var output: string(std::min(woff2::ComputeWOFF2FinalSize(raw_input, input.size()), - woff2::kDefaultMaxSize), 0); - var out: woff2::WOFF2StringOut(&output); - - let ok: const bool = woff2::ConvertWOFF2ToTTF(raw_input, input.size(), &out); - - if (ok) { - woff2::SetFileContents(outfilename, output.begin(), - output.begin() + out.Size()); - } - return ok ? 0 : 1; -} diff --git a/third_party/examples/woff2/carbon/src/woff2_enc.impl.carbon b/third_party/examples/woff2/carbon/src/woff2_enc.impl.carbon deleted file mode 100644 index ad63cdd80610..000000000000 --- a/third_party/examples/woff2/carbon/src/woff2_enc.impl.carbon +++ /dev/null @@ -1,470 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Library for converting TTF format font files to their WOFF2 versions. */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "./buffer.h" -#include "./font.h" -#include "./normalize.h" -#include "./round.h" -#include "./store_bytes.h" -#include "./table_tags.h" -#include "./transform.h" -#include "./variable_length.h" -#include "./woff2_common.h" - -namespace woff2 { - -namespace { - - -using std::string; -using std::vector; - - -let kWoff2HeaderSize: const size_t = 48; -let kWoff2EntrySize: const size_t = 20; - -fn Compress(data: const uint8_t*, let len: const size_t, result: uint8_t*, - result_len: uint32_t*, mode: BrotliEncoderMode, quality: int) -> bool { - var compressed_len: size_t = *result_len; - if (BrotliEncoderCompress(quality, BROTLI_DEFAULT_WINDOW, mode, len, data, - &compressed_len, result) == 0) { - return false; - } - *result_len = compressed_len; - return true; -} - -fn Woff2Compress(data: const uint8_t*, let len: const size_t, - result: uint8_t*, result_len: uint32_t*, - quality: int) -> bool { - return Compress(data, len, result, result_len, - BROTLI_MODE_FONT, quality); -} - -fn TextCompress(data: const uint8_t*, let len: const size_t, - result: uint8_t*, result_len: uint32_t*, - quality: int) -> bool { - return Compress(data, len, result, result_len, - BROTLI_MODE_TEXT, quality); -} - -fn KnownTableIndex(tag: uint32_t) -> int { - for (var i: int = 0; i < 63; ++i) { - if (tag == kKnownTags[i]) { return i; -} - } - return 63; -} - -fn StoreTableEntry(table: const Table&, offset: size_t*, dst: uint8_t*) { - var flag_byte: uint8_t = (table.flags & 0xC0) | KnownTableIndex(table.tag); - dst[(*offset)++] = flag_byte; - // The index here is treated as a set of flag bytes because - // bits 6 and 7 of the byte are reserved for future use as flags. - // 0x3f or 63 means an arbitrary table tag. - if ((flag_byte & 0x3f) == 0x3f) { - StoreU32(table.tag, offset, dst); - } - StoreBase128(table.src_length, offset, dst); - if ((table.flags & kWoff2FlagsTransform) != 0) { - StoreBase128(table.transform_length, offset, dst); - } -} - -fn TableEntrySize(table: const Table&) -> size_t { - var flag_byte: uint8_t = KnownTableIndex(table.tag); - var size: size_t = ((flag_byte & 0x3f) != 0x3f) ? 1 : 5; - size += Base128Size(table.src_length); - if ((table.flags & kWoff2FlagsTransform) != 0) { - size += Base128Size(table.transform_length); - } - return size; -} - -fn ComputeWoff2Length(font_collection: const FontCollection&, - tables: const std::vector
&, - index_by_tag_offset: std::map, uint16_t>, - compressed_data_length: size_t, - extended_metadata_length: size_t) -> size_t { - var size: size_t = kWoff2HeaderSize; - - for (const auto& table in tables) { - size += TableEntrySize(table); - } - - // for collections only, collection tables - if (font_collection.flavor == kTtcFontFlavor) { - size += 4; // UInt32 Version of TTC Header - size += Size255UShort(font_collection.fonts.size()); // 255UInt16 numFonts - - size += 4 * font_collection.fonts.size(); // UInt32 flavor for each - - for (const auto& font in font_collection.fonts) { - size += Size255UShort(font.tables.size()); // 255UInt16 numTables - for (const auto& entry in font.tables) { - var table: const Font::Table& = entry.second; - // no collection entry for xform table - if (table.tag & 0x80808080) { continue; -} - - var tag_offset: std::pair(table.tag, table.offset); - var table_index: uint16_t = index_by_tag_offset[tag_offset]; - size += Size255UShort(table_index); // 255UInt16 index entry - } - } - } - - // compressed data - size += compressed_data_length; - size = Round4(size); - - size += extended_metadata_length; - return size; -} - -fn ComputeUncompressedLength(font: const Font&) -> size_t { - // sfnt header + offset table - var size: size_t = 12 + 16 * font.num_tables; - for (const auto& entry in font.tables) { - var table: const Font::Table& = entry.second; - if (table.tag & 0x80808080) { continue; // xform tables don't stay -} - if (table.IsReused()) { continue; // don't have to pay twice -} - size += Round4(table.length); - } - return size; -} - -fn ComputeUncompressedLength(font_collection: const FontCollection&) -> size_t { - if (font_collection.flavor != kTtcFontFlavor) { - return ComputeUncompressedLength(font_collection.fonts[0]); - } - var size: size_t = CollectionHeaderSize(font_collection.header_version, - font_collection.fonts.size()); - for (const auto& font in font_collection.fonts) { - size += ComputeUncompressedLength(font); - } - return size; -} - -fn ComputeTotalTransformLength(font: const Font&) -> size_t { - var total: size_t = 0; - for (const auto& i in font.tables) { - var table: const Font::Table& = i.second; - if (table.IsReused()) { - continue; - } - if (table.tag & 0x80808080 || !font.FindTable(table.tag ^ 0x80808080)) { - // Count transformed tables and non-transformed tables that do not have - // transformed versions. - total += table.length; - } - } - return total; -} - -} // namespace - -fn MaxWOFF2CompressedSize(data: const uint8_t*, length: size_t) -> size_t { - return MaxWOFF2CompressedSize(data, length, ""); -} - -fn MaxWOFF2CompressedSize(const uint8_t* /*data*/: const uint8_t* length: size_t, - extended_metadata: const string&) -> size_t { - // Except for the header size, which is 32 bytes larger in woff2 format, - // all other parts should be smaller (table header in short format, - // transformations and compression). Just to be sure, we will give some - // headroom anyway. - return length + 1024 + extended_metadata.length(); -} - -fn CompressedBufferSize(original_size: uint32_t) -> uint32_t { - return 1.2 * original_size + 10240; -} - -fn TransformFontCollection(font_collection: FontCollection*) -> bool { - for (auto& font in font_collection->fonts) { - if (!TransformGlyfAndLocaTables(&font)) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "glyf/loca transformation failed.\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - } - - return true; -} - -fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t, - result: uint8_t*, result_length: size_t*) -> bool { - var params: WOFF2Params; - return ConvertTTFToWOFF2(data, length, result, result_length, - params); -} - -fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t, - result: uint8_t*, result_length: size_t*, - params: const WOFF2Params&) -> bool { - var font_collection: FontCollection; - if (!ReadFontCollection(data, length, &font_collection)) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Parsing of the input font failed.\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - - if (!NormalizeFontCollection(&font_collection)) { - return FONT_COMPRESSION_FAILURE(); - } - - if (params.allow_transforms && !TransformFontCollection(&font_collection)) { - return FONT_COMPRESSION_FAILURE(); - } else { - // glyf/loca use 11 to flag "not transformed" - for (auto& font in font_collection.fonts) { - var glyf_table: Font::Table* = font.FindTable(kGlyfTableTag); - var loca_table: Font::Table* = font.FindTable(kLocaTableTag); - if (glyf_table) { - glyf_table->flag_byte |= 0xc0; - } - if (loca_table) { - loca_table->flag_byte |= 0xc0; - } - } - } - - // Although the compressed size of each table in the final woff2 file won't - // be larger than its transform_length, we have to allocate a large enough - // buffer for the compressor, since the compressor can potentially increase - // the size. If the compressor overflows this, it should return false and - // then this function will also return false. - - var total_transform_length: size_t = 0; - for (const auto& font in font_collection.fonts) { - total_transform_length += ComputeTotalTransformLength(font); - } - var compression_buffer_size: size_t = CompressedBufferSize(total_transform_length); - var compression_buf: std::vector(compression_buffer_size); - var total_compressed_length: uint32_t = compression_buffer_size; - - // Collect all transformed data into one place in output order. - var transform_buf: std::vector(total_transform_length); - var transform_offset: size_t = 0; - for (const auto& font in font_collection.fonts) { - for (const auto tag in font.OutputOrderedTags()) { - var original: const Font::Table& = font.tables.at(tag); - if (original.IsReused()) { continue; -} - if (tag & 0x80808080) { continue; -} - var table_to_store: const Font::Table* = font.FindTable(tag ^ 0x80808080); - if (table_to_store == nullptr) { table_to_store = &original; -} - - StoreBytes(table_to_store->data, table_to_store->length, - &transform_offset, &transform_buf[0]); - } - } - - // Compress all transformed data in one stream. - if (!Woff2Compress(transform_buf.data(), total_transform_length, - &compression_buf[0], - &total_compressed_length, - params.brotli_quality)) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Compression of combined table failed.\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Compressed %zu to %u.\n", total_transform_length, - total_compressed_length); -#endif - - // Compress the extended metadata - // TODO(user): how does this apply to collections - var compressed_metadata_buf_length: uint32_t = - CompressedBufferSize(params.extended_metadata.length()); - var compressed_metadata_buf: std::vector(compressed_metadata_buf_length); - - if (params.extended_metadata.length() > 0) { - if (!TextCompress(reinterpret_cast(params.extended_metadata.data()), - params.extended_metadata.length(), - compressed_metadata_buf.data(), - &compressed_metadata_buf_length, - params.brotli_quality)) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Compression of extended metadata failed.\n"); -#endif - return FONT_COMPRESSION_FAILURE(); - } - } else { - compressed_metadata_buf_length = 0; - } - - var tables: std::vector
; - var index_by_tag_offset: std::map, uint16_t>; - - for (const auto& font in font_collection.fonts) { - - for (const auto tag in font.OutputOrderedTags()) { - var src_table: const Font::Table& = font.tables.at(tag); - if (src_table.IsReused()) { - continue; - } - - var tag_offset: std::pair(src_table.tag, src_table.offset); - if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) { - index_by_tag_offset[tag_offset] = tables.size(); - } else { - return false; - } - - var table: Table; - table.tag = src_table.tag; - table.flags = src_table.flag_byte; - table.src_length = src_table.length; - table.transform_length = src_table.length; - var transformed_data: const uint8_t* = src_table.data; - var transformed_table: const Font::Table* = - font.FindTable(src_table.tag ^ 0x80808080); - if (transformed_table != nullptr) { - table.flags = transformed_table->flag_byte; - table.flags |= kWoff2FlagsTransform; - table.transform_length = transformed_table->length; - transformed_data = transformed_table->data; - - } - tables.push_back(table); - } - } - - var woff2_length: size_t = ComputeWoff2Length(font_collection, tables, - index_by_tag_offset, total_compressed_length, - compressed_metadata_buf_length); - if (woff2_length > *result_length) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Result allocation was too small (%zd vs %zd bytes).\n", - *result_length, woff2_length); -#endif - return FONT_COMPRESSION_FAILURE(); - } - *result_length = woff2_length; - - var offset: size_t = 0; - - // start of woff2 header (http://www.w3.org/TR/WOFF2/#woff20Header) - StoreU32(kWoff2Signature, &offset, result); - if (font_collection.flavor != kTtcFontFlavor) { - StoreU32(font_collection.fonts[0].flavor, &offset, result); - } else { - StoreU32(kTtcFontFlavor, &offset, result); - } - StoreU32(woff2_length, &offset, result); - Store16(tables.size(), &offset, result); - Store16(0, &offset, result); // reserved - // totalSfntSize - StoreU32(ComputeUncompressedLength(font_collection), &offset, result); - StoreU32(total_compressed_length, &offset, result); // totalCompressedSize - - // Let's just all be v1.0 - Store16(1, &offset, result); // majorVersion - Store16(0, &offset, result); // minorVersion - if (compressed_metadata_buf_length > 0) { - StoreU32(woff2_length - compressed_metadata_buf_length, - &offset, result); // metaOffset - StoreU32(compressed_metadata_buf_length, &offset, result); // metaLength - StoreU32(params.extended_metadata.length(), - &offset, result); // metaOrigLength - } else { - StoreU32(0, &offset, result); // metaOffset - StoreU32(0, &offset, result); // metaLength - StoreU32(0, &offset, result); // metaOrigLength - } - StoreU32(0, &offset, result); // privOffset - StoreU32(0, &offset, result); // privLength - // end of woff2 header - - // table directory (http://www.w3.org/TR/WOFF2/#table_dir_format) - for (const auto& table in tables) { - StoreTableEntry(table, &offset, result); - } - - // for collections only, collection table directory - if (font_collection.flavor == kTtcFontFlavor) { - StoreU32(font_collection.header_version, &offset, result); - Store255UShort(font_collection.fonts.size(), &offset, result); - for (const Font& font in font_collection.fonts) { - - var num_tables: uint16_t = 0; - for (const auto& entry in font.tables) { - var table: const Font::Table& = entry.second; - if (table.tag & 0x80808080) { continue; // don't write xform tables -} - num_tables++; - } - Store255UShort(num_tables, &offset, result); - - StoreU32(font.flavor, &offset, result); - for (const auto& entry in font.tables) { - var table: const Font::Table& = entry.second; - if (table.tag & 0x80808080) { continue; // don't write xform tables -} - - // for reused tables, only the original has an updated offset - var table_offset: uint32_t = - table.IsReused() ? table.reuse_of->offset : table.offset; - var table_length: uint32_t = - table.IsReused() ? table.reuse_of->length : table.length; - var tag_offset: std::pair(table.tag, table_offset); - if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) { -#ifdef FONT_COMPRESSION_BIN -fprintf(stderr, "Missing table index for offset 0x%08x\n", - table_offset); -#endif - return FONT_COMPRESSION_FAILURE(); - } - var index: uint16_t = index_by_tag_offset[tag_offset]; - Store255UShort(index, &offset, result); - - } - - } - } - - // compressed data format (http://www.w3.org/TR/WOFF2/#table_format) - - StoreBytes(&compression_buf[0], total_compressed_length, &offset, result); - offset = Round4(offset); - - StoreBytes(compressed_metadata_buf.data(), compressed_metadata_buf_length, - &offset, result); - - if (*result_length != offset) { -#ifdef FONT_COMPRESSION_BIN - fprintf(stderr, "Mismatch between computed and actual length " - "(%zd vs %zd)\n", *result_length, offset); -#endif - return FONT_COMPRESSION_FAILURE(); - } - return true; -} - -} // namespace woff2 diff --git a/third_party/examples/woff2/carbon/src/woff2_info.impl.carbon b/third_party/examples/woff2/carbon/src/woff2_info.impl.carbon deleted file mode 100644 index 8e46f7eab5ff..000000000000 --- a/third_party/examples/woff2/carbon/src/woff2_info.impl.carbon +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* A commandline tool for dumping info about a woff2 file. */ - -#include - -#include "file.h" -#include "./woff2_common.h" -#include "./buffer.h" -#include "./font.h" -#include "./table_tags.h" -#include "./variable_length.h" - -fn PrintTag(tag: int) -> std::string { - if (tag & 0x80808080) { - return std::string("_xfm"); // print _xfm for xform tables (else garbage) - } - var printable: char[] = { - static_cast((tag >> 24) & 0xFF), - static_cast((tag >> 16) & 0xFF), - static_cast((tag >> 8) & 0xFF), - static_cast(tag & 0xFF) - }; - return std::string(printable, 4); -} - -fn main(argc: int, argv: char**) -> int { - using std::string; - - if (argc != 2) { - fprintf(stderr, "One argument, the input filename, must be provided.\n"); - return 1; - } - - var filename: string(argv[1]); - var outfilename: string = filename.substr(0, filename.find_last_of('.')) + ".woff2"; - fprintf(stdout, "Processing %s => %s\n", - filename.c_str(), outfilename.c_str()); - var input: string = woff2::GetFileContent(filename); - - var file: woff2::Buffer(reinterpret_cast(input.data()), - input.size()); - - printf("WOFF2Header\n"); - var signature: uint32_t, var flavor: uint32_t, var length: uint32_t, var totalSfntSize: uint32_t, var totalCompressedSize: uint32_t; - var metaOffset: uint32_t, var metaLength: uint32_t, var metaOrigLength: uint32_t, var privOffset: uint32_t, var privLength: uint32_t; - var num_tables: uint16_t, var reserved: uint16_t, var major: uint16_t, var minor: uint16_t; - if (!file.ReadU32(&signature)) { return 1; -} - if (!file.ReadU32(&flavor)) { return 1; -} - if (!file.ReadU32(&length)) { return 1; -} - if (!file.ReadU16(&num_tables)) { return 1; -} - if (!file.ReadU16(&reserved)) { return 1; -} - if (!file.ReadU32(&totalSfntSize)) { return 1; -} - if (!file.ReadU32(&totalCompressedSize)) { return 1; -} - if (!file.ReadU16(&major)) { return 1; -} - if (!file.ReadU16(&minor)) { return 1; -} - if (!file.ReadU32(&metaOffset)) { return 1; -} - if (!file.ReadU32(&metaLength)) { return 1; -} - if (!file.ReadU32(&metaOrigLength)) { return 1; -} - if (!file.ReadU32(&privOffset)) { return 1; -} - if (!file.ReadU32(&privLength)) { return 1; -} - - if (signature != 0x774F4632) { - printf("Invalid signature: %08x\n", signature); - return 1; - } - printf("signature 0x%08x\n", signature); - printf("flavor 0x%08x\n", flavor); - printf("length %d\n", length); - printf("numTables %d\n", num_tables); - printf("reserved %d\n", reserved); - printf("totalSfntSize %d\n", totalSfntSize); - printf("totalCompressedSize %d\n", totalCompressedSize); - printf("majorVersion %d\n", major); - printf("minorVersion %d\n", minor); - printf("metaOffset %d\n", metaOffset); - printf("metaLength %d\n", metaLength); - printf("metaOrigLength %d\n", metaOrigLength); - printf("privOffset %d\n", privOffset); - printf("privLength %d\n", privLength); - - var table_tags: std::vector; - printf("TableDirectory starts at +%zu\n", file.offset()); - printf("Entry offset flags tag origLength txLength\n"); - for (var i: auto = 0; i < num_tables; i++) { - var offset: size_t = file.offset(); - var flags: uint8_t; - var tag: uint32_t, var origLength: uint32_t, var transformLength: uint32_t; - if (!file.ReadU8(&flags)) { return 1; -} - if ((flags & 0x3f) == 0x3f) { - if (!file.ReadU32(&tag)) { return 1; -} - } else { - tag = woff2::kKnownTags[flags & 0x3f]; - } - table_tags.push_back(tag); - if (!ReadBase128(&file, &origLength)) { return 1; -} - - printf("%5d %6zu 0x%02x %s %10d", i, offset, flags, - PrintTag(tag).c_str(), origLength); - - var xform_version: uint8_t = (flags >> 6) & 0x3; - if (tag == woff2::kGlyfTableTag || tag == woff2::kLocaTableTag) { - if (xform_version == 0) { - if (!ReadBase128(&file, &transformLength)) { return 1; -} - printf(" %8d", transformLength); - } - } else if (xform_version > 0) { - if (!ReadBase128(&file, &transformLength)) { return 1; -} - printf(" %8d", transformLength); - } - printf("\n"); - } - - // Collection header - if (flavor == woff2::kTtcFontFlavor) { - var version: uint32_t, var numFonts: uint32_t; - if (!file.ReadU32(&version)) { return 1; -} - if (!woff2::Read255UShort(&file, &numFonts)) { return 1; -} - printf("CollectionHeader 0x%08x %d fonts\n", version, numFonts); - - for (var i: auto = 0; i < numFonts; i++) { - var numTables: uint32_t, var flavor: uint32_t; - if (!woff2::Read255UShort(&file, &numTables)) { return 1; -} - if (!file.ReadU32(&flavor)) { return 1; -} - printf("CollectionFontEntry %d flavor 0x%08x %d tables\n", i, flavor, - numTables); - for (var j: auto = 0; j < numTables; j++) { - var table_idx: uint32_t; - if (!woff2::Read255UShort(&file, &table_idx)) { return 1; -} - if (table_idx >= table_tags.size()) { return 1; -} - printf(" %d %s (idx %d)\n", j, - PrintTag(table_tags[table_idx]).c_str(), table_idx); - } - } - } - - printf("TableDirectory ends at +%zu\n", file.offset()); - - return 0; -} diff --git a/third_party/examples/woff2/carbon/src/woff2_out.impl.carbon b/third_party/examples/woff2/carbon/src/woff2_out.impl.carbon deleted file mode 100644 index 77ed73233414..000000000000 --- a/third_party/examples/woff2/carbon/src/woff2_out.impl.carbon +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Output buffer for WOFF2 decompression. */ - -#include - -using std::string; - -namespace woff2 { - -WOFF2StringOut::WOFF2StringOut(buf: string*) - : buf_(buf), - max_size_(kDefaultMaxSize), - offset_(0) {} - -fn WOFF2StringOut::Write(buf: const void*, n: size_t) -> bool { - return Write(buf, offset_, n); -} - -fn WOFF2StringOut::Write(buf: const void*, offset: size_t, n: size_t) -> bool { - if (offset > max_size_ || n > max_size_ - offset) { - return false; - } - if (offset == buf_->size()) { - buf_->append(static_cast(buf), n); - } else { - if (offset + n > buf_->size()) { - buf_->append(offset + n - buf_->size(), 0); - } - buf_->replace(offset, n, static_cast(buf), n); - } - offset_ = std::max(offset_, offset + n); - - return true; -} - -fn WOFF2StringOut::SetMaxSize(max_size: size_t) { - max_size_ = max_size; - if (offset_ > max_size_) { - offset_ = max_size_; - } -} - -WOFF2MemoryOut::WOFF2MemoryOut(buf: uint8_t*, buf_size: size_t) - : buf_(buf), - buf_size_(buf_size), - offset_(0) {} - -fn WOFF2MemoryOut::Write(buf: const void*, n: size_t) -> bool { - return Write(buf, offset_, n); -} - -fn WOFF2MemoryOut::Write(buf: const void*, offset: size_t, n: size_t) -> bool { - if (offset > buf_size_ || n > buf_size_ - offset) { - return false; - } - std::memcpy(buf_ + offset, buf, n); - offset_ = std::max(offset_, offset + n); - - return true; -} - -} // namespace woff2 diff --git a/third_party/examples/woff2/compile_flags.carbon.txt b/third_party/examples/woff2/compile_flags.carbon.txt deleted file mode 100644 index 0c9c359b4cff..000000000000 --- a/third_party/examples/woff2/compile_flags.carbon.txt +++ /dev/null @@ -1,52 +0,0 @@ --xc++ --Wall --Wextra --Wthread-safety --Wself-assign --Wno-missing-field-initializers --DLLVM_ON_UNIX=1 --DHAVE_BACKTRACE=1 --DBACKTRACE_HEADER= --DLTDL_SHLIB_EXT=".so" --DLLVM_ENABLE_THREADS=1 --DHAVE_SYSEXITS_H=1 --DHAVE_UNISTD_H=1 --DHAVE_STRERROR_R=1 --DHAVE_LIBPTHREAD=1 --DHAVE_PTHREAD_GETNAME_NP=1 --DHAVE_PTHREAD_SETNAME_NP=1 --DHAVE_PTHREAD_GETSPECIFIC=1 --D_GNU_SOURCE --DHAVE_LINK_H=1 --DHAVE_LSEEK64=1 --DHAVE_MALLINFO=1 --DHAVE_POSIX_FALLOCATE=1 --DHAVE_SBRK=1 --DHAVE_STRUCT_STAT_ST_MTIM_TV_NSEC=1 --DLLVM_NATIVE_ARCH="X86" --DLLVM_NATIVE_ASMPARSER=LLVMInitializeX86AsmParser --DLLVM_NATIVE_ASMPRINTER=LLVMInitializeX86AsmPrinter --DLLVM_NATIVE_DISASSEMBLER=LLVMInitializeX86Disassembler --DLLVM_NATIVE_TARGET=LLVMInitializeX86Target --DLLVM_NATIVE_TARGETINFO=LLVMInitializeX86TargetInfo --DLLVM_NATIVE_TARGETMC=LLVMInitializeX86TargetMC --DLLVM_HOST_TRIPLE="x86_64-unknown-linux-gnu" --DLLVM_DEFAULT_TARGET_TRIPLE="x86_64-unknown-linux-gnu" --DLLVM_ENABLE_TERMINFO=1 --DLLVM_ENABLE_ZLIB=1 --DGTEST_HAS_RTTI=0 --D__STDC_LIMIT_MACROS --D__STDC_CONSTANT_MACROS --DGTEST_USE_OWN_TR1_TUPLE=1 --std=c++17 --stdlib=libc++ --I../../brotli/original/c/include --Iinclude --no-canonical-prefixes --Wno-builtin-macro-redefined --D__DATE__="redacted" --D__TIMESTAMP__="redacted" --D__TIME__="redacted" --Wno-unused-variable --Wno-unused-const-variable --Wno-sign-compare diff --git a/third_party/examples/woff2/migrate_cpp.sh b/third_party/examples/woff2/migrate_cpp.sh deleted file mode 100755 index cf700129d0f3..000000000000 --- a/third_party/examples/woff2/migrate_cpp.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash -eux -# -# Part of the Carbon Language project, under the Apache License v2.0 with LLVM -# Exceptions. See /LICENSE for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -# Runs an example migration of woff2 C++ code. - -# cd to the carbon-lang root. -cd "$(dirname "$0")/../../.." - -EXAMPLE="${PWD}/third_party/examples/woff2" - -# Remove any previous conversion. Each time this is run, it should demonstrate -# on a fresh copy of woff2. -rm -rf "${EXAMPLE}/carbon/" - -# Initialize the carbon directory with C++ code only. -mkdir -p "${EXAMPLE}/carbon/" -for x in LICENSE include src; do - cp -R "${EXAMPLE}/original/${x}" "${EXAMPLE}/carbon/${x}" -done - -# Copy files into the carbon directory to simplify the setup. -cp "${EXAMPLE}/BUILD.original" \ - "${EXAMPLE}/carbon/BUILD" -cp "${EXAMPLE}/WORKSPACE.original" \ - "${EXAMPLE}/carbon/WORKSPACE" - -# Kludge for adding LLVM include paths into the compile flags. -# TODO: Find better solution. -COMPILE_FLAGS=($(cat "${EXAMPLE}/compile_flags.carbon.txt" | sed 's/"/\\"/g')) -for x in $( - clang++ -Wp,-v -xc++ -stdlib=libc++ - -fsyntax-only < /dev/null 2>&1 | - grep /llvm/); do - COMPILE_FLAGS+=("-isystem") - COMPILE_FLAGS+=("${x}") -done - -# Construct a compilation database for use by run-clang-tidy.py. -COMPDB="${EXAMPLE}/carbon/compile_commands.json" -echo "[" > "${COMPDB}" -for f in $(find "${EXAMPLE}/carbon" -regex ".*\.\(cc\|h\)"); do - echo "{ \"file\": \"$(realpath --relative-to "${EXAMPLE}/carbon" ${f})\"," >> "${COMPDB}" - echo " \"directory\": \"${EXAMPLE}/carbon\"," >> "${COMPDB}" - echo " \"arguments\": [" >> "${COMPDB}" - echo " \"clang++\"," >> "${COMPDB}" - for index in ${!COMPILE_FLAGS[@]}; do - echo " \"${COMPILE_FLAGS[$index]}\"," >> "${COMPDB}" - done - echo " \"${f}\"" >> "${COMPDB}" - echo " ]" >> "${COMPDB}" - echo "}," >> "${COMPDB}" -done -# Remove the last comma, for JSON syntax correctness. -sed -i '$ s/,$//' "${COMPDB}" -echo "]" >> "${EXAMPLE}/carbon/compile_commands.json" - -# Run the migration tool. -bazel build -c opt //migrate_cpp -# Not sure why, but execution of cpp_refactoring fails while saving refactorings -# if not in the directory. Ideally shouldn't be required, passing the path to -# migrate_cpp should work. -pushd "${EXAMPLE}/carbon" -../../../../bazel-bin/migrate_cpp/migrate_cpp . -popd - -# Don't save the compile flags. -rm "${EXAMPLE}/carbon/compile_commands.json"