glyph.cc 11 KB

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