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