| OLD | NEW |
| (Empty) | |
| 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_LAYOUT_MATH_TABLE_HH |
| 28 #define HB_OT_LAYOUT_MATH_TABLE_HH |
| 29 |
| 30 #include "hb-open-type-private.hh" |
| 31 #include "hb-ot-layout-common-private.hh" |
| 32 #include "hb-ot-math.h" |
| 33 |
| 34 namespace OT { |
| 35 |
| 36 |
| 37 struct MathValueRecord |
| 38 { |
| 39 inline 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 inline 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 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
| 45 { |
| 46 TRACE_SANITIZE (this); |
| 47 return_trace (c->check_struct (this) && deviceTable.sanitize (c, base)); |
| 48 } |
| 49 |
| 50 protected: |
| 51 SHORT value; /* The X or Y value in design units */ |
| 52 OffsetTo<Device> deviceTable; /* Offset to the device table - from the |
| 53 * beginning of parent table. May be NUL
L. |
| 54 * Suggested format for device table is
1. */ |
| 55 |
| 56 public: |
| 57 DEFINE_SIZE_STATIC (4); |
| 58 }; |
| 59 |
| 60 struct MathConstants |
| 61 { |
| 62 inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const |
| 63 { |
| 64 TRACE_SANITIZE (this); |
| 65 |
| 66 unsigned int count = ARRAY_LENGTH (mathValueRecords); |
| 67 for (unsigned int i = 0; i < count; i++) |
| 68 if (!mathValueRecords[i].sanitize (c, this)) |
| 69 return_trace (false); |
| 70 |
| 71 return_trace (true); |
| 72 } |
| 73 |
| 74 inline bool sanitize (hb_sanitize_context_t *c) const |
| 75 { |
| 76 TRACE_SANITIZE (this); |
| 77 return_trace (c->check_struct (this) && sanitize_math_value_records(c)); |
| 78 } |
| 79 |
| 80 inline hb_position_t get_value (hb_ot_math_constant_t constant, |
| 81 hb_font_t *font) const |
| 82 { |
| 83 switch (constant) { |
| 84 |
| 85 case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: |
| 86 case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: |
| 87 return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCAL
E_DOWN]; |
| 88 |
| 89 case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: |
| 90 case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: |
| 91 return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITE
D_SUB_FORMULA_MIN_HEIGHT]); |
| 92 |
| 93 case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: |
| 94 case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: |
| 95 case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: |
| 96 case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: |
| 97 return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x
_value(font, this); |
| 98 |
| 99 case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: |
| 100 case HB_OT_MATH_CONSTANT_AXIS_HEIGHT: |
| 101 case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: |
| 102 case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: |
| 103 case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: |
| 104 case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: |
| 105 case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: |
| 106 case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: |
| 107 case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: |
| 108 case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: |
| 109 case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: |
| 110 case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: |
| 111 case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: |
| 112 case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: |
| 113 case HB_OT_MATH_CONSTANT_MATH_LEADING: |
| 114 case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: |
| 115 case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: |
| 116 case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: |
| 117 case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: |
| 118 case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: |
| 119 case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: |
| 120 case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: |
| 121 case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: |
| 122 case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: |
| 123 case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: |
| 124 case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: |
| 125 case HB_OT_MATH_CONSTANT_STACK_GAP_MIN: |
| 126 case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: |
| 127 case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: |
| 128 case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: |
| 129 case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: |
| 130 case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: |
| 131 case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: |
| 132 case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: |
| 133 case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: |
| 134 case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: |
| 135 case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: |
| 136 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: |
| 137 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: |
| 138 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: |
| 139 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: |
| 140 case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: |
| 141 case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: |
| 142 case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: |
| 143 case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: |
| 144 case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: |
| 145 case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: |
| 146 return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y
_value(font, this); |
| 147 |
| 148 case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: |
| 149 return radicalDegreeBottomRaisePercent; |
| 150 |
| 151 default: |
| 152 return 0; |
| 153 } |
| 154 } |
| 155 |
| 156 protected: |
| 157 SHORT percentScaleDown[2]; |
| 158 USHORT minHeight[2]; |
| 159 MathValueRecord mathValueRecords[51]; |
| 160 SHORT radicalDegreeBottomRaisePercent; |
| 161 |
| 162 public: |
| 163 DEFINE_SIZE_STATIC (214); |
| 164 }; |
| 165 |
| 166 struct MathItalicsCorrectionInfo |
| 167 { |
| 168 inline bool sanitize (hb_sanitize_context_t *c) const |
| 169 { |
| 170 TRACE_SANITIZE (this); |
| 171 return_trace (c->check_struct (this) && |
| 172 coverage.sanitize (c, this) && |
| 173 italicsCorrection.sanitize (c, this)); |
| 174 } |
| 175 |
| 176 inline hb_position_t get_value (hb_codepoint_t glyph, |
| 177 hb_font_t *font) const |
| 178 { |
| 179 unsigned int index = (this+coverage).get_coverage (glyph); |
| 180 return italicsCorrection[index].get_x_value (font, this); |
| 181 } |
| 182 |
| 183 protected: |
| 184 OffsetTo<Coverage> coverage; /* Offset to Coverage table - |
| 185 * from the beginning of |
| 186 * MathItalicsCorrectionInfo |
| 187 * table. */ |
| 188 ArrayOf<MathValueRecord> italicsCorrection; /* Array of MathValueRecords |
| 189 * defining italics correction |
| 190 * values for each |
| 191 * covered glyph. */ |
| 192 |
| 193 public: |
| 194 DEFINE_SIZE_ARRAY (4, italicsCorrection); |
| 195 }; |
| 196 |
| 197 struct MathTopAccentAttachment |
| 198 { |
| 199 inline bool sanitize (hb_sanitize_context_t *c) const |
| 200 { |
| 201 TRACE_SANITIZE (this); |
| 202 return_trace (c->check_struct (this) && |
| 203 topAccentCoverage.sanitize (c, this) && |
| 204 topAccentAttachment.sanitize (c, this)); |
| 205 } |
| 206 |
| 207 inline hb_position_t get_value (hb_codepoint_t glyph, |
| 208 hb_font_t *font) const |
| 209 { |
| 210 unsigned int index = (this+topAccentCoverage).get_coverage (glyph); |
| 211 if (index == NOT_COVERED) |
| 212 return font->get_glyph_h_advance (glyph) / 2; |
| 213 return topAccentAttachment[index].get_x_value(font, this); |
| 214 } |
| 215 |
| 216 protected: |
| 217 OffsetTo<Coverage> topAccentCoverage; /* Offset to Coverage table - |
| 218 * from the beginning of |
| 219 * MathTopAccentAttachment |
| 220 * table. */ |
| 221 ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords |
| 222 * defining top accent |
| 223 * attachment points for each |
| 224 * covered glyph. */ |
| 225 |
| 226 public: |
| 227 DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); |
| 228 }; |
| 229 |
| 230 struct MathKern |
| 231 { |
| 232 inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const |
| 233 { |
| 234 TRACE_SANITIZE (this); |
| 235 unsigned int count = 2 * heightCount + 1; |
| 236 for (unsigned int i = 0; i < count; i++) |
| 237 if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); |
| 238 return_trace (true); |
| 239 } |
| 240 |
| 241 inline bool sanitize (hb_sanitize_context_t *c) const |
| 242 { |
| 243 TRACE_SANITIZE (this); |
| 244 return_trace (c->check_struct (this) && |
| 245 c->check_array (mathValueRecords, |
| 246 mathValueRecords[0].static_size, |
| 247 2 * heightCount + 1) && |
| 248 sanitize_math_value_records (c)); |
| 249 } |
| 250 |
| 251 inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *fo
nt) const |
| 252 { |
| 253 const MathValueRecord* correctionHeight = mathValueRecords; |
| 254 const MathValueRecord* kernValue = mathValueRecords + heightCount; |
| 255 int sign = font->y_scale < 0 ? -1 : +1; |
| 256 |
| 257 /* The description of the MathKern table is a ambiguous, but interpreting |
| 258 * "between the two heights found at those indexes" for 0 < i < len as |
| 259 * |
| 260 * correctionHeight[i-1] < correction_height <= correctionHeight[i] |
| 261 * |
| 262 * makes the result consistent with the limit cases and we can just use the |
| 263 * binary search algorithm of std::upper_bound: |
| 264 */ |
| 265 unsigned int i = 0; |
| 266 unsigned int count = heightCount; |
| 267 while (count > 0) |
| 268 { |
| 269 unsigned int half = count / 2; |
| 270 hb_position_t height = correctionHeight[i + half].get_y_value(font, this); |
| 271 if (sign * height < sign * correction_height) |
| 272 { |
| 273 i += half + 1; |
| 274 count -= half + 1; |
| 275 } else |
| 276 count = half; |
| 277 } |
| 278 return kernValue[i].get_x_value(font, this); |
| 279 } |
| 280 |
| 281 protected: |
| 282 USHORT heightCount; |
| 283 MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at |
| 284 * which the kern value changes. |
| 285 * Sorted by the height value in |
| 286 * design units (heightCount entries), |
| 287 * Followed by: |
| 288 * Array of kern values corresponding |
| 289 * to heights. (heightCount+1 entries). |
| 290 */ |
| 291 |
| 292 public: |
| 293 DEFINE_SIZE_ARRAY (2, mathValueRecords); |
| 294 }; |
| 295 |
| 296 struct MathKernInfoRecord |
| 297 { |
| 298 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
| 299 { |
| 300 TRACE_SANITIZE (this); |
| 301 |
| 302 unsigned int count = ARRAY_LENGTH (mathKern); |
| 303 for (unsigned int i = 0; i < count; i++) |
| 304 if (unlikely (!mathKern[i].sanitize (c, base))) |
| 305 return_trace (false); |
| 306 |
| 307 return_trace (true); |
| 308 } |
| 309 |
| 310 inline hb_position_t get_kerning (hb_ot_math_kern_t kern, |
| 311 hb_position_t correction_height, |
| 312 hb_font_t *font, |
| 313 const void *base) const |
| 314 { |
| 315 unsigned int idx = kern; |
| 316 if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0; |
| 317 return (base+mathKern[idx]).get_value (correction_height, font); |
| 318 } |
| 319 |
| 320 protected: |
| 321 /* Offset to MathKern table for each corner - |
| 322 * from the beginning of MathKernInfo table. May be NULL. */ |
| 323 OffsetTo<MathKern> mathKern[4]; |
| 324 |
| 325 public: |
| 326 DEFINE_SIZE_STATIC (8); |
| 327 }; |
| 328 |
| 329 struct MathKernInfo |
| 330 { |
| 331 inline bool sanitize (hb_sanitize_context_t *c) const |
| 332 { |
| 333 TRACE_SANITIZE (this); |
| 334 return_trace (c->check_struct (this) && |
| 335 mathKernCoverage.sanitize (c, this) && |
| 336 mathKernInfoRecords.sanitize (c, this)); |
| 337 } |
| 338 |
| 339 inline hb_position_t get_kerning (hb_codepoint_t glyph, |
| 340 hb_ot_math_kern_t kern, |
| 341 hb_position_t correction_height, |
| 342 hb_font_t *font) const |
| 343 { |
| 344 unsigned int index = (this+mathKernCoverage).get_coverage (glyph); |
| 345 return mathKernInfoRecords[index].get_kerning (kern, correction_height, font
, this); |
| 346 } |
| 347 |
| 348 protected: |
| 349 OffsetTo<Coverage> mathKernCoverage; /* Offset to Coverage table
- |
| 350 * from the beginning of th
e |
| 351 * MathKernInfo table. */ |
| 352 ArrayOf<MathKernInfoRecord> mathKernInfoRecords; /* Array of |
| 353 * MathKernInfoRecords, |
| 354 * per-glyph information fo
r |
| 355 * mathematical positioning |
| 356 * of subscripts and |
| 357 * superscripts. */ |
| 358 |
| 359 public: |
| 360 DEFINE_SIZE_ARRAY (4, mathKernInfoRecords); |
| 361 }; |
| 362 |
| 363 struct MathGlyphInfo |
| 364 { |
| 365 inline bool sanitize (hb_sanitize_context_t *c) const |
| 366 { |
| 367 TRACE_SANITIZE (this); |
| 368 return_trace (c->check_struct (this) && |
| 369 mathItalicsCorrectionInfo.sanitize (c, this) && |
| 370 mathTopAccentAttachment.sanitize (c, this) && |
| 371 extendedShapeCoverage.sanitize (c, this) && |
| 372 mathKernInfo.sanitize(c, this)); |
| 373 } |
| 374 |
| 375 inline hb_position_t |
| 376 get_italics_correction (hb_codepoint_t glyph, hb_font_t *font) const |
| 377 { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); } |
| 378 |
| 379 inline hb_position_t |
| 380 get_top_accent_attachment (hb_codepoint_t glyph, hb_font_t *font) const |
| 381 { return (this+mathTopAccentAttachment).get_value (glyph, font); } |
| 382 |
| 383 inline bool is_extended_shape (hb_codepoint_t glyph) const |
| 384 { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; } |
| 385 |
| 386 inline hb_position_t get_kerning (hb_codepoint_t glyph, |
| 387 hb_ot_math_kern_t kern, |
| 388 hb_position_t correction_height, |
| 389 hb_font_t *font) const |
| 390 { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font
); } |
| 391 |
| 392 protected: |
| 393 /* Offset to MathItalicsCorrectionInfo table - |
| 394 * from the beginning of MathGlyphInfo table. */ |
| 395 OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo; |
| 396 |
| 397 /* Offset to MathTopAccentAttachment table - |
| 398 * from the beginning of MathGlyphInfo table. */ |
| 399 OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment; |
| 400 |
| 401 /* Offset to coverage table for Extended Shape glyphs - |
| 402 * from the beginning of MathGlyphInfo table. When the left or right glyph of |
| 403 * a box is an extended shape variant, the (ink) box (and not the default |
| 404 * position defined by values in MathConstants table) should be used for |
| 405 * vertical positioning purposes. May be NULL.. */ |
| 406 OffsetTo<Coverage> extendedShapeCoverage; |
| 407 |
| 408 /* Offset to MathKernInfo table - |
| 409 * from the beginning of MathGlyphInfo table. */ |
| 410 OffsetTo<MathKernInfo> mathKernInfo; |
| 411 |
| 412 public: |
| 413 DEFINE_SIZE_STATIC (8); |
| 414 }; |
| 415 |
| 416 struct MathGlyphVariantRecord |
| 417 { |
| 418 friend struct MathGlyphConstruction; |
| 419 |
| 420 inline bool sanitize (hb_sanitize_context_t *c) const |
| 421 { |
| 422 TRACE_SANITIZE (this); |
| 423 return_trace (c->check_struct (this)); |
| 424 } |
| 425 |
| 426 protected: |
| 427 GlyphID variantGlyph; /* Glyph ID for the variant. */ |
| 428 USHORT advanceMeasurement; /* Advance width/height, in design units, of the |
| 429 * variant, in the direction of requested |
| 430 * glyph extension. */ |
| 431 |
| 432 public: |
| 433 DEFINE_SIZE_STATIC (4); |
| 434 }; |
| 435 |
| 436 struct PartFlags : USHORT |
| 437 { |
| 438 enum Flags { |
| 439 Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ |
| 440 |
| 441 Defined = 0x0001u, /* All defined flags. */ |
| 442 }; |
| 443 |
| 444 public: |
| 445 DEFINE_SIZE_STATIC (2); |
| 446 }; |
| 447 |
| 448 struct MathGlyphPartRecord |
| 449 { |
| 450 inline bool sanitize (hb_sanitize_context_t *c) const |
| 451 { |
| 452 TRACE_SANITIZE (this); |
| 453 return_trace (c->check_struct (this)); |
| 454 } |
| 455 |
| 456 inline void extract (hb_ot_math_glyph_part_t &out, |
| 457 int scale, |
| 458 hb_font_t *font) const |
| 459 { |
| 460 out.glyph = glyph; |
| 461 |
| 462 out.start_connector_length = font->em_scale (startConnectorLength, scale); |
| 463 out.end_connector_length = font->em_scale (endConnectorLength, scale); |
| 464 out.full_advance = font->em_scale (fullAdvance, scale); |
| 465 |
| 466 ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER == |
| 467 (unsigned int) PartFlags::Extender); |
| 468 |
| 469 out.flags = (hb_ot_math_glyph_part_flags_t) |
| 470 (unsigned int) |
| 471 (partFlags & PartFlags::Defined); |
| 472 } |
| 473 |
| 474 protected: |
| 475 GlyphID glyph; /* Glyph ID for the part. */ |
| 476 USHORT startConnectorLength; /* Advance width/ height of the straight bar |
| 477 * connector material, in design units, is at |
| 478 * the beginning of the glyph, in the |
| 479 * direction of the extension. */ |
| 480 USHORT endConnectorLength; /* Advance width/ height of the straight bar |
| 481 * connector material, in design units, is at |
| 482 * the end of the glyph, in the direction of |
| 483 * the extension. */ |
| 484 USHORT fullAdvance; /* Full advance width/height for this part, |
| 485 * in the direction of the extension. |
| 486 * In design units. */ |
| 487 PartFlags partFlags; /* Part qualifiers. */ |
| 488 |
| 489 public: |
| 490 DEFINE_SIZE_STATIC (10); |
| 491 }; |
| 492 |
| 493 struct MathGlyphAssembly |
| 494 { |
| 495 inline bool sanitize (hb_sanitize_context_t *c) const |
| 496 { |
| 497 TRACE_SANITIZE (this); |
| 498 return_trace (c->check_struct (this) && |
| 499 italicsCorrection.sanitize(c, this) && |
| 500 partRecords.sanitize(c)); |
| 501 } |
| 502 |
| 503 inline unsigned int get_parts (hb_direction_t direction, |
| 504 hb_font_t *font, |
| 505 unsigned int start_offset, |
| 506 unsigned int *parts_count, /* IN/OUT */ |
| 507 hb_ot_math_glyph_part_t *parts /* OUT */, |
| 508 hb_position_t *italics_correction /* OUT */) co
nst |
| 509 { |
| 510 if (parts_count) |
| 511 { |
| 512 int scale = font->dir_scale (direction); |
| 513 const MathGlyphPartRecord *arr = |
| 514 partRecords.sub_array (start_offset, parts_count); |
| 515 unsigned int count = *parts_count; |
| 516 for (unsigned int i = 0; i < count; i++) |
| 517 arr[i].extract (parts[i], scale, font); |
| 518 } |
| 519 |
| 520 if (italics_correction) |
| 521 *italics_correction = italicsCorrection.get_x_value (font, this); |
| 522 |
| 523 return partRecords.len; |
| 524 } |
| 525 |
| 526 protected: |
| 527 MathValueRecord italicsCorrection; /* Italics correction of this |
| 528 * MathGlyphAssembly. Should not |
| 529 * depend on the assembly size. */ |
| 530 ArrayOf<MathGlyphPartRecord> partRecords; /* Array of part records, from |
| 531 * left to right and bottom to |
| 532 * top. */ |
| 533 |
| 534 public: |
| 535 DEFINE_SIZE_ARRAY (6, partRecords); |
| 536 }; |
| 537 |
| 538 struct MathGlyphConstruction |
| 539 { |
| 540 inline bool sanitize (hb_sanitize_context_t *c) const |
| 541 { |
| 542 TRACE_SANITIZE (this); |
| 543 return_trace (c->check_struct (this) && |
| 544 glyphAssembly.sanitize(c, this) && |
| 545 mathGlyphVariantRecord.sanitize(c)); |
| 546 } |
| 547 |
| 548 inline const MathGlyphAssembly &get_assembly (void) const |
| 549 { return this+glyphAssembly; } |
| 550 |
| 551 inline unsigned int get_variants (hb_direction_t direction, |
| 552 hb_font_t *font, |
| 553 unsigned int start_offset, |
| 554 unsigned int *variants_count, /* IN/OUT */ |
| 555 hb_ot_math_glyph_variant_t *variants /* OUT
*/) const |
| 556 { |
| 557 if (variants_count) |
| 558 { |
| 559 int scale = font->dir_scale (direction); |
| 560 const MathGlyphVariantRecord *arr = |
| 561 mathGlyphVariantRecord.sub_array (start_offset, variants_count); |
| 562 unsigned int count = *variants_count; |
| 563 for (unsigned int i = 0; i < count; i++) |
| 564 { |
| 565 variants[i].glyph = arr[i].variantGlyph; |
| 566 variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale); |
| 567 } |
| 568 } |
| 569 return mathGlyphVariantRecord.len; |
| 570 } |
| 571 |
| 572 protected: |
| 573 /* Offset to MathGlyphAssembly table for this shape - from the beginning of |
| 574 MathGlyphConstruction table. May be NULL. */ |
| 575 OffsetTo<MathGlyphAssembly> glyphAssembly; |
| 576 |
| 577 /* MathGlyphVariantRecords for alternative variants of the glyphs. */ |
| 578 ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord; |
| 579 |
| 580 public: |
| 581 DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord); |
| 582 }; |
| 583 |
| 584 struct MathVariants |
| 585 { |
| 586 inline bool sanitize_offsets (hb_sanitize_context_t *c) const |
| 587 { |
| 588 TRACE_SANITIZE (this); |
| 589 unsigned int count = vertGlyphCount + horizGlyphCount; |
| 590 for (unsigned int i = 0; i < count; i++) |
| 591 if (!glyphConstruction[i].sanitize (c, this)) return_trace (false); |
| 592 return_trace (true); |
| 593 } |
| 594 |
| 595 inline bool sanitize (hb_sanitize_context_t *c) const |
| 596 { |
| 597 TRACE_SANITIZE (this); |
| 598 return_trace (c->check_struct (this) && |
| 599 vertGlyphCoverage.sanitize (c, this) && |
| 600 horizGlyphCoverage.sanitize (c, this) && |
| 601 c->check_array (glyphConstruction, |
| 602 glyphConstruction[0].static_size, |
| 603 vertGlyphCount + horizGlyphCount) && |
| 604 sanitize_offsets (c)); |
| 605 } |
| 606 |
| 607 inline hb_position_t get_min_connector_overlap (hb_direction_t direction, |
| 608 hb_font_t *font) const |
| 609 { return font->em_scale_dir (minConnectorOverlap, direction); } |
| 610 |
| 611 inline unsigned int get_glyph_variants (hb_codepoint_t glyph, |
| 612 hb_direction_t direction, |
| 613 hb_font_t *font, |
| 614 unsigned int start_offset, |
| 615 unsigned int *variants_count, /* IN/OU
T */ |
| 616 hb_ot_math_glyph_variant_t *variants /
* OUT */) const |
| 617 { return get_glyph_construction (glyph, direction, font) |
| 618 .get_variants (direction, font, start_offset, variants_count, variant
s); } |
| 619 |
| 620 inline unsigned int get_glyph_parts (hb_codepoint_t glyph, |
| 621 hb_direction_t direction, |
| 622 hb_font_t *font, |
| 623 unsigned int start_offset, |
| 624 unsigned int *parts_count, /* IN/OUT */ |
| 625 hb_ot_math_glyph_part_t *parts /* OUT */, |
| 626 hb_position_t *italics_correction /* OUT
*/) const |
| 627 { return get_glyph_construction (glyph, direction, font) |
| 628 .get_assembly () |
| 629 .get_parts (direction, font, |
| 630 start_offset, parts_count, parts, |
| 631 italics_correction); } |
| 632 |
| 633 private: |
| 634 inline const MathGlyphConstruction & |
| 635 get_glyph_construction (hb_codepoint_t glyph, |
| 636 hb_direction_t direction, |
| 637 hb_font_t *font) const |
| 638 { |
| 639 bool vertical = HB_DIRECTION_IS_VERTICAL (direction); |
| 640 unsigned int count = vertical ? vertGlyphCount : horizGlyphCount; |
| 641 const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage |
| 642 : horizGlyphCoverage; |
| 643 |
| 644 unsigned int index = (this+coverage).get_coverage (glyph); |
| 645 if (unlikely (index >= count)) return Null(MathGlyphConstruction); |
| 646 |
| 647 if (!vertical) |
| 648 index += vertGlyphCount; |
| 649 |
| 650 return this+glyphConstruction[index]; |
| 651 } |
| 652 |
| 653 protected: |
| 654 USHORT minConnectorOverlap; /* Minimum overlap of connecting |
| 655 * glyphs during glyph construction, |
| 656 * in design units. */ |
| 657 OffsetTo<Coverage> vertGlyphCoverage; /* Offset to Coverage table - |
| 658 * from the beginning of MathVariants |
| 659 * table. */ |
| 660 OffsetTo<Coverage> horizGlyphCoverage; /* Offset to Coverage table - |
| 661 * from the beginning of MathVariants |
| 662 * table. */ |
| 663 USHORT vertGlyphCount; /* Number of glyphs for which |
| 664 * information is provided for |
| 665 * vertically growing variants. */ |
| 666 USHORT horizGlyphCount; /* Number of glyphs for which |
| 667 * information is provided for |
| 668 * horizontally growing variants. */ |
| 669 |
| 670 /* Array of offsets to MathGlyphConstruction tables - from the beginning of |
| 671 the MathVariants table, for shapes growing in vertical/horizontal |
| 672 direction. */ |
| 673 OffsetTo<MathGlyphConstruction> glyphConstruction[VAR]; |
| 674 |
| 675 public: |
| 676 DEFINE_SIZE_ARRAY (10, glyphConstruction); |
| 677 }; |
| 678 |
| 679 |
| 680 /* |
| 681 * MATH -- The MATH Table |
| 682 */ |
| 683 |
| 684 struct MATH |
| 685 { |
| 686 static const hb_tag_t tableTag = HB_OT_TAG_MATH; |
| 687 |
| 688 inline bool sanitize (hb_sanitize_context_t *c) const |
| 689 { |
| 690 TRACE_SANITIZE (this); |
| 691 return_trace (version.sanitize (c) && |
| 692 likely (version.major == 1) && |
| 693 mathConstants.sanitize (c, this) && |
| 694 mathGlyphInfo.sanitize (c, this) && |
| 695 mathVariants.sanitize (c, this)); |
| 696 } |
| 697 |
| 698 inline hb_position_t get_constant (hb_ot_math_constant_t constant, |
| 699 hb_font_t *font) const |
| 700 { return (this+mathConstants).get_value (constant, font); } |
| 701 |
| 702 inline const MathGlyphInfo &get_math_glyph_info (void) const |
| 703 { return this+mathGlyphInfo; } |
| 704 |
| 705 inline const MathVariants &get_math_variants (void) const |
| 706 { return this+mathVariants; } |
| 707 |
| 708 protected: |
| 709 FixedVersion<>version; /* Version of the MATH table |
| 710 * initially set to 0x00010000u */ |
| 711 OffsetTo<MathConstants> mathConstants;/* MathConstants table */ |
| 712 OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */ |
| 713 OffsetTo<MathVariants> mathVariants; /* MathVariants table */ |
| 714 |
| 715 public: |
| 716 DEFINE_SIZE_STATIC (10); |
| 717 }; |
| 718 |
| 719 } /* mathspace OT */ |
| 720 |
| 721 |
| 722 #endif /* HB_OT_LAYOUT_MATH_TABLE_HH */ |
| OLD | NEW |