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 27 #ifndef HB_OT_HMTX_TABLE_HH 28 #define HB_OT_HMTX_TABLE_HH 29 30 #include "hb-open-type.hh" 31 #include "hb-ot-hhea-table.hh" 32 #include "hb-ot-var-hvar-table.hh" 33 #include "hb-ot-metrics.hh" 34 35 /* 36 * hmtx -- Horizontal Metrics 37 * https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx 38 * vmtx -- Vertical Metrics 39 * https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx 40 */ 41 #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x') 42 #define HB_OT_TAG_vmtx HB_TAG('v','m','t','x') 43 44 45 HB_INTERNAL int 46 _glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical); 47 48 HB_INTERNAL unsigned 49 _glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical); 50 51 52 namespace OT { 53 54 55 struct LongMetric 56 { 57 UFWORD advance; /* Advance width/height. */ 58 FWORD sb; /* Leading (left/top) side bearing. */ 59 public: 60 DEFINE_SIZE_STATIC (4); 61 }; 62 63 64 template <typename T, typename H> 65 struct hmtxvmtx 66 { sanitizeOT::hmtxvmtx67 bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const 68 { 69 TRACE_SANITIZE (this); 70 /* We don't check for anything specific here. The users of the 71 * struct do all the hard work... */ 72 return_trace (true); 73 } 74 75 subset_update_headerOT::hmtxvmtx76 bool subset_update_header (hb_subset_plan_t *plan, 77 unsigned int num_hmetrics) const 78 { 79 hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag); 80 hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob); 81 hb_blob_destroy (src_blob); 82 83 if (unlikely (!dest_blob)) { 84 return false; 85 } 86 87 unsigned int length; 88 H *table = (H *) hb_blob_get_data (dest_blob, &length); 89 table->numberOfLongMetrics = num_hmetrics; 90 91 bool result = plan->add_table (H::tableTag, dest_blob); 92 hb_blob_destroy (dest_blob); 93 94 return result; 95 } 96 97 template<typename Iterator, 98 hb_requires (hb_is_iterator (Iterator))> serializeOT::hmtxvmtx99 void serialize (hb_serialize_context_t *c, 100 Iterator it, 101 unsigned num_advances) 102 { 103 unsigned idx = 0; 104 for (auto _ : it) 105 { 106 if (idx < num_advances) 107 { 108 LongMetric lm; 109 lm.advance = _.first; 110 lm.sb = _.second; 111 if (unlikely (!c->embed<LongMetric> (&lm))) return; 112 } 113 else 114 { 115 FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size); 116 if (unlikely (!sb)) return; 117 *sb = _.second; 118 } 119 idx++; 120 } 121 } 122 subsetOT::hmtxvmtx123 bool subset (hb_subset_context_t *c) const 124 { 125 TRACE_SUBSET (this); 126 127 T *table_prime = c->serializer->start_embed <T> (); 128 if (unlikely (!table_prime)) return_trace (false); 129 130 accelerator_t _mtx; 131 _mtx.init (c->plan->source); 132 unsigned num_advances = _mtx.num_advances_for_subset (c->plan); 133 134 auto it = 135 + hb_range (c->plan->num_output_glyphs ()) 136 | hb_map ([c, &_mtx] (unsigned _) 137 { 138 hb_codepoint_t old_gid; 139 if (!c->plan->old_gid_for_new_gid (_, &old_gid)) 140 return hb_pair (0u, 0); 141 return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid)); 142 }) 143 ; 144 145 table_prime->serialize (c->serializer, it, num_advances); 146 147 _mtx.fini (); 148 149 if (unlikely (c->serializer->in_error ())) 150 return_trace (false); 151 152 // Amend header num hmetrics 153 if (unlikely (!subset_update_header (c->plan, num_advances))) 154 return_trace (false); 155 156 return_trace (true); 157 } 158 159 struct accelerator_t 160 { 161 friend struct hmtxvmtx; 162 initOT::hmtxvmtx::accelerator_t163 void init (hb_face_t *face, 164 unsigned int default_advance_ = 0) 165 { 166 default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face); 167 168 num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics; 169 170 table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag); 171 172 /* Cap num_metrics() and num_advances() based on table length. */ 173 unsigned int len = table.get_length (); 174 if (unlikely (num_advances * 4 > len)) 175 num_advances = len / 4; 176 num_metrics = num_advances + (len - 4 * num_advances) / 2; 177 178 /* We MUST set num_metrics to zero if num_advances is zero. 179 * Our get_advance() depends on that. */ 180 if (unlikely (!num_advances)) 181 { 182 num_metrics = num_advances = 0; 183 table.destroy (); 184 table = hb_blob_get_empty (); 185 } 186 187 var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag); 188 } 189 finiOT::hmtxvmtx::accelerator_t190 void fini () 191 { 192 table.destroy (); 193 var_table.destroy (); 194 } 195 get_side_bearingOT::hmtxvmtx::accelerator_t196 int get_side_bearing (hb_codepoint_t glyph) const 197 { 198 if (glyph < num_advances) 199 return table->longMetricZ[glyph].sb; 200 201 if (unlikely (glyph >= num_metrics)) 202 return 0; 203 204 const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances]; 205 return bearings[glyph - num_advances]; 206 } 207 get_side_bearingOT::hmtxvmtx::accelerator_t208 int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const 209 { 210 int side_bearing = get_side_bearing (glyph); 211 212 #ifndef HB_NO_VAR 213 if (unlikely (glyph >= num_metrics) || !font->num_coords) 214 return side_bearing; 215 216 if (var_table.get_length ()) 217 return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?! 218 219 return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); 220 #else 221 return side_bearing; 222 #endif 223 } 224 get_advanceOT::hmtxvmtx::accelerator_t225 unsigned int get_advance (hb_codepoint_t glyph) const 226 { 227 if (unlikely (glyph >= num_metrics)) 228 { 229 /* If num_metrics is zero, it means we don't have the metrics table 230 * for this direction: return default advance. Otherwise, it means that the 231 * glyph index is out of bound: return zero. */ 232 if (num_metrics) 233 return 0; 234 else 235 return default_advance; 236 } 237 238 return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance; 239 } 240 get_advanceOT::hmtxvmtx::accelerator_t241 unsigned int get_advance (hb_codepoint_t glyph, 242 hb_font_t *font) const 243 { 244 unsigned int advance = get_advance (glyph); 245 246 #ifndef HB_NO_VAR 247 if (unlikely (glyph >= num_metrics) || !font->num_coords) 248 return advance; 249 250 if (var_table.get_length ()) 251 return advance + roundf (var_table->get_advance_var (glyph, font)); // TODO Optimize?! 252 253 return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); 254 #else 255 return advance; 256 #endif 257 } 258 num_advances_for_subsetOT::hmtxvmtx::accelerator_t259 unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const 260 { 261 unsigned int num_advances = plan->num_output_glyphs (); 262 unsigned int last_advance = _advance_for_new_gid (plan, 263 num_advances - 1); 264 while (num_advances > 1 && 265 last_advance == _advance_for_new_gid (plan, 266 num_advances - 2)) 267 { 268 num_advances--; 269 } 270 271 return num_advances; 272 } 273 274 private: _advance_for_new_gidOT::hmtxvmtx::accelerator_t275 unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan, 276 hb_codepoint_t new_gid) const 277 { 278 hb_codepoint_t old_gid; 279 if (!plan->old_gid_for_new_gid (new_gid, &old_gid)) 280 return 0; 281 282 return get_advance (old_gid); 283 } 284 285 protected: 286 unsigned int num_metrics; 287 unsigned int num_advances; 288 unsigned int default_advance; 289 290 private: 291 hb_blob_ptr_t<hmtxvmtx> table; 292 hb_blob_ptr_t<HVARVVAR> var_table; 293 }; 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 public: 320 DEFINE_SIZE_ARRAY (0, longMetricZ); 321 }; 322 323 struct hmtx : hmtxvmtx<hmtx, hhea> { 324 static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx; 325 static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR; 326 static constexpr bool is_horizontal = true; 327 }; 328 struct vmtx : hmtxvmtx<vmtx, vhea> { 329 static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx; 330 static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR; 331 static constexpr bool is_horizontal = false; 332 }; 333 334 struct hmtx_accelerator_t : hmtx::accelerator_t {}; 335 struct vmtx_accelerator_t : vmtx::accelerator_t {}; 336 337 } /* namespace OT */ 338 339 340 #endif /* HB_OT_HMTX_TABLE_HH */ 341