1 // Copyright 2013 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Glyph manipulation 16 17 #include "./glyph.h" 18 19 #include <stdlib.h> 20 #include <limits> 21 #include "./buffer.h" 22 #include "./store_bytes.h" 23 24 namespace woff2 { 25 26 static const int32_t kFLAG_ONCURVE = 1; 27 static const int32_t kFLAG_XSHORT = 1 << 1; 28 static const int32_t kFLAG_YSHORT = 1 << 2; 29 static const int32_t kFLAG_REPEAT = 1 << 3; 30 static const int32_t kFLAG_XREPEATSIGN = 1 << 4; 31 static const int32_t kFLAG_YREPEATSIGN = 1 << 5; 32 static const int32_t kFLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0; 33 static const int32_t kFLAG_WE_HAVE_A_SCALE = 1 << 3; 34 static const int32_t kFLAG_MORE_COMPONENTS = 1 << 5; 35 static const int32_t kFLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; 36 static const int32_t kFLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7; 37 static const int32_t kFLAG_WE_HAVE_INSTRUCTIONS = 1 << 8; 38 39 bool ReadCompositeGlyphData(Buffer* buffer, Glyph* glyph) { 40 glyph->have_instructions = false; 41 glyph->composite_data = buffer->buffer() + buffer->offset(); 42 size_t start_offset = buffer->offset(); 43 uint16_t flags = kFLAG_MORE_COMPONENTS; 44 while (flags & kFLAG_MORE_COMPONENTS) { 45 if (!buffer->ReadU16(&flags)) { 46 return FONT_COMPRESSION_FAILURE(); 47 } 48 glyph->have_instructions |= (flags & kFLAG_WE_HAVE_INSTRUCTIONS) != 0; 49 size_t arg_size = 2; // glyph index 50 if (flags & kFLAG_ARG_1_AND_2_ARE_WORDS) { 51 arg_size += 4; 52 } else { 53 arg_size += 2; 54 } 55 if (flags & kFLAG_WE_HAVE_A_SCALE) { 56 arg_size += 2; 57 } else if (flags & kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) { 58 arg_size += 4; 59 } else if (flags & kFLAG_WE_HAVE_A_TWO_BY_TWO) { 60 arg_size += 8; 61 } 62 if (!buffer->Skip(arg_size)) { 63 return FONT_COMPRESSION_FAILURE(); 64 } 65 } 66 if (buffer->offset() - start_offset > std::numeric_limits<uint32_t>::max()) { 67 return FONT_COMPRESSION_FAILURE(); 68 } 69 glyph->composite_data_size = buffer->offset() - start_offset; 70 return true; 71 } 72 73 bool ReadGlyph(const uint8_t* data, size_t len, Glyph* glyph) { 74 Buffer buffer(data, len); 75 76 int16_t num_contours; 77 if (!buffer.ReadS16(&num_contours)) { 78 return FONT_COMPRESSION_FAILURE(); 79 } 80 81 if (num_contours == 0) { 82 // Empty glyph. 83 return true; 84 } 85 86 // Read the bounding box. 87 if (!buffer.ReadS16(&glyph->x_min) || 88 !buffer.ReadS16(&glyph->y_min) || 89 !buffer.ReadS16(&glyph->x_max) || 90 !buffer.ReadS16(&glyph->y_max)) { 91 return FONT_COMPRESSION_FAILURE(); 92 } 93 94 if (num_contours > 0) { 95 // Simple glyph. 96 glyph->contours.resize(num_contours); 97 98 // Read the number of points per contour. 99 uint16_t last_point_index = 0; 100 for (int i = 0; i < num_contours; ++i) { 101 uint16_t point_index; 102 if (!buffer.ReadU16(&point_index)) { 103 return FONT_COMPRESSION_FAILURE(); 104 } 105 uint16_t num_points = point_index - last_point_index + (i == 0 ? 1 : 0); 106 glyph->contours[i].resize(num_points); 107 last_point_index = point_index; 108 } 109 110 // Read the instructions. 111 if (!buffer.ReadU16(&glyph->instructions_size)) { 112 return FONT_COMPRESSION_FAILURE(); 113 } 114 glyph->instructions_data = data + buffer.offset(); 115 if (!buffer.Skip(glyph->instructions_size)) { 116 return FONT_COMPRESSION_FAILURE(); 117 } 118 119 // Read the run-length coded flags. 120 std::vector<std::vector<uint8_t> > flags(num_contours); 121 uint8_t flag = 0; 122 uint8_t flag_repeat = 0; 123 for (int i = 0; i < num_contours; ++i) { 124 flags[i].resize(glyph->contours[i].size()); 125 for (int j = 0; j < glyph->contours[i].size(); ++j) { 126 if (flag_repeat == 0) { 127 if (!buffer.ReadU8(&flag)) { 128 return FONT_COMPRESSION_FAILURE(); 129 } 130 if (flag & kFLAG_REPEAT) { 131 if (!buffer.ReadU8(&flag_repeat)) { 132 return FONT_COMPRESSION_FAILURE(); 133 } 134 } 135 } else { 136 flag_repeat--; 137 } 138 flags[i][j] = flag; 139 glyph->contours[i][j].on_curve = flag & kFLAG_ONCURVE; 140 } 141 } 142 143 // Read the x coordinates. 144 int prev_x = 0; 145 for (int i = 0; i < num_contours; ++i) { 146 for (int j = 0; j < glyph->contours[i].size(); ++j) { 147 uint8_t flag = flags[i][j]; 148 if (flag & kFLAG_XSHORT) { 149 // single byte x-delta coord value 150 uint8_t x_delta; 151 if (!buffer.ReadU8(&x_delta)) { 152 return FONT_COMPRESSION_FAILURE(); 153 } 154 int sign = (flag & kFLAG_XREPEATSIGN) ? 1 : -1; 155 glyph->contours[i][j].x = prev_x + sign * x_delta; 156 } else { 157 // double byte x-delta coord value 158 int16_t x_delta = 0; 159 if (!(flag & kFLAG_XREPEATSIGN)) { 160 if (!buffer.ReadS16(&x_delta)) { 161 return FONT_COMPRESSION_FAILURE(); 162 } 163 } 164 glyph->contours[i][j].x = prev_x + x_delta; 165 } 166 prev_x = glyph->contours[i][j].x; 167 } 168 } 169 170 // Read the y coordinates. 171 int prev_y = 0; 172 for (int i = 0; i < num_contours; ++i) { 173 for (int j = 0; j < glyph->contours[i].size(); ++j) { 174 uint8_t flag = flags[i][j]; 175 if (flag & kFLAG_YSHORT) { 176 // single byte y-delta coord value 177 uint8_t y_delta; 178 if (!buffer.ReadU8(&y_delta)) { 179 return FONT_COMPRESSION_FAILURE(); 180 } 181 int sign = (flag & kFLAG_YREPEATSIGN) ? 1 : -1; 182 glyph->contours[i][j].y = prev_y + sign * y_delta; 183 } else { 184 // double byte y-delta coord value 185 int16_t y_delta = 0; 186 if (!(flag & kFLAG_YREPEATSIGN)) { 187 if (!buffer.ReadS16(&y_delta)) { 188 return FONT_COMPRESSION_FAILURE(); 189 } 190 } 191 glyph->contours[i][j].y = prev_y + y_delta; 192 } 193 prev_y = glyph->contours[i][j].y; 194 } 195 } 196 } else if (num_contours == -1) { 197 // Composite glyph. 198 if (!ReadCompositeGlyphData(&buffer, glyph)) { 199 return FONT_COMPRESSION_FAILURE(); 200 } 201 // Read the instructions. 202 if (glyph->have_instructions) { 203 if (!buffer.ReadU16(&glyph->instructions_size)) { 204 return FONT_COMPRESSION_FAILURE(); 205 } 206 glyph->instructions_data = data + buffer.offset(); 207 if (!buffer.Skip(glyph->instructions_size)) { 208 return FONT_COMPRESSION_FAILURE(); 209 } 210 } else { 211 glyph->instructions_size = 0; 212 } 213 } else { 214 return FONT_COMPRESSION_FAILURE(); 215 } 216 return true; 217 } 218 219 namespace { 220 221 void StoreBbox(const Glyph& glyph, size_t* offset, uint8_t* dst) { 222 Store16(glyph.x_min, offset, dst); 223 Store16(glyph.y_min, offset, dst); 224 Store16(glyph.x_max, offset, dst); 225 Store16(glyph.y_max, offset, dst); 226 } 227 228 void StoreInstructions(const Glyph& glyph, size_t* offset, uint8_t* dst) { 229 Store16(glyph.instructions_size, offset, dst); 230 StoreBytes(glyph.instructions_data, glyph.instructions_size, offset, dst); 231 } 232 233 bool StoreEndPtsOfContours(const Glyph& glyph, size_t* offset, uint8_t* dst) { 234 int end_point = -1; 235 for (const auto& contour : glyph.contours) { 236 end_point += contour.size(); 237 if (contour.size() > std::numeric_limits<uint16_t>::max() || 238 end_point > std::numeric_limits<uint16_t>::max()) { 239 return FONT_COMPRESSION_FAILURE(); 240 } 241 Store16(end_point, offset, dst); 242 } 243 return true; 244 } 245 246 bool StorePoints(const Glyph& glyph, size_t* offset, 247 uint8_t* dst, size_t dst_size) { 248 int last_flag = -1; 249 int repeat_count = 0; 250 int last_x = 0; 251 int last_y = 0; 252 size_t x_bytes = 0; 253 size_t y_bytes = 0; 254 255 // Store the flags and calculate the total size of the x and y coordinates. 256 for (const auto& contour : glyph.contours) { 257 for (const auto& point : contour) { 258 int flag = point.on_curve ? kFLAG_ONCURVE : 0; 259 int dx = point.x - last_x; 260 int dy = point.y - last_y; 261 if (dx == 0) { 262 flag |= kFLAG_XREPEATSIGN; 263 } else if (dx > -256 && dx < 256) { 264 flag |= kFLAG_XSHORT | (dx > 0 ? kFLAG_XREPEATSIGN : 0); 265 x_bytes += 1; 266 } else { 267 x_bytes += 2; 268 } 269 if (dy == 0) { 270 flag |= kFLAG_YREPEATSIGN; 271 } else if (dy > -256 && dy < 256) { 272 flag |= kFLAG_YSHORT | (dy > 0 ? kFLAG_YREPEATSIGN : 0); 273 y_bytes += 1; 274 } else { 275 y_bytes += 2; 276 } 277 if (flag == last_flag && repeat_count != 255) { 278 dst[*offset - 1] |= kFLAG_REPEAT; 279 repeat_count++; 280 } else { 281 if (repeat_count != 0) { 282 if (*offset >= dst_size) { 283 return FONT_COMPRESSION_FAILURE(); 284 } 285 dst[(*offset)++] = repeat_count; 286 } 287 if (*offset >= dst_size) { 288 return FONT_COMPRESSION_FAILURE(); 289 } 290 dst[(*offset)++] = flag; 291 repeat_count = 0; 292 } 293 last_x = point.x; 294 last_y = point.y; 295 last_flag = flag; 296 } 297 } 298 if (repeat_count != 0) { 299 if (*offset >= dst_size) { 300 return FONT_COMPRESSION_FAILURE(); 301 } 302 dst[(*offset)++] = repeat_count; 303 } 304 305 if (*offset + x_bytes + y_bytes > dst_size) { 306 return FONT_COMPRESSION_FAILURE(); 307 } 308 309 // Store the x and y coordinates. 310 size_t x_offset = *offset; 311 size_t y_offset = *offset + x_bytes; 312 last_x = 0; 313 last_y = 0; 314 for (const auto& contour : glyph.contours) { 315 for (const auto& point : contour) { 316 int dx = point.x - last_x; 317 int dy = point.y - last_y; 318 if (dx == 0) { 319 // pass 320 } else if (dx > -256 && dx < 256) { 321 dst[x_offset++] = std::abs(dx); 322 } else { 323 Store16(dx, &x_offset, dst); 324 } 325 if (dy == 0) { 326 // pass 327 } else if (dy > -256 && dy < 256) { 328 dst[y_offset++] = std::abs(dy); 329 } else { 330 Store16(dy, &y_offset, dst); 331 } 332 last_x += dx; 333 last_y += dy; 334 } 335 } 336 *offset = y_offset; 337 return true; 338 } 339 340 } // namespace 341 342 bool StoreGlyph(const Glyph& glyph, uint8_t* dst, size_t* dst_size) { 343 size_t offset = 0; 344 if (glyph.composite_data_size > 0) { 345 // Composite glyph. 346 if (*dst_size < ((10ULL + glyph.composite_data_size) + 347 ((glyph.have_instructions ? 2ULL : 0) + 348 glyph.instructions_size))) { 349 return FONT_COMPRESSION_FAILURE(); 350 } 351 Store16(-1, &offset, dst); 352 StoreBbox(glyph, &offset, dst); 353 StoreBytes(glyph.composite_data, glyph.composite_data_size, &offset, dst); 354 if (glyph.have_instructions) { 355 StoreInstructions(glyph, &offset, dst); 356 } 357 } else if (glyph.contours.size() > 0) { 358 // Simple glyph. 359 if (glyph.contours.size() > std::numeric_limits<int16_t>::max()) { 360 return FONT_COMPRESSION_FAILURE(); 361 } 362 if (*dst_size < ((12ULL + 2 * glyph.contours.size()) + 363 glyph.instructions_size)) { 364 return FONT_COMPRESSION_FAILURE(); 365 } 366 Store16(glyph.contours.size(), &offset, dst); 367 StoreBbox(glyph, &offset, dst); 368 if (!StoreEndPtsOfContours(glyph, &offset, dst)) { 369 return FONT_COMPRESSION_FAILURE(); 370 } 371 StoreInstructions(glyph, &offset, dst); 372 if (!StorePoints(glyph, &offset, dst, *dst_size)) { 373 return FONT_COMPRESSION_FAILURE(); 374 } 375 } 376 *dst_size = offset; 377 return true; 378 } 379 380 } // namespace woff2 381