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 25 */ 26 27 #ifndef HB_OT_HMTX_TABLE_HH 28 #define HB_OT_HMTX_TABLE_HH 29 30 #include "hb-open-type-private.hh" 31 #include "hb-ot-hhea-table.hh" 32 #include "hb-ot-os2-table.hh" 33 #include "hb-ot-var-hvar-table.hh" 34 35 36 namespace OT { 37 38 39 /* 40 * hmtx -- The Horizontal Metrics Table 41 * vmtx -- The Vertical Metrics Table 42 */ 43 44 #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x') 45 #define HB_OT_TAG_vmtx HB_TAG('v','m','t','x') 46 47 48 struct LongMetric 49 { 50 UFWORD advance; /* Advance width/height. */ 51 FWORD lsb; /* Leading (left/top) side bearing. */ 52 public: 53 DEFINE_SIZE_STATIC (4); 54 }; 55 56 template <typename T> 57 struct hmtxvmtx 58 { sanitizeOT::hmtxvmtx59 inline bool sanitize (hb_sanitize_context_t *c) const 60 { 61 TRACE_SANITIZE (this); 62 /* We don't check for anything specific here. The users of the 63 * struct do all the hard work... */ 64 return_trace (true); 65 } 66 67 struct accelerator_t 68 { initOT::hmtxvmtx::accelerator_t69 inline void init (hb_face_t *face, 70 unsigned int default_advance_ = 0) 71 { 72 default_advance = default_advance_ ? default_advance_ : face->get_upem (); 73 74 bool got_font_extents = false; 75 if (T::os2Tag) 76 { 77 hb_blob_t *os2_blob = Sanitizer<os2>::sanitize (face->reference_table (T::os2Tag)); 78 const os2 *os2_table = Sanitizer<os2>::lock_instance (os2_blob); 79 #define USE_TYPO_METRICS (1u<<7) 80 if (0 != (os2_table->fsSelection & USE_TYPO_METRICS)) 81 { 82 ascender = os2_table->sTypoAscender; 83 descender = os2_table->sTypoDescender; 84 line_gap = os2_table->sTypoLineGap; 85 got_font_extents = (ascender | descender) != 0; 86 } 87 hb_blob_destroy (os2_blob); 88 } 89 90 hb_blob_t *_hea_blob = Sanitizer<_hea>::sanitize (face->reference_table (T::headerTag)); 91 const _hea *_hea_table = Sanitizer<_hea>::lock_instance (_hea_blob); 92 num_advances = _hea_table->numberOfLongMetrics; 93 if (!got_font_extents) 94 { 95 ascender = _hea_table->ascender; 96 descender = _hea_table->descender; 97 line_gap = _hea_table->lineGap; 98 got_font_extents = (ascender | descender) != 0; 99 } 100 hb_blob_destroy (_hea_blob); 101 102 has_font_extents = got_font_extents; 103 104 blob = Sanitizer<hmtxvmtx>::sanitize (face->reference_table (T::tableTag)); 105 106 /* Cap num_metrics() and num_advances() based on table length. */ 107 unsigned int len = hb_blob_get_length (blob); 108 if (unlikely (num_advances * 4 > len)) 109 num_advances = len / 4; 110 num_metrics = num_advances + (len - 4 * num_advances) / 2; 111 112 /* We MUST set num_metrics to zero if num_advances is zero. 113 * Our get_advance() depends on that. */ 114 if (unlikely (!num_advances)) 115 { 116 num_metrics = num_advances = 0; 117 hb_blob_destroy (blob); 118 blob = hb_blob_get_empty (); 119 } 120 table = Sanitizer<hmtxvmtx>::lock_instance (blob); 121 122 var_blob = Sanitizer<HVARVVAR>::sanitize (face->reference_table (T::variationsTag)); 123 var_table = Sanitizer<HVARVVAR>::lock_instance (var_blob); 124 } 125 finiOT::hmtxvmtx::accelerator_t126 inline void fini (void) 127 { 128 hb_blob_destroy (blob); 129 hb_blob_destroy (var_blob); 130 } 131 get_advanceOT::hmtxvmtx::accelerator_t132 inline unsigned int get_advance (hb_codepoint_t glyph, 133 hb_font_t *font) const 134 { 135 if (unlikely (glyph >= num_metrics)) 136 { 137 /* If num_metrics is zero, it means we don't have the metrics table 138 * for this direction: return default advance. Otherwise, it means that the 139 * glyph index is out of bound: return zero. */ 140 if (num_metrics) 141 return 0; 142 else 143 return default_advance; 144 } 145 146 return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance 147 + var_table->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?! 148 } 149 150 public: 151 bool has_font_extents; 152 unsigned short ascender; 153 unsigned short descender; 154 unsigned short line_gap; 155 156 private: 157 unsigned int num_metrics; 158 unsigned int num_advances; 159 unsigned int default_advance; 160 161 const hmtxvmtx *table; 162 hb_blob_t *blob; 163 const HVARVVAR *var_table; 164 hb_blob_t *var_blob; 165 }; 166 167 protected: 168 LongMetric longMetric[VAR]; /* Paired advance width and leading 169 * bearing values for each glyph. The 170 * value numOfHMetrics comes from 171 * the 'hhea' table. If the font is 172 * monospaced, only one entry need 173 * be in the array, but that entry is 174 * required. The last entry applies to 175 * all subsequent glyphs. */ 176 FWORD leadingBearingX[VAR]; /* Here the advance is assumed 177 * to be the same as the advance 178 * for the last entry above. The 179 * number of entries in this array is 180 * derived from numGlyphs (from 'maxp' 181 * table) minus numberOfLongMetrics. 182 * This generally is used with a run 183 * of monospaced glyphs (e.g., Kanji 184 * fonts or Courier fonts). Only one 185 * run is allowed and it must be at 186 * the end. This allows a monospaced 187 * font to vary the side bearing 188 * values for each glyph. */ 189 public: 190 DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX); 191 }; 192 193 struct hmtx : hmtxvmtx<hmtx> { 194 static const hb_tag_t tableTag = HB_OT_TAG_hmtx; 195 static const hb_tag_t headerTag = HB_OT_TAG_hhea; 196 static const hb_tag_t variationsTag = HB_OT_TAG_HVAR; 197 static const hb_tag_t os2Tag = HB_OT_TAG_os2; 198 }; 199 struct vmtx : hmtxvmtx<vmtx> { 200 static const hb_tag_t tableTag = HB_OT_TAG_vmtx; 201 static const hb_tag_t headerTag = HB_OT_TAG_vhea; 202 static const hb_tag_t variationsTag = HB_OT_TAG_VVAR; 203 static const hb_tag_t os2Tag = HB_TAG_NONE; 204 }; 205 206 } /* namespace OT */ 207 208 209 #endif /* HB_OT_HMTX_TABLE_HH */ 210