1 /* 2 * Copyright © 2018 Ebrahim Byagowi 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 25 #ifndef HB_OT_STAT_TABLE_HH 26 #define HB_OT_STAT_TABLE_HH 27 28 #include "hb-open-type.hh" 29 #include "hb-ot-layout-common.hh" 30 31 /* 32 * STAT -- Style Attributes 33 * https://docs.microsoft.com/en-us/typography/opentype/spec/stat 34 */ 35 #define HB_OT_TAG_STAT HB_TAG('S','T','A','T') 36 37 38 namespace OT { 39 40 enum 41 { 42 OLDER_SIBLING_FONT_ATTRIBUTE = 0x0001, /* If set, this axis value table 43 * provides axis value information 44 * that is applicable to other fonts 45 * within the same font family. This 46 * is used if the other fonts were 47 * released earlier and did not include 48 * information about values for some axis. 49 * If newer versions of the other 50 * fonts include the information 51 * themselves and are present, 52 * then this record is ignored. */ 53 ELIDABLE_AXIS_VALUE_NAME = 0x0002 /* If set, it indicates that the axis 54 * value represents the “normal” value 55 * for the axis and may be omitted when 56 * composing name strings. */ 57 // Reserved = 0xFFFC /* Reserved for future use — set to zero. */ 58 }; 59 60 struct AxisValueFormat1 61 { get_value_name_idOT::AxisValueFormat162 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } 63 sanitizeOT::AxisValueFormat164 bool sanitize (hb_sanitize_context_t *c) const 65 { 66 TRACE_SANITIZE (this); 67 return_trace (likely (c->check_struct (this))); 68 } 69 70 protected: 71 HBUINT16 format; /* Format identifier — set to 1. */ 72 HBUINT16 axisIndex; /* Zero-base index into the axis record array 73 * identifying the axis of design variation 74 * to which the axis value record applies. 75 * Must be less than designAxisCount. */ 76 HBUINT16 flags; /* Flags — see below for details. */ 77 NameID valueNameID; /* The name ID for entries in the 'name' table 78 * that provide a display string for this 79 * attribute value. */ 80 HBFixed value; /* A numeric value for this attribute value. */ 81 public: 82 DEFINE_SIZE_STATIC (12); 83 }; 84 85 struct AxisValueFormat2 86 { get_value_name_idOT::AxisValueFormat287 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } 88 sanitizeOT::AxisValueFormat289 bool sanitize (hb_sanitize_context_t *c) const 90 { 91 TRACE_SANITIZE (this); 92 return_trace (likely (c->check_struct (this))); 93 } 94 95 protected: 96 HBUINT16 format; /* Format identifier — set to 2. */ 97 HBUINT16 axisIndex; /* Zero-base index into the axis record array 98 * identifying the axis of design variation 99 * to which the axis value record applies. 100 * Must be less than designAxisCount. */ 101 HBUINT16 flags; /* Flags — see below for details. */ 102 NameID valueNameID; /* The name ID for entries in the 'name' table 103 * that provide a display string for this 104 * attribute value. */ 105 HBFixed nominalValue; /* A numeric value for this attribute value. */ 106 HBFixed rangeMinValue; /* The minimum value for a range associated 107 * with the specified name ID. */ 108 HBFixed rangeMaxValue; /* The maximum value for a range associated 109 * with the specified name ID. */ 110 public: 111 DEFINE_SIZE_STATIC (20); 112 }; 113 114 struct AxisValueFormat3 115 { get_value_name_idOT::AxisValueFormat3116 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } 117 sanitizeOT::AxisValueFormat3118 bool sanitize (hb_sanitize_context_t *c) const 119 { 120 TRACE_SANITIZE (this); 121 return_trace (likely (c->check_struct (this))); 122 } 123 124 protected: 125 HBUINT16 format; /* Format identifier — set to 3. */ 126 HBUINT16 axisIndex; /* Zero-base index into the axis record array 127 * identifying the axis of design variation 128 * to which the axis value record applies. 129 * Must be less than designAxisCount. */ 130 HBUINT16 flags; /* Flags — see below for details. */ 131 NameID valueNameID; /* The name ID for entries in the 'name' table 132 * that provide a display string for this 133 * attribute value. */ 134 HBFixed value; /* A numeric value for this attribute value. */ 135 HBFixed linkedValue; /* The numeric value for a style-linked mapping 136 * from this value. */ 137 public: 138 DEFINE_SIZE_STATIC (16); 139 }; 140 141 struct AxisValueRecord 142 { sanitizeOT::AxisValueRecord143 bool sanitize (hb_sanitize_context_t *c) const 144 { 145 TRACE_SANITIZE (this); 146 return_trace (likely (c->check_struct (this))); 147 } 148 149 protected: 150 HBUINT16 axisIndex; /* Zero-base index into the axis record array 151 * identifying the axis to which this value 152 * applies. Must be less than designAxisCount. */ 153 HBFixed value; /* A numeric value for this attribute value. */ 154 public: 155 DEFINE_SIZE_STATIC (6); 156 }; 157 158 struct AxisValueFormat4 159 { get_value_name_idOT::AxisValueFormat4160 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } 161 sanitizeOT::AxisValueFormat4162 bool sanitize (hb_sanitize_context_t *c) const 163 { 164 TRACE_SANITIZE (this); 165 return_trace (likely (c->check_struct (this))); 166 } 167 168 protected: 169 HBUINT16 format; /* Format identifier — set to 4. */ 170 HBUINT16 axisCount; /* The total number of axes contributing to 171 * this axis-values combination. */ 172 HBUINT16 flags; /* Flags — see below for details. */ 173 NameID valueNameID; /* The name ID for entries in the 'name' table 174 * that provide a display string for this 175 * attribute value. */ 176 UnsizedArrayOf<AxisValueRecord> 177 axisValues; /* Array of AxisValue records that provide the 178 * combination of axis values, one for each 179 * contributing axis. */ 180 public: 181 DEFINE_SIZE_ARRAY (8, axisValues); 182 }; 183 184 struct AxisValue 185 { get_value_name_idOT::AxisValue186 hb_ot_name_id_t get_value_name_id () const 187 { 188 switch (u.format) 189 { 190 case 1: return u.format1.get_value_name_id (); 191 case 2: return u.format2.get_value_name_id (); 192 case 3: return u.format3.get_value_name_id (); 193 case 4: return u.format4.get_value_name_id (); 194 default:return HB_OT_NAME_ID_INVALID; 195 } 196 } 197 sanitizeOT::AxisValue198 bool sanitize (hb_sanitize_context_t *c) const 199 { 200 TRACE_SANITIZE (this); 201 if (unlikely (!c->check_struct (this))) 202 return_trace (false); 203 204 switch (u.format) 205 { 206 case 1: return_trace (u.format1.sanitize (c)); 207 case 2: return_trace (u.format2.sanitize (c)); 208 case 3: return_trace (u.format3.sanitize (c)); 209 case 4: return_trace (u.format4.sanitize (c)); 210 default:return_trace (true); 211 } 212 } 213 214 protected: 215 union 216 { 217 HBUINT16 format; 218 AxisValueFormat1 format1; 219 AxisValueFormat2 format2; 220 AxisValueFormat3 format3; 221 AxisValueFormat4 format4; 222 } u; 223 public: 224 DEFINE_SIZE_UNION (2, format); 225 }; 226 227 struct StatAxisRecord 228 { get_name_idOT::StatAxisRecord229 hb_ot_name_id_t get_name_id () const { return nameID; } 230 sanitizeOT::StatAxisRecord231 bool sanitize (hb_sanitize_context_t *c) const 232 { 233 TRACE_SANITIZE (this); 234 return_trace (likely (c->check_struct (this))); 235 } 236 237 protected: 238 Tag tag; /* A tag identifying the axis of design variation. */ 239 NameID nameID; /* The name ID for entries in the 'name' table that 240 * provide a display string for this axis. */ 241 HBUINT16 ordering; /* A value that applications can use to determine 242 * primary sorting of face names, or for ordering 243 * of descriptors when composing family or face names. */ 244 public: 245 DEFINE_SIZE_STATIC (8); 246 }; 247 248 struct STAT 249 { 250 static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT; 251 has_dataOT::STAT252 bool has_data () const { return version.to_int (); } 253 get_design_axis_countOT::STAT254 unsigned get_design_axis_count () const { return designAxisCount; } 255 get_axis_record_name_idOT::STAT256 hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const 257 { 258 if (unlikely (axis_record_index >= designAxisCount)) return HB_OT_NAME_ID_INVALID; 259 const StatAxisRecord &axis_record = get_design_axes ()[axis_record_index]; 260 return axis_record.get_name_id (); 261 } 262 get_axis_value_countOT::STAT263 unsigned get_axis_value_count () const { return axisValueCount; } 264 get_axis_value_name_idOT::STAT265 hb_ot_name_id_t get_axis_value_name_id (unsigned axis_value_index) const 266 { 267 if (unlikely (axis_value_index >= axisValueCount)) return HB_OT_NAME_ID_INVALID; 268 const AxisValue &axis_value = (this + get_axis_value_offsets ()[axis_value_index]); 269 return axis_value.get_value_name_id (); 270 } 271 collect_name_idsOT::STAT272 void collect_name_ids (hb_set_t *nameids_to_retain) const 273 { 274 if (!has_data ()) return; 275 276 + get_design_axes () 277 | hb_map (&StatAxisRecord::get_name_id) 278 | hb_sink (nameids_to_retain) 279 ; 280 281 + get_axis_value_offsets () 282 | hb_map (hb_add (&(this + offsetToAxisValueOffsets))) 283 | hb_map (&AxisValue::get_value_name_id) 284 | hb_sink (nameids_to_retain) 285 ; 286 } 287 sanitizeOT::STAT288 bool sanitize (hb_sanitize_context_t *c) const 289 { 290 TRACE_SANITIZE (this); 291 return_trace (likely (c->check_struct (this) && 292 version.major == 1 && 293 version.minor > 0 && 294 designAxesOffset.sanitize (c, this, designAxisCount) && 295 offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets)))); 296 } 297 298 protected: get_design_axesOT::STAT299 hb_array_t<const StatAxisRecord> const get_design_axes () const 300 { return (this+designAxesOffset).as_array (designAxisCount); } 301 get_axis_value_offsetsOT::STAT302 hb_array_t<const OffsetTo<AxisValue>> const get_axis_value_offsets () const 303 { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); } 304 305 306 protected: 307 FixedVersion<>version; /* Version of the stat table 308 * initially set to 0x00010002u */ 309 HBUINT16 designAxisSize; /* The size in bytes of each axis record. */ 310 HBUINT16 designAxisCount;/* The number of design axis records. In a 311 * font with an 'fvar' table, this value must be 312 * greater than or equal to the axisCount value 313 * in the 'fvar' table. In all fonts, must 314 * be greater than zero if axisValueCount 315 * is greater than zero. */ 316 LNNOffsetTo<UnsizedArrayOf<StatAxisRecord>> 317 designAxesOffset; 318 /* Offset in bytes from the beginning of 319 * the STAT table to the start of the design 320 * axes array. If designAxisCount is zero, 321 * set to zero; if designAxisCount is greater 322 * than zero, must be greater than zero. */ 323 HBUINT16 axisValueCount; /* The number of axis value tables. */ 324 LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue>>> 325 offsetToAxisValueOffsets; 326 /* Offset in bytes from the beginning of 327 * the STAT table to the start of the design 328 * axes value offsets array. If axisValueCount 329 * is zero, set to zero; if axisValueCount is 330 * greater than zero, must be greater than zero. */ 331 NameID elidedFallbackNameID; 332 /* Name ID used as fallback when projection of 333 * names into a particular font model produces 334 * a subfamily name containing only elidable 335 * elements. */ 336 public: 337 DEFINE_SIZE_STATIC (20); 338 }; 339 340 341 } /* namespace OT */ 342 343 344 #endif /* HB_OT_STAT_TABLE_HH */ 345