Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/harfbuzz/src/hb-ot-stat-table.hh @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 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 StatAxisRecord | |
| 61 { | |
| 62 int cmp (hb_tag_t key) const { return tag.cmp (key); } | |
| 63 | |
| 64 hb_ot_name_id_t get_name_id () const { return nameID; } | |
| 65 | |
| 66 hb_tag_t get_axis_tag () const { return tag; } | |
| 67 | |
| 68 bool sanitize (hb_sanitize_context_t *c) const | |
| 69 { | |
| 70 TRACE_SANITIZE (this); | |
| 71 return_trace (likely (c->check_struct (this))); | |
| 72 } | |
| 73 | |
| 74 protected: | |
| 75 Tag tag; /* A tag identifying the axis of design variation. */ | |
| 76 NameID nameID; /* The name ID for entries in the 'name' table that | |
| 77 * provide a display string for this axis. */ | |
| 78 HBUINT16 ordering; /* A value that applications can use to determine | |
| 79 * primary sorting of face names, or for ordering | |
| 80 * of descriptors when composing family or face names. */ | |
| 81 public: | |
| 82 DEFINE_SIZE_STATIC (8); | |
| 83 }; | |
| 84 | |
| 85 struct AxisValueFormat1 | |
| 86 { | |
| 87 unsigned int get_axis_index () const { return axisIndex; } | |
| 88 float get_value () const { return value.to_float (); } | |
| 89 | |
| 90 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } | |
| 91 | |
| 92 hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const | |
| 93 { | |
| 94 unsigned axis_idx = get_axis_index (); | |
| 95 return axis_records[axis_idx].get_axis_tag (); | |
| 96 } | |
| 97 | |
| 98 bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, | |
| 99 const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const | |
| 100 { | |
| 101 hb_tag_t axis_tag = get_axis_tag (axis_records); | |
| 102 float axis_value = get_value (); | |
| 103 | |
| 104 if (!user_axes_location->has (axis_tag) || | |
| 105 fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) | |
| 106 return true; | |
| 107 | |
| 108 return false; | |
| 109 } | |
| 110 | |
| 111 bool subset (hb_subset_context_t *c, | |
| 112 const hb_array_t<const StatAxisRecord> axis_records) const | |
| 113 { | |
| 114 TRACE_SUBSET (this); | |
| 115 const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location; | |
| 116 | |
| 117 if (keep_axis_value (axis_records, user_axes_location)) | |
| 118 return_trace (c->serializer->embed (this)); | |
| 119 | |
| 120 return_trace (false); | |
| 121 } | |
| 122 | |
| 123 bool sanitize (hb_sanitize_context_t *c) const | |
| 124 { | |
| 125 TRACE_SANITIZE (this); | |
| 126 return_trace (c->check_struct (this)); | |
| 127 } | |
| 128 | |
| 129 protected: | |
| 130 HBUINT16 format; /* Format identifier — set to 1. */ | |
| 131 HBUINT16 axisIndex; /* Zero-base index into the axis record array | |
| 132 * identifying the axis of design variation | |
| 133 * to which the axis value record applies. | |
| 134 * Must be less than designAxisCount. */ | |
| 135 HBUINT16 flags; /* Flags — see below for details. */ | |
| 136 NameID valueNameID; /* The name ID for entries in the 'name' table | |
| 137 * that provide a display string for this | |
| 138 * attribute value. */ | |
| 139 F16DOT16 value; /* A numeric value for this attribute value. */ | |
| 140 public: | |
| 141 DEFINE_SIZE_STATIC (12); | |
| 142 }; | |
| 143 | |
| 144 struct AxisValueFormat2 | |
| 145 { | |
| 146 unsigned int get_axis_index () const { return axisIndex; } | |
| 147 float get_value () const { return nominalValue.to_float (); } | |
| 148 | |
| 149 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } | |
| 150 | |
| 151 hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const | |
| 152 { | |
| 153 unsigned axis_idx = get_axis_index (); | |
| 154 return axis_records[axis_idx].get_axis_tag (); | |
| 155 } | |
| 156 | |
| 157 bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, | |
| 158 const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const | |
| 159 { | |
| 160 hb_tag_t axis_tag = get_axis_tag (axis_records); | |
| 161 float axis_value = get_value (); | |
| 162 | |
| 163 if (!user_axes_location->has (axis_tag) || | |
| 164 fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) | |
| 165 return true; | |
| 166 | |
| 167 return false; | |
| 168 } | |
| 169 | |
| 170 bool subset (hb_subset_context_t *c, | |
| 171 const hb_array_t<const StatAxisRecord> axis_records) const | |
| 172 { | |
| 173 TRACE_SUBSET (this); | |
| 174 const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location; | |
| 175 | |
| 176 if (keep_axis_value (axis_records, user_axes_location)) | |
| 177 return_trace (c->serializer->embed (this)); | |
| 178 | |
| 179 return_trace (false); | |
| 180 } | |
| 181 | |
| 182 bool sanitize (hb_sanitize_context_t *c) const | |
| 183 { | |
| 184 TRACE_SANITIZE (this); | |
| 185 return_trace (c->check_struct (this)); | |
| 186 } | |
| 187 | |
| 188 protected: | |
| 189 HBUINT16 format; /* Format identifier — set to 2. */ | |
| 190 HBUINT16 axisIndex; /* Zero-base index into the axis record array | |
| 191 * identifying the axis of design variation | |
| 192 * to which the axis value record applies. | |
| 193 * Must be less than designAxisCount. */ | |
| 194 HBUINT16 flags; /* Flags — see below for details. */ | |
| 195 NameID valueNameID; /* The name ID for entries in the 'name' table | |
| 196 * that provide a display string for this | |
| 197 * attribute value. */ | |
| 198 F16DOT16 nominalValue; /* A numeric value for this attribute value. */ | |
| 199 F16DOT16 rangeMinValue; /* The minimum value for a range associated | |
| 200 * with the specified name ID. */ | |
| 201 F16DOT16 rangeMaxValue; /* The maximum value for a range associated | |
| 202 * with the specified name ID. */ | |
| 203 public: | |
| 204 DEFINE_SIZE_STATIC (20); | |
| 205 }; | |
| 206 | |
| 207 struct AxisValueFormat3 | |
| 208 { | |
| 209 unsigned int get_axis_index () const { return axisIndex; } | |
| 210 float get_value () const { return value.to_float (); } | |
| 211 | |
| 212 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } | |
| 213 | |
| 214 hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const | |
| 215 { | |
| 216 unsigned axis_idx = get_axis_index (); | |
| 217 return axis_records[axis_idx].get_axis_tag (); | |
| 218 } | |
| 219 | |
| 220 bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, | |
| 221 const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const | |
| 222 { | |
| 223 hb_tag_t axis_tag = get_axis_tag (axis_records); | |
| 224 float axis_value = get_value (); | |
| 225 | |
| 226 if (!user_axes_location->has (axis_tag) || | |
| 227 fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f) | |
| 228 return true; | |
| 229 | |
| 230 return false; | |
| 231 } | |
| 232 | |
| 233 bool subset (hb_subset_context_t *c, | |
| 234 const hb_array_t<const StatAxisRecord> axis_records) const | |
| 235 { | |
| 236 TRACE_SUBSET (this); | |
| 237 const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location; | |
| 238 | |
| 239 if (keep_axis_value (axis_records, user_axes_location)) | |
| 240 return_trace (c->serializer->embed (this)); | |
| 241 | |
| 242 return_trace (false); | |
| 243 } | |
| 244 | |
| 245 bool sanitize (hb_sanitize_context_t *c) const | |
| 246 { | |
| 247 TRACE_SANITIZE (this); | |
| 248 return_trace (c->check_struct (this)); | |
| 249 } | |
| 250 | |
| 251 protected: | |
| 252 HBUINT16 format; /* Format identifier — set to 3. */ | |
| 253 HBUINT16 axisIndex; /* Zero-base index into the axis record array | |
| 254 * identifying the axis of design variation | |
| 255 * to which the axis value record applies. | |
| 256 * Must be less than designAxisCount. */ | |
| 257 HBUINT16 flags; /* Flags — see below for details. */ | |
| 258 NameID valueNameID; /* The name ID for entries in the 'name' table | |
| 259 * that provide a display string for this | |
| 260 * attribute value. */ | |
| 261 F16DOT16 value; /* A numeric value for this attribute value. */ | |
| 262 F16DOT16 linkedValue; /* The numeric value for a style-linked mapping | |
| 263 * from this value. */ | |
| 264 public: | |
| 265 DEFINE_SIZE_STATIC (16); | |
| 266 }; | |
| 267 | |
| 268 struct AxisValueRecord | |
| 269 { | |
| 270 unsigned int get_axis_index () const { return axisIndex; } | |
| 271 float get_value () const { return value.to_float (); } | |
| 272 | |
| 273 bool sanitize (hb_sanitize_context_t *c) const | |
| 274 { | |
| 275 TRACE_SANITIZE (this); | |
| 276 return_trace (c->check_struct (this)); | |
| 277 } | |
| 278 | |
| 279 protected: | |
| 280 HBUINT16 axisIndex; /* Zero-base index into the axis record array | |
| 281 * identifying the axis to which this value | |
| 282 * applies. Must be less than designAxisCount. */ | |
| 283 F16DOT16 value; /* A numeric value for this attribute value. */ | |
| 284 public: | |
| 285 DEFINE_SIZE_STATIC (6); | |
| 286 }; | |
| 287 | |
| 288 struct AxisValueFormat4 | |
| 289 { | |
| 290 const AxisValueRecord &get_axis_record (unsigned int axis_index) const | |
| 291 { return axisValues.as_array (axisCount)[axis_index]; } | |
| 292 | |
| 293 bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, | |
| 294 const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const | |
| 295 { | |
| 296 hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount); | |
| 297 | |
| 298 for (const auto& rec : axis_value_records) | |
| 299 { | |
| 300 unsigned axis_idx = rec.get_axis_index (); | |
| 301 float axis_value = rec.get_value (); | |
| 302 hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag (); | |
| 303 | |
| 304 if (user_axes_location->has (axis_tag) && | |
| 305 fabsf(axis_value - user_axes_location->get (axis_tag)) > 0.001f) | |
| 306 return false; | |
| 307 } | |
| 308 | |
| 309 return true; | |
| 310 } | |
| 311 | |
| 312 bool subset (hb_subset_context_t *c, | |
| 313 const hb_array_t<const StatAxisRecord> axis_records) const | |
| 314 { | |
| 315 TRACE_SUBSET (this); | |
| 316 const hb_hashmap_t<hb_tag_t, float> *user_axes_location = c->plan->user_axes_location; | |
| 317 if (!keep_axis_value (axis_records, user_axes_location)) | |
| 318 return_trace (false); | |
| 319 | |
| 320 unsigned total_size = min_size + axisCount * AxisValueRecord::static_size; | |
| 321 auto *out = c->serializer->allocate_size<AxisValueFormat4> (total_size); | |
| 322 if (unlikely (!out)) return_trace (false); | |
| 323 hb_memcpy (out, this, total_size); | |
| 324 return_trace (true); | |
| 325 } | |
| 326 | |
| 327 hb_ot_name_id_t get_value_name_id () const { return valueNameID; } | |
| 328 | |
| 329 bool sanitize (hb_sanitize_context_t *c) const | |
| 330 { | |
| 331 TRACE_SANITIZE (this); | |
| 332 return_trace (likely (c->check_struct (this) && | |
| 333 axisValues.sanitize (c, axisCount))); | |
| 334 } | |
| 335 | |
| 336 protected: | |
| 337 HBUINT16 format; /* Format identifier — set to 4. */ | |
| 338 HBUINT16 axisCount; /* The total number of axes contributing to | |
| 339 * this axis-values combination. */ | |
| 340 HBUINT16 flags; /* Flags — see below for details. */ | |
| 341 NameID valueNameID; /* The name ID for entries in the 'name' table | |
| 342 * that provide a display string for this | |
| 343 * attribute value. */ | |
| 344 UnsizedArrayOf<AxisValueRecord> | |
| 345 axisValues; /* Array of AxisValue records that provide the | |
| 346 * combination of axis values, one for each | |
| 347 * contributing axis. */ | |
| 348 public: | |
| 349 DEFINE_SIZE_ARRAY (8, axisValues); | |
| 350 }; | |
| 351 | |
| 352 struct AxisValue | |
| 353 { | |
| 354 bool get_value (unsigned int axis_index) const | |
| 355 { | |
| 356 switch (u.format) | |
| 357 { | |
| 358 case 1: return u.format1.get_value (); | |
| 359 case 2: return u.format2.get_value (); | |
| 360 case 3: return u.format3.get_value (); | |
| 361 case 4: return u.format4.get_axis_record (axis_index).get_value (); | |
| 362 default:return 0; | |
| 363 } | |
| 364 } | |
| 365 | |
| 366 unsigned int get_axis_index () const | |
| 367 { | |
| 368 switch (u.format) | |
| 369 { | |
| 370 case 1: return u.format1.get_axis_index (); | |
| 371 case 2: return u.format2.get_axis_index (); | |
| 372 case 3: return u.format3.get_axis_index (); | |
| 373 /* case 4: Makes more sense for variable fonts which are handled by fvar in hb-style */ | |
| 374 default:return -1; | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 hb_ot_name_id_t get_value_name_id () const | |
| 379 { | |
| 380 switch (u.format) | |
| 381 { | |
| 382 case 1: return u.format1.get_value_name_id (); | |
| 383 case 2: return u.format2.get_value_name_id (); | |
| 384 case 3: return u.format3.get_value_name_id (); | |
| 385 case 4: return u.format4.get_value_name_id (); | |
| 386 default:return HB_OT_NAME_ID_INVALID; | |
| 387 } | |
| 388 } | |
| 389 | |
| 390 template <typename context_t, typename ...Ts> | |
| 391 typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const | |
| 392 { | |
| 393 TRACE_DISPATCH (this, u.format); | |
| 394 if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); | |
| 395 switch (u.format) { | |
| 396 case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); | |
| 397 case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); | |
| 398 case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); | |
| 399 case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...)); | |
| 400 default:return_trace (c->default_return_value ()); | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records, | |
| 405 hb_hashmap_t<hb_tag_t, float> *user_axes_location) const | |
| 406 { | |
| 407 switch (u.format) | |
| 408 { | |
| 409 case 1: return u.format1.keep_axis_value (axis_records, user_axes_location); | |
| 410 case 2: return u.format2.keep_axis_value (axis_records, user_axes_location); | |
| 411 case 3: return u.format3.keep_axis_value (axis_records, user_axes_location); | |
| 412 case 4: return u.format4.keep_axis_value (axis_records, user_axes_location); | |
| 413 default:return false; | |
| 414 } | |
| 415 } | |
| 416 | |
| 417 bool sanitize (hb_sanitize_context_t *c) const | |
| 418 { | |
| 419 TRACE_SANITIZE (this); | |
| 420 if (unlikely (!c->check_struct (this))) | |
| 421 return_trace (false); | |
| 422 | |
| 423 switch (u.format) | |
| 424 { | |
| 425 case 1: return_trace (u.format1.sanitize (c)); | |
| 426 case 2: return_trace (u.format2.sanitize (c)); | |
| 427 case 3: return_trace (u.format3.sanitize (c)); | |
| 428 case 4: return_trace (u.format4.sanitize (c)); | |
| 429 default:return_trace (true); | |
| 430 } | |
| 431 } | |
| 432 | |
| 433 protected: | |
| 434 union | |
| 435 { | |
| 436 HBUINT16 format; | |
| 437 AxisValueFormat1 format1; | |
| 438 AxisValueFormat2 format2; | |
| 439 AxisValueFormat3 format3; | |
| 440 AxisValueFormat4 format4; | |
| 441 } u; | |
| 442 public: | |
| 443 DEFINE_SIZE_UNION (2, format); | |
| 444 }; | |
| 445 | |
| 446 struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>> | |
| 447 { | |
| 448 bool subset (hb_subset_context_t *c, | |
| 449 unsigned axisValueCount, | |
| 450 unsigned& count, | |
| 451 const hb_array_t<const StatAxisRecord> axis_records) const | |
| 452 { | |
| 453 TRACE_SUBSET (this); | |
| 454 auto *out = c->serializer->start_embed (this); | |
| 455 if (unlikely (!out)) return_trace (false); | |
| 456 | |
| 457 auto axisValueOffsets = as_array (axisValueCount); | |
| 458 count = 0; | |
| 459 for (const auto& offset : axisValueOffsets) | |
| 460 { | |
| 461 if (!offset) continue; | |
| 462 auto o_snap = c->serializer->snapshot (); | |
| 463 auto *o = c->serializer->embed (offset); | |
| 464 if (!o) return_trace (false); | |
| 465 if (!o->serialize_subset (c, offset, this, axis_records)) | |
| 466 { | |
| 467 c->serializer->revert (o_snap); | |
| 468 continue; | |
| 469 } | |
| 470 count++; | |
| 471 } | |
| 472 | |
| 473 return_trace (count); | |
| 474 } | |
| 475 }; | |
| 476 | |
| 477 struct STAT | |
| 478 { | |
| 479 static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT; | |
| 480 | |
| 481 bool has_data () const { return version.to_int (); } | |
| 482 | |
| 483 bool get_value (hb_tag_t tag, float *value) const | |
| 484 { | |
| 485 unsigned int axis_index; | |
| 486 if (!get_design_axes ().lfind (tag, &axis_index)) return false; | |
| 487 | |
| 488 hb_array_t<const Offset16To<AxisValue>> axis_values = get_axis_value_offsets (); | |
| 489 for (unsigned int i = 0; i < axis_values.length; i++) | |
| 490 { | |
| 491 const AxisValue& axis_value = this+axis_values[i]; | |
| 492 if (axis_value.get_axis_index () == axis_index) | |
| 493 { | |
| 494 if (value) | |
| 495 *value = axis_value.get_value (axis_index); | |
| 496 return true; | |
| 497 } | |
| 498 } | |
| 499 return false; | |
| 500 } | |
| 501 | |
| 502 unsigned get_design_axis_count () const { return designAxisCount; } | |
| 503 | |
| 504 hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const | |
| 505 { | |
| 506 if (unlikely (axis_record_index >= designAxisCount)) return HB_OT_NAME_ID_INVALID; | |
| 507 const StatAxisRecord &axis_record = get_design_axes ()[axis_record_index]; | |
| 508 return axis_record.get_name_id (); | |
| 509 } | |
| 510 | |
| 511 unsigned get_axis_value_count () const { return axisValueCount; } | |
| 512 | |
| 513 hb_ot_name_id_t get_axis_value_name_id (unsigned axis_value_index) const | |
| 514 { | |
| 515 if (unlikely (axis_value_index >= axisValueCount)) return HB_OT_NAME_ID_INVALID; | |
| 516 const AxisValue &axis_value = (this + get_axis_value_offsets ()[axis_value_index]); | |
| 517 return axis_value.get_value_name_id (); | |
| 518 } | |
| 519 | |
| 520 void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location, | |
| 521 hb_set_t *nameids_to_retain /* OUT */) const | |
| 522 { | |
| 523 if (!has_data ()) return; | |
| 524 | |
| 525 + get_design_axes () | |
| 526 | hb_map (&StatAxisRecord::get_name_id) | |
| 527 | hb_sink (nameids_to_retain) | |
| 528 ; | |
| 529 | |
| 530 auto designAxes = get_design_axes (); | |
| 531 | |
| 532 + get_axis_value_offsets () | |
| 533 | hb_map (hb_add (&(this + offsetToAxisValueOffsets))) | |
| 534 | hb_filter ([&] (const AxisValue& _) | |
| 535 { return _.keep_axis_value (designAxes, user_axes_location); }) | |
| 536 | hb_map (&AxisValue::get_value_name_id) | |
| 537 | hb_sink (nameids_to_retain) | |
| 538 ; | |
| 539 } | |
| 540 | |
| 541 bool subset (hb_subset_context_t *c) const | |
| 542 { | |
| 543 TRACE_SUBSET (this); | |
| 544 STAT *out = c->serializer->embed (this); | |
| 545 if (unlikely (!out)) return_trace (false); | |
| 546 | |
| 547 auto designAxes = get_design_axes (); | |
| 548 for (unsigned i = 0; i < (unsigned)designAxisCount; i++) | |
| 549 if (unlikely (!c->serializer->embed (designAxes[i]))) | |
| 550 return_trace (false); | |
| 551 | |
| 552 if (designAxisCount) | |
| 553 c->serializer->check_assign (out->designAxesOffset, this->get_size (), | |
| 554 HB_SERIALIZE_ERROR_INT_OVERFLOW); | |
| 555 | |
| 556 unsigned count = 0; | |
| 557 out->offsetToAxisValueOffsets.serialize_subset (c, offsetToAxisValueOffsets, this, | |
| 558 axisValueCount, count, designAxes); | |
| 559 return_trace (c->serializer->check_assign (out->axisValueCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); | |
| 560 } | |
| 561 | |
| 562 bool sanitize (hb_sanitize_context_t *c) const | |
| 563 { | |
| 564 TRACE_SANITIZE (this); | |
| 565 return_trace (likely (c->check_struct (this) && | |
| 566 version.major == 1 && | |
| 567 version.minor > 0 && | |
| 568 designAxesOffset.sanitize (c, this, designAxisCount) && | |
| 569 offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets)))); | |
| 570 } | |
| 571 | |
| 572 protected: | |
| 573 hb_array_t<const StatAxisRecord> const get_design_axes () const | |
| 574 { return (this+designAxesOffset).as_array (designAxisCount); } | |
| 575 | |
| 576 hb_array_t<const Offset16To<AxisValue>> const get_axis_value_offsets () const | |
| 577 { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); } | |
| 578 | |
| 579 | |
| 580 protected: | |
| 581 FixedVersion<>version; /* Version of the stat table | |
| 582 * initially set to 0x00010002u */ | |
| 583 HBUINT16 designAxisSize; /* The size in bytes of each axis record. */ | |
| 584 HBUINT16 designAxisCount;/* The number of design axis records. In a | |
| 585 * font with an 'fvar' table, this value must be | |
| 586 * greater than or equal to the axisCount value | |
| 587 * in the 'fvar' table. In all fonts, must | |
| 588 * be greater than zero if axisValueCount | |
| 589 * is greater than zero. */ | |
| 590 NNOffset32To<UnsizedArrayOf<StatAxisRecord>> | |
| 591 designAxesOffset; | |
| 592 /* Offset in bytes from the beginning of | |
| 593 * the STAT table to the start of the design | |
| 594 * axes array. If designAxisCount is zero, | |
| 595 * set to zero; if designAxisCount is greater | |
| 596 * than zero, must be greater than zero. */ | |
| 597 HBUINT16 axisValueCount; /* The number of axis value tables. */ | |
| 598 NNOffset32To<AxisValueOffsetArray> | |
| 599 offsetToAxisValueOffsets; | |
| 600 /* Offset in bytes from the beginning of | |
| 601 * the STAT table to the start of the design | |
| 602 * axes value offsets array. If axisValueCount | |
| 603 * is zero, set to zero; if axisValueCount is | |
| 604 * greater than zero, must be greater than zero. */ | |
| 605 NameID elidedFallbackNameID; | |
| 606 /* Name ID used as fallback when projection of | |
| 607 * names into a particular font model produces | |
| 608 * a subfamily name containing only elidable | |
| 609 * elements. */ | |
| 610 public: | |
| 611 DEFINE_SIZE_STATIC (20); | |
| 612 }; | |
| 613 | |
| 614 | |
| 615 } /* namespace OT */ | |
| 616 | |
| 617 | |
| 618 #endif /* HB_OT_STAT_TABLE_HH */ |
