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