1142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi// Copyright 2014 Google Inc. All Rights Reserved. 2437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// 3437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// Licensed under the Apache License, Version 2.0 (the "License"); 4437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// you may not use this file except in compliance with the License. 5437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// You may obtain a copy of the License at 6437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// 7437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// http://www.apache.org/licenses/LICENSE-2.0 8437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// 9437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// Unless required by applicable law or agreed to in writing, software 10437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// distributed under the License is distributed on an "AS IS" BASIS, 11437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// See the License for the specific language governing permissions and 13437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// limitations under the License. 14437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// 15c75ed764ef2a74bf3ab645ca7a73c0c692477755Kenichi Ishibashi// Library for converting WOFF2 format font files to their TTF versions. 16437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 17142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi#include "./woff2_dec.h" 18437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 19437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter#include <stdlib.h> 20437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter#include <complex> 21437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter#include <cstring> 22437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter#include <limits> 23437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter#include <string> 24437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter#include <vector> 25437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 26142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi#include "./buffer.h" 27437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter#include "./decode.h" 28437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter#include "./round.h" 29437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter#include "./store_bytes.h" 30142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi#include "./table_tags.h" 31142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi#include "./woff2_common.h" 32437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 33437bbad37074e472b66d427814275de84ca77f19Roderick Sheeternamespace woff2 { 34437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 35437bbad37074e472b66d427814275de84ca77f19Roderick Sheeternamespace { 36437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 37437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterusing std::string; 38437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterusing std::vector; 39437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 40437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 41437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// simple glyph flags 42437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int kGlyfOnCurve = 1 << 0; 43437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int kGlyfXShort = 1 << 1; 44437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int kGlyfYShort = 1 << 2; 45437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int kGlyfRepeat = 1 << 3; 46437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int kGlyfThisXIsSame = 1 << 4; 47437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int kGlyfThisYIsSame = 1 << 5; 48437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 49437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// composite glyph flags 50142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi// See CompositeGlyph.java in sfntly for full definitions 51437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0; 52437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int FLAG_WE_HAVE_A_SCALE = 1 << 3; 53437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int FLAG_MORE_COMPONENTS = 1 << 5; 54437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int FLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; 55437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int FLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7; 56437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8; 57437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 58437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst size_t kSfntHeaderSize = 12; 59437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst size_t kSfntEntrySize = 16; 60437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst size_t kCheckSumAdjustmentOffset = 8; 61437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 62437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst size_t kEndPtsOfContoursOffset = 10; 63437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst size_t kCompositeGlyphBegin = 10; 64437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 65437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// Based on section 6.1.1 of MicroType Express draft spec 66142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashibool Read255UShort(Buffer* buf, unsigned int* value) { 67437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter static const int kWordCode = 253; 68437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter static const int kOneMoreByteCode2 = 254; 69437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter static const int kOneMoreByteCode1 = 255; 70437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter static const int kLowestUCode = 253; 71437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t code = 0; 72437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!buf->ReadU8(&code)) { 73142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 74437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 75437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (code == kWordCode) { 76437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint16_t result = 0; 77437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!buf->ReadU16(&result)) { 78142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 79437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 80437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter *value = result; 81437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 82437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (code == kOneMoreByteCode1) { 83437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t result = 0; 84437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!buf->ReadU8(&result)) { 85142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 86437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 87437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter *value = result + kLowestUCode; 88437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 89437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (code == kOneMoreByteCode2) { 90437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t result = 0; 91437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!buf->ReadU8(&result)) { 92142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 93437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 94437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter *value = result + kLowestUCode * 2; 95437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 96437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 97437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter *value = code; 98437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 99437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 100437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 101437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 102142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashibool ReadBase128(Buffer* buf, uint32_t* value) { 103437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t result = 0; 104437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (size_t i = 0; i < 5; ++i) { 105437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t code = 0; 106437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!buf->ReadU8(&code)) { 107142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 108437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 109437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // If any of the top seven bits are set then we're about to overflow. 110437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (result & 0xe0000000) { 111142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 112437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 113437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter result = (result << 7) | (code & 0x7f); 114437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if ((code & 0x80) == 0) { 115437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter *value = result; 116437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 117437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 118437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 119437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // Make sure not to exceed the size bound 120142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 121437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 122437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 123437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterint WithSign(int flag, int baseval) { 124437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // Precondition: 0 <= baseval < 65536 (to avoid integer overflow) 125437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return (flag & 1) ? baseval : -baseval; 126437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 127437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 128437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterbool TripletDecode(const uint8_t* flags_in, const uint8_t* in, size_t in_size, 129437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int n_points, std::vector<Point>* result, 130437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t* in_bytes_consumed) { 131437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int x = 0; 132437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int y = 0; 133437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 134437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (n_points > in_size) { 135142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 136437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 137437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int triplet_index = 0; 138437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 139437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (unsigned int i = 0; i < n_points; ++i) { 140437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t flag = flags_in[i]; 141437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter bool on_curve = !(flag >> 7); 142437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter flag &= 0x7f; 143437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int n_data_bytes; 144437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (flag < 84) { 145437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter n_data_bytes = 1; 146437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (flag < 120) { 147437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter n_data_bytes = 2; 148437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (flag < 124) { 149437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter n_data_bytes = 3; 150437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 151437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter n_data_bytes = 4; 152437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 153437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (triplet_index + n_data_bytes > in_size || 154437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter triplet_index + n_data_bytes < triplet_index) { 155142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 156437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 157437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int dx, dy; 158437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (flag < 10) { 159437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dx = 0; 160437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dy = WithSign(flag, ((flag & 14) << 7) + in[triplet_index]); 161437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (flag < 20) { 162437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dx = WithSign(flag, (((flag - 10) & 14) << 7) + in[triplet_index]); 163437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dy = 0; 164437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (flag < 84) { 165437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int b0 = flag - 20; 166437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int b1 = in[triplet_index]; 167437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dx = WithSign(flag, 1 + (b0 & 0x30) + (b1 >> 4)); 168437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dy = WithSign(flag >> 1, 1 + ((b0 & 0x0c) << 2) + (b1 & 0x0f)); 169437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (flag < 120) { 170437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int b0 = flag - 84; 171437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dx = WithSign(flag, 1 + ((b0 / 12) << 8) + in[triplet_index]); 172437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dy = WithSign(flag >> 1, 173437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 1 + (((b0 % 12) >> 2) << 8) + in[triplet_index + 1]); 174437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (flag < 124) { 175437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int b2 = in[triplet_index + 1]; 176437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dx = WithSign(flag, (in[triplet_index] << 4) + (b2 >> 4)); 177437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dy = WithSign(flag >> 1, ((b2 & 0x0f) << 8) + in[triplet_index + 2]); 178437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 179437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dx = WithSign(flag, (in[triplet_index] << 8) + in[triplet_index + 1]); 180437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dy = WithSign(flag >> 1, 181437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter (in[triplet_index + 2] << 8) + in[triplet_index + 3]); 182437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 183437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter triplet_index += n_data_bytes; 184437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // Possible overflow but coordinate values are not security sensitive 185437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter x += dx; 186437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter y += dy; 187437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter result->push_back(Point()); 188437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter Point& back = result->back(); 189437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter back.x = x; 190437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter back.y = y; 191437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter back.on_curve = on_curve; 192437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 193437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter *in_bytes_consumed = triplet_index; 194437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 195437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 196437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 197437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// This function stores just the point data. On entry, dst points to the 198437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// beginning of a simple glyph. Returns true on success. 199437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterbool StorePoints(const std::vector<Point>& points, 200437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int n_contours, unsigned int instruction_length, 201437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t* dst, size_t dst_size, size_t* glyph_size) { 202437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // I believe that n_contours < 65536, in which case this is safe. However, a 203437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // comment and/or an assert would be good. 204437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int flag_offset = kEndPtsOfContoursOffset + 2 * n_contours + 2 + 205437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter instruction_length; 206437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int last_flag = -1; 207437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int repeat_count = 0; 208437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int last_x = 0; 209437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int last_y = 0; 210437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int x_bytes = 0; 211437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int y_bytes = 0; 212437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 213437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (unsigned int i = 0; i < points.size(); ++i) { 214437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const Point& point = points[i]; 215437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int flag = point.on_curve ? kGlyfOnCurve : 0; 216437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int dx = point.x - last_x; 217437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int dy = point.y - last_y; 218437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (dx == 0) { 219437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter flag |= kGlyfThisXIsSame; 220437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (dx > -256 && dx < 256) { 221437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter flag |= kGlyfXShort | (dx > 0 ? kGlyfThisXIsSame : 0); 222437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter x_bytes += 1; 223437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 224437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter x_bytes += 2; 225437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 226437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (dy == 0) { 227437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter flag |= kGlyfThisYIsSame; 228437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (dy > -256 && dy < 256) { 229437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter flag |= kGlyfYShort | (dy > 0 ? kGlyfThisYIsSame : 0); 230437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter y_bytes += 1; 231437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 232437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter y_bytes += 2; 233437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 234437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 235437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (flag == last_flag && repeat_count != 255) { 236437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst[flag_offset - 1] |= kGlyfRepeat; 237437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter repeat_count++; 238437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 239437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (repeat_count != 0) { 240437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (flag_offset >= dst_size) { 241142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 242437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 243437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst[flag_offset++] = repeat_count; 244437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 245437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (flag_offset >= dst_size) { 246142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 247437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 248437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst[flag_offset++] = flag; 249437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter repeat_count = 0; 250437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 251437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter last_x = point.x; 252437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter last_y = point.y; 253437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter last_flag = flag; 254437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 255437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 256437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (repeat_count != 0) { 257437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (flag_offset >= dst_size) { 258142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 259437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 260437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst[flag_offset++] = repeat_count; 261437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 262437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int xy_bytes = x_bytes + y_bytes; 263437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (xy_bytes < x_bytes || 264437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter flag_offset + xy_bytes < flag_offset || 265437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter flag_offset + xy_bytes > dst_size) { 266142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 267437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 268437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 269437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int x_offset = flag_offset; 270437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int y_offset = flag_offset + x_bytes; 271437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter last_x = 0; 272437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter last_y = 0; 273437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (unsigned int i = 0; i < points.size(); ++i) { 274437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int dx = points[i].x - last_x; 275437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (dx == 0) { 276437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // pass 277437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (dx > -256 && dx < 256) { 278437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst[x_offset++] = std::abs(dx); 279437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 280437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // will always fit for valid input, but overflow is harmless 281437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter x_offset = Store16(dst, x_offset, dx); 282437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 283437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter last_x += dx; 284437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int dy = points[i].y - last_y; 285437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (dy == 0) { 286437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // pass 287437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (dy > -256 && dy < 256) { 288437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst[y_offset++] = std::abs(dy); 289437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 290437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter y_offset = Store16(dst, y_offset, dy); 291437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 292437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter last_y += dy; 293437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 294437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter *glyph_size = y_offset; 295437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 296437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 297437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 298437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// Compute the bounding box of the coordinates, and store into a glyf buffer. 299437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// A precondition is that there are at least 10 bytes available. 300437bbad37074e472b66d427814275de84ca77f19Roderick Sheetervoid ComputeBbox(const std::vector<Point>& points, uint8_t* dst) { 301437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int x_min = 0; 302437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int y_min = 0; 303437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int x_max = 0; 304437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int y_max = 0; 305437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 306437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (unsigned int i = 0; i < points.size(); ++i) { 307437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int x = points[i].x; 308437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int y = points[i].y; 309437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (i == 0 || x < x_min) x_min = x; 310437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (i == 0 || x > x_max) x_max = x; 311437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (i == 0 || y < y_min) y_min = y; 312437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (i == 0 || y > y_max) y_max = y; 313437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 314437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t offset = 2; 315437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(dst, offset, x_min); 316437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(dst, offset, y_min); 317437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(dst, offset, x_max); 318437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(dst, offset, y_max); 319437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 320437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 321437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// Process entire bbox stream. This is done as a separate pass to allow for 322437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// composite bbox computations (an optional more aggressive transform). 323142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashibool ProcessBboxStream(Buffer* bbox_stream, unsigned int n_glyphs, 324437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const std::vector<uint32_t>& loca_values, uint8_t* glyf_buf, 325437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t glyf_buf_length) { 326437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint8_t* buf = bbox_stream->buffer(); 327437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (n_glyphs >= 65536 || loca_values.size() != n_glyphs + 1) { 328142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 329437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 330437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // Safe because n_glyphs is bounded 331437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int bitmap_length = ((n_glyphs + 31) >> 5) << 2; 332437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!bbox_stream->Skip(bitmap_length)) { 333142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 334437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 335437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (unsigned int i = 0; i < n_glyphs; ++i) { 336437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (buf[i >> 3] & (0x80 >> (i & 7))) { 337437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t loca_offset = loca_values[i]; 338437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (loca_values[i + 1] - loca_offset < kEndPtsOfContoursOffset) { 339142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 340437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 341437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (glyf_buf_length < 2 + 10 || 342437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter loca_offset > glyf_buf_length - 2 - 10) { 343142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 344437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 345437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!bbox_stream->Read(glyf_buf + loca_offset + 2, 8)) { 346142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 347437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 348437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 349437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 350437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 351437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 352437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 353142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashibool ProcessComposite(Buffer* composite_stream, uint8_t* dst, 354437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t dst_size, size_t* glyph_size, bool* have_instructions) { 355437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t start_offset = composite_stream->offset(); 356437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter bool we_have_instructions = false; 357437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 358437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint16_t flags = FLAG_MORE_COMPONENTS; 359437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter while (flags & FLAG_MORE_COMPONENTS) { 360437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!composite_stream->ReadU16(&flags)) { 361142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 362437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 363437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter we_have_instructions |= (flags & FLAG_WE_HAVE_INSTRUCTIONS) != 0; 364437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t arg_size = 2; // glyph index 365437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (flags & FLAG_ARG_1_AND_2_ARE_WORDS) { 366437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter arg_size += 4; 367437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 368437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter arg_size += 2; 369437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 370437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (flags & FLAG_WE_HAVE_A_SCALE) { 371437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter arg_size += 2; 372437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (flags & FLAG_WE_HAVE_AN_X_AND_Y_SCALE) { 373437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter arg_size += 4; 374437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (flags & FLAG_WE_HAVE_A_TWO_BY_TWO) { 375437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter arg_size += 8; 376437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 377437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!composite_stream->Skip(arg_size)) { 378142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 379437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 380437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 381437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t composite_glyph_size = composite_stream->offset() - start_offset; 382437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (composite_glyph_size + kCompositeGlyphBegin > dst_size) { 383142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 384437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 385437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter Store16(dst, 0, 0xffff); // nContours = -1 for composite glyph 386437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter std::memcpy(dst + kCompositeGlyphBegin, 387437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter composite_stream->buffer() + start_offset, 388437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter composite_glyph_size); 389437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter *glyph_size = kCompositeGlyphBegin + composite_glyph_size; 390437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter *have_instructions = we_have_instructions; 391437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 392437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 393437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 394437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// Build TrueType loca table 395437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterbool StoreLoca(const std::vector<uint32_t>& loca_values, int index_format, 396437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t* dst, size_t dst_size) { 397437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint64_t loca_size = loca_values.size(); 398437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint64_t offset_size = index_format ? 4 : 2; 399437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if ((loca_size << 2) >> 2 != loca_size) { 400142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 401437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 402437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (offset_size * loca_size > dst_size) { 403142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 404437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 405437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t offset = 0; 406437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (size_t i = 0; i < loca_values.size(); ++i) { 407437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t value = loca_values[i]; 408437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (index_format) { 409437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = StoreU32(dst, offset, value); 410437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 411437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(dst, offset, value >> 1); 412437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 413437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 414437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 415437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 416437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 417437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// Reconstruct entire glyf table based on transformed original 418437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterbool ReconstructGlyf(const uint8_t* data, size_t data_size, 419437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t* dst, size_t dst_size, 420437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t* loca_buf, size_t loca_size) { 421437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter static const int kNumSubStreams = 7; 422142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer file(data, data_size); 423437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t version; 424437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter std::vector<std::pair<const uint8_t*, size_t> > substreams(kNumSubStreams); 425437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 426437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!file.ReadU32(&version)) { 427142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 428437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 429437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint16_t num_glyphs; 430437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint16_t index_format; 431437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!file.ReadU16(&num_glyphs) || 432437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter !file.ReadU16(&index_format)) { 433142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 434437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 435437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int offset = (2 + kNumSubStreams) * 4; 436437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (offset > data_size) { 437142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 438437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 439437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // Invariant from here on: data_size >= offset 440437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (int i = 0; i < kNumSubStreams; ++i) { 441437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t substream_size; 442437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!file.ReadU32(&substream_size)) { 443142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 444437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 445437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (substream_size > data_size - offset) { 446142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 447437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 448437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter substreams[i] = std::make_pair(data + offset, substream_size); 449437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset += substream_size; 450437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 451142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer n_contour_stream(substreams[0].first, substreams[0].second); 452142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer n_points_stream(substreams[1].first, substreams[1].second); 453142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer flag_stream(substreams[2].first, substreams[2].second); 454142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer glyph_stream(substreams[3].first, substreams[3].second); 455142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer composite_stream(substreams[4].first, substreams[4].second); 456142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer bbox_stream(substreams[5].first, substreams[5].second); 457142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer instruction_stream(substreams[6].first, substreams[6].second); 458437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 459437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter std::vector<uint32_t> loca_values(num_glyphs + 1); 460437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter std::vector<unsigned int> n_points_vec; 461437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter std::vector<Point> points; 462437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t loca_offset = 0; 463437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (unsigned int i = 0; i < num_glyphs; ++i) { 464437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t glyph_size = 0; 465437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint16_t n_contours = 0; 466437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!n_contour_stream.ReadU16(&n_contours)) { 467142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 468437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 469437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t* glyf_dst = dst + loca_offset; 470437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t glyf_dst_size = dst_size - loca_offset; 471437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (n_contours == 0xffff) { 472437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // composite glyph 473437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter bool have_instructions = false; 474437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int instruction_size = 0; 475437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!ProcessComposite(&composite_stream, glyf_dst, glyf_dst_size, 476437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter &glyph_size, &have_instructions)) { 477142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 478437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 479437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (have_instructions) { 480437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!Read255UShort(&glyph_stream, &instruction_size)) { 481142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 482437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 483437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (instruction_size + 2 > glyf_dst_size - glyph_size) { 484142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 485437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 486437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter Store16(glyf_dst, glyph_size, instruction_size); 487437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!instruction_stream.Read(glyf_dst + glyph_size + 2, 488437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter instruction_size)) { 489142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 490437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 491437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter glyph_size += instruction_size + 2; 492437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 493437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if (n_contours > 0) { 494437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // simple glyph 495437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter n_points_vec.clear(); 496437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter points.clear(); 497437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int total_n_points = 0; 498437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int n_points_contour; 499437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (unsigned int j = 0; j < n_contours; ++j) { 500437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!Read255UShort(&n_points_stream, &n_points_contour)) { 501142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 502437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 503437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter n_points_vec.push_back(n_points_contour); 504437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (total_n_points + n_points_contour < total_n_points) { 505142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 506437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 507437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter total_n_points += n_points_contour; 508437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 509437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int flag_size = total_n_points; 510437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (flag_size > flag_stream.length() - flag_stream.offset()) { 511142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 512437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 513437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint8_t* flags_buf = flag_stream.buffer() + flag_stream.offset(); 514437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint8_t* triplet_buf = glyph_stream.buffer() + 515437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter glyph_stream.offset(); 516437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t triplet_size = glyph_stream.length() - glyph_stream.offset(); 517437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t triplet_bytes_consumed = 0; 518437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!TripletDecode(flags_buf, triplet_buf, triplet_size, total_n_points, 519437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter &points, &triplet_bytes_consumed)) { 520142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 521437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 522437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint32_t header_and_endpts_contours_size = 523437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter kEndPtsOfContoursOffset + 2 * n_contours; 524437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (glyf_dst_size < header_and_endpts_contours_size) { 525142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 526437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 527437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter Store16(glyf_dst, 0, n_contours); 528437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter ComputeBbox(points, glyf_dst); 529437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t offset = kEndPtsOfContoursOffset; 530437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter int end_point = -1; 531437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (unsigned int contour_ix = 0; contour_ix < n_contours; ++contour_ix) { 532437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter end_point += n_points_vec[contour_ix]; 533437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (end_point >= 65536) { 534142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 535437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 536437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(glyf_dst, offset, end_point); 537437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 538437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!flag_stream.Skip(flag_size)) { 539142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 540437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 541437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!glyph_stream.Skip(triplet_bytes_consumed)) { 542142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 543437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 544437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned int instruction_size; 545437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!Read255UShort(&glyph_stream, &instruction_size)) { 546142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 547437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 548437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (glyf_dst_size - header_and_endpts_contours_size < 549437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter instruction_size + 2) { 550142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 551437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 552437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t* instruction_dst = glyf_dst + header_and_endpts_contours_size; 553437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter Store16(instruction_dst, 0, instruction_size); 554437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!instruction_stream.Read(instruction_dst + 2, instruction_size)) { 555142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 556437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 557437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!StorePoints(points, n_contours, instruction_size, 558437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter glyf_dst, glyf_dst_size, &glyph_size)) { 559142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 560437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 561437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 562437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter glyph_size = 0; 563437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 564437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter loca_values[i] = loca_offset; 565437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (glyph_size + 3 < glyph_size) { 566142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 567437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 568437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter glyph_size = Round4(glyph_size); 569437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (glyph_size > dst_size - loca_offset) { 570437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // This shouldn't happen, but this test defensively maintains the 571437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // invariant that loca_offset <= dst_size. 572142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 573437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 574437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter loca_offset += glyph_size; 575437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 576437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter loca_values[num_glyphs] = loca_offset; 577437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!ProcessBboxStream(&bbox_stream, num_glyphs, loca_values, 578437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst, dst_size)) { 579142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 580437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 581437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return StoreLoca(loca_values, index_format, loca_buf, loca_size); 582437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 583437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 584437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// This is linear search, but could be changed to binary because we 585437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// do have a guarantee that the tables are sorted by tag. But the total 586437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter// cpu time is expected to be very small in any case. 587437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterconst Table* FindTable(const std::vector<Table>& tables, uint32_t tag) { 588437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t n_tables = tables.size(); 589437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (size_t i = 0; i < n_tables; ++i) { 590437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (tables[i].tag == tag) { 591437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return &tables[i]; 592437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 593437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 594437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return NULL; 595437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 596437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 597437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterbool ReconstructTransformed(const std::vector<Table>& tables, uint32_t tag, 598437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint8_t* transformed_buf, size_t transformed_size, 599437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t* dst, size_t dst_length) { 600142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi if (tag == kGlyfTableTag) { 601437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const Table* glyf_table = FindTable(tables, tag); 602142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi const Table* loca_table = FindTable(tables, kLocaTableTag); 603437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (glyf_table == NULL || loca_table == NULL) { 604142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 605437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 606437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (static_cast<uint64_t>(glyf_table->dst_offset + glyf_table->dst_length) > 607437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst_length) { 608142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 609437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 610437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (static_cast<uint64_t>(loca_table->dst_offset + loca_table->dst_length) > 611437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst_length) { 612142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 613437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 614437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return ReconstructGlyf(transformed_buf, transformed_size, 615437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst + glyf_table->dst_offset, glyf_table->dst_length, 616437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst + loca_table->dst_offset, loca_table->dst_length); 617142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi } else if (tag == kLocaTableTag) { 618437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // processing was already done by glyf table, but validate 619142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi if (!FindTable(tables, kGlyfTableTag)) { 620142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 621437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 622437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 623437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // transform for the tag is not known 624142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 625437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 626437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 627437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 628437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 629437bbad37074e472b66d427814275de84ca77f19Roderick Sheeteruint32_t ComputeChecksum(const uint8_t* buf, size_t size) { 630437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t checksum = 0; 631437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (size_t i = 0; i < size; i += 4) { 632437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // We assume the addition is mod 2^32, which is valid because unsigned 633437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter checksum += (buf[i] << 24) | (buf[i + 1] << 16) | 634437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter (buf[i + 2] << 8) | buf[i + 3]; 635437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 636437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return checksum; 637437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 638437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 639437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterbool FixChecksums(const std::vector<Table>& tables, uint8_t* dst) { 640142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi const Table* head_table = FindTable(tables, kHeadTableTag); 641437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (head_table == NULL || 642437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter head_table->dst_length < kCheckSumAdjustmentOffset + 4) { 643142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 644437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 645437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t adjustment_offset = head_table->dst_offset + kCheckSumAdjustmentOffset; 646437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter StoreU32(dst, adjustment_offset, 0); 647437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t n_tables = tables.size(); 648437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t file_checksum = 0; 649437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (size_t i = 0; i < n_tables; ++i) { 650437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const Table* table = &tables[i]; 651437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t table_length = table->dst_length; 652437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t* table_data = dst + table->dst_offset; 653437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t checksum = ComputeChecksum(table_data, table_length); 654437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter StoreU32(dst, kSfntHeaderSize + i * kSfntEntrySize + 4, checksum); 655437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter file_checksum += checksum; 656437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 657437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter file_checksum += ComputeChecksum(dst, 658437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter kSfntHeaderSize + kSfntEntrySize * n_tables); 659437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t checksum_adjustment = 0xb1b0afba - file_checksum; 660437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter StoreU32(dst, adjustment_offset, checksum_adjustment); 661437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 662437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 663437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 664437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterbool Woff2Uncompress(uint8_t* dst_buf, size_t dst_size, 6652ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter const uint8_t* src_buf, size_t src_size) { 6662ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter size_t uncompressed_size = dst_size; 6672ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter int ok = BrotliDecompressBuffer(src_size, src_buf, 6682ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter &uncompressed_size, dst_buf); 6692ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter if (!ok || uncompressed_size != dst_size) { 670142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 671437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 672437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 673437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 674437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 675142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashibool ReadShortDirectory(Buffer* file, std::vector<Table>* tables, 676437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t num_tables) { 677437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (size_t i = 0; i < num_tables; ++i) { 678437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter Table* table = &(*tables)[i]; 679437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint8_t flag_byte; 680437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!file->ReadU8(&flag_byte)) { 681142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 682437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 683437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t tag; 68447c5016d7f20363602601aa2624229482b5c2e50David Kuettel if ((flag_byte & 0x3f) == 0x3f) { 685437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!file->ReadU32(&tag)) { 686142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 687437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 688437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 689142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi tag = kKnownTags[flag_byte & 0x3f]; 690437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 69147c5016d7f20363602601aa2624229482b5c2e50David Kuettel // Bits 6 and 7 are reserved and must be 0. 69247c5016d7f20363602601aa2624229482b5c2e50David Kuettel if ((flag_byte & 0xC0) != 0) { 693142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 694437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 6952ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter uint32_t flags = 0; 69622e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka if (i > 0) { 69722e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka flags |= kWoff2FlagsContinueStream; 69822e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka } 69947c5016d7f20363602601aa2624229482b5c2e50David Kuettel // Always transform the glyf and loca tables 700142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi if (tag == kGlyfTableTag || tag == kLocaTableTag) { 701437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter flags |= kWoff2FlagsTransform; 702437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 703437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t dst_length; 704437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!ReadBase128(file, &dst_length)) { 705142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 706437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 707437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t transform_length = dst_length; 708437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if ((flags & kWoff2FlagsTransform) != 0) { 709437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!ReadBase128(file, &transform_length)) { 710142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 711437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 712437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 713437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter table->tag = tag; 714437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter table->flags = flags; 715437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter table->transform_length = transform_length; 716437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter table->dst_length = dst_length; 717437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 718437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return true; 719437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 720437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 721437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} // namespace 722437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 723437bbad37074e472b66d427814275de84ca77f19Roderick Sheetersize_t ComputeWOFF2FinalSize(const uint8_t* data, size_t length) { 724142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer file(data, length); 725437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t total_length; 726437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 727437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!file.Skip(16) || 728437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter !file.ReadU32(&total_length)) { 729437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return 0; 730437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 731437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return total_length; 732437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 733437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 734437bbad37074e472b66d427814275de84ca77f19Roderick Sheeterbool ConvertWOFF2ToTTF(uint8_t* result, size_t result_length, 735437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint8_t* data, size_t length) { 736142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi Buffer file(data, length); 737437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 738437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t signature; 739437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t flavor; 740437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!file.ReadU32(&signature) || signature != kWoff2Signature || 741437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter !file.ReadU32(&flavor)) { 742142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 743437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 744437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 745437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // TODO(user): Should call IsValidVersionTag() here. 746437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 747437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t reported_length; 748437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!file.ReadU32(&reported_length) || length != reported_length) { 749142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 750437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 751437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint16_t num_tables; 752437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!file.ReadU16(&num_tables) || !num_tables) { 753142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 754437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 755437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // We don't care about these fields of the header: 756494c85cebbaaa0db345df69ffa1b639aa4652022Zoltan Szabadka // uint16_t reserved 757437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // uint32_t total_sfnt_size 75822e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka if (!file.Skip(6)) { 759142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 76022e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka } 76122e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka uint32_t compressed_length; 76222e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka if (!file.ReadU32(&compressed_length)) { 763142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 76422e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka } 76522e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka // We don't care about these fields of the header: 766437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // uint16_t major_version, minor_version 767437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // uint32_t meta_offset, meta_length, meta_orig_length 768437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // uint32_t priv_offset, priv_length 76922e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka if (!file.Skip(24)) { 770142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 771437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 772437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter std::vector<Table> tables(num_tables); 773437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // Note: change below to ReadLongDirectory to enable long format. 774437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!ReadShortDirectory(&file, &tables, num_tables)) { 775142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 776437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 777437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint64_t src_offset = file.offset(); 778437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint64_t dst_offset = kSfntHeaderSize + 779437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter kSfntEntrySize * static_cast<uint64_t>(num_tables); 780437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint64_t uncompressed_sum = 0; 781437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (uint16_t i = 0; i < num_tables; ++i) { 782437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter Table* table = &tables[i]; 783437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter table->src_offset = src_offset; 78422e2c328288610e63c03e8de0b9c18b1b926cff6Zoltan Szabadka table->src_length = (i == 0 ? compressed_length : 0); 785437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter src_offset += table->src_length; 786437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (src_offset > std::numeric_limits<uint32_t>::max()) { 787142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 788437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 789437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter src_offset = Round4(src_offset); // TODO: reconsider 790437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter table->dst_offset = dst_offset; 791437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst_offset += table->dst_length; 792437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (dst_offset > std::numeric_limits<uint32_t>::max()) { 793142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 794437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 795437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter dst_offset = Round4(dst_offset); 7962ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter 7972ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter uncompressed_sum += table->src_length; 7982ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter if (uncompressed_sum > std::numeric_limits<uint32_t>::max()) { 799142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 800437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 801437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 802437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // Enforce same 30M limit on uncompressed tables as OTS 803437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (uncompressed_sum > 30 * 1024 * 1024) { 804142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 805437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 806437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (src_offset > length || dst_offset > result_length) { 807142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 808437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 809437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 810437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint32_t sfnt_header_and_table_directory_size = 12 + 16 * num_tables; 811437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (sfnt_header_and_table_directory_size > result_length) { 812142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 813437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 814437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 815437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter // Start building the font 816437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t offset = 0; 817437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = StoreU32(result, offset, flavor); 818437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(result, offset, num_tables); 819437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter unsigned max_pow2 = 0; 820437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter while (1u << (max_pow2 + 1) <= num_tables) { 821437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter max_pow2++; 822437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 823437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint16_t output_search_range = (1u << max_pow2) << 4; 824437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(result, offset, output_search_range); 825437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(result, offset, max_pow2); 826437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = Store16(result, offset, (num_tables << 4) - output_search_range); 827437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (uint16_t i = 0; i < num_tables; ++i) { 828437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const Table* table = &tables[i]; 829437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = StoreU32(result, offset, table->tag); 830437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = StoreU32(result, offset, 0); // checksum, to fill in later 831437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = StoreU32(result, offset, table->dst_offset); 832437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter offset = StoreU32(result, offset, table->dst_length); 833437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 834437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter std::vector<uint8_t> uncompressed_buf; 835437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter bool continue_valid = false; 836437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint8_t* transform_buf = NULL; 837437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (uint16_t i = 0; i < num_tables; ++i) { 838437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const Table* table = &tables[i]; 839437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint32_t flags = table->flags; 840437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter const uint8_t* src_buf = data + table->src_offset; 841437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter size_t transform_length = table->transform_length; 842437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if ((flags & kWoff2FlagsContinueStream) != 0) { 843437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!continue_valid) { 844142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 845437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 846437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else if ((flags & kWoff2FlagsContinueStream) == 0) { 847437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uint64_t total_size = transform_length; 848437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter for (uint16_t j = i + 1; j < num_tables; ++j) { 849437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if ((tables[j].flags & kWoff2FlagsContinueStream) == 0) { 850437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter break; 851437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 852437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter total_size += tables[j].transform_length; 853437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (total_size > std::numeric_limits<uint32_t>::max()) { 854142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 855437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 856437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 857437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter uncompressed_buf.resize(total_size); 858437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!Woff2Uncompress(&uncompressed_buf[0], total_size, 8592ec0cb8a7833c14679b9bd734d3336cee7c4cab5Roderick Sheeter src_buf, compressed_length)) { 860142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 861437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 862437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter transform_buf = &uncompressed_buf[0]; 863437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter continue_valid = true; 864437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 865142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 866437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 867437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 868437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if ((flags & kWoff2FlagsTransform) == 0) { 869437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (transform_length != table->dst_length) { 870142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 871437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 872437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (static_cast<uint64_t>(table->dst_offset + transform_length) > 873437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter result_length) { 874142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 875437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 876437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter std::memcpy(result + table->dst_offset, transform_buf, 877437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter transform_length); 878437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } else { 879437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (!ReconstructTransformed(tables, table->tag, 880437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter transform_buf, transform_length, result, result_length)) { 881142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 882437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 883437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 884437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter if (continue_valid) { 885437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter transform_buf += transform_length; 886c75ed764ef2a74bf3ab645ca7a73c0c692477755Kenichi Ishibashi if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) { 887142d8881c174896c0180d60d3efe66a07daa7256Kenichi Ishibashi return FONT_COMPRESSION_FAILURE(); 888437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 889437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 890437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter } 891437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 892437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter return FixChecksums(tables, result); 893437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} 894437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter 895437bbad37074e472b66d427814275de84ca77f19Roderick Sheeter} // namespace woff2 896