summaryrefslogtreecommitdiff
path: root/source/luametatex/source/tex
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/tex')
-rw-r--r--source/luametatex/source/tex/texexpand.c3
-rw-r--r--source/luametatex/source/tex/texfont.h34
-rw-r--r--source/luametatex/source/tex/texmath.c190
-rw-r--r--source/luametatex/source/tex/texmlist.c83
-rw-r--r--source/luametatex/source/tex/texnodes.h10
5 files changed, 130 insertions, 190 deletions
diff --git a/source/luametatex/source/tex/texexpand.c b/source/luametatex/source/tex/texexpand.c
index 6cf887bea..706972bfe 100644
--- a/source/luametatex/source/tex/texexpand.c
+++ b/source/luametatex/source/tex/texexpand.c
@@ -550,7 +550,8 @@ void tex_expand_current_token(void)
/*tex Complain about an undefined macro */
tex_handle_error(
normal_error_type,
- "Undefined control sequence %m", cur_cs,
+ // "Undefined control sequence %m", cur_cs,
+ "Undefined control sequence",
"The control sequence at the end of the top line of your error message was never\n"
"\\def'ed. You can just continue as I'll forget about whatever was undefined."
);
diff --git a/source/luametatex/source/tex/texfont.h b/source/luametatex/source/tex/texfont.h
index 947cdf446..0d3fa9fb3 100644
--- a/source/luametatex/source/tex/texfont.h
+++ b/source/luametatex/source/tex/texfont.h
@@ -465,21 +465,23 @@ extern int tex_get_math_char (halfword f, int c, int size, scaled *scal
*/
typedef enum char_tag_codes {
- no_tag = 0x0000, /*tex vanilla character */
- ligatures_tag = 0x0001, /*tex character has a ligature program, not used */
- kerns_tag = 0x0002, /*tex character has a kerning program, not used */
- list_tag = 0x0004, /*tex character has a successor in a charlist */
- callback_tag = 0x0010,
- extensible_tag = 0x0020, /*tex character is extensible, we can unset it in order to block */
- horizontal_tag = 0x0040, /*tex horizontal extensible */
- vertical_tag = 0x0080, /*tex vertical extensible */
- extend_last_tag = 0x0100, /*tex auto scale last variant */
- inner_left_tag = 0x0200, /*tex anchoring */
- inner_right_tag = 0x0400, /*tex anchoring */
- italic_tag = 0x0800,
- n_ary_tag = 0x1000,
- radical_tag = 0x2000,
- punctuation_tag = 0x4000,
+ no_tag = 0x00000, /*tex vanilla character */
+ ligatures_tag = 0x00001, /*tex character has a ligature program, not used */
+ kerns_tag = 0x00002, /*tex character has a kerning program, not used */
+ list_tag = 0x00004, /*tex character has a successor in a charlist */
+ callback_tag = 0x00010,
+ extensible_tag = 0x00020, /*tex character is extensible, we can unset it in order to block */
+ horizontal_tag = 0x00040, /*tex horizontal extensible */
+ vertical_tag = 0x00080, /*tex vertical extensible */
+ inner_left_tag = 0x00100, /*tex anchoring */
+ inner_right_tag = 0x00200, /*tex anchoring */
+ inner_top_tag = 0x00400, /*tex anchoring */
+ inner_bottom_tag = 0x00800, /*tex anchoring */
+ extend_last_tag = 0x01000, /*tex auto scale last variant */
+ italic_tag = 0x02000,
+ n_ary_tag = 0x04000,
+ radical_tag = 0x08000,
+ punctuation_tag = 0x10000,
} char_tag_codes;
/*tex
@@ -597,8 +599,6 @@ extern scaled tex_char_top_margin_from_font (halfword f, halfword c)
extern scaled tex_char_bottom_margin_from_font (halfword f, halfword c);
extern scaled tex_char_top_overshoot_from_font (halfword f, halfword c);
extern scaled tex_char_bottom_overshoot_from_font (halfword f, halfword c);
-extern scaled tex_char_inner_x_offset_from_font (halfword f, halfword c);
-extern scaled tex_char_inner_y_offset_from_font (halfword f, halfword c);
extern extinfo *tex_char_extensible_recipe_from_font (halfword f, halfword c);
extern halfword tex_char_unchecked_top_anchor_from_font (halfword f, halfword c);
diff --git a/source/luametatex/source/tex/texmath.c b/source/luametatex/source/tex/texmath.c
index 01db082b2..0e52f7c70 100644
--- a/source/luametatex/source/tex/texmath.c
+++ b/source/luametatex/source/tex/texmath.c
@@ -2672,37 +2672,49 @@ void tex_run_math_radical(void)
attrlist = tex_scan_attribute(attrlist);
}
break;
- case 'e': case 'E':
- if (tex_scan_mandate_keyword("exact", 1)) {
- options = options | noad_option_exact;
- }
- break;
case 'b': case 'B':
if (tex_scan_mandate_keyword("bottom", 1)) {
bottom = 1;
}
break;
+ case 'e': case 'E':
+ if (tex_scan_mandate_keyword("exact", 1)) {
+ options = options | noad_option_exact;
+ }
+ break;
case 't': case 'T':
if (tex_scan_mandate_keyword("top", 1)) {
top = 1;
}
break;
case 's': case 'S':
- switch (tex_scan_character("itoITO", 0, 0, 0)) {
+ switch (tex_scan_character("hitoHITO", 0, 0, 0)) {
case 't': case 'T':
- if (tex_scan_mandate_keyword("style", 2)) {
- switch (code) {
- case normal_radical_subtype:
- case radical_radical_subtype:
- case root_radical_subtype:
- case rooted_radical_subtype:
- case delimited_radical_subtype:
- style = tex_scan_math_style_identifier(1, 0);
- break;
- default:
- /* ignore */
- break;
- }
+ switch (tex_scan_character("ryRY", 0, 0, 0)) {
+ case 'y': case 'Y':
+ if (tex_scan_mandate_keyword("style", 3)) {
+ switch (code) {
+ case normal_radical_subtype:
+ case radical_radical_subtype:
+ case root_radical_subtype:
+ case rooted_radical_subtype:
+ case delimited_radical_subtype:
+ style = tex_scan_math_style_identifier(1, 0);
+ break;
+ default:
+ /* ignore */
+ break;
+ }
+ }
+ break;
+ case 'r': case 'R':
+ if (tex_scan_mandate_keyword("stretch", 3)) {
+ options = options | noad_option_stretch;
+ }
+ break;
+ default:
+ tex_aux_show_keyword_error("style|stretch");
+ goto DONE;
}
break;
case 'o': case 'O':
@@ -2715,8 +2727,13 @@ void tex_run_math_radical(void)
radical_size(radical) = tex_scan_int(0, NULL);
}
break;
+ case 'h': case 'H':
+ if (tex_scan_mandate_keyword("shrink", 2)) {
+ options = options | noad_option_shrink;
+ }
+ break;
default:
- tex_aux_show_keyword_error("style|source");
+ tex_aux_show_keyword_error("style|source|stretch|shrink");
goto DONE;
}
break;
@@ -2898,132 +2915,6 @@ void tex_finish_math_radical(void)
}
}
-// void tex_run_math_accent(void)
-// {
-// mathcodeval t = tex_no_math_code();
-// mathcodeval b = tex_no_math_code();
-// mathcodeval o = tex_no_math_code();
-// halfword code = cur_chr;
-// halfword accent = tex_new_node(accent_noad, bothflexible_accent_subtype);
-// quarterword subtype = ordinary_noad_subtype;
-// halfword attrlist = null;
-// if (cur_cmd == accent_cmd) {
-// tex_handle_error(
-// normal_error_type,
-// "Please use \\mathaccent for accents in math mode",
-// "I'm changing \\accent to \\mathaccent here; wish me luck. (Accents are not the\n"
-// "same in formulas as they are in text.)" );
-// }
-// tex_tail_append(accent);
-// switch (code) {
-// case math_accent_code:
-// /*tex |\mathaccent| */
-// t = tex_scan_mathchar(tex_mathcode);
-// break;
-// case math_uaccent_code:
-// /*tex |\Umathaccent| */
-// while (1) {
-// switch (tex_scan_character("abnsfABNSF", 0, 1, 0)) {
-// case 'a': case 'A':
-// if (tex_scan_mandate_keyword("attr", 1)) {
-// attrlist = tex_scan_attribute(attrlist);
-// }
-// break;
-// case 's': case 'S':
-// if (tex_scan_mandate_keyword("source", 1)) {
-// noad_source(accent) = tex_scan_int(0, NULL);
-// }
-// break;
-// case 'f': case 'F':
-// if (tex_scan_mandate_keyword("fraction", 1)) {
-// accent_fraction(accent) = tex_scan_int(0, NULL);
-// }
-// break;
-// case 'n': case 'N':
-// if (tex_scan_mandate_keyword("nooverflow", 1)) {
-// /*tex
-// Actually there never is an overflow but for consistency we do
-// accept this key. Mayebe in the future it will be used.
-// */
-// noad_options(accent) |= noad_option_no_overflow;
-// }
-// break;
-// case 'b': case 'B':
-// if (tex_scan_mandate_keyword("base", 1)) {
-// noad_options(accent) |= noad_option_auto_base;
-// }
-// break;
-// default:
-// goto DONE;
-// }
-// }
-// DONE:
-// /* todo: integrate in the above */
-// if (tex_scan_keyword("fixed")) {
-// /*tex top */
-// node_subtype(accent) = fixedtop_accent_subtype;
-// t = tex_scan_mathchar(umath_mathcode);
-// } else if (tex_scan_keyword("both")) {
-// /*tex top bottom */
-// if (tex_scan_keyword("fixed")) {
-// node_subtype(accent) = fixedtop_accent_subtype;
-// }
-// t = tex_scan_mathchar(umath_mathcode);
-// if (tex_scan_keyword("fixed")) {
-// node_subtype(accent) = fixedboth_accent_subtype;
-// }
-// b = tex_scan_mathchar(umath_mathcode);
-// } else if (tex_scan_keyword("bottom")) {
-// /*tex bottom */
-// if (tex_scan_keyword("fixed")) {
-// node_subtype(accent) = fixedbottom_accent_subtype;
-// }
-// b = tex_scan_mathchar(umath_mathcode);
-// } else if (tex_scan_keyword("top")) {
-// /*tex top */
-// if (tex_scan_keyword("fixed")) {
-// node_subtype(accent) = fixedtop_accent_subtype;
-// }
-// t = tex_scan_mathchar(umath_mathcode);
-// } else if (tex_scan_keyword("overlay")) {
-// /* overlay */
-// if (tex_scan_keyword("fixed")) {
-// node_subtype(accent) = fixedtop_accent_subtype;
-// }
-// o = tex_scan_mathchar(umath_mathcode);
-// } else {
-// /*tex top */
-// t = tex_scan_mathchar(umath_mathcode);
-// }
-// break;
-// default:
-// tex_confusion("scan math accent");
-// }
-// if (attrlist) {
-// tex_attach_attribute_list_attribute(accent, attrlist);
-// }
-// if (! (t.character_value == 0 && t.family_value == 0)) {
-// halfword n = tex_new_node(math_char_node, 0);
-// subtype = tex_aux_set_math_char(n, &t, NULL);
-// accent_top_character(accent) = n;
-// }
-// if (! (b.character_value == 0 && b.family_value == 0)) {
-// halfword n = tex_new_node(math_char_node, 0);
-// subtype = tex_aux_set_math_char(n, &b, NULL);
-// accent_bottom_character(accent) = n;
-// }
-// if (! (o.character_value == 0 && o.family_value == 0)) {
-// halfword n = tex_new_node(math_char_node, 0);
-// subtype = tex_aux_set_math_char(n, &o, NULL);
-// accent_middle_character(accent) = n;
-// }
-// {
-// halfword n = tex_new_node(math_char_node, subtype);
-// noad_nucleus(accent) = n;
-// tex_aux_scan_math(n, tex_math_style_variant(cur_list.math_style, math_parameter_accent_variant), 0, 0, 0, 0, unset_noad_class, unset_noad_class);
-// }
-// }
-
void tex_run_math_accent(void)
{
mathcodeval t = tex_no_math_code();
@@ -3049,12 +2940,17 @@ void tex_run_math_accent(void)
case math_uaccent_code:
/*tex |\Umathaccent| */
while (1) {
- switch (tex_scan_character("abnsftoABNSFTO", 0, 1, 0)) {
+ switch (tex_scan_character("abcnsftoABCNSFTO", 0, 1, 0)) {
case 'a': case 'A':
if (tex_scan_mandate_keyword("attr", 1)) {
attrlist = tex_scan_attribute(attrlist);
}
break;
+ case 'c': case 'C':
+ if (tex_scan_mandate_keyword("center", 1)) {
+ noad_options(accent) |= noad_option_center;
+ }
+ break;
case 's': case 'S':
if (tex_scan_mandate_keyword("source", 1)) {
noad_source(accent) = tex_scan_int(0, NULL);
diff --git a/source/luametatex/source/tex/texmlist.c b/source/luametatex/source/tex/texmlist.c
index 56b780506..3b7734ccf 100644
--- a/source/luametatex/source/tex/texmlist.c
+++ b/source/luametatex/source/tex/texmlist.c
@@ -861,7 +861,7 @@ static halfword tex_aux_underbar(halfword box, scaled gap, scaled height, scaled
*/
-static halfword tex_aux_char_box(halfword fnt, int chr, halfword att, scaled *ic, quarterword subtype, scaled target, int style)
+static halfword tex_aux_char_box(halfword fnt, int chr, halfword att, scaled *ic, quarterword subtype, scaled target, int style, int shrink, int stretch)
{
/*tex The new box and its character node. */
halfword glyph = tex_aux_new_math_glyph(fnt, chr, subtype);
@@ -876,7 +876,7 @@ static halfword tex_aux_char_box(halfword fnt, int chr, halfword att, scaled *ic
if (tex_has_glyph_option(glyph, glyph_option_no_italic_correction)) {
whd.ic = 0;
}
- if (whd.ic) {
+ if (! (stretch || shrink) && whd.ic) {
if (ic) {
*ic = whd.ic; /* also in open type? needs checking */
}
@@ -889,12 +889,19 @@ static halfword tex_aux_char_box(halfword fnt, int chr, halfword att, scaled *ic
} else if (ic) {
*ic = 0;
}
- if (target && whd.wd > 0 && whd.wd < target && tex_aux_math_engine_control(fnt, math_control_extend_accents) && tex_char_has_tag_from_font(fnt, chr, extend_last_tag)) {
- scaled margin = tex_get_math_x_parameter_default(style, math_parameter_accent_extend_margin, 0);
- scaled amount = target - 2 * margin;
- if (amount > 0) {
- glyph_x_scale(glyph) = lround((double) glyph_x_scale(glyph) * amount/whd.wd);
- glyph_x_offset(glyph) = (whd.wd - amount)/2;
+ if (target && whd.wd > 0) {
+ if (whd.wd < target && tex_aux_math_engine_control(fnt, math_control_extend_accents) && tex_char_has_tag_from_font(fnt, chr, extend_last_tag)) {
+ scaled margin = tex_get_math_x_parameter_default(style, math_parameter_accent_extend_margin, 0);
+ scaled amount = target - 2 * margin;
+ if (amount > 0) {
+ glyph_x_scale(glyph) = lround((double) glyph_x_scale(glyph) * amount/whd.wd);
+ glyph_x_offset(glyph) = (whd.wd - amount)/2;
+ }
+ return box;
+ }
+ if ((shrink && (whd.wd > target)) || (stretch && (whd.wd < target))) {
+ glyph_x_scale(glyph) = lround((double) glyph_x_scale(glyph) * target/whd.wd);
+ glyph_x_offset(glyph) = (whd.wd - target)/2;
}
}
return box;
@@ -1384,6 +1391,8 @@ static halfword tex_aux_make_delimiter(halfword target, halfword delimiter, int
/*tex are we trying the large variant? */
int large_attempt = 0;
int do_parts = 0;
+ int shrink = flat && tex_has_noad_option(target, noad_option_shrink);
+ int stretch = flat && tex_has_noad_option(target, noad_option_stretch);
/*tex to save the current attribute list */
halfword att = null;
if (extremes) {
@@ -1448,7 +1457,7 @@ static halfword tex_aux_make_delimiter(halfword target, halfword delimiter, int
if (total >= (targetsize - tolerance)) {
goto FOUND;
}
- }
+ }
if (tex_char_has_tag_from_font(curfnt, curchr, extensible_tag)) {
if (tex_char_has_tag_from_font(curfnt, curchr, horizontal_tag) || tex_char_has_tag_from_font(curfnt, curchr, vertical_tag)) {
/*tex We only check when we are explicit. */
@@ -1498,8 +1507,13 @@ static halfword tex_aux_make_delimiter(halfword target, halfword delimiter, int
*/
extinfo *ext = do_parts ? tex_char_extensible_recipe_from_font(fnt, chr) : NULL;
if (ext) {
- scaled minoverlap = flat ? tex_get_math_x_parameter_default(style, math_parameter_connector_overlap_min, 0) : tex_get_math_y_parameter_default(style, math_parameter_connector_overlap_min, 0);;
+ scaled minoverlap = flat ? tex_get_math_x_parameter_default(style, math_parameter_connector_overlap_min, 0) : tex_get_math_y_parameter_default(style, math_parameter_connector_overlap_min, 0);
result = tex_aux_get_delimiter_box(fnt, chr, targetsize, minoverlap, flat, att);
+ if (stretch && flat && (box_width(result) > targetsize)) { // threshold nooverflow
+ tex_flush_node_list(result);
+ do_parts = 0;
+ goto HERE;
+ }
if (delta) {
/*tex Not yet done: horizontal italics. */
if (tex_aux_math_engine_control(fnt, math_control_apply_vertical_italic_kern)) {
@@ -1529,7 +1543,8 @@ static halfword tex_aux_make_delimiter(halfword target, halfword delimiter, int
the traditional width (which is fake width + italic) becomes less and the delta is
added. See (**).
*/
- result = tex_aux_char_box(fnt, chr, att, delta, glyph_math_delimiter_subtype, flat ? targetsize : 0, style);
+ HERE:
+ result = tex_aux_char_box(fnt, chr, att, delta, glyph_math_delimiter_subtype, flat ? targetsize : 0, style, shrink, stretch);
if (flat) {
/* This will be done when we have a reasonable example. */
} else {
@@ -2395,12 +2410,20 @@ static void tex_aux_make_root_radical(halfword target, int style, int size, kern
}
delimiter = tex_aux_make_delimiter(target, delimiter, size, box_total(nucleus) + clearance + theta, 0, style, 1, NULL, NULL, 0, has_noad_option_nooverflow(target), &extremes, 0);
if (radical_degree(target)) {
+ halfword innerf = 0;
+ halfword innerc = 0;
if (tex_char_has_tag_from_font(extremes.bfont, extremes.bchar, inner_left_tag)) {
- innerx = tex_char_inner_x_offset_from_font(extremes.bfont, extremes.bchar);
- innery = tex_char_inner_y_offset_from_font(extremes.bfont, extremes.bchar);
+ innerf = extremes.bfont;
+ innerc = extremes.bchar;
} else if (tex_char_has_tag_from_font(extremes.tfont, extremes.tchar, inner_left_tag)) {
- innerx = tex_char_inner_x_offset_from_font(extremes.tfont, extremes.tchar);
- innery = tex_char_inner_y_offset_from_font(extremes.tfont, extremes.tchar);
+ innerf = extremes.tfont;
+ innerc = extremes.tchar;
+ }
+ if (innerc) {
+ innerx = tex_char_inner_x_offset_from_font(innerf, innerc);
+ innery = tex_char_inner_y_offset_from_font(innerf, innerc);
+ innerx = innerx == INT_MIN ? 0 : tex_aux_math_y_size_scaled(innerf, innerx, size);
+ innery = innery == INT_MIN ? 0 : tex_aux_math_y_size_scaled(innerf, innery, size);
}
}
if (companion) {
@@ -2790,7 +2813,7 @@ static void tex_aux_preroll_radical(halfword target, int style, int size)
typedef enum math_accent_location_codes {
top_accent_code = 1,
- bot_accent_code = 2,
+ bot_accent_code = 2, // todo : bottom_accent_code
overlay_accent_code = 4,
stretch_accent_code = 8, /* reserved, not yet set */
} math_accent_location_codes;
@@ -2896,6 +2919,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal
scaled fraction = accent_fraction(target) > 0 ? accent_fraction(target) : 1000;
scaled skew = 0;
scaled offset = 0;
+ scaled innery = 0;
halfword accent = null;
halfword base = null;
halfword result = null;
@@ -3008,7 +3032,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal
}
if (! accent) {
/*tex Italic gets added to width for traditional fonts (no italic anyway): */
- accent = tex_aux_char_box(accentfnt, accentchr, attrlist, NULL, glyph_math_accent_subtype, basewidth, style); // usedwidth
+ accent = tex_aux_char_box(accentfnt, accentchr, attrlist, NULL, glyph_math_accent_subtype, basewidth, style, 0, 0); // usedwidth
}
if (flags & top_accent_code) {
scaled b = tex_get_math_y_parameter(style, math_parameter_accent_base_height);
@@ -3019,7 +3043,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal
halfword flatchr = tex_char_flat_accent_from_font(accentfnt, accentchr);
if (flatchr != INT_MIN && flatchr != accentchr) {
tex_flush_node(accent);
- accent = tex_aux_char_box(accentfnt, flatchr, attrlist, NULL, glyph_math_accent_subtype, usedwidth, style);
+ accent = tex_aux_char_box(accentfnt, flatchr, attrlist, NULL, glyph_math_accent_subtype, usedwidth, style, 0, 0);
if (tracing_math_par >= 2) {
tex_begin_diagnostic();
tex_print_format("[math: flattening accent, old %x, new %x]", accentchr, flatchr);
@@ -3039,6 +3063,10 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal
if (u != undefined_math_parameter) {
delta -= u;
}
+ if (tex_char_has_tag_from_font(accentfnt, accentchr, inner_top_tag)) {
+ innery = tex_char_inner_y_offset_from_font(accentfnt, accentchr);
+ innery = innery == INT_MIN ? 0 : tex_aux_math_y_size_scaled(accentfnt, innery, size);
+ }
} else if (flags & bot_accent_code) {
// scaled b = tex_get_math_y_parameter(style, math_parameter_accent_base_depth, 0);
// scaled f = tex_get_math_y_parameter(style, math_parameter_flattened_accent_base_depth, 0);
@@ -3050,6 +3078,10 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal
if (l != undefined_math_parameter) {
delta += l;
}
+ if (tex_char_has_tag_from_font(accentfnt, accentchr, inner_bottom_tag)) {
+ innery = tex_char_inner_y_offset_from_font(accentfnt, accentchr);
+ innery = innery == INT_MIN ? 0 : tex_aux_math_y_size_scaled(accentfnt, innery, size);
+ }
} else { /* if (flags & overlay_accent_code) { */
/*tex Center the accent vertically around base: */
delta = tex_half_scaled(box_total(accent) + box_total(base));
@@ -3082,11 +3114,11 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal
anchor = tex_half_scaled(accentwidth);
} else {
anchor = tex_char_unchecked_top_anchor_from_font(accentfnt, accentchr); /* no bot accent key */
- if (anchor != INT_MIN) {
- anchor = tex_aux_math_y_size_scaled(accentfnt, anchor, size); /* why y and not x */
- } else {
+ if (anchor == INT_MIN || has_noad_option_center(target)) {
/*tex just take the center */
anchor = tex_half_scaled(accentwidth);
+ } else {
+ anchor = tex_aux_math_x_size_scaled(accentfnt, anchor, size);
}
}
if (math_direction_par == dir_righttoleft) {
@@ -3117,6 +3149,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal
accent_bot_overshoot(target) = overshoot;
}
if (flags & (top_accent_code | overlay_accent_code)) {
+ delta += innery;
if (delta) {
halfword kern = tex_new_kern_node(-delta, vertical_math_kern_subtype);
tex_attach_attribute_list_copy(kern, target);
@@ -3126,6 +3159,12 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal
tex_couple_nodes(accent, base);
}
result = accent;
+ } else if ((flags & bot_accent_code) && innery) {
+ halfword kern = tex_new_kern_node(innery, vertical_math_kern_subtype);
+ tex_attach_attribute_list_copy(kern, target);
+ tex_couple_nodes(base, kern);
+ tex_couple_nodes(kern, accent);
+ result = base;
} else {
tex_couple_nodes(base, accent);
result = base;
@@ -7107,7 +7146,7 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state)
tex_couple_nodes(p, box_list(l));
box_list(l) = null;
tex_flush_node(l);
- } else if (current_type == simple_noad && current_subtype == math_end_class) {
+ } else if (current_type == simple_noad && (current_subtype == math_end_class) || (current_subtype == math_begin_class)) {
if (noad_new_hlist(current)) {
tex_flush_node(noad_new_hlist(current));
noad_new_hlist(current) = null;
diff --git a/source/luametatex/source/tex/texnodes.h b/source/luametatex/source/tex/texnodes.h
index f3f9276a6..cb666f874 100644
--- a/source/luametatex/source/tex/texnodes.h
+++ b/source/luametatex/source/tex/texnodes.h
@@ -1788,13 +1788,16 @@ typedef enum noad_options {
# define noad_option_fixed_super_or_sub_script 0x0200000000
# define noad_option_fixed_super_and_sub_script 0x0400000000
# define noad_option_auto_base 0x0800000000
+# define noad_option_stretch 0x1000000000
+# define noad_option_shrink 0x2000000000
+# define noad_option_center 0x4000000000
# define has_option(a,b) (((a) & (b)) == (b))
# define unset_option(a,b) ((a) & ~(b))
-inline static void tex_add_noad_option (halfword a, halfword r) { noad_options(a) |= r; }
-inline static void tex_remove_noad_option (halfword a, halfword r) { noad_options(a) &= ~(r | noad_options(a)); }
-inline static int tex_has_noad_option (halfword a, halfword r) { return (noad_options(a) & r) == r; }
+inline static void tex_add_noad_option (halfword a, long long r) { noad_options(a) |= r; }
+inline static void tex_remove_noad_option (halfword a, long long r) { noad_options(a) &= ~(r | noad_options(a)); }
+inline static int tex_has_noad_option (halfword a, long long r) { return (noad_options(a) & r) == r; }
inline static int has_noad_no_script_option(halfword n, halfword option)
{
@@ -1842,6 +1845,7 @@ inline static int has_noad_no_script_option(halfword n, halfword option)
# define has_noad_option_unrolllist(a) (has_option(noad_options(a), noad_option_unroll_list))
# define has_noad_option_followedbyspace(a) (has_option(noad_options(a), noad_option_followed_by_space))
# define has_noad_option_proportional(a) (has_option(noad_options(a), noad_option_proportional))
+# define has_noad_option_center(a) (has_option(noad_options(a), noad_option_center))
# define has_noad_option_source_on_nucleus(a) (has_option(noad_options(a), noad_option_source_on_nucleus))
# define has_noad_option_fixed_super_or_sub_script(a) (has_option(noad_options(a), noad_option_fixed_super_or_sub_script))
# define has_noad_option_fixed_super_and_sub_script(a) (has_option(noad_options(a), noad_option_fixed_super_and_sub_script))