hb-aat-layout-trak-table.hh (8011B)
1 /* 2 * Copyright © 2018 Ebrahim Byagowi 3 * Copyright © 2018 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 * Google Author(s): Behdad Esfahbod 26 */ 27 28 #ifndef HB_AAT_LAYOUT_TRAK_TABLE_HH 29 #define HB_AAT_LAYOUT_TRAK_TABLE_HH 30 31 #include "hb-aat-layout-common.hh" 32 #include "hb-ot-layout.hh" 33 #include "hb-open-type.hh" 34 #include "hb-ot-stat-table.hh" 35 36 /* 37 * trak -- Tracking 38 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html 39 */ 40 #define HB_AAT_TAG_trak HB_TAG('t','r','a','k') 41 42 43 namespace AAT { 44 45 46 struct TrackTableEntry 47 { 48 friend struct TrackData; 49 50 float get_track_value () const { return track.to_float (); } 51 52 float interpolate_at (unsigned int idx, 53 float ptem, 54 const void *base, 55 hb_array_t<const F16DOT16> size_table) const 56 { 57 const FWORD *values = (base+valuesZ).arrayZ; 58 59 float s0 = size_table[idx].to_float (); 60 float s1 = size_table[idx + 1].to_float (); 61 int v0 = values[idx]; 62 int v1 = values[idx + 1]; 63 64 // Deal with font bugs. 65 if (unlikely (s1 < s0)) 66 { hb_swap (s0, s1); hb_swap (v0, v1); } 67 if (unlikely (ptem < s0)) return v0; 68 if (unlikely (ptem > s1)) return v1; 69 if (unlikely (s0 == s1)) return (v0 + v1) * 0.5f; 70 71 float t = (ptem - s0) / (s1 - s0); 72 return v0 + t * (v1 - v0); 73 } 74 75 float get_value (float ptem, 76 const void *base, 77 hb_array_t<const F16DOT16> size_table) const 78 { 79 const FWORD *values = (base+valuesZ).arrayZ; 80 81 unsigned int n_sizes = size_table.length; 82 83 /* 84 * Choose size. 85 */ 86 if (!n_sizes) return 0.f; 87 if (n_sizes == 1) return values[0]; 88 89 // At least two entries. 90 91 unsigned i; 92 for (i = 0; i < n_sizes; i++) 93 if (size_table[i].to_float () >= ptem) 94 break; 95 96 // Boundary conditions. 97 if (i == 0) return values[0]; 98 if (i == n_sizes) return values[n_sizes - 1]; 99 100 // Exact match. 101 if (size_table[i].to_float () == ptem) return values[i]; 102 103 // Interpolate. 104 return interpolate_at (i - 1, ptem, base, size_table); 105 } 106 107 public: 108 bool sanitize (hb_sanitize_context_t *c, 109 const void *base, 110 unsigned int n_sizes) const 111 { 112 TRACE_SANITIZE (this); 113 return_trace (likely (c->check_struct (this) && 114 (valuesZ.sanitize (c, base, n_sizes)))); 115 } 116 117 protected: 118 F16DOT16 track; /* Track value for this record. */ 119 OT::NameID trackNameID; /* The 'name' table index for this track. 120 * (a short word or phrase like "loose" 121 * or "very tight") */ 122 NNOffset16To<UnsizedArrayOf<FWORD>> 123 valuesZ; /* Offset from start of tracking table to 124 * per-size tracking values for this track. */ 125 126 public: 127 DEFINE_SIZE_STATIC (8); 128 }; 129 130 struct TrackData 131 { 132 float get_tracking (const void *base, float ptem, float track = 0.f) const 133 { 134 unsigned count = nTracks; 135 hb_array_t<const F16DOT16> size_table = (base+sizeTable).as_array (nSizes); 136 137 if (!count) return 0.f; 138 if (count == 1) return trackTable[0].get_value (ptem, base, size_table); 139 140 // At least two entries. 141 142 unsigned i = 0; 143 unsigned j = count - 1; 144 145 // Find the two entries that track is between. 146 while (i + 1 < count && trackTable[i + 1].get_track_value () <= track) 147 i++; 148 while (j > 0 && trackTable[j - 1].get_track_value () >= track) 149 j--; 150 151 // Exact match. 152 if (i == j) return trackTable[i].get_value (ptem, base, size_table); 153 154 // Interpolate. 155 156 float t0 = trackTable[i].get_track_value (); 157 float t1 = trackTable[j].get_track_value (); 158 159 float t = (track - t0) / (t1 - t0); 160 161 float a = trackTable[i].get_value (ptem, base, size_table); 162 float b = trackTable[j].get_value (ptem, base, size_table); 163 return a + t * (b - a); 164 } 165 166 bool sanitize (hb_sanitize_context_t *c, const void *base) const 167 { 168 TRACE_SANITIZE (this); 169 return_trace (likely (c->check_struct (this) && 170 hb_barrier () && 171 sizeTable.sanitize (c, base, nSizes) && 172 trackTable.sanitize (c, nTracks, base, nSizes))); 173 } 174 175 protected: 176 HBUINT16 nTracks; /* Number of separate tracks included in this table. */ 177 HBUINT16 nSizes; /* Number of point sizes included in this table. */ 178 NNOffset32To<UnsizedArrayOf<F16DOT16>> 179 sizeTable; /* Offset from start of the tracking table to 180 * Array[nSizes] of size values.. */ 181 UnsizedArrayOf<TrackTableEntry> 182 trackTable; /* Array[nTracks] of TrackTableEntry records. */ 183 184 public: 185 DEFINE_SIZE_ARRAY (8, trackTable); 186 }; 187 188 struct trak 189 { 190 static constexpr hb_tag_t tableTag = HB_AAT_TAG_trak; 191 192 bool has_data () const { return version.to_int (); } 193 194 hb_position_t get_h_tracking (hb_font_t *font, float track = 0.f) const 195 { 196 float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE; 197 return font->em_scalef_x ((this+horizData).get_tracking (this, ptem, track)); 198 } 199 hb_position_t get_v_tracking (hb_font_t *font, float track = 0.f) const 200 { 201 float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE; 202 return font->em_scalef_y ((this+vertData).get_tracking (this, ptem, track)); 203 } 204 hb_position_t get_tracking (hb_font_t *font, hb_direction_t dir, float track = 0.f) const 205 { 206 #ifndef HB_NO_STYLE 207 if (!font->face->table.STAT->has_data ()) 208 return 0; 209 return HB_DIRECTION_IS_HORIZONTAL (dir) ? 210 get_h_tracking (font, track) : 211 get_v_tracking (font, track); 212 #else 213 return 0; 214 #endif 215 } 216 217 bool apply (hb_aat_apply_context_t *c, float track = 0.f) const 218 { 219 TRACE_APPLY (this); 220 221 float ptem = c->font->ptem; 222 if (unlikely (ptem <= 0.f)) 223 { 224 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ 225 ptem = HB_CORETEXT_DEFAULT_FONT_SIZE; 226 } 227 228 hb_buffer_t *buffer = c->buffer; 229 if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) 230 { 231 hb_position_t advance_to_add = get_h_tracking (c->font, track); 232 foreach_grapheme (buffer, start, end) 233 buffer->pos[start].x_advance += advance_to_add; 234 } 235 else 236 { 237 hb_position_t advance_to_add = get_v_tracking (c->font, track); 238 foreach_grapheme (buffer, start, end) 239 buffer->pos[start].y_advance += advance_to_add; 240 } 241 242 return_trace (true); 243 } 244 245 bool sanitize (hb_sanitize_context_t *c) const 246 { 247 TRACE_SANITIZE (this); 248 249 return_trace (likely (c->check_struct (this) && 250 hb_barrier () && 251 version.major == 1 && 252 horizData.sanitize (c, this, this) && 253 vertData.sanitize (c, this, this))); 254 } 255 256 protected: 257 FixedVersion<>version; /* Version of the tracking table 258 * (0x00010000u for version 1.0). */ 259 HBUINT16 format; /* Format of the tracking table (set to 0). */ 260 Offset16To<TrackData> 261 horizData; /* Offset from start of tracking table to TrackData 262 * for horizontal text (or 0 if none). */ 263 Offset16To<TrackData> 264 vertData; /* Offset from start of tracking table to TrackData 265 * for vertical text (or 0 if none). */ 266 HBUINT16 reserved; /* Reserved. Set to 0. */ 267 268 public: 269 DEFINE_SIZE_STATIC (12); 270 }; 271 272 } /* namespace AAT */ 273 274 275 #endif /* HB_AAT_LAYOUT_TRAK_TABLE_HH */