PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/gfx/harfbuzz/src/hb-ot-layout-common-private.hh

https://bitbucket.org/MeeGoAdmin/mozilla-central/
C++ Header | 604 lines | 432 code | 99 blank | 73 comment | 50 complexity | 503943949fc8c8cc1437d260e2ce0f60 MD5 | raw file
Possible License(s): AGPL-1.0, MIT, BSD-3-Clause, Apache-2.0, LGPL-2.1, 0BSD, LGPL-3.0, MPL-2.0-no-copyleft-exception, GPL-2.0, JSON
  1. /*
  2. * Copyright (C) 2007,2008,2009 Red Hat, Inc.
  3. * Copyright (C) 2010 Google, Inc.
  4. *
  5. * This is part of HarfBuzz, a text shaping library.
  6. *
  7. * Permission is hereby granted, without written agreement and without
  8. * license or royalty fees, to use, copy, modify, and distribute this
  9. * software and its documentation for any purpose, provided that the
  10. * above copyright notice and the following two paragraphs appear in
  11. * all copies of this software.
  12. *
  13. * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  14. * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  15. * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  16. * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  17. * DAMAGE.
  18. *
  19. * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  20. * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  21. * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
  22. * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  23. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  24. *
  25. * Red Hat Author(s): Behdad Esfahbod
  26. * Google Author(s): Behdad Esfahbod
  27. */
  28. #ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
  29. #define HB_OT_LAYOUT_COMMON_PRIVATE_HH
  30. #include "hb-ot-layout-private.hh"
  31. #include "hb-open-type-private.hh"
  32. #define NO_CONTEXT ((unsigned int) 0x110000)
  33. #define NOT_COVERED ((unsigned int) 0x110000)
  34. #define MAX_NESTING_LEVEL 8
  35. HB_BEGIN_DECLS
  36. HB_END_DECLS
  37. /*
  38. *
  39. * OpenType Layout Common Table Formats
  40. *
  41. */
  42. /*
  43. * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
  44. */
  45. template <typename Type>
  46. struct Record
  47. {
  48. inline int cmp (hb_tag_t a) const {
  49. return tag.cmp (a);
  50. }
  51. inline bool sanitize (hb_sanitize_context_t *c, void *base) {
  52. TRACE_SANITIZE ();
  53. return c->check_struct (this)
  54. && offset.sanitize (c, base);
  55. }
  56. Tag tag; /* 4-byte Tag identifier */
  57. OffsetTo<Type>
  58. offset; /* Offset from beginning of object holding
  59. * the Record */
  60. public:
  61. DEFINE_SIZE_STATIC (6);
  62. };
  63. template <typename Type>
  64. struct RecordArrayOf : SortedArrayOf<Record<Type> > {
  65. inline const Tag& get_tag (unsigned int i) const
  66. {
  67. /* We cheat slightly and don't define separate Null objects
  68. * for Record types. Instead, we return the correct Null(Tag)
  69. * here. */
  70. if (unlikely (i >= this->len)) return Null(Tag);
  71. return (*this)[i].tag;
  72. }
  73. inline unsigned int get_tags (unsigned int start_offset,
  74. unsigned int *record_count /* IN/OUT */,
  75. hb_tag_t *record_tags /* OUT */) const
  76. {
  77. if (record_count) {
  78. const Record<Type> *array = this->sub_array (start_offset, record_count);
  79. unsigned int count = *record_count;
  80. for (unsigned int i = 0; i < count; i++)
  81. record_tags[i] = array[i].tag;
  82. }
  83. return this->len;
  84. }
  85. inline bool find_index (hb_tag_t tag, unsigned int *index) const
  86. {
  87. int i = this->search (tag);
  88. if (i != -1) {
  89. if (index) *index = i;
  90. return true;
  91. } else {
  92. if (index) *index = Index::NOT_FOUND_INDEX;
  93. return false;
  94. }
  95. }
  96. };
  97. template <typename Type>
  98. struct RecordListOf : RecordArrayOf<Type>
  99. {
  100. inline const Type& operator [] (unsigned int i) const
  101. { return this+RecordArrayOf<Type>::operator [](i).offset; }
  102. inline bool sanitize (hb_sanitize_context_t *c) {
  103. TRACE_SANITIZE ();
  104. return RecordArrayOf<Type>::sanitize (c, this);
  105. }
  106. };
  107. struct RangeRecord
  108. {
  109. inline int cmp (hb_codepoint_t g) const {
  110. hb_codepoint_t a = start, b = end;
  111. return g < a ? -1 : g <= b ? 0 : +1 ;
  112. }
  113. inline bool sanitize (hb_sanitize_context_t *c) {
  114. TRACE_SANITIZE ();
  115. return c->check_struct (this);
  116. }
  117. GlyphID start; /* First GlyphID in the range */
  118. GlyphID end; /* Last GlyphID in the range */
  119. USHORT value; /* Value */
  120. public:
  121. DEFINE_SIZE_STATIC (6);
  122. };
  123. DEFINE_NULL_DATA (RangeRecord, "\000\001");
  124. struct IndexArray : ArrayOf<Index>
  125. {
  126. inline unsigned int get_indexes (unsigned int start_offset,
  127. unsigned int *_count /* IN/OUT */,
  128. unsigned int *_indexes /* OUT */) const
  129. {
  130. if (_count) {
  131. const USHORT *array = this->sub_array (start_offset, _count);
  132. unsigned int count = *_count;
  133. for (unsigned int i = 0; i < count; i++)
  134. _indexes[i] = array[i];
  135. }
  136. return this->len;
  137. }
  138. };
  139. struct Script;
  140. struct LangSys;
  141. struct Feature;
  142. struct LangSys
  143. {
  144. inline unsigned int get_feature_count (void) const
  145. { return featureIndex.len; }
  146. inline hb_tag_t get_feature_index (unsigned int i) const
  147. { return featureIndex[i]; }
  148. inline unsigned int get_feature_indexes (unsigned int start_offset,
  149. unsigned int *feature_count /* IN/OUT */,
  150. unsigned int *feature_indexes /* OUT */) const
  151. { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
  152. inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
  153. inline unsigned int get_required_feature_index (void) const
  154. {
  155. if (reqFeatureIndex == 0xffff)
  156. return Index::NOT_FOUND_INDEX;
  157. return reqFeatureIndex;;
  158. }
  159. inline bool sanitize (hb_sanitize_context_t *c) {
  160. TRACE_SANITIZE ();
  161. return c->check_struct (this)
  162. && featureIndex.sanitize (c);
  163. }
  164. Offset lookupOrder; /* = Null (reserved for an offset to a
  165. * reordering table) */
  166. USHORT reqFeatureIndex;/* Index of a feature required for this
  167. * language system--if no required features
  168. * = 0xFFFF */
  169. IndexArray featureIndex; /* Array of indices into the FeatureList */
  170. public:
  171. DEFINE_SIZE_ARRAY (6, featureIndex);
  172. };
  173. DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
  174. struct Script
  175. {
  176. inline unsigned int get_lang_sys_count (void) const
  177. { return langSys.len; }
  178. inline const Tag& get_lang_sys_tag (unsigned int i) const
  179. { return langSys.get_tag (i); }
  180. inline unsigned int get_lang_sys_tags (unsigned int start_offset,
  181. unsigned int *lang_sys_count /* IN/OUT */,
  182. hb_tag_t *lang_sys_tags /* OUT */) const
  183. { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
  184. inline const LangSys& get_lang_sys (unsigned int i) const
  185. {
  186. if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
  187. return this+langSys[i].offset;
  188. }
  189. inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
  190. { return langSys.find_index (tag, index); }
  191. inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
  192. inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
  193. inline bool sanitize (hb_sanitize_context_t *c) {
  194. TRACE_SANITIZE ();
  195. return defaultLangSys.sanitize (c, this)
  196. && langSys.sanitize (c, this);
  197. }
  198. private:
  199. OffsetTo<LangSys>
  200. defaultLangSys; /* Offset to DefaultLangSys table--from
  201. * beginning of Script table--may be Null */
  202. RecordArrayOf<LangSys>
  203. langSys; /* Array of LangSysRecords--listed
  204. * alphabetically by LangSysTag */
  205. public:
  206. DEFINE_SIZE_ARRAY (4, langSys);
  207. };
  208. typedef RecordListOf<Script> ScriptList;
  209. struct Feature
  210. {
  211. inline unsigned int get_lookup_count (void) const
  212. { return lookupIndex.len; }
  213. inline hb_tag_t get_lookup_index (unsigned int i) const
  214. { return lookupIndex[i]; }
  215. inline unsigned int get_lookup_indexes (unsigned int start_index,
  216. unsigned int *lookup_count /* IN/OUT */,
  217. unsigned int *lookup_tags /* OUT */) const
  218. { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
  219. inline bool sanitize (hb_sanitize_context_t *c) {
  220. TRACE_SANITIZE ();
  221. return c->check_struct (this)
  222. && lookupIndex.sanitize (c);
  223. }
  224. Offset featureParams; /* Offset to Feature Parameters table (if one
  225. * has been defined for the feature), relative
  226. * to the beginning of the Feature Table; = Null
  227. * if not required */
  228. IndexArray lookupIndex; /* Array of LookupList indices */
  229. public:
  230. DEFINE_SIZE_ARRAY (4, lookupIndex);
  231. };
  232. typedef RecordListOf<Feature> FeatureList;
  233. struct LookupFlag : USHORT
  234. {
  235. enum {
  236. RightToLeft = 0x0001u,
  237. IgnoreBaseGlyphs = 0x0002u,
  238. IgnoreLigatures = 0x0004u,
  239. IgnoreMarks = 0x0008u,
  240. IgnoreFlags = 0x000Eu,
  241. UseMarkFilteringSet = 0x0010u,
  242. Reserved = 0x00E0u,
  243. MarkAttachmentType = 0xFF00u
  244. };
  245. public:
  246. DEFINE_SIZE_STATIC (2);
  247. };
  248. struct Lookup
  249. {
  250. inline unsigned int get_subtable_count (void) const { return subTable.len; }
  251. inline unsigned int get_type (void) const { return lookupType; }
  252. /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
  253. * higher 16-bit is mark-filtering-set if the lookup uses one.
  254. * Not to be confused with glyph_props which is very similar. */
  255. inline uint32_t get_props (void) const
  256. {
  257. unsigned int flag = lookupFlag;
  258. if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
  259. {
  260. const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
  261. flag += (markFilteringSet << 16);
  262. }
  263. return flag;
  264. }
  265. inline bool sanitize (hb_sanitize_context_t *c) {
  266. TRACE_SANITIZE ();
  267. /* Real sanitize of the subtables is done by GSUB/GPOS/... */
  268. if (!(c->check_struct (this)
  269. && subTable.sanitize (c))) return false;
  270. if (unlikely (lookupFlag & LookupFlag::UseMarkFilteringSet))
  271. {
  272. USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
  273. if (!markFilteringSet.sanitize (c)) return false;
  274. }
  275. return true;
  276. }
  277. USHORT lookupType; /* Different enumerations for GSUB and GPOS */
  278. USHORT lookupFlag; /* Lookup qualifiers */
  279. ArrayOf<Offset>
  280. subTable; /* Array of SubTables */
  281. USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
  282. * structure. This field is only present if bit
  283. * UseMarkFilteringSet of lookup flags is set. */
  284. public:
  285. DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
  286. };
  287. typedef OffsetListOf<Lookup> LookupList;
  288. /*
  289. * Coverage Table
  290. */
  291. struct CoverageFormat1
  292. {
  293. friend struct Coverage;
  294. private:
  295. inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
  296. {
  297. int i = glyphArray.search (glyph_id);
  298. if (i != -1)
  299. return i;
  300. return NOT_COVERED;
  301. }
  302. inline bool sanitize (hb_sanitize_context_t *c) {
  303. TRACE_SANITIZE ();
  304. return glyphArray.sanitize (c);
  305. }
  306. private:
  307. USHORT coverageFormat; /* Format identifier--format = 1 */
  308. SortedArrayOf<GlyphID>
  309. glyphArray; /* Array of GlyphIDs--in numerical order */
  310. public:
  311. DEFINE_SIZE_ARRAY (4, glyphArray);
  312. };
  313. struct CoverageFormat2
  314. {
  315. friend struct Coverage;
  316. private:
  317. inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
  318. {
  319. int i = rangeRecord.search (glyph_id);
  320. if (i != -1) {
  321. const RangeRecord &range = rangeRecord[i];
  322. return (unsigned int) range.value + (glyph_id - range.start);
  323. }
  324. return NOT_COVERED;
  325. }
  326. inline bool sanitize (hb_sanitize_context_t *c) {
  327. TRACE_SANITIZE ();
  328. return rangeRecord.sanitize (c);
  329. }
  330. private:
  331. USHORT coverageFormat; /* Format identifier--format = 2 */
  332. SortedArrayOf<RangeRecord>
  333. rangeRecord; /* Array of glyph ranges--ordered by
  334. * Start GlyphID. rangeCount entries
  335. * long */
  336. public:
  337. DEFINE_SIZE_ARRAY (4, rangeRecord);
  338. };
  339. struct Coverage
  340. {
  341. inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_coverage (glyph_id); }
  342. inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
  343. {
  344. switch (u.format) {
  345. case 1: return u.format1.get_coverage(glyph_id);
  346. case 2: return u.format2.get_coverage(glyph_id);
  347. default:return NOT_COVERED;
  348. }
  349. }
  350. inline bool sanitize (hb_sanitize_context_t *c) {
  351. TRACE_SANITIZE ();
  352. if (!u.format.sanitize (c)) return false;
  353. switch (u.format) {
  354. case 1: return u.format1.sanitize (c);
  355. case 2: return u.format2.sanitize (c);
  356. default:return true;
  357. }
  358. }
  359. private:
  360. union {
  361. USHORT format; /* Format identifier */
  362. CoverageFormat1 format1;
  363. CoverageFormat2 format2;
  364. } u;
  365. public:
  366. DEFINE_SIZE_UNION (2, format);
  367. };
  368. /*
  369. * Class Definition Table
  370. */
  371. struct ClassDefFormat1
  372. {
  373. friend struct ClassDef;
  374. private:
  375. inline unsigned int get_class (hb_codepoint_t glyph_id) const
  376. {
  377. if ((unsigned int) (glyph_id - startGlyph) < classValue.len)
  378. return classValue[glyph_id - startGlyph];
  379. return 0;
  380. }
  381. inline bool sanitize (hb_sanitize_context_t *c) {
  382. TRACE_SANITIZE ();
  383. return c->check_struct (this)
  384. && classValue.sanitize (c);
  385. }
  386. USHORT classFormat; /* Format identifier--format = 1 */
  387. GlyphID startGlyph; /* First GlyphID of the classValueArray */
  388. ArrayOf<USHORT>
  389. classValue; /* Array of Class Values--one per GlyphID */
  390. public:
  391. DEFINE_SIZE_ARRAY (6, classValue);
  392. };
  393. struct ClassDefFormat2
  394. {
  395. friend struct ClassDef;
  396. private:
  397. inline unsigned int get_class (hb_codepoint_t glyph_id) const
  398. {
  399. int i = rangeRecord.search (glyph_id);
  400. if (i != -1)
  401. return rangeRecord[i].value;
  402. return 0;
  403. }
  404. inline bool sanitize (hb_sanitize_context_t *c) {
  405. TRACE_SANITIZE ();
  406. return rangeRecord.sanitize (c);
  407. }
  408. USHORT classFormat; /* Format identifier--format = 2 */
  409. SortedArrayOf<RangeRecord>
  410. rangeRecord; /* Array of glyph ranges--ordered by
  411. * Start GlyphID */
  412. public:
  413. DEFINE_SIZE_ARRAY (4, rangeRecord);
  414. };
  415. struct ClassDef
  416. {
  417. inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_class (glyph_id); }
  418. inline unsigned int get_class (hb_codepoint_t glyph_id) const
  419. {
  420. switch (u.format) {
  421. case 1: return u.format1.get_class(glyph_id);
  422. case 2: return u.format2.get_class(glyph_id);
  423. default:return 0;
  424. }
  425. }
  426. inline bool sanitize (hb_sanitize_context_t *c) {
  427. TRACE_SANITIZE ();
  428. if (!u.format.sanitize (c)) return false;
  429. switch (u.format) {
  430. case 1: return u.format1.sanitize (c);
  431. case 2: return u.format2.sanitize (c);
  432. default:return true;
  433. }
  434. }
  435. private:
  436. union {
  437. USHORT format; /* Format identifier */
  438. ClassDefFormat1 format1;
  439. ClassDefFormat2 format2;
  440. } u;
  441. public:
  442. DEFINE_SIZE_UNION (2, format);
  443. };
  444. /*
  445. * Device Tables
  446. */
  447. struct Device
  448. {
  449. inline hb_position_t get_x_delta (hb_ot_layout_context_t *c) const
  450. { return get_delta (c->font->x_ppem, c->font->x_scale); }
  451. inline hb_position_t get_y_delta (hb_ot_layout_context_t *c) const
  452. { return get_delta (c->font->y_ppem, c->font->y_scale); }
  453. inline int get_delta (unsigned int ppem, unsigned int scale) const
  454. {
  455. if (!ppem) return 0;
  456. int pixels = get_delta_pixels (ppem);
  457. if (!pixels) return 0;
  458. /* pixels is at most in the -8..7 range. So 64-bit arithmetic is
  459. * not really necessary here. A simple cast to int may just work
  460. * as well. But since this code is not reached that often and
  461. * for the sake of correctness, we do a 64bit operation. */
  462. return pixels * (int64_t) scale / ppem;
  463. }
  464. inline int get_delta_pixels (unsigned int ppem_size) const
  465. {
  466. unsigned int f = deltaFormat;
  467. if (unlikely (f < 1 || f > 3))
  468. return 0;
  469. if (ppem_size < startSize || ppem_size > endSize)
  470. return 0;
  471. unsigned int s = ppem_size - startSize;
  472. unsigned int byte = deltaValue[s >> (4 - f)];
  473. unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
  474. unsigned int mask = (0xFFFF >> (16 - (1 << f)));
  475. int delta = bits & mask;
  476. if ((unsigned int) delta >= ((mask + 1) >> 1))
  477. delta -= mask + 1;
  478. return delta;
  479. }
  480. inline unsigned int get_size (void) const
  481. {
  482. unsigned int f = deltaFormat;
  483. if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
  484. return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
  485. }
  486. inline bool sanitize (hb_sanitize_context_t *c) {
  487. TRACE_SANITIZE ();
  488. return c->check_struct (this)
  489. && c->check_range (this, this->get_size ());
  490. }
  491. private:
  492. USHORT startSize; /* Smallest size to correct--in ppem */
  493. USHORT endSize; /* Largest size to correct--in ppem */
  494. USHORT deltaFormat; /* Format of DeltaValue array data: 1, 2, or 3
  495. * 1 Signed 2-bit value, 8 values per uint16
  496. * 2 Signed 4-bit value, 4 values per uint16
  497. * 3 Signed 8-bit value, 2 values per uint16
  498. */
  499. USHORT deltaValue[VAR]; /* Array of compressed data */
  500. public:
  501. DEFINE_SIZE_ARRAY (6, deltaValue);
  502. };
  503. HB_BEGIN_DECLS
  504. HB_END_DECLS
  505. #endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */