diff --git a/third_party/woff2/.gitignore b/third_party/woff2/.gitignore index e327693fe18a..6b35b1f0f4ae 100644 --- a/third_party/woff2/.gitignore +++ b/third_party/woff2/.gitignore @@ -2,3 +2,4 @@ *.a /woff2_compress /woff2_decompress +/woff2_info diff --git a/third_party/woff2/BUILD.gn b/third_party/woff2/BUILD.gn index 33303151d9a6..c6308daa3547 100644 --- a/third_party/woff2/BUILD.gn +++ b/third_party/woff2/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. +# Copyright 2015 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -25,16 +25,10 @@ static_library("woff2_dec") { "src/woff2_out.cc", ] -if (is_starboard) { - configs -= [ "//starboard/build/config:size" ] - configs += [ "//starboard/build/config:speed" ] -} else { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] -} deps = [ "//third_party/brotli:dec" ] - deps += [ "//starboard/common" ] public_configs = [ ":woff2_includes" ] diff --git a/third_party/woff2/DIR_METADATA b/third_party/woff2/DIR_METADATA new file mode 100644 index 000000000000..d27651d1a95e --- /dev/null +++ b/third_party/woff2/DIR_METADATA @@ -0,0 +1,4 @@ +monorail: { + component: "Blink>Fonts" +} +team_email: "loading-dev@chromium.org" diff --git a/third_party/woff2/LICENSE b/third_party/woff2/LICENSE index d64569567334..4f9441b6e1b9 100644 --- a/third_party/woff2/LICENSE +++ b/third_party/woff2/LICENSE @@ -1,202 +1,19 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +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/woff2/METADATA b/third_party/woff2/METADATA index 9caa8af06959..0b7cbf87e77c 100644 --- a/third_party/woff2/METADATA +++ b/third_party/woff2/METADATA @@ -5,12 +5,12 @@ description: third_party { identifier { type: "ChromiumVersion" - value: "87.0.4280.142" # from https://chromereleases.googleblog.com/2021/01/stable-channel-update-for-chrome-os.html + value: "114.0.5735.358" # from https://chromereleases.googleblog.com/2024/03/long-term-support-channel-update-for_26.html } identifier { type: "Git" value: "https://chromium.googlesource.com/chromium/src.git" - version: "f73da6d3eaeb33e9d4bcb497bf13c655143a82f9" + version: "1759c6ae9316996b9f150c0ce9d0ca78a3d15c02" } identifier { type: "UpstreamSubdir" diff --git a/third_party/woff2/Makefile b/third_party/woff2/Makefile index 622a2af369a6..fbb945c8e789 100644 --- a/third_party/woff2/Makefile +++ b/third_party/woff2/Makefile @@ -1,6 +1,6 @@ OS := $(shell uname) -CPPFLAGS = -I./brotli/include/ -I./src +CPPFLAGS = -I./brotli/c/include/ -I./src -I./include AR ?= ar CC ?= gcc @@ -11,13 +11,16 @@ CANONICAL_PREFIXES ?= -no-canonical-prefixes NOISY_LOGGING ?= -DFONT_COMPRESSION_BIN COMMON_FLAGS = -fno-omit-frame-pointer $(CANONICAL_PREFIXES) $(NOISY_LOGGING) -D __STDC_FORMAT_MACROS +ARFLAGS = crf + ifeq ($(OS), Darwin) CPPFLAGS += -DOS_MACOSX + ARFLAGS = cr else COMMON_FLAGS += -fno-tree-vrp endif -ARFLAGS = crf + CFLAGS += $(COMMON_FLAGS) CXXFLAGS += $(COMMON_FLAGS) -std=c++11 @@ -28,13 +31,13 @@ OUROBJ = font.o glyph.o normalize.o table_tags.o transform.o \ variable_length.o BROTLI = brotli -BROTLIOBJ = $(BROTLI)/bin/obj +BROTLIOBJ = $(BROTLI)/bin/obj/c ENCOBJ = $(BROTLIOBJ)/enc/*.o DECOBJ = $(BROTLIOBJ)/dec/*.o COMMONOBJ = $(BROTLIOBJ)/common/*.o OBJS = $(patsubst %, $(SRCDIR)/%, $(OUROBJ)) -EXECUTABLES=woff2_compress woff2_decompress +EXECUTABLES=woff2_compress woff2_decompress woff2_info EXE_OBJS=$(patsubst %, $(SRCDIR)/%.o, $(EXECUTABLES)) ARCHIVES=convert_woff2ttf_fuzzer convert_woff2ttf_fuzzer_new_entry ARCHIVE_OBJS=$(patsubst %, $(SRCDIR)/%.o, $(ARCHIVES)) diff --git a/third_party/woff2/OWNERS b/third_party/woff2/OWNERS index f3d45a13cc9b..458697e6d588 100644 --- a/third_party/woff2/OWNERS +++ b/third_party/woff2/OWNERS @@ -1,4 +1,2 @@ ksakamoto@chromium.org bashi@chromium.org -# COMPONENT: Blink>Fonts -# TEAM: loading-dev@chromium.org diff --git a/third_party/woff2/README.chromium b/third_party/woff2/README.chromium index c97a8e407a67..74ea0d53fe1f 100644 --- a/third_party/woff2/README.chromium +++ b/third_party/woff2/README.chromium @@ -1,7 +1,7 @@ Name: woff2 URL: https://github.com/google/woff2 -Version: 1bccf208bca986e53a647dfe4811322adb06ecf8 -License: Apache 2.0 +Version: 4721483ad780ee2b63cb787bfee4aa64b61a0446 +License: MIT License File: LICENSE Security Critical: yes @@ -12,4 +12,3 @@ format (http://www.w3.org/TR/WOFF2/). Local Modifications: - BUILD.gn: Added. -- woff2.gyp: Added. diff --git a/third_party/woff2/README.md b/third_party/woff2/README.md index f5210afc1401..657677217509 100644 --- a/third_party/woff2/README.md +++ b/third_party/woff2/README.md @@ -25,6 +25,29 @@ cd woff2 make clean all ``` +Alternatively, if Brotli is already installed on your system you can use CMake +to build executables and libraries: + +``` +git clone https://github.com/google/woff2.git +cd woff2 +mkdir out +cd out +cmake .. +make +make install +``` + +By default, shared libraries are built. To use static linkage, do: + +``` +cd woff2 +mkdir out-static +cmake -DBUILD_SHARED_LIBS=OFF .. +make +make install +``` + ## Run Ensure the binaries from the build process are in your $PATH, then: diff --git a/third_party/woff2/include/woff2/encode.h b/third_party/woff2/include/woff2/encode.h index 34b772297495..2ac563032d1d 100644 --- a/third_party/woff2/include/woff2/encode.h +++ b/third_party/woff2/include/woff2/encode.h @@ -26,8 +26,8 @@ struct WOFF2Params { // Returns an upper bound on the size of the compressed file. size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length); -size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length, - const std::string& extended_metadata); +size_t MaxWOFF2CompressedSize(const uint8_t *data, size_t length, + const std::string &extended_metadata); // 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 diff --git a/third_party/woff2/include/woff2/output.h b/third_party/woff2/include/woff2/output.h index c325f67be728..dc78ccf82679 100644 --- a/third_party/woff2/include/woff2/output.h +++ b/third_party/woff2/include/woff2/output.h @@ -51,7 +51,7 @@ class WOFF2StringOut : public WOFF2Out { // 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(std::string* buf); + explicit WOFF2StringOut(std::string *buf); bool Write(const void *buf, size_t n) override; bool Write(const void *buf, size_t offset, size_t n) override; @@ -59,7 +59,7 @@ class WOFF2StringOut : public WOFF2Out { size_t MaxSize() { return max_size_; } void SetMaxSize(size_t max_size); private: - std::string* buf_; + std::string *buf_; size_t max_size_; size_t offset_; }; diff --git a/third_party/woff2/src/file.h b/third_party/woff2/src/file.h index 61318776be3b..70ea7a7fb1b9 100644 --- a/third_party/woff2/src/file.h +++ b/third_party/woff2/src/file.h @@ -14,18 +14,14 @@ namespace woff2 { -using std::string; - - -inline string GetFileContent(string filename) { +inline std::string GetFileContent(std::string filename) { std::ifstream ifs(filename.c_str(), std::ios::binary); - return string( - std::istreambuf_iterator(ifs.rdbuf()), - std::istreambuf_iterator()); + return std::string(std::istreambuf_iterator(ifs.rdbuf()), + std::istreambuf_iterator()); } -inline void SetFileContents(string filename, string::iterator start, - string::iterator end) { +inline void SetFileContents(std::string filename, std::string::iterator start, + std::string::iterator end) { std::ofstream ofs(filename.c_str(), std::ios::binary); std::copy(start, end, std::ostream_iterator(ofs)); } diff --git a/third_party/woff2/src/glyph.cc b/third_party/woff2/src/glyph.cc index 057174de2193..5b4948679c76 100644 --- a/third_party/woff2/src/glyph.cc +++ b/third_party/woff2/src/glyph.cc @@ -21,6 +21,7 @@ static const int32_t kFLAG_YSHORT = 1 << 2; static const int32_t kFLAG_REPEAT = 1 << 3; static const int32_t kFLAG_XREPEATSIGN = 1 << 4; static const int32_t kFLAG_YREPEATSIGN = 1 << 5; +static const int32_t kFLAG_OVERLAP_SIMPLE = 1 << 6; static const int32_t kFLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0; static const int32_t kFLAG_WE_HAVE_A_SCALE = 1 << 3; static const int32_t kFLAG_MORE_COMPONENTS = 1 << 5; @@ -134,6 +135,10 @@ bool ReadGlyph(const uint8_t* data, size_t len, Glyph* glyph) { } } + if (!flags.empty() && !flags[0].empty()) { + glyph->overlap_simple_flag_set = (flags[0][0] & kFLAG_OVERLAP_SIMPLE); + } + // Read the x coordinates. int prev_x = 0; for (int i = 0; i < num_contours; ++i) { @@ -239,7 +244,7 @@ bool StoreEndPtsOfContours(const Glyph& glyph, size_t* offset, uint8_t* dst) { bool StorePoints(const Glyph& glyph, size_t* offset, uint8_t* dst, size_t dst_size) { - int last_flag = -1; + int previous_flag = -1; int repeat_count = 0; int last_x = 0; int last_y = 0; @@ -250,6 +255,10 @@ bool StorePoints(const Glyph& glyph, size_t* offset, for (const auto& contour : glyph.contours) { for (const auto& point : contour) { int flag = point.on_curve ? kFLAG_ONCURVE : 0; + if (previous_flag == -1 && glyph.overlap_simple_flag_set) { + // First flag needs to have overlap simple bit set. + flag = flag | kFLAG_OVERLAP_SIMPLE; + } int dx = point.x - last_x; int dy = point.y - last_y; if (dx == 0) { @@ -268,7 +277,7 @@ bool StorePoints(const Glyph& glyph, size_t* offset, } else { y_bytes += 2; } - if (flag == last_flag && repeat_count != 255) { + if (flag == previous_flag && repeat_count != 255) { dst[*offset - 1] |= kFLAG_REPEAT; repeat_count++; } else { @@ -286,7 +295,7 @@ bool StorePoints(const Glyph& glyph, size_t* offset, } last_x = point.x; last_y = point.y; - last_flag = flag; + previous_flag = flag; } } if (repeat_count != 0) { diff --git a/third_party/woff2/src/glyph.h b/third_party/woff2/src/glyph.h index f24056f4c8c8..c38eb5f2bc46 100644 --- a/third_party/woff2/src/glyph.h +++ b/third_party/woff2/src/glyph.h @@ -10,8 +10,10 @@ #ifndef WOFF2_GLYPH_H_ #define WOFF2_GLYPH_H_ -#include #include +#include + +#include #include namespace woff2 { @@ -22,7 +24,10 @@ namespace woff2 { // is around. class Glyph { public: - Glyph() : instructions_size(0), composite_data_size(0) {} + Glyph() + : instructions_size(0), + overlap_simple_flag_set(false), + composite_data_size(0) {} // Bounding box. int16_t x_min; @@ -34,6 +39,9 @@ class Glyph { uint16_t instructions_size; const uint8_t* instructions_data; + // Flags. + bool overlap_simple_flag_set; + // Data model for simple glyphs. struct Point { int x; diff --git a/third_party/woff2/src/port.h b/third_party/woff2/src/port.h index 431ecc83d58b..8b60fee8bc98 100644 --- a/third_party/woff2/src/port.h +++ b/third_party/woff2/src/port.h @@ -56,22 +56,11 @@ inline int Log2Floor(uint32 n) { (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(STARBOARD) -#include "starboard/configuration.h" -#if SB_IS(BIG_ENDIAN) -#define WOFF_BIG_ENDIAN -#else -#define WOFF_LITTLE_ENDIAN -#endif -#else /* not defined STARBOARD */ #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 /* STARBOARD */ - #endif /* CPU whitelist */ #endif // WOFF2_PORT_H_ diff --git a/third_party/woff2/src/transform.cc b/third_party/woff2/src/transform.cc index 999bef37458e..1016efcd2bb0 100644 --- a/third_party/woff2/src/transform.cc +++ b/third_party/woff2/src/transform.cc @@ -22,6 +22,7 @@ namespace { const int FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0; const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8; +const int FLAG_OVERLAP_SIMPLE_BITMAP = 1 << 0; void WriteBytes(std::vector* out, const uint8_t* data, size_t len) { if (len == 0) return; @@ -69,7 +70,10 @@ class GlyfEncoder { } void GetTransformedGlyfBytes(std::vector* result) { - WriteLong(result, 0); // version + WriteUShort(result, 0); // Version + WriteUShort(result, overlap_bitmap_.empty() + ? 0x00 + : FLAG_OVERLAP_SIMPLE_BITMAP); // Flags WriteUShort(result, n_glyphs_); WriteUShort(result, 0); // index_format, will be set later WriteLong(result, n_contour_stream_.size()); @@ -87,6 +91,9 @@ class GlyfEncoder { WriteBytes(result, bbox_bitmap_); WriteBytes(result, bbox_stream_); WriteBytes(result, instruction_stream_); + if (!overlap_bitmap_.empty()) { + WriteBytes(result, overlap_bitmap_); + } } private: @@ -127,6 +134,10 @@ class GlyfEncoder { } void WriteSimpleGlyph(int glyph_id, const Glyph& glyph) { + if (glyph.overlap_simple_flag_set) { + EnsureOverlapBitmap(); + overlap_bitmap_[glyph_id >> 3] |= 0x80 >> (glyph_id & 7); + } int num_contours = glyph.contours.size(); WriteUShort(&n_contour_stream_, num_contours); if (ShouldWriteSimpleGlyphBbox(glyph)) { @@ -214,6 +225,12 @@ class GlyfEncoder { } } + void EnsureOverlapBitmap() { + if (overlap_bitmap_.empty()) { + overlap_bitmap_.resize((n_glyphs_ + 7) >> 3); + } + } + std::vector n_contour_stream_; std::vector n_points_stream_; std::vector flag_byte_stream_; @@ -222,6 +239,7 @@ class GlyfEncoder { std::vector bbox_stream_; std::vector glyph_stream_; std::vector instruction_stream_; + std::vector overlap_bitmap_; int n_glyphs_; }; diff --git a/third_party/woff2/src/woff2_compress.cc b/third_party/woff2/src/woff2_compress.cc index 80e310866764..36e8fcafe9c0 100644 --- a/third_party/woff2/src/woff2_compress.cc +++ b/third_party/woff2/src/woff2_compress.cc @@ -13,22 +13,20 @@ int main(int argc, char **argv) { - using std::string; - if (argc != 2) { fprintf(stderr, "One argument, the input filename, must be provided.\n"); return 1; } - string filename(argv[1]); - string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2"; + std::string filename(argv[1]); + std::string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2"; fprintf(stdout, "Processing %s => %s\n", filename.c_str(), outfilename.c_str()); - string input = woff2::GetFileContent(filename); + std::string input = woff2::GetFileContent(filename); const uint8_t* input_data = reinterpret_cast(input.data()); size_t output_size = woff2::MaxWOFF2CompressedSize(input_data, input.size()); - string output(output_size, 0); + std::string output(output_size, 0); uint8_t* output_data = reinterpret_cast(&output[0]); woff2::WOFF2Params params; diff --git a/third_party/woff2/src/woff2_dec.cc b/third_party/woff2/src/woff2_dec.cc index 8186c8e5d9e5..efb579bbf845 100644 --- a/third_party/woff2/src/woff2_dec.cc +++ b/third_party/woff2/src/woff2_dec.cc @@ -32,10 +32,6 @@ namespace woff2 { namespace { -using std::string; -using std::vector; - - // simple glyph flags const int kGlyfOnCurve = 1 << 0; const int kGlyfXShort = 1 << 1; @@ -43,6 +39,7 @@ const int kGlyfYShort = 1 << 2; const int kGlyfRepeat = 1 << 3; const int kGlyfThisXIsSame = 1 << 4; const int kGlyfThisYIsSame = 1 << 5; +const int kOverlapSimple = 1 << 6; // composite glyph flags // See CompositeGlyph.java in sfntly for full definitions @@ -53,6 +50,9 @@ const int FLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; const int FLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7; const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8; +// glyf flags +const int FLAG_OVERLAP_SIMPLE_BITMAP = 1 << 0; + const size_t kCheckSumAdjustmentOffset = 8; const size_t kEndPtsOfContoursOffset = 10; @@ -111,6 +111,16 @@ int WithSign(int flag, int baseval) { return (flag & 1) ? baseval : -baseval; } +bool _SafeIntAddition(int a, int b, int* result) { + 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; +} + bool TripletDecode(const uint8_t* flags_in, const uint8_t* in, size_t in_size, unsigned int n_points, Point* result, size_t* in_bytes_consumed) { int x = 0; @@ -166,9 +176,12 @@ bool TripletDecode(const uint8_t* flags_in, const uint8_t* in, size_t in_size, (in[triplet_index + 2] << 8) + in[triplet_index + 3]); } triplet_index += n_data_bytes; - // Possible overflow but coordinate values are not security sensitive - x += dx; - y += dy; + if (!_SafeIntAddition(x, dx, &x)) { + return false; + } + if (!_SafeIntAddition(y, dy, &y)) { + return false; + } *result++ = {x, y, on_curve}; } *in_bytes_consumed = triplet_index; @@ -178,8 +191,9 @@ bool TripletDecode(const uint8_t* flags_in, const uint8_t* in, size_t in_size, // This function stores just the point data. On entry, dst points to the // beginning of a simple glyph. Returns true on success. bool StorePoints(unsigned int n_points, const Point* points, - unsigned int n_contours, unsigned int instruction_length, - uint8_t* dst, size_t dst_size, size_t* glyph_size) { + unsigned int n_contours, unsigned int instruction_length, + bool has_overlap_bit, uint8_t* dst, size_t dst_size, + size_t* glyph_size) { // I believe that n_contours < 65536, in which case this is safe. However, a // comment and/or an assert would be good. unsigned int flag_offset = kEndPtsOfContoursOffset + 2 * n_contours + 2 + @@ -194,6 +208,10 @@ bool StorePoints(unsigned int n_points, const Point* points, for (unsigned int i = 0; i < n_points; ++i) { const Point& point = points[i]; int flag = point.on_curve ? kGlyfOnCurve : 0; + if (has_overlap_bit && i == 0) { + flag |= kOverlapSimple; + } + int dx = point.x - last_x; int dy = point.y - last_y; if (dx == 0) { @@ -391,13 +409,20 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table, WOFF2Out* out) { static const int kNumSubStreams = 7; Buffer file(data, glyf_table->transform_length); - uint32_t version; + uint16_t version; std::vector > substreams(kNumSubStreams); const size_t glyf_start = out->Size(); - if (PREDICT_FALSE(!file.ReadU32(&version))) { + if (PREDICT_FALSE(!file.ReadU16(&version))) { return FONT_COMPRESSION_FAILURE(); } + + uint16_t flags; + if (PREDICT_FALSE(!file.ReadU16(&flags))) { + return FONT_COMPRESSION_FAILURE(); + } + bool has_overlap_bitmap = (flags & FLAG_OVERLAP_SIMPLE_BITMAP); + if (PREDICT_FALSE(!file.ReadU16(&info->num_glyphs) || !file.ReadU16(&info->index_format))) { return FONT_COMPRESSION_FAILURE(); @@ -435,6 +460,17 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table, Buffer bbox_stream(substreams[5].first, substreams[5].second); Buffer instruction_stream(substreams[6].first, substreams[6].second); + const uint8_t* overlap_bitmap = nullptr; + unsigned int overlap_bitmap_length = 0; + if (has_overlap_bitmap) { + overlap_bitmap_length = (info->num_glyphs + 7) >> 3; + overlap_bitmap = data + offset; + if (PREDICT_FALSE(overlap_bitmap_length > + glyf_table->transform_length - offset)) { + return FONT_COMPRESSION_FAILURE(); + } + } + std::vector loca_values(info->num_glyphs + 1); std::vector n_points_vec; std::unique_ptr points; @@ -588,8 +624,12 @@ bool ReconstructGlyf(const uint8_t* data, Table* glyf_table, } 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))) { + bool has_overlap_bit = + has_overlap_bitmap && overlap_bitmap[i >> 3] & (0x80 >> (i & 7)); + + if (PREDICT_FALSE(!StorePoints( + total_n_points, points.get(), n_contours, instruction_size, + has_overlap_bit, glyph_buf.get(), glyph_buf_size, &glyph_size))) { return FONT_COMPRESSION_FAILURE(); } } else { diff --git a/third_party/woff2/src/woff2_decompress.cc b/third_party/woff2/src/woff2_decompress.cc index de088b9ec0f8..47394781ad3d 100644 --- a/third_party/woff2/src/woff2_decompress.cc +++ b/third_party/woff2/src/woff2_decompress.cc @@ -14,21 +14,21 @@ int main(int argc, char **argv) { - using std::string; - if (argc != 2) { fprintf(stderr, "One argument, the input filename, must be provided.\n"); return 1; } - string filename(argv[1]); - string outfilename = filename.substr(0, filename.find_last_of(".")) + ".ttf"; + std::string filename(argv[1]); + std::string outfilename = filename.substr(0, filename.find_last_of(".")) + ".ttf"; // Note: update woff2_dec_fuzzer_new_entry.cc if this pattern changes. - string input = woff2::GetFileContent(filename); + std::string input = woff2::GetFileContent(filename); const uint8_t* raw_input = reinterpret_cast(input.data()); - string output(std::min(woff2::ComputeWOFF2FinalSize(raw_input, input.size()), - woff2::kDefaultMaxSize), 0); + std::string output( + std::min(woff2::ComputeWOFF2FinalSize(raw_input, input.size()), + woff2::kDefaultMaxSize), + 0); woff2::WOFF2StringOut out(&output); const bool ok = woff2::ConvertWOFF2ToTTF(raw_input, input.size(), &out); diff --git a/third_party/woff2/src/woff2_enc.cc b/third_party/woff2/src/woff2_enc.cc index ec00878bcd64..f3f46e5759eb 100644 --- a/third_party/woff2/src/woff2_enc.cc +++ b/third_party/woff2/src/woff2_enc.cc @@ -28,12 +28,8 @@ namespace woff2 { -namespace { - - -using std::string; -using std::vector; +namespace { const size_t kWoff2HeaderSize = 48; const size_t kWoff2EntrySize = 20; @@ -183,7 +179,7 @@ size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length) { } size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length, - const string& extended_metadata) { + const std::string& extended_metadata) { // 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 diff --git a/third_party/woff2/src/woff2_info.cc b/third_party/woff2/src/woff2_info.cc index 2b51adcb6221..b13230453700 100644 --- a/third_party/woff2/src/woff2_info.cc +++ b/third_party/woff2/src/woff2_info.cc @@ -29,18 +29,16 @@ std::string PrintTag(int tag) { } int main(int argc, char **argv) { - using std::string; - if (argc != 2) { fprintf(stderr, "One argument, the input filename, must be provided.\n"); return 1; } - string filename(argv[1]); - string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2"; + std::string filename(argv[1]); + std::string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2"; fprintf(stdout, "Processing %s => %s\n", filename.c_str(), outfilename.c_str()); - string input = woff2::GetFileContent(filename); + std::string input = woff2::GetFileContent(filename); woff2::Buffer file(reinterpret_cast(input.data()), input.size()); diff --git a/third_party/woff2/src/woff2_out.cc b/third_party/woff2/src/woff2_out.cc index 8ab32681f1d2..a22d3bf8bed2 100644 --- a/third_party/woff2/src/woff2_out.cc +++ b/third_party/woff2/src/woff2_out.cc @@ -8,14 +8,10 @@ #include -using std::string; - namespace woff2 { -WOFF2StringOut::WOFF2StringOut(string* buf) - : buf_(buf), - max_size_(kDefaultMaxSize), - offset_(0) {} +WOFF2StringOut::WOFF2StringOut(std::string *buf) + : buf_(buf), max_size_(kDefaultMaxSize), offset_(0) {} bool WOFF2StringOut::Write(const void *buf, size_t n) { return Write(buf, offset_, n);