blob: 191d79e98a071323b45415862c542b08eb574899 [file] [log] [blame]
Frédéric Wang5fbcb992016-08-25 10:47:15 +02001/*
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
Behdad Esfahbod93ef6842017-01-09 21:11:00 -080027#ifndef HB_OT_MATH_TABLE_HH
28#define HB_OT_MATH_TABLE_HH
Frédéric Wang5fbcb992016-08-25 10:47:15 +020029
30#include "hb-open-type-private.hh"
31#include "hb-ot-layout-common-private.hh"
Frédéric Wang319ff592016-08-25 11:06:41 +020032#include "hb-ot-math.h"
Frédéric Wang5fbcb992016-08-25 10:47:15 +020033
34namespace OT {
35
Frédéric Wang319ff592016-08-25 11:06:41 +020036
37struct MathValueRecord
38{
Behdad Esfahbod1a381152016-09-26 11:15:59 +010039 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); }
Frédéric Wang319ff592016-08-25 11:06:41 +020043
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
Behdad Esfahbod353f4552016-09-26 21:22:48 +020050 protected:
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +010051 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 NULL.
54 * Suggested format for device table is 1. */
Frédéric Wang319ff592016-08-25 11:06:41 +020055
Behdad Esfahbod353f4552016-09-26 21:22:48 +020056 public:
Behdad Esfahbod1a381152016-09-26 11:15:59 +010057 DEFINE_SIZE_STATIC (4);
Frédéric Wang319ff592016-08-25 11:06:41 +020058};
59
60struct MathConstants
61{
62 inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
63 {
64 TRACE_SANITIZE (this);
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +010065
Behdad Esfahbod6fd2fe42016-09-26 11:24:39 +010066 unsigned int count = ARRAY_LENGTH (mathValueRecords);
Frédéric Wang319ff592016-08-25 11:06:41 +020067 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +010068 if (!mathValueRecords[i].sanitize (c, this))
69 return_trace (false);
70
Frédéric Wang319ff592016-08-25 11:06:41 +020071 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
Behdad Esfahbod54c0cc32016-09-26 11:56:40 +010080 inline hb_position_t get_value (hb_ot_math_constant_t constant,
81 hb_font_t *font) const
Frédéric Wang319ff592016-08-25 11:06:41 +020082 {
83 switch (constant) {
Behdad Esfahbod6fd2fe42016-09-26 11:24:39 +010084
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_SCALE_DOWN];
88
Frédéric Wang319ff592016-08-25 11:06:41 +020089 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_DELIMITED_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:
Behdad Esfahbod1a381152016-09-26 11:15:59 +010097 return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this);
Frédéric Wang319ff592016-08-25 11:06:41 +020098
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:
Behdad Esfahbod1a381152016-09-26 11:15:59 +0100146 return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this);
Frédéric Wang319ff592016-08-25 11:06:41 +0200147
Frédéric Wang319ff592016-08-25 11:06:41 +0200148 case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
149 return radicalDegreeBottomRaisePercent;
Behdad Esfahbod6fd2fe42016-09-26 11:24:39 +0100150
Behdad Esfahbod1a381152016-09-26 11:15:59 +0100151 default:
152 return 0;
Frédéric Wang319ff592016-08-25 11:06:41 +0200153 }
154 }
155
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200156 protected:
Behdad Esfahbod6fd2fe42016-09-26 11:24:39 +0100157 SHORT percentScaleDown[2];
158 USHORT minHeight[2];
159 MathValueRecord mathValueRecords[51];
Frédéric Wang319ff592016-08-25 11:06:41 +0200160 SHORT radicalDegreeBottomRaisePercent;
161
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200162 public:
Behdad Esfahbod6fd2fe42016-09-26 11:24:39 +0100163 DEFINE_SIZE_STATIC (214);
Frédéric Wang319ff592016-08-25 11:06:41 +0200164};
165
Frédéric Wangd7182d12016-08-25 11:15:31 +0200166struct MathItalicsCorrectionInfo
167{
168 inline bool sanitize (hb_sanitize_context_t *c) const
169 {
170 TRACE_SANITIZE (this);
171 return_trace (c->check_struct (this) &&
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100172 coverage.sanitize (c, this) &&
173 italicsCorrection.sanitize (c, this));
Frédéric Wangd7182d12016-08-25 11:15:31 +0200174 }
175
Behdad Esfahbod8bcf5172016-09-26 12:12:41 +0100176 inline hb_position_t get_value (hb_codepoint_t glyph,
177 hb_font_t *font) const
Frédéric Wangd7182d12016-08-25 11:15:31 +0200178 {
179 unsigned int index = (this+coverage).get_coverage (glyph);
Behdad Esfahbod8bcf5172016-09-26 12:12:41 +0100180 return italicsCorrection[index].get_x_value (font, this);
Frédéric Wangd7182d12016-08-25 11:15:31 +0200181 }
182
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200183 protected:
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100184 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. */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200192
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200193 public:
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100194 DEFINE_SIZE_ARRAY (4, italicsCorrection);
Frédéric Wangd7182d12016-08-25 11:15:31 +0200195};
196
197struct MathTopAccentAttachment
198{
199 inline bool sanitize (hb_sanitize_context_t *c) const
200 {
201 TRACE_SANITIZE (this);
202 return_trace (c->check_struct (this) &&
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100203 topAccentCoverage.sanitize (c, this) &&
204 topAccentAttachment.sanitize (c, this));
Frédéric Wangd7182d12016-08-25 11:15:31 +0200205 }
206
Behdad Esfahbod17ff30e2016-09-26 12:18:32 +0100207 inline hb_position_t get_value (hb_codepoint_t glyph,
208 hb_font_t *font) const
Frédéric Wangd7182d12016-08-25 11:15:31 +0200209 {
210 unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
Behdad Esfahbod17ff30e2016-09-26 12:18:32 +0100211 if (index == NOT_COVERED)
212 return font->get_glyph_h_advance (glyph) / 2;
213 return topAccentAttachment[index].get_x_value(font, this);
Frédéric Wangd7182d12016-08-25 11:15:31 +0200214 }
215
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200216 protected:
Frédéric Wangd7182d12016-08-25 11:15:31 +0200217 OffsetTo<Coverage> topAccentCoverage; /* Offset to Coverage table -
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100218 * from the beginning of
219 * MathTopAccentAttachment
220 * table. */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200221 ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100222 * defining top accent
223 * attachment points for each
224 * covered glyph. */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200225
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200226 public:
Frédéric Wangd7182d12016-08-25 11:15:31 +0200227 DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment);
228};
229
230struct 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) &&
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100245 c->check_array (mathValueRecords,
246 mathValueRecords[0].static_size,
247 2 * heightCount + 1) &&
248 sanitize_math_value_records (c));
Frédéric Wangd7182d12016-08-25 11:15:31 +0200249 }
250
Behdad Esfahbod94f5df52016-09-26 13:31:47 +0100251 inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
Frédéric Wangd7182d12016-08-25 11:15:31 +0200252 {
253 const MathValueRecord* correctionHeight = mathValueRecords;
254 const MathValueRecord* kernValue = mathValueRecords + heightCount;
Behdad Esfahbod8d58e342016-09-26 13:39:58 +0100255 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 */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200265 unsigned int i = 0;
Behdad Esfahbod8d58e342016-09-26 13:39:58 +0100266 unsigned int count = heightCount;
267 while (count > 0)
268 {
Frédéric Wangd7182d12016-08-25 11:15:31 +0200269 unsigned int half = count / 2;
Behdad Esfahbod8d58e342016-09-26 13:39:58 +0100270 hb_position_t height = correctionHeight[i + half].get_y_value(font, this);
271 if (sign * height < sign * correction_height)
272 {
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100273 i += half + 1;
274 count -= half + 1;
Frédéric Wangd7182d12016-08-25 11:15:31 +0200275 } else
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100276 count = half;
Frédéric Wangd7182d12016-08-25 11:15:31 +0200277 }
278 return kernValue[i].get_x_value(font, this);
279 }
280
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200281 protected:
Frédéric Wang51da7a12016-08-25 11:17:50 +0200282 USHORT heightCount;
Frédéric Wangd7182d12016-08-25 11:15:31 +0200283 MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100284 * which the kern value changes.
285 * Sorted by the height value in
Behdad Esfahbod8d58e342016-09-26 13:39:58 +0100286 * design units (heightCount entries),
287 * Followed by:
288 * Array of kern values corresponding
289 * to heights. (heightCount+1 entries).
290 */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200291
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200292 public:
Frédéric Wangd7182d12016-08-25 11:15:31 +0200293 DEFINE_SIZE_ARRAY (2, mathValueRecords);
294};
295
296struct MathKernInfoRecord
297{
298 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
299 {
300 TRACE_SANITIZE (this);
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100301
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);
Frédéric Wangd7182d12016-08-25 11:15:31 +0200308 }
309
Behdad Esfahbod94f5df52016-09-26 13:31:47 +0100310 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
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100314 {
315 unsigned int idx = kern;
Behdad Esfahbod94f5df52016-09-26 13:31:47 +0100316 if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0;
317 return (base+mathKern[idx]).get_value (correction_height, font);
Frédéric Wangd7182d12016-08-25 11:15:31 +0200318 }
319
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200320 protected:
Frédéric Wangd7182d12016-08-25 11:15:31 +0200321 /* Offset to MathKern table for each corner -
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100322 * from the beginning of MathKernInfo table. May be NULL. */
323 OffsetTo<MathKern> mathKern[4];
Frédéric Wangd7182d12016-08-25 11:15:31 +0200324
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200325 public:
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100326 DEFINE_SIZE_STATIC (8);
Frédéric Wangd7182d12016-08-25 11:15:31 +0200327};
328
329struct MathKernInfo
330{
331 inline bool sanitize (hb_sanitize_context_t *c) const
332 {
333 TRACE_SANITIZE (this);
334 return_trace (c->check_struct (this) &&
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100335 mathKernCoverage.sanitize (c, this) &&
336 mathKernInfoRecords.sanitize (c, this));
Frédéric Wangd7182d12016-08-25 11:15:31 +0200337 }
338
Behdad Esfahbod94f5df52016-09-26 13:31:47 +0100339 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
Frédéric Wangd7182d12016-08-25 11:15:31 +0200343 {
344 unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
Behdad Esfahbod94f5df52016-09-26 13:31:47 +0100345 return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
Frédéric Wangd7182d12016-08-25 11:15:31 +0200346 }
347
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200348 protected:
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100349 OffsetTo<Coverage> mathKernCoverage; /* Offset to Coverage table -
350 * from the beginning of the
351 * MathKernInfo table. */
352 ArrayOf<MathKernInfoRecord> mathKernInfoRecords; /* Array of
353 * MathKernInfoRecords,
354 * per-glyph information for
355 * mathematical positioning
356 * of subscripts and
357 * superscripts. */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200358
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200359 public:
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100360 DEFINE_SIZE_ARRAY (4, mathKernInfoRecords);
Frédéric Wangd7182d12016-08-25 11:15:31 +0200361};
362
363struct MathGlyphInfo
364{
365 inline bool sanitize (hb_sanitize_context_t *c) const
366 {
367 TRACE_SANITIZE (this);
368 return_trace (c->check_struct (this) &&
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100369 mathItalicsCorrectionInfo.sanitize (c, this) &&
370 mathTopAccentAttachment.sanitize (c, this) &&
371 extendedShapeCoverage.sanitize (c, this) &&
372 mathKernInfo.sanitize(c, this));
Frédéric Wangd7182d12016-08-25 11:15:31 +0200373 }
374
Behdad Esfahbod8bcf5172016-09-26 12:12:41 +0100375 inline hb_position_t
Behdad Esfahbod17ff30e2016-09-26 12:18:32 +0100376 get_italics_correction (hb_codepoint_t glyph, hb_font_t *font) const
377 { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); }
Frédéric Wangd7182d12016-08-25 11:15:31 +0200378
Behdad Esfahbod17ff30e2016-09-26 12:18:32 +0100379 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); }
Frédéric Wangd7182d12016-08-25 11:15:31 +0200382
383 inline bool is_extended_shape (hb_codepoint_t glyph) const
Behdad Esfahbod17ff30e2016-09-26 12:18:32 +0100384 { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; }
Frédéric Wangd7182d12016-08-25 11:15:31 +0200385
Behdad Esfahbod94f5df52016-09-26 13:31:47 +0100386 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); }
Frédéric Wangd7182d12016-08-25 11:15:31 +0200391
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200392 protected:
Frédéric Wangd7182d12016-08-25 11:15:31 +0200393 /* Offset to MathItalicsCorrectionInfo table -
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100394 * from the beginning of MathGlyphInfo table. */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200395 OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
396
397 /* Offset to MathTopAccentAttachment table -
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100398 * from the beginning of MathGlyphInfo table. */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200399 OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
400
401 /* Offset to coverage table for Extended Shape glyphs -
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100402 * 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.. */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200406 OffsetTo<Coverage> extendedShapeCoverage;
407
408 /* Offset to MathKernInfo table -
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100409 * from the beginning of MathGlyphInfo table. */
Frédéric Wangd7182d12016-08-25 11:15:31 +0200410 OffsetTo<MathKernInfo> mathKernInfo;
411
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200412 public:
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100413 DEFINE_SIZE_STATIC (8);
Frédéric Wangd7182d12016-08-25 11:15:31 +0200414};
415
Frédéric Wang51da7a12016-08-25 11:17:50 +0200416struct MathGlyphVariantRecord
417{
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200418 friend struct MathGlyphConstruction;
419
Frédéric Wang51da7a12016-08-25 11:17:50 +0200420 inline bool sanitize (hb_sanitize_context_t *c) const
421 {
422 TRACE_SANITIZE (this);
423 return_trace (c->check_struct (this));
424 }
425
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200426 protected:
Frédéric Wang51da7a12016-08-25 11:17:50 +0200427 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
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200432 public:
Behdad Esfahbod1f3327f2016-09-26 16:10:08 +0100433 DEFINE_SIZE_STATIC (4);
Frédéric Wang51da7a12016-08-25 11:17:50 +0200434};
435
436struct PartFlags : USHORT
437{
438 enum Flags {
Behdad Esfahbod559eb562016-09-26 21:46:05 +0200439 Extender = 0x0001u, /* If set, the part can be skipped or repeated. */
440
441 Defined = 0x0001u, /* All defined flags. */
Frédéric Wang51da7a12016-08-25 11:17:50 +0200442 };
443
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200444 public:
Frédéric Wang51da7a12016-08-25 11:17:50 +0200445 DEFINE_SIZE_STATIC (2);
446};
447
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200448struct MathGlyphPartRecord
Frédéric Wang51da7a12016-08-25 11:17:50 +0200449{
450 inline bool sanitize (hb_sanitize_context_t *c) const
451 {
452 TRACE_SANITIZE (this);
453 return_trace (c->check_struct (this));
454 }
455
Behdad Esfahbod46cc4a32016-09-27 16:44:22 +0200456 inline void extract (hb_ot_math_glyph_part_t &out,
Behdad Esfahbod559eb562016-09-26 21:46:05 +0200457 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
Behdad Esfahbod46cc4a32016-09-27 16:44:22 +0200469 out.flags = (hb_ot_math_glyph_part_flags_t)
Behdad Esfahbod559eb562016-09-26 21:46:05 +0200470 (unsigned int)
471 (partFlags & PartFlags::Defined);
472 }
473
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200474 protected:
Frédéric Wang51da7a12016-08-25 11:17:50 +0200475 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
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200489 public:
Behdad Esfahbod1f3327f2016-09-26 16:10:08 +0100490 DEFINE_SIZE_STATIC (10);
Frédéric Wang51da7a12016-08-25 11:17:50 +0200491};
492
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200493struct MathGlyphAssembly
Frédéric Wang51da7a12016-08-25 11:17:50 +0200494{
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
Behdad Esfahbod559eb562016-09-26 21:46:05 +0200503 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 */
Behdad Esfahbod46cc4a32016-09-27 16:44:22 +0200507 hb_ot_math_glyph_part_t *parts /* OUT */,
Behdad Esfahbod559eb562016-09-26 21:46:05 +0200508 hb_position_t *italics_correction /* OUT */) const
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++)
Behdad Esfahbod97b72da2016-09-26 21:53:25 +0200517 arr[i].extract (parts[i], scale, font);
Behdad Esfahbod559eb562016-09-26 21:46:05 +0200518 }
519
520 if (italics_correction)
521 *italics_correction = italicsCorrection.get_x_value (font, this);
522
523 return partRecords.len;
524 }
Frédéric Wang51da7a12016-08-25 11:17:50 +0200525
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200526 protected:
Frédéric Wang51da7a12016-08-25 11:17:50 +0200527 MathValueRecord italicsCorrection; /* Italics correction of this
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200528 * MathGlyphAssembly. Should not
Frédéric Wang51da7a12016-08-25 11:17:50 +0200529 * depend on the assembly size. */
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200530 ArrayOf<MathGlyphPartRecord> partRecords; /* Array of part records, from
Frédéric Wang51da7a12016-08-25 11:17:50 +0200531 * left to right and bottom to
532 * top. */
533
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200534 public:
Behdad Esfahbod1f3327f2016-09-26 16:10:08 +0100535 DEFINE_SIZE_ARRAY (6, partRecords);
Frédéric Wang51da7a12016-08-25 11:17:50 +0200536};
537
538struct 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
Behdad Esfahbod559eb562016-09-26 21:46:05 +0200548 inline const MathGlyphAssembly &get_assembly (void) const
549 { return this+glyphAssembly; }
550
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200551 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 */
Behdad Esfahbod46cc4a32016-09-27 16:44:22 +0200555 hb_ot_math_glyph_variant_t *variants /* OUT */) const
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200556 {
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
Frédéric Wang51da7a12016-08-25 11:17:50 +0200574 MathGlyphConstruction table. May be NULL. */
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200575 OffsetTo<MathGlyphAssembly> glyphAssembly;
Frédéric Wang51da7a12016-08-25 11:17:50 +0200576
577 /* MathGlyphVariantRecords for alternative variants of the glyphs. */
578 ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
579
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200580 public:
Behdad Esfahbod1f3327f2016-09-26 16:10:08 +0100581 DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
Frédéric Wang51da7a12016-08-25 11:17:50 +0200582};
583
584struct 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
Behdad Esfahbod7fe0e282016-09-26 17:51:47 +0100607 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); }
Frédéric Wang51da7a12016-08-25 11:17:50 +0200610
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200611 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/OUT */
Behdad Esfahbod46cc4a32016-09-27 16:44:22 +0200616 hb_ot_math_glyph_variant_t *variants /* OUT */) const
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200617 { return get_glyph_construction (glyph, direction, font)
618 .get_variants (direction, font, start_offset, variants_count, variants); }
Frédéric Wang51da7a12016-08-25 11:17:50 +0200619
Behdad Esfahbod559eb562016-09-26 21:46:05 +0200620 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 */
Behdad Esfahbod46cc4a32016-09-27 16:44:22 +0200625 hb_ot_math_glyph_part_t *parts /* OUT */,
Behdad Esfahbod559eb562016-09-26 21:46:05 +0200626 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
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200633 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;
Frédéric Wang51da7a12016-08-25 11:17:50 +0200643
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200644 unsigned int index = (this+coverage).get_coverage (glyph);
645 if (unlikely (index >= count)) return Null(MathGlyphConstruction);
646
647 if (!vertical)
Frédéric Wang51da7a12016-08-25 11:17:50 +0200648 index += vertGlyphCount;
649
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200650 return this+glyphConstruction[index];
Frédéric Wang51da7a12016-08-25 11:17:50 +0200651 }
652
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200653 protected:
Frédéric Wang51da7a12016-08-25 11:17:50 +0200654 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. */
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200673 OffsetTo<MathGlyphConstruction> glyphConstruction[VAR];
Frédéric Wang51da7a12016-08-25 11:17:50 +0200674
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200675 public:
Behdad Esfahbod1f3327f2016-09-26 16:10:08 +0100676 DEFINE_SIZE_ARRAY (10, glyphConstruction);
Frédéric Wang51da7a12016-08-25 11:17:50 +0200677};
678
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100679
Frédéric Wang5fbcb992016-08-25 10:47:15 +0200680/*
681 * MATH -- The MATH Table
682 */
683
684struct MATH
685{
Behdad Esfahbod4d3892e2016-09-26 10:45:58 +0100686 static const hb_tag_t tableTag = HB_OT_TAG_MATH;
Frédéric Wang5fbcb992016-08-25 10:47:15 +0200687
688 inline bool sanitize (hb_sanitize_context_t *c) const
689 {
690 TRACE_SANITIZE (this);
691 return_trace (version.sanitize (c) &&
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100692 likely (version.major == 1) &&
693 mathConstants.sanitize (c, this) &&
Frédéric Wang51da7a12016-08-25 11:17:50 +0200694 mathGlyphInfo.sanitize (c, this) &&
695 mathVariants.sanitize (c, this));
Frédéric Wang319ff592016-08-25 11:06:41 +0200696 }
697
Behdad Esfahbod54c0cc32016-09-26 11:56:40 +0100698 inline hb_position_t get_constant (hb_ot_math_constant_t constant,
Frédéric Wang51da7a12016-08-25 11:17:50 +0200699 hb_font_t *font) const
Behdad Esfahbod54c0cc32016-09-26 11:56:40 +0100700 { return (this+mathConstants).get_value (constant, font); }
Frédéric Wang5fbcb992016-08-25 10:47:15 +0200701
Behdad Esfahbod1f3327f2016-09-26 16:10:08 +0100702 inline const MathGlyphInfo &get_math_glyph_info (void) const
703 { return this+mathGlyphInfo; }
Frédéric Wang51da7a12016-08-25 11:17:50 +0200704
Behdad Esfahbod1f3327f2016-09-26 16:10:08 +0100705 inline const MathVariants &get_math_variants (void) const
706 { return this+mathVariants; }
Frédéric Wang51da7a12016-08-25 11:17:50 +0200707
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200708 protected:
Behdad Esfahbod8a8cfad2016-09-26 11:47:05 +0100709 FixedVersion<>version; /* Version of the MATH table
710 * initially set to 0x00010000u */
711 OffsetTo<MathConstants> mathConstants;/* MathConstants table */
712 OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
Frédéric Wang51da7a12016-08-25 11:17:50 +0200713 OffsetTo<MathVariants> mathVariants; /* MathVariants table */
Frédéric Wang319ff592016-08-25 11:06:41 +0200714
Behdad Esfahbod353f4552016-09-26 21:22:48 +0200715 public:
Frédéric Wang51da7a12016-08-25 11:17:50 +0200716 DEFINE_SIZE_STATIC (10);
Frédéric Wang5fbcb992016-08-25 10:47:15 +0200717};
718
Behdad Esfahbod3b5263b2017-01-09 15:49:08 -0800719} /* namespace OT */
Frédéric Wang5fbcb992016-08-25 10:47:15 +0200720
721
Behdad Esfahbod93ef6842017-01-09 21:11:00 -0800722#endif /* HB_OT_MATH_TABLE_HH */