hb-ot-hmtx-table.hh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. * Copyright © 2011,2012 Google, Inc.
  3. *
  4. * This is part of HarfBuzz, a text shaping library.
  5. *
  6. * Permission is hereby granted, without written agreement and without
  7. * license or royalty fees, to use, copy, modify, and distribute this
  8. * software and its documentation for any purpose, provided that the
  9. * above copyright notice and the following two paragraphs appear in
  10. * all copies of this software.
  11. *
  12. * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  13. * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  14. * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  15. * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  16. * DAMAGE.
  17. *
  18. * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  19. * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  20. * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
  21. * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  22. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  23. *
  24. * Google Author(s): Behdad Esfahbod, Roderick Sheeter
  25. */
  26. #ifndef HB_OT_HMTX_TABLE_HH
  27. #define HB_OT_HMTX_TABLE_HH
  28. #include "hb-open-type.hh"
  29. #include "hb-ot-maxp-table.hh"
  30. #include "hb-ot-hhea-table.hh"
  31. #include "hb-ot-var-hvar-table.hh"
  32. #include "hb-ot-metrics.hh"
  33. /*
  34. * hmtx -- Horizontal Metrics
  35. * https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx
  36. * vmtx -- Vertical Metrics
  37. * https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx
  38. */
  39. #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
  40. #define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
  41. HB_INTERNAL bool
  42. _glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical, int *lsb);
  43. HB_INTERNAL unsigned
  44. _glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
  45. namespace OT {
  46. struct LongMetric
  47. {
  48. UFWORD advance; /* Advance width/height. */
  49. FWORD sb; /* Leading (left/top) side bearing. */
  50. public:
  51. DEFINE_SIZE_STATIC (4);
  52. };
  53. template <typename T/*Data table type*/, typename H/*Header table type*/, typename V/*Var table type*/>
  54. struct hmtxvmtx
  55. {
  56. bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
  57. {
  58. TRACE_SANITIZE (this);
  59. /* We don't check for anything specific here. The users of the
  60. * struct do all the hard work... */
  61. return_trace (true);
  62. }
  63. const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>>* get_mtx_map (const hb_subset_plan_t *plan) const
  64. { return T::is_horizontal ? plan->hmtx_map : plan->vmtx_map; }
  65. bool subset_update_header (hb_subset_plan_t *plan,
  66. unsigned int num_hmetrics) const
  67. {
  68. hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
  69. hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
  70. hb_blob_destroy (src_blob);
  71. if (unlikely (!dest_blob)) {
  72. return false;
  73. }
  74. unsigned int length;
  75. H *table = (H *) hb_blob_get_data (dest_blob, &length);
  76. table->numberOfLongMetrics = num_hmetrics;
  77. bool result = plan->add_table (H::tableTag, dest_blob);
  78. hb_blob_destroy (dest_blob);
  79. return result;
  80. }
  81. template<typename Iterator,
  82. hb_requires (hb_is_iterator (Iterator))>
  83. void serialize (hb_serialize_context_t *c,
  84. Iterator it,
  85. unsigned num_long_metrics)
  86. {
  87. unsigned idx = 0;
  88. for (auto _ : it)
  89. {
  90. if (idx < num_long_metrics)
  91. {
  92. LongMetric lm;
  93. lm.advance = _.first;
  94. lm.sb = _.second;
  95. if (unlikely (!c->embed<LongMetric> (&lm))) return;
  96. }
  97. else
  98. {
  99. FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
  100. if (unlikely (!sb)) return;
  101. *sb = _.second;
  102. }
  103. idx++;
  104. }
  105. }
  106. bool subset (hb_subset_context_t *c) const
  107. {
  108. TRACE_SUBSET (this);
  109. T *table_prime = c->serializer->start_embed <T> ();
  110. if (unlikely (!table_prime)) return_trace (false);
  111. accelerator_t _mtx (c->plan->source);
  112. unsigned num_long_metrics;
  113. const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *mtx_map = get_mtx_map (c->plan);
  114. {
  115. /* Determine num_long_metrics to encode. */
  116. auto& plan = c->plan;
  117. num_long_metrics = plan->num_output_glyphs ();
  118. unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx);
  119. while (num_long_metrics > 1 &&
  120. last_advance == get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 2, _mtx))
  121. {
  122. num_long_metrics--;
  123. }
  124. }
  125. auto it =
  126. + hb_range (c->plan->num_output_glyphs ())
  127. | hb_map ([c, &_mtx, mtx_map] (unsigned _)
  128. {
  129. if (!mtx_map->has (_))
  130. {
  131. hb_codepoint_t old_gid;
  132. if (!c->plan->old_gid_for_new_gid (_, &old_gid))
  133. return hb_pair (0u, 0);
  134. int lsb = 0;
  135. (void) _mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb);
  136. return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
  137. }
  138. return mtx_map->get (_);
  139. })
  140. ;
  141. table_prime->serialize (c->serializer, it, num_long_metrics);
  142. if (unlikely (c->serializer->in_error ()))
  143. return_trace (false);
  144. // Amend header num hmetrics
  145. if (unlikely (!subset_update_header (c->plan, num_long_metrics)))
  146. return_trace (false);
  147. return_trace (true);
  148. }
  149. struct accelerator_t
  150. {
  151. friend struct hmtxvmtx;
  152. accelerator_t (hb_face_t *face)
  153. {
  154. table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
  155. var_table = hb_sanitize_context_t ().reference_table<V> (face, T::variationsTag);
  156. default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face);
  157. /* Populate count variables and sort them out as we go */
  158. unsigned int len = table.get_length ();
  159. if (len & 1)
  160. len--;
  161. num_long_metrics = T::is_horizontal ?
  162. face->table.hhea->numberOfLongMetrics :
  163. #ifndef HB_NO_VERTICAL
  164. face->table.vhea->numberOfLongMetrics
  165. #else
  166. 0
  167. #endif
  168. ;
  169. if (unlikely (num_long_metrics * 4 > len))
  170. num_long_metrics = len / 4;
  171. len -= num_long_metrics * 4;
  172. num_bearings = face->table.maxp->get_num_glyphs ();
  173. if (unlikely (num_bearings < num_long_metrics))
  174. num_bearings = num_long_metrics;
  175. if (unlikely ((num_bearings - num_long_metrics) * 2 > len))
  176. num_bearings = num_long_metrics + len / 2;
  177. len -= (num_bearings - num_long_metrics) * 2;
  178. /* We MUST set num_bearings to zero if num_long_metrics is zero.
  179. * Our get_advance() depends on that. */
  180. if (unlikely (!num_long_metrics))
  181. num_bearings = num_long_metrics = 0;
  182. num_advances = num_bearings + len / 2;
  183. num_glyphs = face->get_num_glyphs ();
  184. if (num_glyphs < num_advances)
  185. num_glyphs = num_advances;
  186. }
  187. ~accelerator_t ()
  188. {
  189. table.destroy ();
  190. var_table.destroy ();
  191. }
  192. bool has_data () const { return (bool) num_bearings; }
  193. bool get_leading_bearing_without_var_unscaled (hb_codepoint_t glyph,
  194. int *lsb) const
  195. {
  196. if (glyph < num_long_metrics)
  197. {
  198. *lsb = table->longMetricZ[glyph].sb;
  199. return true;
  200. }
  201. if (unlikely (glyph >= num_bearings))
  202. return false;
  203. const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
  204. *lsb = bearings[glyph - num_long_metrics];
  205. return true;
  206. }
  207. bool get_leading_bearing_with_var_unscaled (hb_font_t *font,
  208. hb_codepoint_t glyph,
  209. int *lsb) const
  210. {
  211. if (!font->num_coords)
  212. return get_leading_bearing_without_var_unscaled (glyph, lsb);
  213. #ifndef HB_NO_VAR
  214. float delta;
  215. if (var_table->get_lsb_delta_unscaled (glyph, font->coords, font->num_coords, &delta) &&
  216. get_leading_bearing_without_var_unscaled (glyph, lsb))
  217. {
  218. *lsb += roundf (delta);
  219. return true;
  220. }
  221. return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx, lsb);
  222. #else
  223. return false;
  224. #endif
  225. }
  226. unsigned int get_advance_without_var_unscaled (hb_codepoint_t glyph) const
  227. {
  228. /* OpenType case. */
  229. if (glyph < num_bearings)
  230. return table->longMetricZ[hb_min (glyph, (uint32_t) num_long_metrics - 1)].advance;
  231. /* If num_advances is zero, it means we don't have the metrics table
  232. * for this direction: return default advance. Otherwise, there's a
  233. * well-defined answer. */
  234. if (unlikely (!num_advances))
  235. return default_advance;
  236. #ifdef HB_NO_BEYOND_64K
  237. return 0;
  238. #endif
  239. if (unlikely (glyph >= num_glyphs))
  240. return 0;
  241. /* num_bearings <= glyph < num_glyphs;
  242. * num_bearings <= num_advances */
  243. /* TODO Optimize */
  244. if (num_bearings == num_advances)
  245. return get_advance_without_var_unscaled (num_bearings - 1);
  246. const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
  247. const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics];
  248. return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)];
  249. }
  250. unsigned get_advance_with_var_unscaled (hb_codepoint_t glyph,
  251. hb_font_t *font,
  252. VariationStore::cache_t *store_cache = nullptr) const
  253. {
  254. unsigned int advance = get_advance_without_var_unscaled (glyph);
  255. #ifndef HB_NO_VAR
  256. if (unlikely (glyph >= num_bearings) || !font->num_coords)
  257. return advance;
  258. if (var_table.get_length ())
  259. return advance + roundf (var_table->get_advance_delta_unscaled (glyph,
  260. font->coords, font->num_coords,
  261. store_cache)); // TODO Optimize?!
  262. return _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
  263. #else
  264. return advance;
  265. #endif
  266. }
  267. protected:
  268. // 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs
  269. unsigned num_long_metrics;
  270. unsigned num_bearings;
  271. unsigned num_advances;
  272. unsigned num_glyphs;
  273. unsigned int default_advance;
  274. public:
  275. hb_blob_ptr_t<hmtxvmtx> table;
  276. hb_blob_ptr_t<V> var_table;
  277. };
  278. /* get advance: when no variations, call get_advance_without_var_unscaled.
  279. * when there're variations, get advance value from mtx_map in subset_plan*/
  280. unsigned get_new_gid_advance_unscaled (const hb_subset_plan_t *plan,
  281. const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *mtx_map,
  282. unsigned new_gid,
  283. const accelerator_t &_mtx) const
  284. {
  285. if (mtx_map->is_empty () ||
  286. (new_gid == 0 && !mtx_map->has (new_gid)))
  287. {
  288. hb_codepoint_t old_gid = 0;
  289. return plan->old_gid_for_new_gid (new_gid, &old_gid) ?
  290. _mtx.get_advance_without_var_unscaled (old_gid) : 0;
  291. }
  292. else
  293. { return mtx_map->get (new_gid).first; }
  294. }
  295. protected:
  296. UnsizedArrayOf<LongMetric>
  297. longMetricZ; /* Paired advance width and leading
  298. * bearing values for each glyph. The
  299. * value numOfHMetrics comes from
  300. * the 'hhea' table. If the font is
  301. * monospaced, only one entry need
  302. * be in the array, but that entry is
  303. * required. The last entry applies to
  304. * all subsequent glyphs. */
  305. /*UnsizedArrayOf<FWORD> leadingBearingX;*/
  306. /* Here the advance is assumed
  307. * to be the same as the advance
  308. * for the last entry above. The
  309. * number of entries in this array is
  310. * derived from numGlyphs (from 'maxp'
  311. * table) minus numberOfLongMetrics.
  312. * This generally is used with a run
  313. * of monospaced glyphs (e.g., Kanji
  314. * fonts or Courier fonts). Only one
  315. * run is allowed and it must be at
  316. * the end. This allows a monospaced
  317. * font to vary the side bearing
  318. * values for each glyph. */
  319. /*UnsizedArrayOf<UFWORD>advancesX;*/
  320. /* TODO Document. */
  321. public:
  322. DEFINE_SIZE_ARRAY (0, longMetricZ);
  323. };
  324. struct hmtx : hmtxvmtx<hmtx, hhea, HVAR> {
  325. static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
  326. static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
  327. static constexpr bool is_horizontal = true;
  328. };
  329. struct vmtx : hmtxvmtx<vmtx, vhea, VVAR> {
  330. static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
  331. static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
  332. static constexpr bool is_horizontal = false;
  333. };
  334. struct hmtx_accelerator_t : hmtx::accelerator_t {
  335. hmtx_accelerator_t (hb_face_t *face) : hmtx::accelerator_t (face) {}
  336. };
  337. struct vmtx_accelerator_t : vmtx::accelerator_t {
  338. vmtx_accelerator_t (hb_face_t *face) : vmtx::accelerator_t (face) {}
  339. };
  340. } /* namespace OT */
  341. #endif /* HB_OT_HMTX_TABLE_HH */