Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/harfbuzz/src/hb-ot-math-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 © 2016 Igalia S.L. | |
| 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 * Igalia Author(s): Frédéric Wang | |
| 25 */ | |
| 26 | |
| 27 #ifndef HB_OT_MATH_TABLE_HH | |
| 28 #define HB_OT_MATH_TABLE_HH | |
| 29 | |
| 30 #include "hb-open-type.hh" | |
| 31 #include "hb-ot-layout-common.hh" | |
| 32 #include "hb-ot-math.h" | |
| 33 | |
| 34 namespace OT { | |
| 35 | |
| 36 | |
| 37 struct MathValueRecord | |
| 38 { | |
| 39 hb_position_t get_x_value (hb_font_t *font, const void *base) const | |
| 40 { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); } | |
| 41 hb_position_t get_y_value (hb_font_t *font, const void *base) const | |
| 42 { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); } | |
| 43 | |
| 44 MathValueRecord* copy (hb_serialize_context_t *c, const void *base) const | |
| 45 { | |
| 46 TRACE_SERIALIZE (this); | |
| 47 auto *out = c->embed (this); | |
| 48 if (unlikely (!out)) return_trace (nullptr); | |
| 49 out->deviceTable.serialize_copy (c, deviceTable, base, 0, hb_serialize_context_t::Head); | |
| 50 | |
| 51 return_trace (out); | |
| 52 } | |
| 53 | |
| 54 bool sanitize (hb_sanitize_context_t *c, const void *base) const | |
| 55 { | |
| 56 TRACE_SANITIZE (this); | |
| 57 return_trace (c->check_struct (this) && deviceTable.sanitize (c, base)); | |
| 58 } | |
| 59 | |
| 60 protected: | |
| 61 HBINT16 value; /* The X or Y value in design units */ | |
| 62 Offset16To<Device> deviceTable; /* Offset to the device table - from the | |
| 63 * beginning of parent table. May be NULL. | |
| 64 * Suggested format for device table is 1. */ | |
| 65 | |
| 66 public: | |
| 67 DEFINE_SIZE_STATIC (4); | |
| 68 }; | |
| 69 | |
| 70 struct MathConstants | |
| 71 { | |
| 72 MathConstants* copy (hb_serialize_context_t *c) const | |
| 73 { | |
| 74 TRACE_SERIALIZE (this); | |
| 75 auto *out = c->start_embed (this); | |
| 76 if (unlikely (!out)) return_trace (nullptr); | |
| 77 | |
| 78 HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2); | |
| 79 if (unlikely (!p)) return_trace (nullptr); | |
| 80 hb_memcpy (p, percentScaleDown, HBINT16::static_size * 2); | |
| 81 | |
| 82 HBUINT16 *m = c->allocate_size<HBUINT16> (HBUINT16::static_size * 2); | |
| 83 if (unlikely (!m)) return_trace (nullptr); | |
| 84 hb_memcpy (m, minHeight, HBUINT16::static_size * 2); | |
| 85 | |
| 86 unsigned count = ARRAY_LENGTH (mathValueRecords); | |
| 87 for (unsigned i = 0; i < count; i++) | |
| 88 if (!c->copy (mathValueRecords[i], this)) | |
| 89 return_trace (nullptr); | |
| 90 | |
| 91 if (!c->embed (radicalDegreeBottomRaisePercent)) return_trace (nullptr); | |
| 92 return_trace (out); | |
| 93 } | |
| 94 | |
| 95 bool sanitize_math_value_records (hb_sanitize_context_t *c) const | |
| 96 { | |
| 97 TRACE_SANITIZE (this); | |
| 98 | |
| 99 unsigned int count = ARRAY_LENGTH (mathValueRecords); | |
| 100 for (unsigned int i = 0; i < count; i++) | |
| 101 if (!mathValueRecords[i].sanitize (c, this)) | |
| 102 return_trace (false); | |
| 103 | |
| 104 return_trace (true); | |
| 105 } | |
| 106 | |
| 107 bool sanitize (hb_sanitize_context_t *c) const | |
| 108 { | |
| 109 TRACE_SANITIZE (this); | |
| 110 return_trace (c->check_struct (this) && sanitize_math_value_records (c)); | |
| 111 } | |
| 112 | |
| 113 hb_position_t get_value (hb_ot_math_constant_t constant, | |
| 114 hb_font_t *font) const | |
| 115 { | |
| 116 switch (constant) { | |
| 117 | |
| 118 case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: | |
| 119 case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: | |
| 120 return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; | |
| 121 | |
| 122 case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: | |
| 123 case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: | |
| 124 return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]); | |
| 125 | |
| 126 case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: | |
| 127 case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: | |
| 128 case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: | |
| 129 case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: | |
| 130 return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value (font, this); | |
| 131 | |
| 132 case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: | |
| 133 case HB_OT_MATH_CONSTANT_AXIS_HEIGHT: | |
| 134 case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: | |
| 135 case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: | |
| 136 case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: | |
| 137 case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: | |
| 138 case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: | |
| 139 case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: | |
| 140 case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: | |
| 141 case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: | |
| 142 case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: | |
| 143 case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: | |
| 144 case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: | |
| 145 case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: | |
| 146 case HB_OT_MATH_CONSTANT_MATH_LEADING: | |
| 147 case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: | |
| 148 case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: | |
| 149 case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: | |
| 150 case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: | |
| 151 case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: | |
| 152 case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: | |
| 153 case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: | |
| 154 case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: | |
| 155 case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: | |
| 156 case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: | |
| 157 case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: | |
| 158 case HB_OT_MATH_CONSTANT_STACK_GAP_MIN: | |
| 159 case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: | |
| 160 case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: | |
| 161 case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: | |
| 162 case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: | |
| 163 case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: | |
| 164 case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: | |
| 165 case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: | |
| 166 case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: | |
| 167 case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: | |
| 168 case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: | |
| 169 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: | |
| 170 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: | |
| 171 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: | |
| 172 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: | |
| 173 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: | |
| 174 case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: | |
| 175 case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: | |
| 176 case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: | |
| 177 case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: | |
| 178 case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: | |
| 179 return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value (font, this); | |
| 180 | |
| 181 case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: | |
| 182 return radicalDegreeBottomRaisePercent; | |
| 183 | |
| 184 default: | |
| 185 return 0; | |
| 186 } | |
| 187 } | |
| 188 | |
| 189 protected: | |
| 190 HBINT16 percentScaleDown[2]; | |
| 191 HBUINT16 minHeight[2]; | |
| 192 MathValueRecord mathValueRecords[51]; | |
| 193 HBINT16 radicalDegreeBottomRaisePercent; | |
| 194 | |
| 195 public: | |
| 196 DEFINE_SIZE_STATIC (214); | |
| 197 }; | |
| 198 | |
| 199 struct MathItalicsCorrectionInfo | |
| 200 { | |
| 201 bool subset (hb_subset_context_t *c) const | |
| 202 { | |
| 203 TRACE_SUBSET (this); | |
| 204 const hb_set_t &glyphset = *c->plan->_glyphset_mathed; | |
| 205 const hb_map_t &glyph_map = *c->plan->glyph_map; | |
| 206 | |
| 207 auto *out = c->serializer->start_embed (*this); | |
| 208 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| 209 | |
| 210 hb_sorted_vector_t<hb_codepoint_t> new_coverage; | |
| 211 + hb_zip (this+coverage, italicsCorrection) | |
| 212 | hb_filter (glyphset, hb_first) | |
| 213 | hb_filter (serialize_math_record_array (c->serializer, out->italicsCorrection, this), hb_second) | |
| 214 | hb_map (hb_first) | |
| 215 | hb_map (glyph_map) | |
| 216 | hb_sink (new_coverage) | |
| 217 ; | |
| 218 | |
| 219 out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); | |
| 220 return_trace (true); | |
| 221 } | |
| 222 | |
| 223 bool sanitize (hb_sanitize_context_t *c) const | |
| 224 { | |
| 225 TRACE_SANITIZE (this); | |
| 226 return_trace (c->check_struct (this) && | |
| 227 coverage.sanitize (c, this) && | |
| 228 italicsCorrection.sanitize (c, this)); | |
| 229 } | |
| 230 | |
| 231 hb_position_t get_value (hb_codepoint_t glyph, | |
| 232 hb_font_t *font) const | |
| 233 { | |
| 234 unsigned int index = (this+coverage).get_coverage (glyph); | |
| 235 return italicsCorrection[index].get_x_value (font, this); | |
| 236 } | |
| 237 | |
| 238 protected: | |
| 239 Offset16To<Coverage> coverage; /* Offset to Coverage table - | |
| 240 * from the beginning of | |
| 241 * MathItalicsCorrectionInfo | |
| 242 * table. */ | |
| 243 Array16Of<MathValueRecord> italicsCorrection; /* Array of MathValueRecords | |
| 244 * defining italics correction | |
| 245 * values for each | |
| 246 * covered glyph. */ | |
| 247 | |
| 248 public: | |
| 249 DEFINE_SIZE_ARRAY (4, italicsCorrection); | |
| 250 }; | |
| 251 | |
| 252 struct MathTopAccentAttachment | |
| 253 { | |
| 254 bool subset (hb_subset_context_t *c) const | |
| 255 { | |
| 256 TRACE_SUBSET (this); | |
| 257 const hb_set_t &glyphset = *c->plan->_glyphset_mathed; | |
| 258 const hb_map_t &glyph_map = *c->plan->glyph_map; | |
| 259 | |
| 260 auto *out = c->serializer->start_embed (*this); | |
| 261 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| 262 | |
| 263 hb_sorted_vector_t<hb_codepoint_t> new_coverage; | |
| 264 + hb_zip (this+topAccentCoverage, topAccentAttachment) | |
| 265 | hb_filter (glyphset, hb_first) | |
| 266 | hb_filter (serialize_math_record_array (c->serializer, out->topAccentAttachment, this), hb_second) | |
| 267 | hb_map (hb_first) | |
| 268 | hb_map (glyph_map) | |
| 269 | hb_sink (new_coverage) | |
| 270 ; | |
| 271 | |
| 272 out->topAccentCoverage.serialize_serialize (c->serializer, new_coverage.iter ()); | |
| 273 return_trace (true); | |
| 274 } | |
| 275 | |
| 276 bool sanitize (hb_sanitize_context_t *c) const | |
| 277 { | |
| 278 TRACE_SANITIZE (this); | |
| 279 return_trace (c->check_struct (this) && | |
| 280 topAccentCoverage.sanitize (c, this) && | |
| 281 topAccentAttachment.sanitize (c, this)); | |
| 282 } | |
| 283 | |
| 284 hb_position_t get_value (hb_codepoint_t glyph, | |
| 285 hb_font_t *font) const | |
| 286 { | |
| 287 unsigned int index = (this+topAccentCoverage).get_coverage (glyph); | |
| 288 if (index == NOT_COVERED) | |
| 289 return font->get_glyph_h_advance (glyph) / 2; | |
| 290 return topAccentAttachment[index].get_x_value (font, this); | |
| 291 } | |
| 292 | |
| 293 protected: | |
| 294 Offset16To<Coverage> topAccentCoverage; /* Offset to Coverage table - | |
| 295 * from the beginning of | |
| 296 * MathTopAccentAttachment | |
| 297 * table. */ | |
| 298 Array16Of<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords | |
| 299 * defining top accent | |
| 300 * attachment points for each | |
| 301 * covered glyph. */ | |
| 302 | |
| 303 public: | |
| 304 DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); | |
| 305 }; | |
| 306 | |
| 307 struct MathKern | |
| 308 { | |
| 309 MathKern* copy (hb_serialize_context_t *c) const | |
| 310 { | |
| 311 TRACE_SERIALIZE (this); | |
| 312 auto *out = c->start_embed (this); | |
| 313 if (unlikely (!out)) return_trace (nullptr); | |
| 314 | |
| 315 if (unlikely (!c->embed (heightCount))) return_trace (nullptr); | |
| 316 | |
| 317 unsigned count = 2 * heightCount + 1; | |
| 318 for (unsigned i = 0; i < count; i++) | |
| 319 if (!c->copy (mathValueRecordsZ.arrayZ[i], this)) | |
| 320 return_trace (nullptr); | |
| 321 | |
| 322 return_trace (out); | |
| 323 } | |
| 324 | |
| 325 bool sanitize_math_value_records (hb_sanitize_context_t *c) const | |
| 326 { | |
| 327 TRACE_SANITIZE (this); | |
| 328 unsigned int count = 2 * heightCount + 1; | |
| 329 for (unsigned int i = 0; i < count; i++) | |
| 330 if (!mathValueRecordsZ.arrayZ[i].sanitize (c, this)) return_trace (false); | |
| 331 return_trace (true); | |
| 332 } | |
| 333 | |
| 334 bool sanitize (hb_sanitize_context_t *c) const | |
| 335 { | |
| 336 TRACE_SANITIZE (this); | |
| 337 return_trace (c->check_struct (this) && | |
| 338 c->check_array (mathValueRecordsZ.arrayZ, 2 * heightCount + 1) && | |
| 339 sanitize_math_value_records (c)); | |
| 340 } | |
| 341 | |
| 342 hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const | |
| 343 { | |
| 344 const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ; | |
| 345 const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount; | |
| 346 int sign = font->y_scale < 0 ? -1 : +1; | |
| 347 | |
| 348 /* The description of the MathKern table is a ambiguous, but interpreting | |
| 349 * "between the two heights found at those indexes" for 0 < i < len as | |
| 350 * | |
| 351 * correctionHeight[i-1] < correction_height <= correctionHeight[i] | |
| 352 * | |
| 353 * makes the result consistent with the limit cases and we can just use the | |
| 354 * binary search algorithm of std::upper_bound: | |
| 355 */ | |
| 356 unsigned int i = 0; | |
| 357 unsigned int count = heightCount; | |
| 358 while (count > 0) | |
| 359 { | |
| 360 unsigned int half = count / 2; | |
| 361 hb_position_t height = correctionHeight[i + half].get_y_value (font, this); | |
| 362 if (sign * height < sign * correction_height) | |
| 363 { | |
| 364 i += half + 1; | |
| 365 count -= half + 1; | |
| 366 } else | |
| 367 count = half; | |
| 368 } | |
| 369 return kernValue[i].get_x_value (font, this); | |
| 370 } | |
| 371 | |
| 372 unsigned int get_entries (unsigned int start_offset, | |
| 373 unsigned int *entries_count, /* IN/OUT */ | |
| 374 hb_ot_math_kern_entry_t *kern_entries, /* OUT */ | |
| 375 hb_font_t *font) const | |
| 376 { | |
| 377 const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ; | |
| 378 const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount; | |
| 379 const unsigned int entriesCount = heightCount + 1; | |
| 380 | |
| 381 if (entries_count) | |
| 382 { | |
| 383 unsigned int start = hb_min (start_offset, entriesCount); | |
| 384 unsigned int end = hb_min (start + *entries_count, entriesCount); | |
| 385 *entries_count = end - start; | |
| 386 | |
| 387 for (unsigned int i = 0; i < *entries_count; i++) { | |
| 388 unsigned int j = start + i; | |
| 389 | |
| 390 hb_position_t max_height; | |
| 391 if (j == heightCount) { | |
| 392 max_height = INT32_MAX; | |
| 393 } else { | |
| 394 max_height = correctionHeight[j].get_y_value (font, this); | |
| 395 } | |
| 396 | |
| 397 kern_entries[i] = {max_height, kernValue[j].get_x_value (font, this)}; | |
| 398 } | |
| 399 } | |
| 400 return entriesCount; | |
| 401 } | |
| 402 | |
| 403 protected: | |
| 404 HBUINT16 heightCount; | |
| 405 UnsizedArrayOf<MathValueRecord> | |
| 406 mathValueRecordsZ; | |
| 407 /* Array of correction heights at | |
| 408 * which the kern value changes. | |
| 409 * Sorted by the height value in | |
| 410 * design units (heightCount entries), | |
| 411 * Followed by: | |
| 412 * Array of kern values corresponding | |
| 413 * to heights. (heightCount+1 entries). | |
| 414 */ | |
| 415 | |
| 416 public: | |
| 417 DEFINE_SIZE_ARRAY (2, mathValueRecordsZ); | |
| 418 }; | |
| 419 | |
| 420 struct MathKernInfoRecord | |
| 421 { | |
| 422 MathKernInfoRecord* copy (hb_serialize_context_t *c, const void *base) const | |
| 423 { | |
| 424 TRACE_SERIALIZE (this); | |
| 425 auto *out = c->embed (this); | |
| 426 if (unlikely (!out)) return_trace (nullptr); | |
| 427 | |
| 428 unsigned count = ARRAY_LENGTH (mathKern); | |
| 429 for (unsigned i = 0; i < count; i++) | |
| 430 out->mathKern[i].serialize_copy (c, mathKern[i], base, 0, hb_serialize_context_t::Head); | |
| 431 | |
| 432 return_trace (out); | |
| 433 } | |
| 434 | |
| 435 bool sanitize (hb_sanitize_context_t *c, const void *base) const | |
| 436 { | |
| 437 TRACE_SANITIZE (this); | |
| 438 | |
| 439 unsigned int count = ARRAY_LENGTH (mathKern); | |
| 440 for (unsigned int i = 0; i < count; i++) | |
| 441 if (unlikely (!mathKern[i].sanitize (c, base))) | |
| 442 return_trace (false); | |
| 443 | |
| 444 return_trace (true); | |
| 445 } | |
| 446 | |
| 447 hb_position_t get_kerning (hb_ot_math_kern_t kern, | |
| 448 hb_position_t correction_height, | |
| 449 hb_font_t *font, | |
| 450 const void *base) const | |
| 451 { | |
| 452 unsigned int idx = kern; | |
| 453 if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0; | |
| 454 return (base+mathKern[idx]).get_value (correction_height, font); | |
| 455 } | |
| 456 | |
| 457 unsigned int get_kernings (hb_ot_math_kern_t kern, | |
| 458 unsigned int start_offset, | |
| 459 unsigned int *entries_count, /* IN/OUT */ | |
| 460 hb_ot_math_kern_entry_t *kern_entries, /* OUT */ | |
| 461 hb_font_t *font, | |
| 462 const void *base) const | |
| 463 { | |
| 464 unsigned int idx = kern; | |
| 465 if (unlikely (idx >= ARRAY_LENGTH (mathKern)) || !mathKern[idx]) { | |
| 466 if (entries_count) *entries_count = 0; | |
| 467 return 0; | |
| 468 } | |
| 469 return (base+mathKern[idx]).get_entries (start_offset, | |
| 470 entries_count, | |
| 471 kern_entries, | |
| 472 font); | |
| 473 } | |
| 474 | |
| 475 protected: | |
| 476 /* Offset to MathKern table for each corner - | |
| 477 * from the beginning of MathKernInfo table. May be NULL. */ | |
| 478 Offset16To<MathKern> mathKern[4]; | |
| 479 | |
| 480 public: | |
| 481 DEFINE_SIZE_STATIC (8); | |
| 482 }; | |
| 483 | |
| 484 struct MathKernInfo | |
| 485 { | |
| 486 bool subset (hb_subset_context_t *c) const | |
| 487 { | |
| 488 TRACE_SUBSET (this); | |
| 489 const hb_set_t &glyphset = *c->plan->_glyphset_mathed; | |
| 490 const hb_map_t &glyph_map = *c->plan->glyph_map; | |
| 491 | |
| 492 auto *out = c->serializer->start_embed (*this); | |
| 493 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| 494 | |
| 495 hb_sorted_vector_t<hb_codepoint_t> new_coverage; | |
| 496 + hb_zip (this+mathKernCoverage, mathKernInfoRecords) | |
| 497 | hb_filter (glyphset, hb_first) | |
| 498 | hb_filter (serialize_math_record_array (c->serializer, out->mathKernInfoRecords, this), hb_second) | |
| 499 | hb_map (hb_first) | |
| 500 | hb_map (glyph_map) | |
| 501 | hb_sink (new_coverage) | |
| 502 ; | |
| 503 | |
| 504 out->mathKernCoverage.serialize_serialize (c->serializer, new_coverage.iter ()); | |
| 505 return_trace (true); | |
| 506 } | |
| 507 | |
| 508 bool sanitize (hb_sanitize_context_t *c) const | |
| 509 { | |
| 510 TRACE_SANITIZE (this); | |
| 511 return_trace (c->check_struct (this) && | |
| 512 mathKernCoverage.sanitize (c, this) && | |
| 513 mathKernInfoRecords.sanitize (c, this)); | |
| 514 } | |
| 515 | |
| 516 hb_position_t get_kerning (hb_codepoint_t glyph, | |
| 517 hb_ot_math_kern_t kern, | |
| 518 hb_position_t correction_height, | |
| 519 hb_font_t *font) const | |
| 520 { | |
| 521 unsigned int index = (this+mathKernCoverage).get_coverage (glyph); | |
| 522 return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); | |
| 523 } | |
| 524 | |
| 525 unsigned int get_kernings (hb_codepoint_t glyph, | |
| 526 hb_ot_math_kern_t kern, | |
| 527 unsigned int start_offset, | |
| 528 unsigned int *entries_count, /* IN/OUT */ | |
| 529 hb_ot_math_kern_entry_t *kern_entries, /* OUT */ | |
| 530 hb_font_t *font) const | |
| 531 { | |
| 532 unsigned int index = (this+mathKernCoverage).get_coverage (glyph); | |
| 533 return mathKernInfoRecords[index].get_kernings (kern, | |
| 534 start_offset, | |
| 535 entries_count, | |
| 536 kern_entries, | |
| 537 font, | |
| 538 this); | |
| 539 } | |
| 540 | |
| 541 protected: | |
| 542 Offset16To<Coverage> | |
| 543 mathKernCoverage; | |
| 544 /* Offset to Coverage table - | |
| 545 * from the beginning of the | |
| 546 * MathKernInfo table. */ | |
| 547 Array16Of<MathKernInfoRecord> | |
| 548 mathKernInfoRecords; | |
| 549 /* Array of MathKernInfoRecords, | |
| 550 * per-glyph information for | |
| 551 * mathematical positioning | |
| 552 * of subscripts and | |
| 553 * superscripts. */ | |
| 554 | |
| 555 public: | |
| 556 DEFINE_SIZE_ARRAY (4, mathKernInfoRecords); | |
| 557 }; | |
| 558 | |
| 559 struct MathGlyphInfo | |
| 560 { | |
| 561 bool subset (hb_subset_context_t *c) const | |
| 562 { | |
| 563 TRACE_SUBSET (this); | |
| 564 auto *out = c->serializer->embed (*this); | |
| 565 if (unlikely (!out)) return_trace (false); | |
| 566 | |
| 567 out->mathItalicsCorrectionInfo.serialize_subset (c, mathItalicsCorrectionInfo, this); | |
| 568 out->mathTopAccentAttachment.serialize_subset (c, mathTopAccentAttachment, this); | |
| 569 | |
| 570 const hb_set_t &glyphset = *c->plan->_glyphset_mathed; | |
| 571 const hb_map_t &glyph_map = *c->plan->glyph_map; | |
| 572 | |
| 573 auto it = | |
| 574 + hb_iter (this+extendedShapeCoverage) | |
| 575 | hb_filter (glyphset) | |
| 576 | hb_map_retains_sorting (glyph_map) | |
| 577 ; | |
| 578 | |
| 579 if (it) out->extendedShapeCoverage.serialize_serialize (c->serializer, it); | |
| 580 else out->extendedShapeCoverage = 0; | |
| 581 | |
| 582 out->mathKernInfo.serialize_subset (c, mathKernInfo, this); | |
| 583 return_trace (true); | |
| 584 } | |
| 585 | |
| 586 bool sanitize (hb_sanitize_context_t *c) const | |
| 587 { | |
| 588 TRACE_SANITIZE (this); | |
| 589 return_trace (c->check_struct (this) && | |
| 590 mathItalicsCorrectionInfo.sanitize (c, this) && | |
| 591 mathTopAccentAttachment.sanitize (c, this) && | |
| 592 extendedShapeCoverage.sanitize (c, this) && | |
| 593 mathKernInfo.sanitize (c, this)); | |
| 594 } | |
| 595 | |
| 596 hb_position_t | |
| 597 get_italics_correction (hb_codepoint_t glyph, hb_font_t *font) const | |
| 598 { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); } | |
| 599 | |
| 600 hb_position_t | |
| 601 get_top_accent_attachment (hb_codepoint_t glyph, hb_font_t *font) const | |
| 602 { return (this+mathTopAccentAttachment).get_value (glyph, font); } | |
| 603 | |
| 604 bool is_extended_shape (hb_codepoint_t glyph) const | |
| 605 { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; } | |
| 606 | |
| 607 hb_position_t get_kerning (hb_codepoint_t glyph, | |
| 608 hb_ot_math_kern_t kern, | |
| 609 hb_position_t correction_height, | |
| 610 hb_font_t *font) const | |
| 611 { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } | |
| 612 | |
| 613 hb_position_t get_kernings (hb_codepoint_t glyph, | |
| 614 hb_ot_math_kern_t kern, | |
| 615 unsigned int start_offset, | |
| 616 unsigned int *entries_count, /* IN/OUT */ | |
| 617 hb_ot_math_kern_entry_t *kern_entries, /* OUT */ | |
| 618 hb_font_t *font) const | |
| 619 { return (this+mathKernInfo).get_kernings (glyph, | |
| 620 kern, | |
| 621 start_offset, | |
| 622 entries_count, | |
| 623 kern_entries, | |
| 624 font); } | |
| 625 | |
| 626 protected: | |
| 627 /* Offset to MathItalicsCorrectionInfo table - | |
| 628 * from the beginning of MathGlyphInfo table. */ | |
| 629 Offset16To<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo; | |
| 630 | |
| 631 /* Offset to MathTopAccentAttachment table - | |
| 632 * from the beginning of MathGlyphInfo table. */ | |
| 633 Offset16To<MathTopAccentAttachment> mathTopAccentAttachment; | |
| 634 | |
| 635 /* Offset to coverage table for Extended Shape glyphs - | |
| 636 * from the beginning of MathGlyphInfo table. When the left or right glyph of | |
| 637 * a box is an extended shape variant, the (ink) box (and not the default | |
| 638 * position defined by values in MathConstants table) should be used for | |
| 639 * vertical positioning purposes. May be NULL.. */ | |
| 640 Offset16To<Coverage> extendedShapeCoverage; | |
| 641 | |
| 642 /* Offset to MathKernInfo table - | |
| 643 * from the beginning of MathGlyphInfo table. */ | |
| 644 Offset16To<MathKernInfo> mathKernInfo; | |
| 645 | |
| 646 public: | |
| 647 DEFINE_SIZE_STATIC (8); | |
| 648 }; | |
| 649 | |
| 650 struct MathGlyphVariantRecord | |
| 651 { | |
| 652 friend struct MathGlyphConstruction; | |
| 653 | |
| 654 bool subset (hb_subset_context_t *c) const | |
| 655 { | |
| 656 TRACE_SUBSET (this); | |
| 657 auto *out = c->serializer->embed (this); | |
| 658 if (unlikely (!out)) return_trace (false); | |
| 659 | |
| 660 const hb_map_t& glyph_map = *c->plan->glyph_map; | |
| 661 return_trace (c->serializer->check_assign (out->variantGlyph, glyph_map.get (variantGlyph), HB_SERIALIZE_ERROR_INT_OVERFLOW)); | |
| 662 } | |
| 663 | |
| 664 bool sanitize (hb_sanitize_context_t *c) const | |
| 665 { | |
| 666 TRACE_SANITIZE (this); | |
| 667 return_trace (c->check_struct (this)); | |
| 668 } | |
| 669 | |
| 670 void closure_glyphs (hb_set_t *variant_glyphs) const | |
| 671 { variant_glyphs->add (variantGlyph); } | |
| 672 | |
| 673 protected: | |
| 674 HBGlyphID16 variantGlyph; /* Glyph ID for the variant. */ | |
| 675 HBUINT16 advanceMeasurement; /* Advance width/height, in design units, of the | |
| 676 * variant, in the direction of requested | |
| 677 * glyph extension. */ | |
| 678 | |
| 679 public: | |
| 680 DEFINE_SIZE_STATIC (4); | |
| 681 }; | |
| 682 | |
| 683 struct PartFlags : HBUINT16 | |
| 684 { | |
| 685 enum Flags { | |
| 686 Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ | |
| 687 | |
| 688 Defined = 0x0001u, /* All defined flags. */ | |
| 689 }; | |
| 690 | |
| 691 public: | |
| 692 DEFINE_SIZE_STATIC (2); | |
| 693 }; | |
| 694 | |
| 695 struct MathGlyphPartRecord | |
| 696 { | |
| 697 bool subset (hb_subset_context_t *c) const | |
| 698 { | |
| 699 TRACE_SUBSET (this); | |
| 700 auto *out = c->serializer->embed (this); | |
| 701 if (unlikely (!out)) return_trace (false); | |
| 702 | |
| 703 const hb_map_t& glyph_map = *c->plan->glyph_map; | |
| 704 return_trace (c->serializer->check_assign (out->glyph, glyph_map.get (glyph), HB_SERIALIZE_ERROR_INT_OVERFLOW)); | |
| 705 } | |
| 706 | |
| 707 bool sanitize (hb_sanitize_context_t *c) const | |
| 708 { | |
| 709 TRACE_SANITIZE (this); | |
| 710 return_trace (c->check_struct (this)); | |
| 711 } | |
| 712 | |
| 713 void extract (hb_ot_math_glyph_part_t &out, | |
| 714 int64_t mult, | |
| 715 hb_font_t *font) const | |
| 716 { | |
| 717 out.glyph = glyph; | |
| 718 | |
| 719 out.start_connector_length = font->em_mult (startConnectorLength, mult); | |
| 720 out.end_connector_length = font->em_mult (endConnectorLength, mult); | |
| 721 out.full_advance = font->em_mult (fullAdvance, mult); | |
| 722 | |
| 723 static_assert ((unsigned int) HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER == | |
| 724 (unsigned int) PartFlags::Extender, ""); | |
| 725 | |
| 726 out.flags = (hb_ot_math_glyph_part_flags_t) | |
| 727 (unsigned int) | |
| 728 (partFlags & PartFlags::Defined); | |
| 729 } | |
| 730 | |
| 731 void closure_glyphs (hb_set_t *variant_glyphs) const | |
| 732 { variant_glyphs->add (glyph); } | |
| 733 | |
| 734 protected: | |
| 735 HBGlyphID16 glyph; /* Glyph ID for the part. */ | |
| 736 HBUINT16 startConnectorLength; | |
| 737 /* Advance width/ height of the straight bar | |
| 738 * connector material, in design units, is at | |
| 739 * the beginning of the glyph, in the | |
| 740 * direction of the extension. */ | |
| 741 HBUINT16 endConnectorLength; | |
| 742 /* Advance width/ height of the straight bar | |
| 743 * connector material, in design units, is at | |
| 744 * the end of the glyph, in the direction of | |
| 745 * the extension. */ | |
| 746 HBUINT16 fullAdvance; /* Full advance width/height for this part, | |
| 747 * in the direction of the extension. | |
| 748 * In design units. */ | |
| 749 PartFlags partFlags; /* Part qualifiers. */ | |
| 750 | |
| 751 public: | |
| 752 DEFINE_SIZE_STATIC (10); | |
| 753 }; | |
| 754 | |
| 755 struct MathGlyphAssembly | |
| 756 { | |
| 757 bool subset (hb_subset_context_t *c) const | |
| 758 { | |
| 759 TRACE_SUBSET (this); | |
| 760 auto *out = c->serializer->start_embed (*this); | |
| 761 if (unlikely (!out)) return_trace (false); | |
| 762 | |
| 763 if (!c->serializer->copy (italicsCorrection, this)) return_trace (false); | |
| 764 if (!c->serializer->copy<HBUINT16> (partRecords.len)) return_trace (false); | |
| 765 | |
| 766 for (const auto& record : partRecords.iter ()) | |
| 767 if (!record.subset (c)) return_trace (false); | |
| 768 return_trace (true); | |
| 769 } | |
| 770 | |
| 771 bool sanitize (hb_sanitize_context_t *c) const | |
| 772 { | |
| 773 TRACE_SANITIZE (this); | |
| 774 return_trace (c->check_struct (this) && | |
| 775 italicsCorrection.sanitize (c, this) && | |
| 776 partRecords.sanitize (c)); | |
| 777 } | |
| 778 | |
| 779 unsigned int get_parts (hb_direction_t direction, | |
| 780 hb_font_t *font, | |
| 781 unsigned int start_offset, | |
| 782 unsigned int *parts_count, /* IN/OUT */ | |
| 783 hb_ot_math_glyph_part_t *parts /* OUT */, | |
| 784 hb_position_t *italics_correction /* OUT */) const | |
| 785 { | |
| 786 if (parts_count) | |
| 787 { | |
| 788 int64_t mult = font->dir_mult (direction); | |
| 789 for (auto _ : hb_zip (partRecords.as_array ().sub_array (start_offset, parts_count), | |
| 790 hb_array (parts, *parts_count))) | |
| 791 _.first.extract (_.second, mult, font); | |
| 792 } | |
| 793 | |
| 794 if (italics_correction) | |
| 795 *italics_correction = italicsCorrection.get_x_value (font, this); | |
| 796 | |
| 797 return partRecords.len; | |
| 798 } | |
| 799 | |
| 800 void closure_glyphs (hb_set_t *variant_glyphs) const | |
| 801 { | |
| 802 for (const auto& _ : partRecords.iter ()) | |
| 803 _.closure_glyphs (variant_glyphs); | |
| 804 } | |
| 805 | |
| 806 protected: | |
| 807 MathValueRecord | |
| 808 italicsCorrection; | |
| 809 /* Italics correction of this | |
| 810 * MathGlyphAssembly. Should not | |
| 811 * depend on the assembly size. */ | |
| 812 Array16Of<MathGlyphPartRecord> | |
| 813 partRecords; /* Array of part records, from | |
| 814 * left to right and bottom to | |
| 815 * top. */ | |
| 816 | |
| 817 public: | |
| 818 DEFINE_SIZE_ARRAY (6, partRecords); | |
| 819 }; | |
| 820 | |
| 821 struct MathGlyphConstruction | |
| 822 { | |
| 823 bool subset (hb_subset_context_t *c) const | |
| 824 { | |
| 825 TRACE_SUBSET (this); | |
| 826 auto *out = c->serializer->start_embed (*this); | |
| 827 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| 828 | |
| 829 out->glyphAssembly.serialize_subset (c, glyphAssembly, this); | |
| 830 | |
| 831 if (!c->serializer->check_assign (out->mathGlyphVariantRecord.len, mathGlyphVariantRecord.len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) | |
| 832 return_trace (false); | |
| 833 for (const auto& record : mathGlyphVariantRecord.iter ()) | |
| 834 if (!record.subset (c)) return_trace (false); | |
| 835 | |
| 836 return_trace (true); | |
| 837 } | |
| 838 | |
| 839 bool sanitize (hb_sanitize_context_t *c) const | |
| 840 { | |
| 841 TRACE_SANITIZE (this); | |
| 842 return_trace (c->check_struct (this) && | |
| 843 glyphAssembly.sanitize (c, this) && | |
| 844 mathGlyphVariantRecord.sanitize (c)); | |
| 845 } | |
| 846 | |
| 847 const MathGlyphAssembly &get_assembly () const { return this+glyphAssembly; } | |
| 848 | |
| 849 unsigned int get_variants (hb_direction_t direction, | |
| 850 hb_font_t *font, | |
| 851 unsigned int start_offset, | |
| 852 unsigned int *variants_count, /* IN/OUT */ | |
| 853 hb_ot_math_glyph_variant_t *variants /* OUT */) const | |
| 854 { | |
| 855 if (variants_count) | |
| 856 { | |
| 857 int64_t mult = font->dir_mult (direction); | |
| 858 for (auto _ : hb_zip (mathGlyphVariantRecord.as_array ().sub_array (start_offset, variants_count), | |
| 859 hb_array (variants, *variants_count))) | |
| 860 _.second = {_.first.variantGlyph, font->em_mult (_.first.advanceMeasurement, mult)}; | |
| 861 } | |
| 862 return mathGlyphVariantRecord.len; | |
| 863 } | |
| 864 | |
| 865 void closure_glyphs (hb_set_t *variant_glyphs) const | |
| 866 { | |
| 867 (this+glyphAssembly).closure_glyphs (variant_glyphs); | |
| 868 | |
| 869 for (const auto& _ : mathGlyphVariantRecord.iter ()) | |
| 870 _.closure_glyphs (variant_glyphs); | |
| 871 } | |
| 872 | |
| 873 protected: | |
| 874 /* Offset to MathGlyphAssembly table for this shape - from the beginning of | |
| 875 MathGlyphConstruction table. May be NULL. */ | |
| 876 Offset16To<MathGlyphAssembly> glyphAssembly; | |
| 877 | |
| 878 /* MathGlyphVariantRecords for alternative variants of the glyphs. */ | |
| 879 Array16Of<MathGlyphVariantRecord> mathGlyphVariantRecord; | |
| 880 | |
| 881 public: | |
| 882 DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord); | |
| 883 }; | |
| 884 | |
| 885 struct MathVariants | |
| 886 { | |
| 887 void closure_glyphs (const hb_set_t *glyph_set, | |
| 888 hb_set_t *variant_glyphs) const | |
| 889 { | |
| 890 const hb_array_t<const Offset16To<MathGlyphConstruction>> glyph_construction_offsets = glyphConstruction.as_array (vertGlyphCount + horizGlyphCount); | |
| 891 | |
| 892 if (vertGlyphCoverage) | |
| 893 { | |
| 894 const auto vert_offsets = glyph_construction_offsets.sub_array (0, vertGlyphCount); | |
| 895 + hb_zip (this+vertGlyphCoverage, vert_offsets) | |
| 896 | hb_filter (glyph_set, hb_first) | |
| 897 | hb_map (hb_second) | |
| 898 | hb_map (hb_add (this)) | |
| 899 | hb_apply ([=] (const MathGlyphConstruction &_) { _.closure_glyphs (variant_glyphs); }) | |
| 900 ; | |
| 901 } | |
| 902 | |
| 903 if (horizGlyphCoverage) | |
| 904 { | |
| 905 const auto hori_offsets = glyph_construction_offsets.sub_array (vertGlyphCount, horizGlyphCount); | |
| 906 + hb_zip (this+horizGlyphCoverage, hori_offsets) | |
| 907 | hb_filter (glyph_set, hb_first) | |
| 908 | hb_map (hb_second) | |
| 909 | hb_map (hb_add (this)) | |
| 910 | hb_apply ([=] (const MathGlyphConstruction &_) { _.closure_glyphs (variant_glyphs); }) | |
| 911 ; | |
| 912 } | |
| 913 } | |
| 914 | |
| 915 void collect_coverage_and_indices (hb_sorted_vector_t<hb_codepoint_t>& new_coverage, | |
| 916 const Offset16To<Coverage>& coverage, | |
| 917 unsigned i, | |
| 918 unsigned end_index, | |
| 919 hb_set_t& indices, | |
| 920 const hb_set_t& glyphset, | |
| 921 const hb_map_t& glyph_map) const | |
| 922 { | |
| 923 if (!coverage) return; | |
| 924 | |
| 925 for (const auto _ : (this+coverage).iter ()) | |
| 926 { | |
| 927 if (i >= end_index) return; | |
| 928 if (glyphset.has (_)) | |
| 929 { | |
| 930 unsigned new_gid = glyph_map.get (_); | |
| 931 new_coverage.push (new_gid); | |
| 932 indices.add (i); | |
| 933 } | |
| 934 i++; | |
| 935 } | |
| 936 } | |
| 937 | |
| 938 bool subset (hb_subset_context_t *c) const | |
| 939 { | |
| 940 TRACE_SUBSET (this); | |
| 941 const hb_set_t &glyphset = *c->plan->_glyphset_mathed; | |
| 942 const hb_map_t &glyph_map = *c->plan->glyph_map; | |
| 943 | |
| 944 auto *out = c->serializer->start_embed (*this); | |
| 945 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| 946 if (!c->serializer->check_assign (out->minConnectorOverlap, minConnectorOverlap, HB_SERIALIZE_ERROR_INT_OVERFLOW)) | |
| 947 return_trace (false); | |
| 948 | |
| 949 hb_sorted_vector_t<hb_codepoint_t> new_vert_coverage; | |
| 950 hb_sorted_vector_t<hb_codepoint_t> new_hori_coverage; | |
| 951 hb_set_t indices; | |
| 952 collect_coverage_and_indices (new_vert_coverage, vertGlyphCoverage, 0, vertGlyphCount, indices, glyphset, glyph_map); | |
| 953 collect_coverage_and_indices (new_hori_coverage, horizGlyphCoverage, vertGlyphCount, vertGlyphCount + horizGlyphCount, indices, glyphset, glyph_map); | |
| 954 | |
| 955 if (!c->serializer->check_assign (out->vertGlyphCount, new_vert_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) | |
| 956 return_trace (false); | |
| 957 if (!c->serializer->check_assign (out->horizGlyphCount, new_hori_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) | |
| 958 return_trace (false); | |
| 959 | |
| 960 for (unsigned i : indices.iter ()) | |
| 961 { | |
| 962 auto *o = c->serializer->embed (glyphConstruction[i]); | |
| 963 if (!o) return_trace (false); | |
| 964 o->serialize_subset (c, glyphConstruction[i], this); | |
| 965 } | |
| 966 | |
| 967 if (new_vert_coverage) | |
| 968 out->vertGlyphCoverage.serialize_serialize (c->serializer, new_vert_coverage.iter ()); | |
| 969 | |
| 970 if (new_hori_coverage) | |
| 971 out->horizGlyphCoverage.serialize_serialize (c->serializer, new_hori_coverage.iter ()); | |
| 972 return_trace (true); | |
| 973 } | |
| 974 | |
| 975 bool sanitize_offsets (hb_sanitize_context_t *c) const | |
| 976 { | |
| 977 TRACE_SANITIZE (this); | |
| 978 unsigned int count = vertGlyphCount + horizGlyphCount; | |
| 979 for (unsigned int i = 0; i < count; i++) | |
| 980 if (!glyphConstruction.arrayZ[i].sanitize (c, this)) return_trace (false); | |
| 981 return_trace (true); | |
| 982 } | |
| 983 | |
| 984 bool sanitize (hb_sanitize_context_t *c) const | |
| 985 { | |
| 986 TRACE_SANITIZE (this); | |
| 987 return_trace (c->check_struct (this) && | |
| 988 vertGlyphCoverage.sanitize (c, this) && | |
| 989 horizGlyphCoverage.sanitize (c, this) && | |
| 990 c->check_array (glyphConstruction.arrayZ, vertGlyphCount + horizGlyphCount) && | |
| 991 sanitize_offsets (c)); | |
| 992 } | |
| 993 | |
| 994 hb_position_t get_min_connector_overlap (hb_direction_t direction, | |
| 995 hb_font_t *font) const | |
| 996 { return font->em_scale_dir (minConnectorOverlap, direction); } | |
| 997 | |
| 998 unsigned int get_glyph_variants (hb_codepoint_t glyph, | |
| 999 hb_direction_t direction, | |
| 1000 hb_font_t *font, | |
| 1001 unsigned int start_offset, | |
| 1002 unsigned int *variants_count, /* IN/OUT */ | |
| 1003 hb_ot_math_glyph_variant_t *variants /* OUT */) const | |
| 1004 { return get_glyph_construction (glyph, direction, font) | |
| 1005 .get_variants (direction, font, start_offset, variants_count, variants); } | |
| 1006 | |
| 1007 unsigned int get_glyph_parts (hb_codepoint_t glyph, | |
| 1008 hb_direction_t direction, | |
| 1009 hb_font_t *font, | |
| 1010 unsigned int start_offset, | |
| 1011 unsigned int *parts_count, /* IN/OUT */ | |
| 1012 hb_ot_math_glyph_part_t *parts /* OUT */, | |
| 1013 hb_position_t *italics_correction /* OUT */) const | |
| 1014 { return get_glyph_construction (glyph, direction, font) | |
| 1015 .get_assembly () | |
| 1016 .get_parts (direction, font, | |
| 1017 start_offset, parts_count, parts, | |
| 1018 italics_correction); } | |
| 1019 | |
| 1020 private: | |
| 1021 const MathGlyphConstruction & | |
| 1022 get_glyph_construction (hb_codepoint_t glyph, | |
| 1023 hb_direction_t direction, | |
| 1024 hb_font_t *font HB_UNUSED) const | |
| 1025 { | |
| 1026 bool vertical = HB_DIRECTION_IS_VERTICAL (direction); | |
| 1027 unsigned int count = vertical ? vertGlyphCount : horizGlyphCount; | |
| 1028 const Offset16To<Coverage> &coverage = vertical ? vertGlyphCoverage | |
| 1029 : horizGlyphCoverage; | |
| 1030 | |
| 1031 unsigned int index = (this+coverage).get_coverage (glyph); | |
| 1032 if (unlikely (index >= count)) return Null (MathGlyphConstruction); | |
| 1033 | |
| 1034 if (!vertical) | |
| 1035 index += vertGlyphCount; | |
| 1036 | |
| 1037 return this+glyphConstruction[index]; | |
| 1038 } | |
| 1039 | |
| 1040 protected: | |
| 1041 HBUINT16 minConnectorOverlap; | |
| 1042 /* Minimum overlap of connecting | |
| 1043 * glyphs during glyph construction, | |
| 1044 * in design units. */ | |
| 1045 Offset16To<Coverage> vertGlyphCoverage; | |
| 1046 /* Offset to Coverage table - | |
| 1047 * from the beginning of MathVariants | |
| 1048 * table. */ | |
| 1049 Offset16To<Coverage> horizGlyphCoverage; | |
| 1050 /* Offset to Coverage table - | |
| 1051 * from the beginning of MathVariants | |
| 1052 * table. */ | |
| 1053 HBUINT16 vertGlyphCount; /* Number of glyphs for which | |
| 1054 * information is provided for | |
| 1055 * vertically growing variants. */ | |
| 1056 HBUINT16 horizGlyphCount;/* Number of glyphs for which | |
| 1057 * information is provided for | |
| 1058 * horizontally growing variants. */ | |
| 1059 | |
| 1060 /* Array of offsets to MathGlyphConstruction tables - from the beginning of | |
| 1061 the MathVariants table, for shapes growing in vertical/horizontal | |
| 1062 direction. */ | |
| 1063 UnsizedArrayOf<Offset16To<MathGlyphConstruction>> | |
| 1064 glyphConstruction; | |
| 1065 | |
| 1066 public: | |
| 1067 DEFINE_SIZE_ARRAY (10, glyphConstruction); | |
| 1068 }; | |
| 1069 | |
| 1070 | |
| 1071 /* | |
| 1072 * MATH -- Mathematical typesetting | |
| 1073 * https://docs.microsoft.com/en-us/typography/opentype/spec/math | |
| 1074 */ | |
| 1075 | |
| 1076 struct MATH | |
| 1077 { | |
| 1078 static constexpr hb_tag_t tableTag = HB_OT_TAG_MATH; | |
| 1079 | |
| 1080 bool has_data () const { return version.to_int (); } | |
| 1081 | |
| 1082 void closure_glyphs (hb_set_t *glyph_set) const | |
| 1083 { | |
| 1084 if (mathVariants) | |
| 1085 { | |
| 1086 hb_set_t variant_glyphs; | |
| 1087 (this+mathVariants).closure_glyphs (glyph_set, &variant_glyphs); | |
| 1088 hb_set_union (glyph_set, &variant_glyphs); | |
| 1089 } | |
| 1090 } | |
| 1091 | |
| 1092 bool subset (hb_subset_context_t *c) const | |
| 1093 { | |
| 1094 TRACE_SUBSET (this); | |
| 1095 auto *out = c->serializer->embed (*this); | |
| 1096 if (unlikely (!out)) return_trace (false); | |
| 1097 | |
| 1098 out->mathConstants.serialize_copy (c->serializer, mathConstants, this, 0, hb_serialize_context_t::Head); | |
| 1099 out->mathGlyphInfo.serialize_subset (c, mathGlyphInfo, this); | |
| 1100 out->mathVariants.serialize_subset (c, mathVariants, this); | |
| 1101 return_trace (true); | |
| 1102 } | |
| 1103 | |
| 1104 bool sanitize (hb_sanitize_context_t *c) const | |
| 1105 { | |
| 1106 TRACE_SANITIZE (this); | |
| 1107 return_trace (version.sanitize (c) && | |
| 1108 likely (version.major == 1) && | |
| 1109 mathConstants.sanitize (c, this) && | |
| 1110 mathGlyphInfo.sanitize (c, this) && | |
| 1111 mathVariants.sanitize (c, this)); | |
| 1112 } | |
| 1113 | |
| 1114 hb_position_t get_constant (hb_ot_math_constant_t constant, | |
| 1115 hb_font_t *font) const | |
| 1116 { return (this+mathConstants).get_value (constant, font); } | |
| 1117 | |
| 1118 const MathGlyphInfo &get_glyph_info () const { return this+mathGlyphInfo; } | |
| 1119 | |
| 1120 const MathVariants &get_variants () const { return this+mathVariants; } | |
| 1121 | |
| 1122 protected: | |
| 1123 FixedVersion<>version; /* Version of the MATH table | |
| 1124 * initially set to 0x00010000u */ | |
| 1125 Offset16To<MathConstants> | |
| 1126 mathConstants; /* MathConstants table */ | |
| 1127 Offset16To<MathGlyphInfo> | |
| 1128 mathGlyphInfo; /* MathGlyphInfo table */ | |
| 1129 Offset16To<MathVariants> | |
| 1130 mathVariants; /* MathVariants table */ | |
| 1131 | |
| 1132 public: | |
| 1133 DEFINE_SIZE_STATIC (10); | |
| 1134 }; | |
| 1135 | |
| 1136 } /* namespace OT */ | |
| 1137 | |
| 1138 | |
| 1139 #endif /* HB_OT_MATH_TABLE_HH */ |
