PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/gfx/ots/src/gdef.cc

http://github.com/zpao/v8monkey
C++ | 393 lines | 326 code | 42 blank | 25 comment | 89 complexity | 874b466ed83df5ef336e83aba35cf565 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD
  1. // Copyright (c) 2011 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "gdef.h"
  5. #include <limits>
  6. #include <vector>
  7. #include "gpos.h"
  8. #include "gsub.h"
  9. #include "layout.h"
  10. #include "maxp.h"
  11. // GDEF - The Glyph Definition Table
  12. // http://www.microsoft.com/typography/otspec/gdef.htm
  13. namespace {
  14. // The maximum class value in class definition tables.
  15. const uint16_t kMaxClassDefValue = 0xFFFF;
  16. // The maximum class value in the glyph class definision table.
  17. const uint16_t kMaxGlyphClassDefValue = 4;
  18. // The maximum format number of caret value tables.
  19. // We don't support format 3 for now. See the comment in
  20. // ParseLigCaretListTable() for the reason.
  21. const uint16_t kMaxCaretValueFormat = 2;
  22. bool ParseGlyphClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
  23. size_t length, const uint16_t num_glyphs) {
  24. return ots::ParseClassDefTable(data, length, num_glyphs,
  25. kMaxGlyphClassDefValue);
  26. }
  27. bool ParseAttachListTable(ots::OpenTypeFile *file, const uint8_t *data,
  28. size_t length, const uint16_t num_glyphs) {
  29. ots::Buffer subtable(data, length);
  30. uint16_t offset_coverage = 0;
  31. uint16_t glyph_count = 0;
  32. if (!subtable.ReadU16(&offset_coverage) ||
  33. !subtable.ReadU16(&glyph_count)) {
  34. return OTS_FAILURE();
  35. }
  36. const unsigned attach_points_end =
  37. 2 * static_cast<unsigned>(glyph_count) + 4;
  38. if (attach_points_end > std::numeric_limits<uint16_t>::max()) {
  39. return OTS_FAILURE();
  40. }
  41. if (offset_coverage == 0 || offset_coverage >= length ||
  42. offset_coverage < attach_points_end) {
  43. return OTS_FAILURE();
  44. }
  45. if (glyph_count > num_glyphs) {
  46. OTS_WARNING("bad glyph count: %u", glyph_count);
  47. return OTS_FAILURE();
  48. }
  49. std::vector<uint16_t> attach_points;
  50. attach_points.resize(glyph_count);
  51. for (unsigned i = 0; i < glyph_count; ++i) {
  52. if (!subtable.ReadU16(&attach_points[i])) {
  53. return OTS_FAILURE();
  54. }
  55. if (attach_points[i] >= length ||
  56. attach_points[i] < attach_points_end) {
  57. return OTS_FAILURE();
  58. }
  59. }
  60. // Parse coverage table
  61. if (!ots::ParseCoverageTable(data + offset_coverage,
  62. length - offset_coverage, num_glyphs)) {
  63. return OTS_FAILURE();
  64. }
  65. // Parse attach point table
  66. for (unsigned i = 0; i < attach_points.size(); ++i) {
  67. subtable.set_offset(attach_points[i]);
  68. uint16_t point_count = 0;
  69. if (!subtable.ReadU16(&point_count)) {
  70. return OTS_FAILURE();
  71. }
  72. if (point_count == 0) {
  73. return OTS_FAILURE();
  74. }
  75. uint16_t last_point_index = 0;
  76. uint16_t point_index = 0;
  77. for (unsigned j = 0; j < point_count; ++j) {
  78. if (!subtable.ReadU16(&point_index)) {
  79. return OTS_FAILURE();
  80. }
  81. // Contour point indeces are in increasing numerical order
  82. if (last_point_index != 0 && last_point_index >= point_index) {
  83. OTS_WARNING("bad contour indeces: %u >= %u",
  84. last_point_index, point_index);
  85. return OTS_FAILURE();
  86. }
  87. last_point_index = point_index;
  88. }
  89. }
  90. return true;
  91. }
  92. bool ParseLigCaretListTable(ots::OpenTypeFile *file, const uint8_t *data,
  93. size_t length, const uint16_t num_glyphs) {
  94. ots::Buffer subtable(data, length);
  95. uint16_t offset_coverage = 0;
  96. uint16_t lig_glyph_count = 0;
  97. if (!subtable.ReadU16(&offset_coverage) ||
  98. !subtable.ReadU16(&lig_glyph_count)) {
  99. return OTS_FAILURE();
  100. }
  101. const unsigned lig_glyphs_end =
  102. 2 * static_cast<unsigned>(lig_glyph_count) + 4;
  103. if (lig_glyphs_end > std::numeric_limits<uint16_t>::max()) {
  104. return OTS_FAILURE();
  105. }
  106. if (offset_coverage == 0 || offset_coverage >= length ||
  107. offset_coverage < lig_glyphs_end) {
  108. return OTS_FAILURE();
  109. }
  110. if (lig_glyph_count > num_glyphs) {
  111. OTS_WARNING("bad ligature glyph count: %u", lig_glyph_count);
  112. return OTS_FAILURE();
  113. }
  114. std::vector<uint16_t> lig_glyphs;
  115. lig_glyphs.resize(lig_glyph_count);
  116. for (unsigned i = 0; i < lig_glyph_count; ++i) {
  117. if (!subtable.ReadU16(&lig_glyphs[i])) {
  118. return OTS_FAILURE();
  119. }
  120. if (lig_glyphs[i] >= length || lig_glyphs[i] < lig_glyphs_end) {
  121. return OTS_FAILURE();
  122. }
  123. }
  124. // Parse coverage table
  125. if (!ots::ParseCoverageTable(data + offset_coverage,
  126. length - offset_coverage, num_glyphs)) {
  127. return OTS_FAILURE();
  128. }
  129. // Parse ligature glyph table
  130. for (unsigned i = 0; i < lig_glyphs.size(); ++i) {
  131. subtable.set_offset(lig_glyphs[i]);
  132. uint16_t caret_count = 0;
  133. if (!subtable.ReadU16(&caret_count)) {
  134. return OTS_FAILURE();
  135. }
  136. if (caret_count == 0) {
  137. OTS_WARNING("bad caret value count: %u", caret_count);
  138. return OTS_FAILURE();
  139. }
  140. std::vector<uint16_t> caret_values;
  141. caret_values.resize(caret_count);
  142. uint16_t last_offset_caret = 0;
  143. unsigned caret_values_end = 2 * static_cast<unsigned>(caret_count) + 2;
  144. for (unsigned j = 0; j < caret_count; ++j) {
  145. if (!subtable.ReadU16(&caret_values[j])) {
  146. return OTS_FAILURE();
  147. }
  148. if (caret_values[j] >= length || caret_values[j] < caret_values_end) {
  149. return OTS_FAILURE();
  150. }
  151. // Caret offsets are in increasing coordinate order
  152. if (last_offset_caret != 0 && last_offset_caret >= caret_values[j]) {
  153. OTS_WARNING("offset isn't in increasing coordinate order: %u >= %u",
  154. last_offset_caret, caret_values[j]);
  155. return OTS_FAILURE();
  156. }
  157. last_offset_caret = caret_values[j];
  158. }
  159. // Parse caret values table
  160. for (unsigned j = 0; j < caret_count; ++j) {
  161. subtable.set_offset(lig_glyphs[i] + caret_values[j]);
  162. uint16_t caret_format = 0;
  163. if (!subtable.ReadU16(&caret_format)) {
  164. return OTS_FAILURE();
  165. }
  166. // TODO(bashi): We only support caret value format 1 and 2 for now
  167. // because there are no fonts which contain caret value format 3
  168. // as far as we investigated.
  169. if (caret_format == 0 || caret_format > kMaxCaretValueFormat) {
  170. OTS_WARNING("bad caret value format: %u", caret_format);
  171. return OTS_FAILURE();
  172. }
  173. // CaretValueFormats contain a 2-byte field which could be
  174. // arbitrary value.
  175. if (!subtable.Skip(2)) {
  176. return OTS_FAILURE();
  177. }
  178. }
  179. }
  180. return true;
  181. }
  182. bool ParseMarkAttachClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
  183. size_t length, const uint16_t num_glyphs) {
  184. return ots::ParseClassDefTable(data, length, num_glyphs, kMaxClassDefValue);
  185. }
  186. bool ParseMarkGlyphSetsDefTable(ots::OpenTypeFile *file, const uint8_t *data,
  187. size_t length, const uint16_t num_glyphs) {
  188. ots::Buffer subtable(data, length);
  189. uint16_t format = 0;
  190. uint16_t mark_set_count = 0;
  191. if (!subtable.ReadU16(&format) ||
  192. !subtable.ReadU16(&mark_set_count)) {
  193. return OTS_FAILURE();
  194. }
  195. if (format != 1) {
  196. OTS_WARNING("bad mark glyph set table format: %u", format);
  197. return OTS_FAILURE();
  198. }
  199. const unsigned mark_sets_end = 2 * static_cast<unsigned>(mark_set_count) + 4;
  200. if (mark_sets_end > std::numeric_limits<uint16_t>::max()) {
  201. return OTS_FAILURE();
  202. }
  203. for (unsigned i = 0; i < mark_set_count; ++i) {
  204. uint32_t offset_coverage = 0;
  205. if (!subtable.ReadU32(&offset_coverage)) {
  206. return OTS_FAILURE();
  207. }
  208. if (offset_coverage >= length ||
  209. offset_coverage < mark_sets_end) {
  210. return OTS_FAILURE();
  211. }
  212. if (!ots::ParseCoverageTable(data + offset_coverage,
  213. length - offset_coverage, num_glyphs)) {
  214. return OTS_FAILURE();
  215. }
  216. }
  217. file->gdef->num_mark_glyph_sets = mark_set_count;
  218. return true;
  219. }
  220. } // namespace
  221. #define DROP_THIS_TABLE \
  222. do { file->gdef->data = 0; file->gdef->length = 0; } while (0)
  223. namespace ots {
  224. bool ots_gdef_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
  225. // Grab the number of glyphs in the file from the maxp table to check
  226. // GlyphIDs in GDEF table.
  227. if (!file->maxp) {
  228. return OTS_FAILURE();
  229. }
  230. const uint16_t num_glyphs = file->maxp->num_glyphs;
  231. Buffer table(data, length);
  232. OpenTypeGDEF *gdef = new OpenTypeGDEF;
  233. file->gdef = gdef;
  234. uint32_t version = 0;
  235. if (!table.ReadU32(&version)) {
  236. return OTS_FAILURE();
  237. }
  238. if (version < 0x00010000 || version == 0x00010001) {
  239. OTS_WARNING("bad GDEF version");
  240. DROP_THIS_TABLE;
  241. return true;
  242. }
  243. if (version >= 0x00010002) {
  244. gdef->version_2 = true;
  245. }
  246. uint16_t offset_glyph_class_def = 0;
  247. uint16_t offset_attach_list = 0;
  248. uint16_t offset_lig_caret_list = 0;
  249. uint16_t offset_mark_attach_class_def = 0;
  250. if (!table.ReadU16(&offset_glyph_class_def) ||
  251. !table.ReadU16(&offset_attach_list) ||
  252. !table.ReadU16(&offset_lig_caret_list) ||
  253. !table.ReadU16(&offset_mark_attach_class_def)) {
  254. return OTS_FAILURE();
  255. }
  256. uint16_t offset_mark_glyph_sets_def = 0;
  257. if (gdef->version_2) {
  258. if (!table.ReadU16(&offset_mark_glyph_sets_def)) {
  259. return OTS_FAILURE();
  260. }
  261. }
  262. unsigned gdef_header_end = 8;
  263. if (gdef->version_2)
  264. gdef_header_end += 2;
  265. // Parse subtables
  266. if (offset_glyph_class_def) {
  267. if (offset_glyph_class_def >= length ||
  268. offset_glyph_class_def < gdef_header_end) {
  269. return OTS_FAILURE();
  270. }
  271. if (!ParseGlyphClassDefTable(file, data + offset_glyph_class_def,
  272. length - offset_glyph_class_def,
  273. num_glyphs)) {
  274. DROP_THIS_TABLE;
  275. return true;
  276. }
  277. gdef->has_glyph_class_def = true;
  278. }
  279. if (offset_attach_list) {
  280. if (offset_attach_list >= length ||
  281. offset_attach_list < gdef_header_end) {
  282. return OTS_FAILURE();
  283. }
  284. if (!ParseAttachListTable(file, data + offset_attach_list,
  285. length - offset_attach_list,
  286. num_glyphs)) {
  287. DROP_THIS_TABLE;
  288. return true;
  289. }
  290. }
  291. if (offset_lig_caret_list) {
  292. if (offset_lig_caret_list >= length ||
  293. offset_lig_caret_list < gdef_header_end) {
  294. return OTS_FAILURE();
  295. }
  296. if (!ParseLigCaretListTable(file, data + offset_lig_caret_list,
  297. length - offset_lig_caret_list,
  298. num_glyphs)) {
  299. DROP_THIS_TABLE;
  300. return true;
  301. }
  302. }
  303. if (offset_mark_attach_class_def) {
  304. if (offset_mark_attach_class_def >= length ||
  305. offset_mark_attach_class_def < gdef_header_end) {
  306. return OTS_FAILURE();
  307. }
  308. if (!ParseMarkAttachClassDefTable(file,
  309. data + offset_mark_attach_class_def,
  310. length - offset_mark_attach_class_def,
  311. num_glyphs)) {
  312. DROP_THIS_TABLE;
  313. return true;
  314. }
  315. gdef->has_mark_attachment_class_def = true;
  316. }
  317. if (offset_mark_glyph_sets_def) {
  318. if (offset_mark_glyph_sets_def >= length ||
  319. offset_mark_glyph_sets_def < gdef_header_end) {
  320. return OTS_FAILURE();
  321. }
  322. if (!ParseMarkGlyphSetsDefTable(file,
  323. data + offset_mark_glyph_sets_def,
  324. length - offset_mark_glyph_sets_def,
  325. num_glyphs)) {
  326. DROP_THIS_TABLE;
  327. return true;
  328. }
  329. gdef->has_mark_glyph_sets_def = true;
  330. }
  331. gdef->data = data;
  332. gdef->length = length;
  333. return true;
  334. }
  335. bool ots_gdef_should_serialise(OpenTypeFile *file) {
  336. const bool needed_tables_dropped =
  337. (file->gsub && file->gsub->data == NULL) ||
  338. (file->gpos && file->gpos->data == NULL);
  339. return file->gdef != NULL && file->gdef->data != NULL &&
  340. !needed_tables_dropped;
  341. }
  342. bool ots_gdef_serialise(OTSStream *out, OpenTypeFile *file) {
  343. if (!out->Write(file->gdef->data, file->gdef->length)) {
  344. return OTS_FAILURE();
  345. }
  346. return true;
  347. }
  348. void ots_gdef_free(OpenTypeFile *file) {
  349. delete file->gdef;
  350. }
  351. } // namespace ots