/* Copyright 2016-2018 The Tectonic Project * Licensed under the MIT License. */ #include "xetex-core.h" #include "xetex-xetexd.h" #include "xetex-synctex.h" #include "tectonic_bridge_core.h" static scaled_t math_x_height(int32_t size_code); static scaled_t math_quad(int32_t size_code); static scaled_t num1(int32_t size_code); static scaled_t num2(int32_t size_code); static scaled_t num3(int32_t size_code); static scaled_t denom1(int32_t size_code); static scaled_t denom2(int32_t size_code); static scaled_t sup1(int32_t size_code); static scaled_t sup2(int32_t size_code); static scaled_t sup3(int32_t size_code); static scaled_t sub1(int32_t size_code); static scaled_t sub2(int32_t size_code); static scaled_t sup_drop(int32_t size_code); static scaled_t sub_drop(int32_t size_code); static scaled_t delim1(int32_t size_code); static scaled_t delim2(int32_t size_code); static scaled_t axis_height(int32_t size_code); static scaled_t default_rule_thickness(void); static scaled_t big_op_spacing1(void); static scaled_t big_op_spacing2(void); static scaled_t big_op_spacing3(void); static scaled_t big_op_spacing4(void); static scaled_t big_op_spacing5(void); static int32_t fraction_rule(scaled_t t); static int32_t overbar(int32_t b, scaled_t k, scaled_t t); static int32_t char_box(internal_font_number f, int32_t c); static void stack_into_box(int32_t b, internal_font_number f, uint16_t c); static scaled_t height_plus_depth(internal_font_number f, uint16_t c); static void stack_glyph_into_box(int32_t b, internal_font_number f, int32_t g); static void stack_glue_into_box(int32_t b, scaled_t min, scaled_t max); static int32_t build_opentype_assembly(internal_font_number f, void *a, scaled_t s, bool horiz); static int32_t var_delimiter(int32_t d, int32_t s, scaled_t v); static int32_t rebox(int32_t b, scaled_t w); static int32_t math_glue(int32_t g, scaled_t m); static void math_kern(int32_t p, scaled_t m); static int32_t clean_box(int32_t p, small_number s); static void fetch(int32_t a); static void make_over(int32_t q); static void make_under(int32_t q); static void make_vcenter(int32_t q); static void make_radical(int32_t q); static scaled_t compute_ot_math_accent_pos(int32_t p); static void make_math_accent(int32_t q); static void make_fraction(int32_t q); static scaled_t make_op(int32_t q); static void make_ord(int32_t q); static int32_t attach_hkern_to_new_hlist(int32_t q, scaled_t delta); static void make_scripts(int32_t q, scaled_t delta); static small_number make_left_right(int32_t q, small_number style, scaled_t max_d, scaled_t max_h); static void mlist_to_hlist(void); static b16x4 null_delimiter; static int32_t cur_mlist; static small_number cur_style; static int32_t cur_size; static scaled_t cur_mu; static bool mlist_penalties; void initialize_math_variables(void) { null_delimiter.s3 = 0; null_delimiter.s2 = 0; null_delimiter.s1 = 0; null_delimiter.s0 = 0; } void init_math(void) { scaled_t w; int32_t j; int32_t x; scaled_t l; scaled_t s; int32_t p; int32_t q; internal_font_number f; int32_t n; scaled_t v; scaled_t d; get_token(); if ((cur_cmd == MATH_SHIFT) && (cur_list.mode > 0)) { /*1180: */ j = TEX_NULL; w = -MAX_HALFWORD; if (cur_list.head == cur_list.tail) { /*1520: */ pop_nest(); if (cur_list.eTeX_aux == TEX_NULL) x = 0; else if (mem[cur_list.eTeX_aux].b32.s0 >= R_CODE) x = -1; else x = 1 /*:1519 */ ; } else { line_break(true); /*1528: */ if (GLUEPAR(right_skip) == 0) j = new_kern(0); else j = new_param_glue(GLUE_PAR__right_skip); if (GLUEPAR(left_skip) == 0) p = new_kern(0); else p = new_param_glue(GLUE_PAR__left_skip); mem[p].b32.s1 = j; j = new_null_box(); mem[j + 1].b32.s1 = mem[just_box + 1].b32.s1; mem[j + 4].b32.s1 = mem[just_box + 4].b32.s1; mem[j + 5].b32.s1 = p; mem[j + 5].b16.s0 = mem[just_box + 5].b16.s0; mem[j + 5].b16.s1 = mem[just_box + 5].b16.s1; BOX_glue_set(j) = BOX_glue_set(just_box); v = mem[just_box + 4].b32.s1; if (cur_list.eTeX_aux == TEX_NULL) x = 0; else if (mem[cur_list.eTeX_aux].b32.s0 >= R_CODE) x = -1; else x = 1 /*:1519 */ ; if (x >= 0) { p = mem[just_box + 5].b32.s1; mem[TEMP_HEAD].b32.s1 = TEX_NULL; } else { v = -(int32_t) v - mem[just_box + 1].b32.s1; p = new_math(0, BEGIN_L_CODE); mem[TEMP_HEAD].b32.s1 = p; just_copy(mem[just_box + 5].b32.s1, p, new_math(0, END_L_CODE)); cur_dir = RIGHT_TO_LEFT; } v = v + 2 * font_info[QUAD_CODE + param_base[eqtb[CUR_FONT_LOC].b32.s1]].b32.s1; if (INTPAR(texxet) > 0) { /*1497: */ temp_ptr = get_avail(); mem[temp_ptr].b32.s0 = BEFORE; mem[temp_ptr].b32.s1 = LR_ptr; LR_ptr = temp_ptr; } while (p != TEX_NULL) { reswitch: if ((is_char_node(p))) { f = CHAR_NODE_font(p); d = FONT_CHARACTER_WIDTH(f, effective_char(true, f, CHAR_NODE_character(p))); goto found; } switch (mem[p].b16.s1) { case 0: case 1: case 2: { d = mem[p + 1].b32.s1; goto found; } break; case 6: { mem[GARBAGE] = mem[p + 1]; mem[GARBAGE].b32.s1 = mem[p].b32.s1; p = GARBAGE; xtx_ligature_present = true; goto reswitch; } break; case 11: d = mem[p + 1].b32.s1; break; case 40: d = mem[p + 1].b32.s1; break; case 9: { d = mem[p + 1].b32.s1; if (INTPAR(texxet) > 0) { /*1525: */ if (odd(mem[p].b16.s0)) { if (mem[LR_ptr].b32.s0 == (L_CODE * (mem[p].b16.s0 / L_CODE) + 3)) { temp_ptr = LR_ptr; LR_ptr = mem[temp_ptr].b32.s1; { mem[temp_ptr].b32.s1 = avail; avail = temp_ptr; } } else if (mem[p].b16.s0 > L_CODE) { w = MAX_HALFWORD; goto done; } } else { { temp_ptr = get_avail(); mem[temp_ptr].b32.s0 = (L_CODE * (mem[p].b16.s0 / L_CODE) + 3); mem[temp_ptr].b32.s1 = LR_ptr; LR_ptr = temp_ptr; } if ((mem[p].b16.s0 / R_CODE) != cur_dir) { just_reverse(p); p = TEMP_HEAD; } } } else if (mem[p].b16.s0 >= L_CODE) { w = MAX_HALFWORD; goto done; } } break; case 14: { d = mem[p + 1].b32.s1; cur_dir = mem[p].b16.s0; } break; case 10: { q = mem[p + 1].b32.s0; d = mem[q + 1].b32.s1; if (mem[just_box + 5].b16.s1 == STRETCHING) { if ((mem[just_box + 5].b16.s0 == mem[q].b16.s1) && (mem[q + 2].b32.s1 != 0)) v = MAX_HALFWORD; } else if (mem[just_box + 5].b16.s1 == SHRINKING) { if ((mem[just_box + 5].b16.s0 == mem[q].b16.s0) && (mem[q + 3].b32.s1 != 0)) v = MAX_HALFWORD; } if (mem[p].b16.s0 >= A_LEADERS) goto found; } break; case 8: if ((mem[p].b16.s0 == NATIVE_WORD_NODE) || (mem[p].b16.s0 == NATIVE_WORD_NODE_AT) || (mem[p].b16.s0 == GLYPH_NODE) || (mem[p].b16.s0 == PIC_NODE) || (mem[p].b16.s0 == PDF_NODE)) { d = mem[p + 1].b32.s1; goto found; } else d = 0 /*:1398 */ ; break; default: d = 0; break; } if (v < MAX_HALFWORD) v = v + d; goto not_found; found: if (v < MAX_HALFWORD) { v = v + d; w = v; } else { w = MAX_HALFWORD; goto done; } not_found: p = LLIST_link(p); } /*1523:*/ done: if (INTPAR(texxet) > 0) { while (LR_ptr != TEX_NULL) { temp_ptr = LR_ptr; LR_ptr = mem[temp_ptr].b32.s1; { mem[temp_ptr].b32.s1 = avail; avail = temp_ptr; } } if (LR_problems != 0) { w = MAX_HALFWORD; LR_problems = 0; } } cur_dir = LEFT_TO_RIGHT; flush_node_list(mem[TEMP_HEAD].b32.s1); } if (LOCAL(par_shape) == TEX_NULL) { if ((DIMENPAR(hang_indent) != 0) && (((INTPAR(hang_after) >= 0) && (cur_list.prev_graf + 2 > INTPAR(hang_after))) || (cur_list.prev_graf + 1 < -(int32_t) INTPAR(hang_after)))) { l = DIMENPAR(hsize) - abs(DIMENPAR(hang_indent)); if (DIMENPAR(hang_indent) > 0) s = DIMENPAR(hang_indent); else s = 0; } else { l = DIMENPAR(hsize); s = 0; } } else { n = mem[LOCAL(par_shape)].b32.s0; if (cur_list.prev_graf + 2 >= n) p = LOCAL(par_shape) + 2 * n; else p = LOCAL(par_shape) + 2 * (cur_list.prev_graf + 2); s = mem[p - 1].b32.s1; l = mem[p].b32.s1; } push_math(MATH_SHIFT_GROUP); cur_list.mode = MMODE; eq_word_define(INT_BASE + INT_PAR__cur_fam, -1); eq_word_define(DIMEN_BASE + DIMEN_PAR__pre_display_size, w); cur_list.eTeX_aux = j; eq_word_define(INT_BASE + INT_PAR__pre_display_direction, x); eq_word_define(DIMEN_BASE + DIMEN_PAR__display_width, l); eq_word_define(DIMEN_BASE + DIMEN_PAR__display_indent, s); /* Tectonic customization: flag canvas start */ if (semantic_pagination_enabled) tt_insert_special("tdux:cs dmath"); if (LOCAL(every_display) != TEX_NULL) begin_token_list(LOCAL(every_display), EVERY_DISPLAY_TEXT); if (nest_ptr == 1) build_page(); } else { back_input(); { push_math(MATH_SHIFT_GROUP); eq_word_define(INT_BASE + INT_PAR__cur_fam, -1); if ((insert_src_special_every_math)) insert_src_special(); /* Tectonic customization: flag canvas start */ if (semantic_pagination_enabled) tt_insert_special("tdux:cs math"); if (LOCAL(every_math) != TEX_NULL) begin_token_list(LOCAL(every_math), EVERY_MATH_TEXT); } } } void start_eq_no(void) { save_stack[save_ptr + 0].b32.s1 = cur_chr; save_ptr++; push_math(MATH_SHIFT_GROUP); eq_word_define(INT_BASE + INT_PAR__cur_fam, -1); if (insert_src_special_every_math) insert_src_special(); if (LOCAL(every_math) != TEX_NULL) begin_token_list(LOCAL(every_math), EVERY_MATH_TEXT); } void math_limit_switch(void) { if (cur_list.head != cur_list.tail) { if (mem[cur_list.tail].b16.s1 == OP_NOAD) { mem[cur_list.tail].b16.s0 = cur_chr; return; } } error_here_with_diagnostic("Limit controls must follow a math operator"); capture_to_diagnostic(NULL); { help_ptr = 1; help_line[0] = "I'm ignoring this misplaced \\limits or \\nolimits command."; } error(); } static void scan_delimiter(int32_t p, bool r) { if (r) { if (cur_chr == 1) { cur_val1 = 0x40000000; scan_math_fam_int(); cur_val1 += cur_val * 0x200000; scan_usv_num(); cur_val += cur_val1; } else { scan_delimiter_int(); } } else { do { get_x_token(); } while (cur_cmd == SPACER || cur_cmd == RELAX); switch (cur_cmd) { case LETTER: case OTHER_CHAR: cur_val = DEL_CODE(cur_chr); break; case DELIM_NUM: if (cur_chr == 1) { cur_val1 = 0x40000000; scan_math_class_int(); scan_math_fam_int(); cur_val1 += cur_val * 0x20000; scan_usv_num(); cur_val += cur_val1; } else { scan_delimiter_int(); } break; default: cur_val = -1; break; } } if (cur_val < 0) { if (file_line_error_style_p) print_file_line(); else print_nl_cstr("! "); print_cstr("Missing delimiter (. inserted)"); help_ptr = 6; help_line[5] = "I was expecting to see something like `(' or `\\{' or"; help_line[4] = "`\\}' here. If you typed, e.g., `{' instead of `\\{', you"; help_line[3] = "should probably delete the `{' by typing `1' now, so that"; help_line[2] = "braces don't get unbalanced. Otherwise just proceed."; help_line[1] = "Acceptable delimiters are characters whose \\delcode is"; help_line[0] = "nonnegative, or you can use `\\delimiter '."; back_error(); cur_val = 0; } if (cur_val >= 0x40000000) { mem[p].b16.s3 = ((cur_val % 0x200000) / 0x10000) * 0x100 + (cur_val / 0x200000) % 0x100; mem[p].b16.s2 = cur_val % 0x10000; mem[p].b16.s1 = 0; mem[p].b16.s0 = 0; } else { mem[p].b16.s3 = (cur_val / 0x100000) % 16; mem[p].b16.s2 = (cur_val / 0x1000) % 0x100; mem[p].b16.s1 = (cur_val / 0x100) % 16; mem[p].b16.s0 = cur_val % 0x100; } } void math_radical(void) { { mem[cur_list.tail].b32.s1 = get_node(RADICAL_NOAD_SIZE); cur_list.tail = LLIST_link(cur_list.tail); } mem[cur_list.tail].b16.s1 = RADICAL_NOAD; mem[cur_list.tail].b16.s0 = NORMAL; mem[cur_list.tail + 1].b32 = empty; mem[cur_list.tail + 3].b32 = empty; mem[cur_list.tail + 2].b32 = empty; scan_delimiter(cur_list.tail + 4, true); scan_math(cur_list.tail + 1); } void math_ac(void) { int32_t c; if (cur_cmd == ACCENT) { /*1201: */ error_here_with_diagnostic("Please use "); print_esc_cstr("mathaccent"); print_cstr(" for accents in math mode"); capture_to_diagnostic(NULL); { help_ptr = 2; help_line[1] = "I'm changing \\accent to \\mathaccent here; wish me luck."; help_line[0] = "(Accents are not the same in formulas as they are in text.)"; } error(); } { mem[cur_list.tail].b32.s1 = get_node(ACCENT_NOAD_SIZE); cur_list.tail = LLIST_link(cur_list.tail); } mem[cur_list.tail].b16.s1 = ACCENT_NOAD; mem[cur_list.tail].b16.s0 = NORMAL; mem[cur_list.tail + 1].b32 = empty; mem[cur_list.tail + 3].b32 = empty; mem[cur_list.tail + 2].b32 = empty; mem[cur_list.tail + 4].b32.s1 = MATH_CHAR; if (cur_chr == 1) { if (scan_keyword("fixed")) mem[cur_list.tail].b16.s0 = FIXED_ACC; else if (scan_keyword("bottom")) { if (scan_keyword("fixed")) mem[cur_list.tail].b16.s0 = (BOTTOM_ACC + 1); else mem[cur_list.tail].b16.s0 = BOTTOM_ACC; } scan_math_class_int(); c = set_class(cur_val); scan_math_fam_int(); c = c + set_family(cur_val); scan_usv_num(); cur_val = cur_val + c; } else { scan_fifteen_bit_int(); cur_val = set_class(cur_val / 4096) + set_family((cur_val % 4096) / 256) + (cur_val % 256); } mem[cur_list.tail + 4].b16.s0 = cur_val % 65536L; if ((math_class(cur_val) == 7) && ((INTPAR(cur_fam) >= 0) && (INTPAR(cur_fam) < NUMBER_MATH_FAMILIES))) mem[cur_list.tail + 4].b16.s1 = INTPAR(cur_fam); else mem[cur_list.tail + 4].b16.s1 = math_fam(cur_val); mem[cur_list.tail + 4].b16.s1 = mem[cur_list.tail + 4].b16.s1 + (math_char(cur_val) / 65536L) * 256; scan_math(cur_list.tail + 1); } void append_choices(void) { { mem[cur_list.tail].b32.s1 = new_choice(); cur_list.tail = LLIST_link(cur_list.tail); } save_ptr++; save_stack[save_ptr - 1].b32.s1 = 0; push_math(MATH_CHOICE_GROUP); scan_left_brace(); } int32_t fin_mlist(int32_t p) { int32_t q; if (cur_list.aux.b32.s1 != TEX_NULL) { /*1220: */ mem[cur_list.aux.b32.s1 + 3].b32.s1 = SUB_MLIST; mem[cur_list.aux.b32.s1 + 3].b32.s0 = mem[cur_list.head].b32.s1; if (p == TEX_NULL) q = cur_list.aux.b32.s1; else { q = mem[cur_list.aux.b32.s1 + 2].b32.s0; if ((mem[q].b16.s1 != LEFT_NOAD) || (cur_list.eTeX_aux == TEX_NULL)) confusion("right"); mem[cur_list.aux.b32.s1 + 2].b32.s0 = mem[cur_list.eTeX_aux].b32.s1; mem[cur_list.eTeX_aux].b32.s1 = cur_list.aux.b32.s1; mem[cur_list.aux.b32.s1].b32.s1 = p; } } else { mem[cur_list.tail].b32.s1 = p; q = mem[cur_list.head].b32.s1; } pop_nest(); return q; } void build_choices(void) { int32_t p; unsave(); p = fin_mlist(TEX_NULL); switch (save_stack[save_ptr - 1].b32.s1) { case 0: mem[cur_list.tail + 1].b32.s0 = p; break; case 1: mem[cur_list.tail + 1].b32.s1 = p; break; case 2: mem[cur_list.tail + 2].b32.s0 = p; break; case 3: { mem[cur_list.tail + 2].b32.s1 = p; save_ptr--; return; } break; } save_stack[save_ptr - 1].b32.s1++; push_math(MATH_CHOICE_GROUP); scan_left_brace(); } void sub_sup(void) { small_number t; int32_t p; t = EMPTY; p = TEX_NULL; if (cur_list.tail != cur_list.head) { if ((mem[cur_list.tail].b16.s1 >= ORD_NOAD) && (mem[cur_list.tail].b16.s1 < LEFT_NOAD)) { p = cur_list.tail + 2 + cur_cmd - 7; t = mem[p].b32.s1; } } if ((p == TEX_NULL) || (t != EMPTY)) { /*1212: */ { mem[cur_list.tail].b32.s1 = new_noad(); cur_list.tail = LLIST_link(cur_list.tail); } p = cur_list.tail + 2 + cur_cmd - 7; if (t != EMPTY) { if (cur_cmd == SUP_MARK) { error_here_with_diagnostic("Double superscript"); capture_to_diagnostic(NULL); { help_ptr = 1; help_line[0] = "I treat `x^1^2' essentially like `x^1{}^2'."; } } else { error_here_with_diagnostic("Double subscript"); capture_to_diagnostic(NULL); { help_ptr = 1; help_line[0] = "I treat `x_1_2' essentially like `x_1{}_2'."; } } error(); } } scan_math(p); } void math_fraction(void) { small_number c; c = cur_chr; if (cur_list.aux.b32.s1 != TEX_NULL) { /*1218:*/ if (c >= DELIMITED_CODE) { scan_delimiter(GARBAGE, false); scan_delimiter(GARBAGE, false); } if (c % DELIMITED_CODE == ABOVE_CODE) scan_dimen(false, false, false); if (file_line_error_style_p) print_file_line(); else print_nl_cstr("! "); print_cstr("Ambiguous; you need another { and }"); help_ptr = 3; help_line[2] = "I'm ignoring this fraction specification, since I don't"; help_line[1] = "know whether a construction like `x \\over y \\over z'"; help_line[0] = "means `{x \\over y} \\over z' or `x \\over {y \\over z}'."; error(); } else { cur_list.aux.b32.s1 = get_node(FRACTION_NOAD_SIZE); mem[cur_list.aux.b32.s1].b16.s1 = FRACTION_NOAD; mem[cur_list.aux.b32.s1].b16.s0 = NORMAL; mem[cur_list.aux.b32.s1 + 2].b32.s1 = SUB_MLIST; mem[cur_list.aux.b32.s1 + 2].b32.s0 = mem[cur_list.head].b32.s1; mem[cur_list.aux.b32.s1 + 3].b32 = empty; mem[cur_list.aux.b32.s1 + 4].b16 = null_delimiter; mem[cur_list.aux.b32.s1 + 5].b16 = null_delimiter; mem[cur_list.head].b32.s1 = TEX_NULL; cur_list.tail = cur_list.head; if (c >= DELIMITED_CODE) { scan_delimiter(cur_list.aux.b32.s1 + 4, false); scan_delimiter(cur_list.aux.b32.s1 + 5, false); } switch (c % DELIMITED_CODE) { case ABOVE_CODE: scan_dimen(false, false, false); mem[cur_list.aux.b32.s1 + 1].b32.s1 = cur_val; break; case OVER_CODE: mem[cur_list.aux.b32.s1 + 1].b32.s1 = DEFAULT_CODE; break; case ATOP_CODE: mem[cur_list.aux.b32.s1 + 1].b32.s1 = 0; break; } } } void math_left_right(void) { small_number t; int32_t p; int32_t q; t = cur_chr; if ((t != LEFT_NOAD) && (cur_group != MATH_LEFT_GROUP)) { /*1227: */ if (cur_group == MATH_SHIFT_GROUP) { scan_delimiter(GARBAGE, false); error_here_with_diagnostic("Extra "); if (t == 1) { print_esc_cstr("middle"); { help_ptr = 1; help_line[0] = "I'm ignoring a \\middle that had no matching \\left."; } } else { print_esc_cstr("right"); { help_ptr = 1; help_line[0] = "I'm ignoring a \\right that had no matching \\left."; } } capture_to_diagnostic(NULL); error(); } else off_save(); } else { p = new_noad(); mem[p].b16.s1 = t; scan_delimiter(p + 1, false); if (t == 1) { mem[p].b16.s1 = RIGHT_NOAD; mem[p].b16.s0 = 1; } if (t == LEFT_NOAD) q = p; else { q = fin_mlist(p); unsave(); } if (t != RIGHT_NOAD) { push_math(MATH_LEFT_GROUP); mem[cur_list.head].b32.s1 = q; cur_list.tail = p; cur_list.eTeX_aux = p; } else { { mem[cur_list.tail].b32.s1 = new_noad(); cur_list.tail = LLIST_link(cur_list.tail); } mem[cur_list.tail].b16.s1 = INNER_NOAD; mem[cur_list.tail + 1].b32.s1 = SUB_MLIST; mem[cur_list.tail + 1].b32.s0 = q; } } } static void app_display(int32_t j, int32_t b, scaled_t d) { scaled_t z; scaled_t s; scaled_t e; int32_t x; int32_t p, q, r, t, u; s = DIMENPAR(display_indent); x = INTPAR(pre_display_direction); if (x == 0) mem[b + 4].b32.s1 = s + d; else { z = DIMENPAR(display_width); p = b; if (x > 0) e = z - d - mem[p + 1].b32.s1; else { e = d; d = z - e - mem[p + 1].b32.s1; } if (j != TEX_NULL) { b = copy_node_list(j); mem[b + 3].b32.s1 = mem[p + 3].b32.s1; mem[b + 2].b32.s1 = mem[p + 2].b32.s1; s = s - mem[b + 4].b32.s1; d = d + s; e = e + mem[b + 1].b32.s1 - z - s; } if ((mem[p].b16.s0) == DLIST) q = p; else { r = mem[p + 5].b32.s1; free_node(p, BOX_NODE_SIZE); if (r == TEX_NULL) confusion("LR4"); if (x > 0) { p = r; do { q = r; r = LLIST_link(r); } while (!(r == TEX_NULL)); } else { p = TEX_NULL; q = r; do { t = mem[r].b32.s1; mem[r].b32.s1 = p; p = r; r = t; } while (!(r == TEX_NULL)); } } if (j == TEX_NULL) { r = new_kern(0); t = new_kern(0); } else { r = mem[b + 5].b32.s1; t = mem[r].b32.s1; } u = new_math(0, END_M_CODE); if (NODE_type(t) == GLUE_NODE) { j = new_skip_param(GLUE_PAR__right_skip); mem[q].b32.s1 = j; mem[j].b32.s1 = u; j = mem[t + 1].b32.s0; mem[temp_ptr].b16.s1 = mem[j].b16.s1; mem[temp_ptr].b16.s0 = mem[j].b16.s0; mem[temp_ptr + 1].b32.s1 = e - mem[j + 1].b32.s1; mem[temp_ptr + 2].b32.s1 = -(int32_t) mem[j + 2].b32.s1; mem[temp_ptr + 3].b32.s1 = -(int32_t) mem[j + 3].b32.s1; mem[u].b32.s1 = t; } else { mem[t + 1].b32.s1 = e; mem[t].b32.s1 = u; mem[q].b32.s1 = t; } u = new_math(0, BEGIN_M_CODE); if (NODE_type(r) == GLUE_NODE) { j = new_skip_param(GLUE_PAR__left_skip); mem[u].b32.s1 = j; mem[j].b32.s1 = p; j = mem[r + 1].b32.s0; mem[temp_ptr].b16.s1 = mem[j].b16.s1; mem[temp_ptr].b16.s0 = mem[j].b16.s0; mem[temp_ptr + 1].b32.s1 = d - mem[j + 1].b32.s1; mem[temp_ptr + 2].b32.s1 = -(int32_t) mem[j + 2].b32.s1; mem[temp_ptr + 3].b32.s1 = -(int32_t) mem[j + 3].b32.s1; mem[r].b32.s1 = u; } else { mem[r + 1].b32.s1 = d; mem[r].b32.s1 = p; mem[u].b32.s1 = r; if (j == TEX_NULL) { b = hpack(u, 0, ADDITIONAL); mem[b + 4].b32.s1 = s; } else mem[b + 5].b32.s1 = u; } } append_to_vlist(b); } void after_math(void) { bool l; bool danger; int32_t m; int32_t p; int32_t a; int32_t b; scaled_t w; scaled_t z; scaled_t e; scaled_t q; scaled_t d; scaled_t s; small_number g1, g2; int32_t r; int32_t t; int32_t pre_t; int32_t j = TEX_NULL; danger = false; if (cur_list.mode == MMODE) j = cur_list.eTeX_aux /*:1530 */ ; if (((font_params[MATH_FONT(2)] < TOTAL_MATHSY_PARAMS) && (!((font_area[MATH_FONT(2)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(2)]))))) || ((font_params[MATH_FONT(2 + SCRIPT_SIZE)] < TOTAL_MATHSY_PARAMS) && (!((font_area[MATH_FONT(2 + SCRIPT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(2 + SCRIPT_SIZE)]))))) || ((font_params[MATH_FONT(2 + SCRIPT_SCRIPT_SIZE)] < TOTAL_MATHSY_PARAMS) && (!((font_area[MATH_FONT(2 + SCRIPT_SCRIPT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(2 + SCRIPT_SCRIPT_SIZE)])))))) { error_here_with_diagnostic("Math formula deleted: Insufficient symbol fonts"); capture_to_diagnostic(NULL); { help_ptr = 3; help_line[2] = "Sorry, but I can't typeset math unless \\textfont 2"; help_line[1] = "and \\scriptfont 2 and \\scriptscriptfont 2 have all"; help_line[0] = "the \\fontdimen values needed in math symbol fonts."; } error(); flush_math(); danger = true; } else if (((font_params[MATH_FONT(3 + TEXT_SIZE)] < TOTAL_MATHEX_PARAMS) && (!((font_area[MATH_FONT(3 + TEXT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(3 + TEXT_SIZE)]))))) || ((font_params[MATH_FONT(3 + SCRIPT_SIZE)] < TOTAL_MATHEX_PARAMS) && (!((font_area[MATH_FONT(3 + SCRIPT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(3 + SCRIPT_SIZE)]))))) || ((font_params[MATH_FONT(3 + SCRIPT_SCRIPT_SIZE)] < TOTAL_MATHEX_PARAMS) && (!((font_area[MATH_FONT(3 + SCRIPT_SCRIPT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(3 + SCRIPT_SCRIPT_SIZE)])))))) { error_here_with_diagnostic("Math formula deleted: Insufficient extension fonts"); capture_to_diagnostic(NULL); { help_ptr = 3; help_line[2] = "Sorry, but I can't typeset math unless \\textfont 3"; help_line[1] = "and \\scriptfont 3 and \\scriptscriptfont 3 have all"; help_line[0] = "the \\fontdimen values needed in math extension fonts."; } error(); flush_math(); danger = true; } m = cur_list.mode; l = false; p = fin_mlist(TEX_NULL); if (cur_list.mode == -(int32_t) m) { { get_x_token(); if (cur_cmd != MATH_SHIFT) { error_here_with_diagnostic("Display math should end with $$"); capture_to_diagnostic(NULL); { help_ptr = 2; help_line[1] = "The `$' that I just saw supposedly matches a previous `$$'."; help_line[0] = "So I shall assume that you typed `$$' both times."; } back_error(); } } cur_mlist = p; cur_style = TEXT_STYLE; mlist_penalties = false; mlist_to_hlist(); a = hpack(mem[TEMP_HEAD].b32.s1, 0, ADDITIONAL); mem[a].b16.s0 = DLIST; unsave(); save_ptr--; if (save_stack[save_ptr + 0].b32.s1 == 1) l = true; danger = false; if (cur_list.mode == MMODE) j = cur_list.eTeX_aux /*:1530 */ ; if (((font_params[MATH_FONT(2)] < TOTAL_MATHSY_PARAMS) && (!((font_area[MATH_FONT(2)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(2)]))))) || ((font_params[MATH_FONT(2 + SCRIPT_SIZE)] < TOTAL_MATHSY_PARAMS) && (!((font_area[MATH_FONT(2 + SCRIPT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(2 + SCRIPT_SIZE)]))))) || ((font_params[MATH_FONT(2 + SCRIPT_SCRIPT_SIZE)] < TOTAL_MATHSY_PARAMS) && (!((font_area[MATH_FONT(2 + SCRIPT_SCRIPT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(2 + SCRIPT_SCRIPT_SIZE)])))))) { error_here_with_diagnostic("Math formula deleted: Insufficient symbol fonts"); capture_to_diagnostic(NULL); { help_ptr = 3; help_line[2] = "Sorry, but I can't typeset math unless \\textfont 2"; help_line[1] = "and \\scriptfont 2 and \\scriptscriptfont 2 have all"; help_line[0] = "the \\fontdimen values needed in math symbol fonts."; } error(); flush_math(); danger = true; } else if (((font_params[MATH_FONT(3 + TEXT_SIZE)] < TOTAL_MATHEX_PARAMS) && (!((font_area[MATH_FONT(3 + TEXT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(3 + TEXT_SIZE)]))))) || ((font_params[MATH_FONT(3 + SCRIPT_SIZE)] < TOTAL_MATHEX_PARAMS) && (!((font_area[MATH_FONT(3 + SCRIPT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(3 + SCRIPT_SIZE)]))))) || ((font_params[MATH_FONT(3 + SCRIPT_SCRIPT_SIZE)] < TOTAL_MATHEX_PARAMS) && (!((font_area[MATH_FONT(3 + SCRIPT_SCRIPT_SIZE)] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[MATH_FONT(3 + SCRIPT_SCRIPT_SIZE)])))))) { error_here_with_diagnostic("Math formula deleted: Insufficient extension fonts"); capture_to_diagnostic(NULL); { help_ptr = 3; help_line[2] = "Sorry, but I can't typeset math unless \\textfont 3"; help_line[1] = "and \\scriptfont 3 and \\scriptscriptfont 3 have all"; help_line[0] = "the \\fontdimen values needed in math extension fonts."; } error(); flush_math(); danger = true; } m = cur_list.mode; p = fin_mlist(TEX_NULL); } else a = TEX_NULL; if (m < 0) { /*1231: */ { mem[cur_list.tail].b32.s1 = new_math(DIMENPAR(math_surround), BEFORE); cur_list.tail = LLIST_link(cur_list.tail); } cur_mlist = p; cur_style = TEXT_STYLE; mlist_penalties = (cur_list.mode > 0); mlist_to_hlist(); mem[cur_list.tail].b32.s1 = mem[TEMP_HEAD].b32.s1; while (mem[cur_list.tail].b32.s1 != TEX_NULL) cur_list.tail = LLIST_link(cur_list.tail); { mem[cur_list.tail].b32.s1 = new_math(DIMENPAR(math_surround), AFTER); cur_list.tail = LLIST_link(cur_list.tail); } cur_list.aux.b32.s0 = 1000; /* Tectonic customization: flag canvas end */ if (semantic_pagination_enabled) tt_insert_special("tdux:ce math"); unsave(); } else { if (a == TEX_NULL) { /*1232: */ get_x_token(); if (cur_cmd != MATH_SHIFT) { error_here_with_diagnostic("Display math should end with $$"); capture_to_diagnostic(NULL); { help_ptr = 2; help_line[1] = "The `$' that I just saw supposedly matches a previous `$$'."; help_line[0] = "So I shall assume that you typed `$$' both times."; } back_error(); } } cur_mlist = p; cur_style = DISPLAY_STYLE; mlist_penalties = false; mlist_to_hlist(); p = mem[TEMP_HEAD].b32.s1; adjust_tail = ADJUST_HEAD; pre_adjust_tail = PRE_ADJUST_HEAD; b = hpack(p, 0, ADDITIONAL); p = mem[b + 5].b32.s1; t = adjust_tail; adjust_tail = TEX_NULL; pre_t = pre_adjust_tail; pre_adjust_tail = TEX_NULL; w = mem[b + 1].b32.s1; z = DIMENPAR(display_width); s = DIMENPAR(display_indent); if (INTPAR(pre_display_direction) < 0) s = -(int32_t) s - z; if ((a == TEX_NULL) || danger) { e = 0; q = 0; } else { e = mem[a + 1].b32.s1; q = e + math_quad(TEXT_SIZE); } if (w + q > z) { /*1236: */ if ((e != 0) && ((w - total_shrink[NORMAL] + q <= z) || (total_shrink[FIL] != 0) || (total_shrink[FILL] != 0) || (total_shrink[FILLL] != 0))) { free_node(b, BOX_NODE_SIZE); b = hpack(p, z - q, EXACTLY); } else { e = 0; if (w > z) { free_node(b, BOX_NODE_SIZE); b = hpack(p, z, EXACTLY); } } w = mem[b + 1].b32.s1; } mem[b].b16.s0 = DLIST; d = half(z - w); if ((e > 0) && (d < 2 * e)) { d = half(z - w - e); if (p != TEX_NULL) { if (!(is_char_node(p))) { if (NODE_type(p) == GLUE_NODE) d = 0; } } } { mem[cur_list.tail].b32.s1 = new_penalty(INTPAR(pre_display_penalty)); cur_list.tail = LLIST_link(cur_list.tail); } if ((d + s <= DIMENPAR(pre_display_size)) || l) { g1 = GLUE_PAR__above_display_skip; g2 = GLUE_PAR__below_display_skip; } else { g1 = GLUE_PAR__above_display_short_skip; g2 = GLUE_PAR__below_display_short_skip; } if (l && (e == 0)) { app_display(j, a, 0); { mem[cur_list.tail].b32.s1 = new_penalty(INF_PENALTY); cur_list.tail = LLIST_link(cur_list.tail); } } else { mem[cur_list.tail].b32.s1 = new_param_glue(g1); cur_list.tail = LLIST_link(cur_list.tail); } if (e != 0) { r = new_kern(z - w - e - d); if (l) { mem[a].b32.s1 = r; mem[r].b32.s1 = b; b = a; d = 0; } else { mem[b].b32.s1 = r; mem[r].b32.s1 = a; } b = hpack(b, 0, ADDITIONAL); } app_display(j, b, d); if ((a != TEX_NULL) && (e == 0) && !l) { { mem[cur_list.tail].b32.s1 = new_penalty(INF_PENALTY); cur_list.tail = LLIST_link(cur_list.tail); } app_display(j, a, z - mem[a + 1].b32.s1); g2 = 0; } if (t != ADJUST_HEAD) { mem[cur_list.tail].b32.s1 = mem[ADJUST_HEAD].b32.s1; cur_list.tail = t; } if (pre_t != PRE_ADJUST_HEAD) { mem[cur_list.tail].b32.s1 = mem[PRE_ADJUST_HEAD].b32.s1; cur_list.tail = pre_t; } { mem[cur_list.tail].b32.s1 = new_penalty(INTPAR(post_display_penalty)); cur_list.tail = LLIST_link(cur_list.tail); } if (g2 > 0) { mem[cur_list.tail].b32.s1 = new_param_glue(g2); cur_list.tail = LLIST_link(cur_list.tail); } flush_node_list(j); /* Tectonic customization: flag canvas end */ if (semantic_pagination_enabled) tt_insert_special("tdux:ce dmath"); resume_after_display(); } } void resume_after_display(void) { if (cur_group != MATH_SHIFT_GROUP) confusion("display"); unsave(); cur_list.prev_graf = cur_list.prev_graf + 3; push_nest(); cur_list.mode = HMODE; cur_list.aux.b32.s0 = 1000; if (INTPAR(language) <= 0) cur_lang = 0; else if (INTPAR(language) > BIGGEST_LANG) cur_lang = 0; else cur_lang = INTPAR(language); cur_list.aux.b32.s1 = cur_lang; cur_list.prev_graf = (norm_min(INTPAR(left_hyphen_min)) * 64 + norm_min(INTPAR(right_hyphen_min))) * 65536L + cur_lang; { get_x_token(); if (cur_cmd != SPACER) back_input(); } if (nest_ptr == 1) build_page(); } static scaled_t math_x_height(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 5); else rval = font_info[5 + param_base[f]].b32.s1; return rval; } static scaled_t math_quad(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 6); else rval = font_info[6 + param_base[f]].b32.s1; return rval; } static scaled_t num1(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 8); else rval = font_info[8 + param_base[f]].b32.s1; return rval; } static scaled_t num2(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 9); else rval = font_info[9 + param_base[f]].b32.s1; return rval; } static scaled_t num3(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 10); else rval = font_info[10 + param_base[f]].b32.s1; return rval; } static scaled_t denom1(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 11); else rval = font_info[11 + param_base[f]].b32.s1; return rval; } static scaled_t denom2(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 12); else rval = font_info[12 + param_base[f]].b32.s1; return rval; } static scaled_t sup1(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 13); else rval = font_info[13 + param_base[f]].b32.s1; return rval; } static scaled_t sup2(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 14); else rval = font_info[14 + param_base[f]].b32.s1; return rval; } static scaled_t sup3(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 15); else rval = font_info[15 + param_base[f]].b32.s1; return rval; } static scaled_t sub1(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 16); else rval = font_info[16 + param_base[f]].b32.s1; return rval; } static scaled_t sub2(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 17); else rval = font_info[17 + param_base[f]].b32.s1; return rval; } static scaled_t sup_drop(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 18); else rval = font_info[18 + param_base[f]].b32.s1; return rval; } static scaled_t sub_drop(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 19); else rval = font_info[19 + param_base[f]].b32.s1; return rval; } static scaled_t delim1(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 20); else rval = font_info[20 + param_base[f]].b32.s1; return rval; } static scaled_t delim2(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 21); else rval = font_info[21 + param_base[f]].b32.s1; return rval; } static scaled_t axis_height(int32_t size_code) { int32_t f; scaled_t rval; f = MATH_FONT(2 + size_code); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathsy_param(f, 22); else rval = font_info[22 + param_base[f]].b32.s1; return rval; } static scaled_t default_rule_thickness(void) { int32_t f; scaled_t rval; f = MATH_FONT(3 + cur_size); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathex_param(f, 8); else rval = font_info[8 + param_base[f]].b32.s1; return rval; } static scaled_t big_op_spacing1(void) { int32_t f; scaled_t rval; f = MATH_FONT(3 + cur_size); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathex_param(f, 9); else rval = font_info[9 + param_base[f]].b32.s1; return rval; } static scaled_t big_op_spacing2(void) { int32_t f; scaled_t rval; f = MATH_FONT(3 + cur_size); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathex_param(f, 10); else rval = font_info[10 + param_base[f]].b32.s1; return rval; } static scaled_t big_op_spacing3(void) { int32_t f; scaled_t rval; f = MATH_FONT(3 + cur_size); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathex_param(f, 11); else rval = font_info[11 + param_base[f]].b32.s1; return rval; } static scaled_t big_op_spacing4(void) { int32_t f; scaled_t rval; f = MATH_FONT(3 + cur_size); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathex_param(f, 12); else rval = font_info[12 + param_base[f]].b32.s1; return rval; } static scaled_t big_op_spacing5(void) { int32_t f; scaled_t rval; f = MATH_FONT(3 + cur_size); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rval = get_native_mathex_param(f, 13); else rval = font_info[13 + param_base[f]].b32.s1; return rval; } static int32_t fraction_rule(scaled_t t) { int32_t p; p = new_rule(); mem[p + 3].b32.s1 = t; mem[p + 2].b32.s1 = 0; return p; } static int32_t overbar(int32_t b, scaled_t k, scaled_t t) { int32_t p, q; p = new_kern(k); mem[p].b32.s1 = b; q = fraction_rule(t); mem[q].b32.s1 = p; p = new_kern(t); mem[p].b32.s1 = q; return vpackage(p, 0, ADDITIONAL, MAX_HALFWORD); } static int32_t math_glue(int32_t g, scaled_t m) { int32_t p; int32_t n; scaled_t f; n = x_over_n(m, 65536L); f = tex_remainder; if (f < 0) { n--; f = f + 65536L; } p = get_node(GLUE_SPEC_SIZE); mem[p + 1].b32.s1 = mult_and_add(n, mem[g + 1].b32.s1, xn_over_d(mem[g + 1].b32.s1, f, 65536L), MAX_HALFWORD); mem[p].b16.s1 = mem[g].b16.s1; if (mem[p].b16.s1 == NORMAL) mem[p + 2].b32.s1 = mult_and_add(n, mem[g + 2].b32.s1, xn_over_d(mem[g + 2].b32.s1, f, 65536L), MAX_HALFWORD); else mem[p + 2].b32.s1 = mem[g + 2].b32.s1; mem[p].b16.s0 = mem[g].b16.s0; if (GLUE_SPEC_shrink_order(p) == NORMAL) mem[p + 3].b32.s1 = mult_and_add(n, mem[g + 3].b32.s1, xn_over_d(mem[g + 3].b32.s1, f, 65536L), MAX_HALFWORD); else mem[p + 3].b32.s1 = mem[g + 3].b32.s1; return p; } static void math_kern(int32_t p, scaled_t m) { int32_t n; scaled_t f; if (mem[p].b16.s0 == MU_GLUE) { n = x_over_n(m, 65536L); f = tex_remainder; if (f < 0) { n--; f = f + 65536L; } mem[p + 1].b32.s1 = mult_and_add(n, mem[p + 1].b32.s1, xn_over_d(mem[p + 1].b32.s1, f, 65536L), MAX_HALFWORD); NODE_subtype(p) = EXPLICIT; } } void flush_math(void) { flush_node_list(mem[cur_list.head].b32.s1); flush_node_list(cur_list.aux.b32.s1); mem[cur_list.head].b32.s1 = TEX_NULL; cur_list.tail = cur_list.head; cur_list.aux.b32.s1 = TEX_NULL; } static int32_t clean_box(int32_t p, small_number s) { int32_t q; small_number save_style; int32_t x; int32_t r; switch (mem[p].b32.s1) { case 1: { cur_mlist = new_noad(); mem[cur_mlist + 1] = mem[p]; } break; case 2: q = mem[p].b32.s0; goto found; case 3: cur_mlist = mem[p].b32.s0; break; default: q = new_null_box(); goto found; } save_style = cur_style; cur_style = s; mlist_penalties = false; mlist_to_hlist(); q = mem[TEMP_HEAD].b32.s1; cur_style = save_style; { if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } found: if ((is_char_node(q)) || (q == TEX_NULL)) x = hpack(q, 0, ADDITIONAL); else if ((mem[q].b32.s1 == TEX_NULL) && (NODE_type(q) <= VLIST_NODE) && (mem[q + 4].b32.s1 == 0)) x = q; else x = hpack(q, 0, ADDITIONAL); q = mem[x + 5].b32.s1; if ((is_char_node(q))) { r = mem[q].b32.s1; if (r != TEX_NULL) { if (mem[r].b32.s1 == TEX_NULL) { if (!(is_char_node(r))) { if (NODE_type(r) == KERN_NODE) { free_node(r, MEDIUM_NODE_SIZE); mem[q].b32.s1 = TEX_NULL; } } } } } return x; } static void fetch(int32_t a) { cur_c = (unsigned short) mem[a].b16.s0; cur_f = MATH_FONT((mem[a].b16.s1 % 256) + cur_size); cur_c = cur_c + (mem[a].b16.s1 / 256) * 65536L; if (cur_f == FONT_BASE) { /*749: */ error_here_with_diagnostic(""); print_size(cur_size); print_char(' '); print_int((mem[a].b16.s1 % 256)); print_cstr(" is undefined (character "); print(cur_c); print_char(')'); capture_to_diagnostic(NULL); { help_ptr = 4; help_line[3] = "Somewhere in the math formula just ended, you used the"; help_line[2] = "stated character from an undefined font family. For example,"; help_line[1] = "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed,"; help_line[0] = "and I'll try to forget that I needed that character."; } error(); cur_i = null_character; mem[a].b32.s1 = EMPTY; } else if (((font_area[cur_f] == AAT_FONT_FLAG) || (font_area[cur_f] == OTGR_FONT_FLAG))) { cur_i = null_character; } else { if ((cur_c >= font_bc[cur_f]) && (cur_c <= font_ec[cur_f])) cur_i = FONT_CHARACTER_INFO(cur_f, cur_c); else cur_i = null_character; if (!((cur_i.s3 > 0))) { char_warning(cur_f, cur_c); mem[a].b32.s1 = EMPTY; cur_i = null_character; } } } static void make_over(int32_t q) { mem[q + 1].b32.s0 = overbar(clean_box(q + 1, 2 * (cur_style / 2) + 1), 3 * default_rule_thickness(), default_rule_thickness()); mem[q + 1].b32.s1 = SUB_BOX; } static void make_under(int32_t q) { int32_t p, x, y; scaled_t delta; x = clean_box(q + 1, cur_style); p = new_kern(3 * default_rule_thickness()); mem[x].b32.s1 = p; mem[p].b32.s1 = fraction_rule(default_rule_thickness()); y = vpackage(x, 0, ADDITIONAL, MAX_HALFWORD); delta = mem[y + 3].b32.s1 + mem[y + 2].b32.s1 + default_rule_thickness(); mem[y + 3].b32.s1 = mem[x + 3].b32.s1; mem[y + 2].b32.s1 = delta - mem[y + 3].b32.s1; mem[q + 1].b32.s0 = y; mem[q + 1].b32.s1 = SUB_BOX; } static void make_vcenter(int32_t q) { int32_t v; scaled_t delta; v = mem[q + 1].b32.s0; if (NODE_type(v) != VLIST_NODE) confusion("vcenter"); delta = mem[v + 3].b32.s1 + mem[v + 2].b32.s1; mem[v + 3].b32.s1 = axis_height(cur_size) + half(delta); mem[v + 2].b32.s1 = delta - mem[v + 3].b32.s1; } static void make_radical(int32_t q) { int32_t x, y; internal_font_number f; scaled_t rule_thickness; scaled_t delta, clr; f = MATH_FONT((mem[q + 4].b16.s3 % 256) + cur_size); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) rule_thickness = get_ot_math_constant(f, RADICALRULETHICKNESS); else rule_thickness = default_rule_thickness(); x = clean_box(q + 1, 2 * (cur_style / 2) + 1); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) { if (cur_style < TEXT_STYLE) clr = get_ot_math_constant(f, RADICALDISPLAYSTYLEVERTICALGAP); else clr = get_ot_math_constant(f, RADICALVERTICALGAP); } else { if (cur_style < TEXT_STYLE) clr = rule_thickness + (abs(math_x_height(cur_size)) / 4); else { clr = rule_thickness; clr = clr + (abs(clr) / 4); } } y = var_delimiter(q + 4, cur_size, mem[x + 3].b32.s1 + mem[x + 2].b32.s1 + clr + rule_thickness); if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) { mem[y + 2].b32.s1 = mem[y + 3].b32.s1 + mem[y + 2].b32.s1 - rule_thickness; mem[y + 3].b32.s1 = rule_thickness; } delta = mem[y + 2].b32.s1 - (mem[x + 3].b32.s1 + mem[x + 2].b32.s1 + clr); if (delta > 0) clr = clr + half(delta); mem[y + 4].b32.s1 = -(int32_t) (mem[x + 3].b32.s1 + clr); mem[y].b32.s1 = overbar(x, clr, mem[y + 3].b32.s1); mem[q + 1].b32.s0 = hpack(y, 0, ADDITIONAL); mem[q + 1].b32.s1 = SUB_BOX; } static scaled_t compute_ot_math_accent_pos(int32_t p) { int32_t q, r; scaled_t s, g; if (mem[p + 1].b32.s1 == MATH_CHAR) { fetch(p + 1); q = new_native_character(cur_f, cur_c); g = get_native_glyph(q, 0); s = get_ot_math_accent_pos(cur_f, g); } else { if (mem[p + 1].b32.s1 == SUB_MLIST) { r = mem[p + 1].b32.s0; if ((r != TEX_NULL) && (mem[r].b16.s1 == ACCENT_NOAD)) s = compute_ot_math_accent_pos(r); else s = TEX_INFINITY; } else s = TEX_INFINITY; } return s; } static void make_math_accent(int32_t q) { int32_t p, x, y; int32_t a; int32_t c, g; internal_font_number f; b16x4 i; scaled_t s, sa; scaled_t h; scaled_t delta; scaled_t w, w2; void *ot_assembly_ptr; fetch(q + 4); x = TEX_NULL; ot_assembly_ptr = NULL; if (((font_area[cur_f] == AAT_FONT_FLAG) || (font_area[cur_f] == OTGR_FONT_FLAG))) { c = cur_c; f = cur_f; if (!((mem[q].b16.s0 == BOTTOM_ACC) || (mem[q].b16.s0 == (BOTTOM_ACC + 1)))) s = compute_ot_math_accent_pos(q); else s = 0; x = clean_box(q + 1, 2 * (cur_style / 2) + 1); w = mem[x + 1].b32.s1; h = mem[x + 3].b32.s1; } else if ((cur_i.s3 > 0)) { i = cur_i; c = cur_c; f = cur_f; s = 0; if (mem[q + 1].b32.s1 == MATH_CHAR) { fetch(q + 1); if (((cur_i.s1) % 4) == LIG_TAG) { a = lig_kern_base[cur_f] + cur_i.s0; cur_i = font_info[a].b16; if (cur_i.s3 > 128) { a = lig_kern_base[cur_f] + 256 * cur_i.s1 + cur_i.s0 + 32768L - 256 * (128); cur_i = font_info[a].b16; } while (true) { if (cur_i.s2 == skew_char[cur_f]) { if (cur_i.s1 >= 128) { if (cur_i.s3 <= 128) s = font_info[kern_base[cur_f] + 256 * cur_i.s1 + cur_i.s0].b32.s1; } goto done1; } if (cur_i.s3 >= 128) goto done1; a = a + cur_i.s3 + 1; cur_i = font_info[a].b16; } } } done1: x = clean_box(q + 1, 2 * (cur_style / 2) + 1); w = mem[x + 1].b32.s1; h = mem[x + 3].b32.s1; while (true) { if (((i.s1) % 4) != LIST_TAG) goto done; y = i.s0; i = FONT_CHARACTER_INFO(f, y); if (!(i.s3 > 0)) goto done; if (FONT_CHARINFO_WIDTH(f, i) > w) goto done; c = y; } /*:767*/ done: ; } if (x != TEX_NULL) { if (((font_area[f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[f])))) { if (((mem[q].b16.s0 == BOTTOM_ACC) || (mem[q].b16.s0 == (BOTTOM_ACC + 1)))) delta = 0; else if (h < get_ot_math_constant(f, ACCENTBASEHEIGHT)) delta = h; else delta = get_ot_math_constant(f, ACCENTBASEHEIGHT); } else if (h < font_info[X_HEIGHT_CODE + param_base[f]].b32.s1) delta = h; else delta = font_info[X_HEIGHT_CODE + param_base[f]].b32.s1; if ((mem[q + 2].b32.s1 != EMPTY) || (mem[q + 3].b32.s1 != EMPTY)) { if (mem[q + 1].b32.s1 == MATH_CHAR) { /*769: */ flush_node_list(x); x = new_noad(); mem[x + 1] = mem[q + 1]; mem[x + 2] = mem[q + 2]; mem[x + 3] = mem[q + 3]; mem[q + 2].b32 = empty; mem[q + 3].b32 = empty; mem[q + 1].b32.s1 = SUB_MLIST; mem[q + 1].b32.s0 = x; x = clean_box(q + 1, cur_style); delta = delta + mem[x + 3].b32.s1 - h; h = mem[x + 3].b32.s1; } } y = char_box(f, c); if (((font_area[f] == AAT_FONT_FLAG) || (font_area[f] == OTGR_FONT_FLAG))) { p = get_node(GLYPH_NODE_SIZE); NODE_type(p) = WHATSIT_NODE; mem[p].b16.s0 = GLYPH_NODE; mem[p + 4].b16.s2 = f; mem[p + 4].b16.s1 = get_native_glyph(mem[y + 5].b32.s1, 0); set_native_glyph_metrics(p, 1); free_node(mem[y + 5].b32.s1, mem[mem[y + 5].b32.s1 + 4].b16.s3); mem[y + 5].b32.s1 = p; if (odd(mem[q].b16.s0)) set_native_glyph_metrics(p, 1); else { c = mem[p + 4].b16.s1; a = 0; do { g = get_ot_math_variant(f, c, a, &w2, 1); if ((w2 > 0) && (w2 <= w)) { mem[p + 4].b16.s1 = g; set_native_glyph_metrics(p, 1); a++; } } while (!((w2 < 0) || (w2 >= w))); if ((w2 < 0)) { ot_assembly_ptr = get_ot_assembly_ptr(f, c, 1); if (ot_assembly_ptr != NULL) { free_node(p, GLYPH_NODE_SIZE); p = build_opentype_assembly(f, ot_assembly_ptr, w, 1); mem[y + 5].b32.s1 = p; goto found; } } else set_native_glyph_metrics(p, 1); } found: mem[y + 1].b32.s1 = mem[p + 1].b32.s1; mem[y + 3].b32.s1 = mem[p + 3].b32.s1; mem[y + 2].b32.s1 = mem[p + 2].b32.s1; if (((mem[q].b16.s0 == BOTTOM_ACC) || (mem[q].b16.s0 == (BOTTOM_ACC + 1)))) { if (mem[y + 3].b32.s1 < 0) mem[y + 3].b32.s1 = 0; } else if (mem[y + 2].b32.s1 < 0) mem[y + 2].b32.s1 = 0; if ((((p) != TEX_NULL && (!(is_char_node(p))) && (NODE_type(p) == WHATSIT_NODE) && (mem[p].b16.s0 == GLYPH_NODE)))) { sa = get_ot_math_accent_pos(f, mem[p + 4].b16.s1); if (sa == TEX_INFINITY) sa = half(mem[y + 1].b32.s1); } else sa = half(mem[y + 1].b32.s1); if (((mem[q].b16.s0 == BOTTOM_ACC) || (mem[q].b16.s0 == (BOTTOM_ACC + 1))) || (s == TEX_INFINITY)) s = half(w); mem[y + 4].b32.s1 = s - sa; } else mem[y + 4].b32.s1 = s + half(w - mem[y + 1].b32.s1); mem[y + 1].b32.s1 = 0; if (((mem[q].b16.s0 == BOTTOM_ACC) || (mem[q].b16.s0 == (BOTTOM_ACC + 1)))) { mem[x].b32.s1 = y; y = vpackage(x, 0, ADDITIONAL, MAX_HALFWORD); mem[y + 4].b32.s1 = -(int32_t) (h - mem[y + 3].b32.s1); } else { p = new_kern(-(int32_t) delta); mem[p].b32.s1 = x; mem[y].b32.s1 = p; y = vpackage(y, 0, ADDITIONAL, MAX_HALFWORD); if (mem[y + 3].b32.s1 < h) { /*765: */ p = new_kern(h - mem[y + 3].b32.s1); mem[p].b32.s1 = mem[y + 5].b32.s1; mem[y + 5].b32.s1 = p; mem[y + 3].b32.s1 = h; } } mem[y + 1].b32.s1 = mem[x + 1].b32.s1; mem[q + 1].b32.s0 = y; mem[q + 1].b32.s1 = SUB_BOX; } free_ot_assembly(ot_assembly_ptr); } static void make_fraction(int32_t q) { int32_t p, v, x, y, z; scaled_t delta, delta1, delta2, shift_up, shift_down, clr; if (mem[q + 1].b32.s1 == DEFAULT_CODE) mem[q + 1].b32.s1 = default_rule_thickness(); x = clean_box(q + 2, cur_style + 2 - 2 * (cur_style / 6)); z = clean_box(q + 3, 2 * (cur_style / 2) + 3 - 2 * (cur_style / 6)); if (mem[x + 1].b32.s1 < mem[z + 1].b32.s1) x = rebox(x, mem[z + 1].b32.s1); else z = rebox(z, mem[x + 1].b32.s1); if (cur_style < TEXT_STYLE) { shift_up = num1(cur_size); shift_down = denom1(cur_size); } else { shift_down = denom2(cur_size); if (mem[q + 1].b32.s1 != 0) shift_up = num2(cur_size); else shift_up = num3(cur_size); } if (mem[q + 1].b32.s1 == 0) { /*772:*/ if (font_area[cur_f] == OTGR_FONT_FLAG && isOpenTypeMathFont(font_layout_engine[cur_f])) { if (cur_style < TEXT_STYLE) clr = get_ot_math_constant(cur_f, STACKDISPLAYSTYLEGAPMIN); else clr = get_ot_math_constant(cur_f, STACKGAPMIN); } else { if (cur_style < TEXT_STYLE) clr = 7 * default_rule_thickness(); else clr = 3 * default_rule_thickness(); } delta = half(clr - ((shift_up - mem[x + 2].b32.s1) - (mem[z + 3].b32.s1 - shift_down))); if (delta > 0) { shift_up = shift_up + delta; shift_down = shift_down + delta; } } else { /*773:*/ if (font_area[cur_f] == OTGR_FONT_FLAG && isOpenTypeMathFont(font_layout_engine[cur_f])) { delta = half(mem[q + 1].b32.s1); if (cur_style < TEXT_STYLE) clr = get_ot_math_constant(cur_f, FRACTIONNUMDISPLAYSTYLEGAPMIN); else clr = get_ot_math_constant(cur_f, FRACTIONNUMERATORGAPMIN); delta1 = clr - ((shift_up - mem[x + 2].b32.s1) - (axis_height(cur_size) + delta)); if (cur_style < TEXT_STYLE) clr = get_ot_math_constant(cur_f, FRACTIONDENOMDISPLAYSTYLEGAPMIN); else clr = get_ot_math_constant(cur_f, FRACTIONDENOMINATORGAPMIN); delta2 = clr - ((axis_height(cur_size) - delta) - (mem[z + 3].b32.s1 - shift_down)); } else { if (cur_style < TEXT_STYLE) clr = 3 * mem[q + 1].b32.s1; else clr = mem[q + 1].b32.s1; delta = half(mem[q + 1].b32.s1); delta1 = clr - ((shift_up - mem[x + 2].b32.s1) - (axis_height(cur_size) + delta)); delta2 = clr - ((axis_height(cur_size) - delta) - (mem[z + 3].b32.s1 - shift_down)); } if (delta1 > 0) shift_up = shift_up + delta1; if (delta2 > 0) shift_down = shift_down + delta2; } v = new_null_box(); NODE_type(v) = VLIST_NODE; mem[v + 3].b32.s1 = shift_up + mem[x + 3].b32.s1; mem[v + 2].b32.s1 = mem[z + 2].b32.s1 + shift_down; mem[v + 1].b32.s1 = mem[x + 1].b32.s1; if (mem[q + 1].b32.s1 == 0) { p = new_kern((shift_up - mem[x + 2].b32.s1) - (mem[z + 3].b32.s1 - shift_down)); mem[p].b32.s1 = z; } else { y = fraction_rule(mem[q + 1].b32.s1); p = new_kern((axis_height(cur_size) - delta) - (mem[z + 3].b32.s1 - shift_down)); mem[y].b32.s1 = p; mem[p].b32.s1 = z; p = new_kern((shift_up - mem[x + 2].b32.s1) - (axis_height(cur_size) + delta)); mem[p].b32.s1 = y; } mem[x].b32.s1 = p; mem[v + 5].b32.s1 = x; /*:774*/ if (cur_style < TEXT_STYLE) delta = delim1(cur_size); else delta = delim2(cur_size); x = var_delimiter(q + 4, cur_size, delta); mem[x].b32.s1 = v; z = var_delimiter(q + 5, cur_size, delta); mem[v].b32.s1 = z; mem[q + 1].b32.s1 = hpack(x, 0, ADDITIONAL); /*:775*/ } static scaled_t make_op(int32_t q) { scaled_t delta; int32_t p, v, x, y, z; uint16_t c; b16x4 i; scaled_t shift_up, shift_down; scaled_t h1, h2; int32_t n, g; void *ot_assembly_ptr; internal_font_number save_f; if ((mem[q].b16.s0 == NORMAL) && (cur_style < TEXT_STYLE)) mem[q].b16.s0 = LIMITS; delta = 0; ot_assembly_ptr = NULL; if (mem[q + 1].b32.s1 == MATH_CHAR) { fetch(q + 1); if (!((font_area[cur_f] == OTGR_FONT_FLAG) && (usingOpenType(font_layout_engine[cur_f])))) { if ((cur_style < TEXT_STYLE) && (((cur_i.s1) % 4) == LIST_TAG)) { c = cur_i.s0; i = FONT_CHARACTER_INFO(cur_f, c); if ((i.s3 > 0)) { cur_c = c; cur_i = i; mem[q + 1].b16.s0 = c; } } delta = FONT_CHARINFO_ITALCORR(cur_f, cur_i); } x = clean_box(q + 1, cur_style); if (((font_area[cur_f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[cur_f])))) { p = mem[x + 5].b32.s1; if ((((p) != TEX_NULL && (!(is_char_node(p))) && (NODE_type(p) == WHATSIT_NODE) && (mem[p].b16.s0 == GLYPH_NODE)))) { if (cur_style < TEXT_STYLE) { h1 = get_ot_math_constant(cur_f, DISPLAYOPERATORMINHEIGHT); if (h1 < (mem[p + 3].b32.s1 + mem[p + 2].b32.s1) * 5 / ((double)4)) h1 = (mem[p + 3].b32.s1 + mem[p + 2].b32.s1) * 5 / ((double)4); c = mem[p + 4].b16.s1; n = 0; do { g = get_ot_math_variant(cur_f, c, n, &h2, 0); if (h2 > 0) { mem[p + 4].b16.s1 = g; set_native_glyph_metrics(p, 1); } n++; } while (!((h2 < 0) || (h2 >= h1))); if ((h2 < 0)) { ot_assembly_ptr = get_ot_assembly_ptr(cur_f, c, 0); if (ot_assembly_ptr != NULL) { free_node(p, GLYPH_NODE_SIZE); p = build_opentype_assembly(cur_f, ot_assembly_ptr, h1, 0); mem[x + 5].b32.s1 = p; delta = 0; goto found; } } else set_native_glyph_metrics(p, 1); } delta = get_ot_math_ital_corr(cur_f, mem[p + 4].b16.s1); found: mem[x + 1].b32.s1 = mem[p + 1].b32.s1; mem[x + 3].b32.s1 = mem[p + 3].b32.s1; mem[x + 2].b32.s1 = mem[p + 2].b32.s1; } } if ((mem[q + 3].b32.s1 != EMPTY) && (mem[q].b16.s0 != LIMITS)) mem[x + 1].b32.s1 = mem[x + 1].b32.s1 - delta; mem[x + 4].b32.s1 = half(mem[x + 3].b32.s1 - mem[x + 2].b32.s1) - axis_height(cur_size); mem[q + 1].b32.s1 = SUB_BOX; mem[q + 1].b32.s0 = x; } save_f = cur_f; if (mem[q].b16.s0 == LIMITS) { /*777: */ x = clean_box(q + 2, 2 * (cur_style / 4) + 4 + (cur_style % 2)); y = clean_box(q + 1, cur_style); z = clean_box(q + 3, 2 * (cur_style / 4) + 5); v = new_null_box(); NODE_type(v) = VLIST_NODE; mem[v + 1].b32.s1 = mem[y + 1].b32.s1; if (mem[x + 1].b32.s1 > mem[v + 1].b32.s1) mem[v + 1].b32.s1 = mem[x + 1].b32.s1; if (mem[z + 1].b32.s1 > mem[v + 1].b32.s1) mem[v + 1].b32.s1 = mem[z + 1].b32.s1; x = rebox(x, mem[v + 1].b32.s1); y = rebox(y, mem[v + 1].b32.s1); z = rebox(z, mem[v + 1].b32.s1); mem[x + 4].b32.s1 = half(delta); mem[z + 4].b32.s1 = -(int32_t) mem[x + 4].b32.s1; mem[v + 3].b32.s1 = mem[y + 3].b32.s1; mem[v + 2].b32.s1 = mem[y + 2].b32.s1; cur_f = save_f; if (mem[q + 2].b32.s1 == EMPTY) { free_node(x, BOX_NODE_SIZE); mem[v + 5].b32.s1 = y; } else { shift_up = big_op_spacing3() - mem[x + 2].b32.s1; if (shift_up < big_op_spacing1()) shift_up = big_op_spacing1(); p = new_kern(shift_up); mem[p].b32.s1 = y; mem[x].b32.s1 = p; p = new_kern(big_op_spacing5()); mem[p].b32.s1 = x; mem[v + 5].b32.s1 = p; mem[v + 3].b32.s1 = mem[v + 3].b32.s1 + big_op_spacing5() + mem[x + 3].b32.s1 + mem[x + 2].b32.s1 + shift_up; } if (mem[q + 3].b32.s1 == EMPTY) free_node(z, BOX_NODE_SIZE); else { shift_down = big_op_spacing4() - mem[z + 3].b32.s1; if (shift_down < big_op_spacing2()) shift_down = big_op_spacing2(); p = new_kern(shift_down); mem[y].b32.s1 = p; mem[p].b32.s1 = z; p = new_kern(big_op_spacing5()); mem[z].b32.s1 = p; mem[v + 2].b32.s1 = mem[v + 2].b32.s1 + big_op_spacing5() + mem[z + 3].b32.s1 + mem[z + 2].b32.s1 + shift_down; } mem[q + 1].b32.s1 = v; } free_ot_assembly(ot_assembly_ptr); return delta; } static void make_ord(int32_t q) { int32_t a; int32_t p, r; restart: if (mem[q + 3].b32.s1 == EMPTY) { if (mem[q + 2].b32.s1 == EMPTY) { if (mem[q + 1].b32.s1 == MATH_CHAR) { p = mem[q].b32.s1; if (p != TEX_NULL) { if ((mem[p].b16.s1 >= ORD_NOAD) && (mem[p].b16.s1 <= PUNCT_NOAD)) { if (mem[p + 1].b32.s1 == MATH_CHAR) { if ((mem[p + 1].b16.s1 % 256) == (mem[q + 1].b16.s1 % 256)) { mem[q + 1].b32.s1 = MATH_TEXT_CHAR; fetch(q + 1); if (((cur_i.s1) % 4) == LIG_TAG) { a = lig_kern_base[cur_f] + cur_i.s0; cur_c = mem[p + 1].b16.s0; cur_i = font_info[a].b16; if (cur_i.s3 > 128) { a = lig_kern_base[cur_f] + 256 * cur_i.s1 + cur_i.s0 + 32768L - 256 * (128); cur_i = font_info[a].b16; } while (true) { if (cur_i.s2 == cur_c) { if (cur_i.s3 <= 128) { if (cur_i.s1 >= 128) { p = new_kern(font_info [kern_base[cur_f] + 256 * cur_i.s1 + cur_i.s0].b32.s1); mem[p].b32.s1 = mem[q].b32.s1; mem[q].b32.s1 = p; return; } else { switch (cur_i.s1) { case 1: case 5: mem[q + 1].b16.s0 = cur_i.s0; break; case 2: case 6: mem[p + 1].b16.s0 = cur_i.s0; break; case 3: case 7: case 11: { r = new_noad(); mem[r + 1].b16.s0 = cur_i.s0; mem[r + 1].b16.s1 = (mem[q + 1].b16.s1 % 256); mem[q].b32.s1 = r; mem[r].b32.s1 = p; if (cur_i.s1 < 11) mem[r + 1].b32.s1 = MATH_CHAR; else mem[r + 1].b32.s1 = MATH_TEXT_CHAR; } break; default: { mem[q].b32.s1 = mem[p].b32.s1; mem[q + 1].b16.s0 = cur_i.s0; mem[q + 3] = mem[p + 3]; mem[q + 2] = mem[p + 2]; free_node(p, NOAD_SIZE); } break; } if (cur_i.s1 > 3) return; mem[q + 1].b32.s1 = MATH_CHAR; goto restart; } } } if (cur_i.s3 >= 128) return; a = a + cur_i.s3 + 1; cur_i = font_info[a].b16; } } } } } } } } } } static int32_t attach_hkern_to_new_hlist(int32_t q, scaled_t delta) { int32_t y, z; z = new_kern(delta); if (mem[q + 1].b32.s1 == TEX_NULL) mem[q + 1].b32.s1 = z; else { y = mem[q + 1].b32.s1; while (mem[y].b32.s1 != TEX_NULL) y = LLIST_link(y); mem[y].b32.s1 = z; } return mem[q + 1].b32.s1; } static void make_scripts(int32_t q, scaled_t delta) { int32_t p, x, y, z; scaled_t shift_up, shift_down, clr, sub_kern, sup_kern; int32_t script_c; uint16_t script_g; internal_font_number script_f; uint16_t sup_g; internal_font_number sup_f; uint16_t sub_g; internal_font_number sub_f; int32_t t; internal_font_number save_f; int32_t script_head; int32_t script_ptr; small_number saved_math_style; small_number this_math_style; p = mem[q + 1].b32.s1; script_c = TEX_NULL; script_g = 0; script_f = 0; sup_kern = 0; sub_kern = 0; if ((is_char_node(p)) || (((p) != TEX_NULL && (!(is_char_node(p))) && (NODE_type(p) == WHATSIT_NODE) && (mem[p].b16.s0 == GLYPH_NODE)))) { shift_up = 0; shift_down = 0; } else { z = hpack(p, 0, ADDITIONAL); if (cur_style < SCRIPT_STYLE) t = SCRIPT_SIZE; else t = SCRIPT_SCRIPT_SIZE; shift_up = mem[z + 3].b32.s1 - sup_drop(t); shift_down = mem[z + 2].b32.s1 + sub_drop(t); free_node(z, BOX_NODE_SIZE); } if (mem[q + 2].b32.s1 == EMPTY) { /*801: */ /* "Construct a subscript box when there is no superscript[.] The top of * the subscript should not exceed the baseline plus four-fifths of the * x-height." */ script_head = q + 3; /* 805: fetch first character of a sub/superscript */ script_c = TEX_NULL; script_g = 0; script_f = 0; this_math_style = 2 * (cur_style / 4) + 5; /* "Loop through the sub mlist looking for the first character-like * thing. Ignore kerns or glue so that, for example, changing P_j to * P_{\,j} will have a predictable effect. Intercept style nodes and * execute them. If we encounter a choice node, follow the appropriate * branch. Anything else halts the search and inhibits OpenType kerning. * Don’t try to do anything clever if the nucleus of the script head * is empty, e.g., Pj and the such." */ if (mem[script_head].b32.s1 == SUB_MLIST) { /* math_type(script_head) */ script_ptr = LLIST_info(script_head); script_head = TEX_NULL; while (script_ptr >= 0 && script_ptr <= mem_end) { /* is_valid_pointer() */ switch (NODE_type(script_ptr)) { case KERN_NODE: case GLUE_NODE: case CHOICE_NODE: break; case STYLE_NODE: this_math_style = NODE_subtype(script_ptr); break; case ORD_NOAD: case OP_NOAD: case BIN_NOAD: case REL_NOAD: case OPEN_NOAD: case CLOSE_NOAD: case PUNCT_NOAD: script_head = script_ptr + 1; /* nucleus(script_ptr) */ script_ptr = TEX_NULL; break; default: script_ptr = TEX_NULL; } if (script_ptr >= 0 && script_ptr <= mem_end) { if (NODE_type(script_ptr) == CHOICE_NODE) { switch (this_math_style / 2) { case 0: script_ptr = mem[script_ptr + 1].b32.s0; /*display_mlist(.)*/ break; case 1: script_ptr = mem[script_ptr + 1].b32.s1; /*text_mlist(.)*/ break; case 2: script_ptr = mem[script_ptr + 2].b32.s0; /*script_mlist(.)*/ break; case 3: script_ptr = mem[script_ptr + 2].b32.s1; /*script_script_mlist(.)*/ break; } } else { script_ptr = LLIST_link(script_ptr); } } } } if (script_head >= 0 && script_head <= mem_end && mem[script_head].b32.s1 == MATH_CHAR) { save_f = cur_f; saved_math_style = cur_style; cur_style = this_math_style; if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); fetch(script_head); if (font_area[cur_f] == OTGR_FONT_FLAG && isOpenTypeMathFont(font_layout_engine[cur_f])) { script_c = new_native_character(cur_f, cur_c); script_g = get_native_glyph(script_c, 0); script_f = cur_f; } cur_f = save_f; cur_style = saved_math_style; if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } sub_g = script_g; sub_f = script_f; save_f = cur_f; x = clean_box(q + 3, 2 * (cur_style / 4) + 5); cur_f = save_f; mem[x + 1].b32.s1 = mem[x + 1].b32.s1 + DIMENPAR(script_space); if (shift_down < sub1(cur_size)) shift_down = sub1(cur_size); if (((font_area[cur_f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[cur_f])))) clr = mem[x + 3].b32.s1 - get_ot_math_constant(cur_f, SUBSCRIPTTOPMAX); else clr = mem[x + 3].b32.s1 - (abs(math_x_height(cur_size) * 4) / 5); if (shift_down < clr) shift_down = clr; mem[x + 4].b32.s1 = shift_down; if (font_area[cur_f] == OTGR_FONT_FLAG && isOpenTypeMathFont(font_layout_engine[cur_f])) { /*787: */ if (p != TEX_NULL && !is_char_node(p) && NODE_type(p) == WHATSIT_NODE && mem[p].b16.s0 == GLYPH_NODE) { sub_kern = get_ot_math_kern(mem[p + 4].b16.s2, mem[p + 4].b16.s1, sub_f, sub_g, SUB_CMD, shift_down); if (sub_kern != 0) p = attach_hkern_to_new_hlist(q, sub_kern); } } } else { /*********************/ script_head = q + 2; /* Lots of code duplication here ... */ script_c = TEX_NULL; script_g = 0; script_f = 0; this_math_style = 2 * (cur_style / 4) + 5; if (mem[script_head].b32.s1 == SUB_MLIST) { /* math_type(script_head) */ script_ptr = LLIST_info(script_head); script_head = TEX_NULL; while (script_ptr >= 0 && script_ptr <= mem_end) { /* is_valid_pointer() */ switch (NODE_type(script_ptr)) { case KERN_NODE: case GLUE_NODE: case CHOICE_NODE: break; case STYLE_NODE: this_math_style = NODE_subtype(script_ptr); break; case ORD_NOAD: case OP_NOAD: case BIN_NOAD: case REL_NOAD: case OPEN_NOAD: case CLOSE_NOAD: case PUNCT_NOAD: script_head = script_ptr + 1; /* nucleus(script_ptr) */ script_ptr = TEX_NULL; break; default: script_ptr = TEX_NULL; } if (script_ptr >= 0 && script_ptr <= mem_end) { if (NODE_type(script_ptr) == CHOICE_NODE) { switch (this_math_style / 2) { case 0: script_ptr = mem[script_ptr + 1].b32.s0; /*display_mlist(.)*/ break; case 1: script_ptr = mem[script_ptr + 1].b32.s1; /*text_mlist(.)*/ break; case 2: script_ptr = mem[script_ptr + 2].b32.s0; /*script_mlist(.)*/ break; case 3: script_ptr = mem[script_ptr + 2].b32.s1; /*script_script_mlist(.)*/ break; } } else { script_ptr = LLIST_link(script_ptr); } } } } if (script_head >= 0 && script_head <= mem_end && mem[script_head].b32.s1 == MATH_CHAR) { save_f = cur_f; saved_math_style = cur_style; cur_style = this_math_style; if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); fetch(script_head); if (font_area[cur_f] == OTGR_FONT_FLAG && isOpenTypeMathFont(font_layout_engine[cur_f])) { script_c = new_native_character(cur_f, cur_c); script_g = get_native_glyph(script_c, 0); script_f = cur_f; } cur_f = save_f; cur_style = saved_math_style; if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } sup_g = script_g; sup_f = script_f; save_f = cur_f; x = clean_box(q + 2, 2 * (cur_style / 4) + 4 + (cur_style % 2)); cur_f = save_f; mem[x + 1].b32.s1 = mem[x + 1].b32.s1 + DIMENPAR(script_space); if (odd(cur_style)) clr = sup3(cur_size); else if (cur_style < TEXT_STYLE) clr = sup1(cur_size); else clr = sup2(cur_size); if (shift_up < clr) shift_up = clr; if (font_area[cur_f] == OTGR_FONT_FLAG && isOpenTypeMathFont(font_layout_engine[cur_f])) clr = mem[x + 2].b32.s1 + get_ot_math_constant(cur_f, SUPERSCRIPTBOTTOMMIN); else clr = mem[x + 2].b32.s1 + (abs(math_x_height(cur_size)) / 4); if (shift_up < clr) shift_up = clr; if (font_area[cur_f] == OTGR_FONT_FLAG && isOpenTypeMathFont(font_layout_engine[cur_f])) { /*788: */ if (mem[q + 3].b32.s1 == EMPTY) { if (p != TEX_NULL && !is_char_node(p) && NODE_type(p) == WHATSIT_NODE && mem[p].b16.s0 == GLYPH_NODE) { sup_kern = get_ot_math_kern(mem[p + 4].b16.s2, mem[p + 4].b16.s1, sup_f, sup_g, SUP_CMD, shift_up); if (sup_kern != 0) p = attach_hkern_to_new_hlist(q, sup_kern); } } } if (mem[q + 3].b32.s1 == EMPTY) mem[x + 4].b32.s1 = -(int32_t) shift_up; else { /*786: */ save_f = cur_f; /* Yet more duplication */ script_head = q + 3; script_c = TEX_NULL; script_g = 0; script_f = 0; this_math_style = 2 * (cur_style / 4) + 5; if (mem[script_head].b32.s1 == SUB_MLIST) { /* math_type(script_head) */ script_ptr = LLIST_info(script_head); script_head = TEX_NULL; while (script_ptr >= 0 && script_ptr <= mem_end) { /* is_valid_pointer() */ switch (NODE_type(script_ptr)) { case KERN_NODE: case GLUE_NODE: case CHOICE_NODE: break; case STYLE_NODE: this_math_style = NODE_subtype(script_ptr); break; case ORD_NOAD: case OP_NOAD: case BIN_NOAD: case REL_NOAD: case OPEN_NOAD: case CLOSE_NOAD: case PUNCT_NOAD: script_head = script_ptr + 1; /* nucleus(script_ptr) */ script_ptr = TEX_NULL; break; default: script_ptr = TEX_NULL; } if (script_ptr >= 0 && script_ptr <= mem_end) { if (NODE_type(script_ptr) == CHOICE_NODE) { switch (this_math_style / 2) { case 0: script_ptr = mem[script_ptr + 1].b32.s0; /*display_mlist(.)*/ break; case 1: script_ptr = mem[script_ptr + 1].b32.s1; /*text_mlist(.)*/ break; case 2: script_ptr = mem[script_ptr + 2].b32.s0; /*script_mlist(.)*/ break; case 3: script_ptr = mem[script_ptr + 2].b32.s1; /*script_script_mlist(.)*/ break; } } else { script_ptr = LLIST_link(script_ptr); } } } } if (script_head >= 0 && script_head <= mem_end && mem[script_head].b32.s1 == MATH_CHAR) { save_f = cur_f; saved_math_style = cur_style; cur_style = this_math_style; if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); fetch(script_head); if (font_area[cur_f] == OTGR_FONT_FLAG && isOpenTypeMathFont(font_layout_engine[cur_f])) { script_c = new_native_character(cur_f, cur_c); script_g = get_native_glyph(script_c, 0); script_f = cur_f; } cur_f = save_f; cur_style = saved_math_style; if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } sub_g = script_g; sub_f = script_f; y = clean_box(q + 3, 2 * (cur_style / 4) + 5); cur_f = save_f; mem[y + 1].b32.s1 = mem[y + 1].b32.s1 + DIMENPAR(script_space); if (shift_down < sub2(cur_size)) shift_down = sub2(cur_size); if (((font_area[cur_f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[cur_f])))) clr = get_ot_math_constant(cur_f, SUBSUPERSCRIPTGAPMIN) - ((shift_up - mem[x + 2].b32.s1) - (mem[y + 3].b32.s1 - shift_down)); else clr = 4 * default_rule_thickness() - ((shift_up - mem[x + 2].b32.s1) - (mem[y + 3].b32.s1 - shift_down)); if (clr > 0) { shift_down = shift_down + clr; if (((font_area[cur_f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[cur_f])))) clr = get_ot_math_constant(cur_f, SUPERSCRIPTBOTTOMMAXWITHSUBSCRIPT) - (shift_up - mem[x + 2].b32.s1); else clr = (abs(math_x_height(cur_size) * 4) / 5) - (shift_up - mem[x + 2].b32.s1); if (clr > 0) { shift_up = shift_up + clr; shift_down = shift_down - clr; } } if (font_area[cur_f] == OTGR_FONT_FLAG && isOpenTypeMathFont(font_layout_engine[cur_f])) { if (p != TEX_NULL && !is_char_node(p) && NODE_type(p) == WHATSIT_NODE && mem[p].b16.s0 == GLYPH_NODE) { sub_kern = get_ot_math_kern(mem[p + 4].b16.s2, mem[p + 4].b16.s1, sub_f, sub_g, SUB_CMD, shift_down); if (sub_kern != 0) p = attach_hkern_to_new_hlist(q, sub_kern); } if (mem[q + 3].b32.s1 == EMPTY) { if (p != TEX_NULL && !is_char_node(p) && NODE_type(p) == WHATSIT_NODE && mem[p].b16.s0 == GLYPH_NODE) { sup_kern = get_ot_math_kern(mem[p + 4].b16.s2, mem[p + 4].b16.s1, sup_f, sup_g, SUP_CMD, shift_up); if (sup_kern != 0) p = attach_hkern_to_new_hlist(q, sup_kern); } } } else { sup_kern = 0; sub_kern = 0; } mem[x + 4].b32.s1 = sup_kern + delta - sub_kern; p = new_kern((shift_up - mem[x + 2].b32.s1) - (mem[y + 3].b32.s1 - shift_down)); mem[x].b32.s1 = p; mem[p].b32.s1 = y; x = vpackage(x, 0, ADDITIONAL, MAX_HALFWORD); mem[x + 4].b32.s1 = shift_down; } } if (mem[q + 1].b32.s1 == TEX_NULL) mem[q + 1].b32.s1 = x; else { p = mem[q + 1].b32.s1; while (mem[p].b32.s1 != TEX_NULL) p = LLIST_link(p); mem[p].b32.s1 = x; } } static small_number make_left_right(int32_t q, small_number style, scaled_t max_d, scaled_t max_h) { scaled_t delta, delta1, delta2; cur_style = style; { if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } delta2 = max_d + axis_height(cur_size); delta1 = max_h + max_d - delta2; if (delta2 > delta1) delta1 = delta2; delta = (delta1 / 500) * INTPAR(delimiter_factor); delta2 = delta1 + delta1 - DIMENPAR(delimiter_shortfall); if (delta < delta2) delta = delta2; mem[q + 1].b32.s1 = var_delimiter(q + 1, cur_size, delta); return mem[q].b16.s1 - ((LEFT_NOAD - 20)); } static void mlist_to_hlist(void) { int32_t mlist; bool penalties; small_number style; small_number save_style; int32_t q; int32_t r; small_number r_type; small_number t; int32_t p = TEX_NULL, x, y, z; int32_t pen; small_number s; scaled_t max_h, max_d; scaled_t delta; mlist = cur_mlist; penalties = mlist_penalties; style = cur_style; q = mlist; r = TEX_NULL; r_type = OP_NOAD; max_h = 0; max_d = 0; { if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } while (q != TEX_NULL) { /*753: */ reswitch: delta = 0; switch (mem[q].b16.s1) { case BIN_NOAD: switch (r_type) { case BIN_NOAD: case OP_NOAD: case REL_NOAD: case OPEN_NOAD: case PUNCT_NOAD: case LEFT_NOAD: mem[q].b16.s1 = ORD_NOAD; goto reswitch; default: break; } break; case REL_NOAD: case CLOSE_NOAD: case PUNCT_NOAD: case RIGHT_NOAD: { if (r_type == BIN_NOAD) mem[r].b16.s1 = ORD_NOAD /*:755 */ ; if (mem[q].b16.s1 == RIGHT_NOAD) goto lab80; } break; case LEFT_NOAD: goto lab80; break; case FRACTION_NOAD: make_fraction(q); goto lab82; case OP_NOAD: delta = make_op(q); if (mem[q].b16.s0 == LIMITS) goto lab82; break; case ORD_NOAD: make_ord(q); break; case OPEN_NOAD: case INNER_NOAD: break; case RADICAL_NOAD: make_radical(q); break; case OVER_NOAD: make_over(q); break; case UNDER_NOAD: make_under(q); break; case ACCENT_NOAD: make_math_accent(q); break; case VCENTER_NOAD: make_vcenter(q); break; case STYLE_NODE: { cur_style = mem[q].b16.s0; { if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } goto lab81; } break; case CHOICE_NODE: { switch (cur_style / 2) { case 0: { p = mem[q + 1].b32.s0; mem[q + 1].b32.s0 = TEX_NULL; } break; case 1: { p = mem[q + 1].b32.s1; mem[q + 1].b32.s1 = TEX_NULL; } break; case 2: { p = mem[q + 2].b32.s0; mem[q + 2].b32.s0 = TEX_NULL; } break; case 3: { p = mem[q + 2].b32.s1; mem[q + 2].b32.s1 = TEX_NULL; } break; } flush_node_list(mem[q + 1].b32.s0); flush_node_list(mem[q + 1].b32.s1); flush_node_list(mem[q + 2].b32.s0); flush_node_list(mem[q + 2].b32.s1); NODE_type(q) = STYLE_NODE; mem[q].b16.s0 = cur_style; mem[q + 1].b32.s1 = 0; mem[q + 2].b32.s1 = 0; if (p != TEX_NULL) { z = mem[q].b32.s1; mem[q].b32.s1 = p; while (mem[p].b32.s1 != TEX_NULL) p = LLIST_link(p); mem[p].b32.s1 = z; } goto lab81; } break; case INS_NODE: case MARK_NODE: case ADJUST_NODE: case WHATSIT_NODE: case PENALTY_NODE: case DISC_NODE: goto lab81; case RULE_NODE: if (mem[q + 3].b32.s1 > max_h) max_h = mem[q + 3].b32.s1; if (mem[q + 2].b32.s1 > max_d) max_d = mem[q + 2].b32.s1; goto lab81; case GLUE_NODE: { if (mem[q].b16.s0 == MU_GLUE) { x = mem[q + 1].b32.s0; y = math_glue(x, cur_mu); delete_glue_ref(x); mem[q + 1].b32.s0 = y; mem[q].b16.s0 = NORMAL; } else if ((cur_size != TEXT_SIZE) && (mem[q].b16.s0 == COND_MATH_GLUE)) { p = mem[q].b32.s1; if (p != TEX_NULL) { if ((NODE_type(p) == GLUE_NODE) || (NODE_type(p) == KERN_NODE)) { mem[q].b32.s1 = mem[p].b32.s1; mem[p].b32.s1 = TEX_NULL; flush_node_list(p); } } } goto lab81; } break; case KERN_NODE: { math_kern(q, cur_mu); goto lab81; } break; default: confusion("mlist1"); break; } switch (mem[q + 1].b32.s1) { case 1: case 4: { fetch(q + 1); if (((font_area[cur_f] == AAT_FONT_FLAG) || (font_area[cur_f] == OTGR_FONT_FLAG))) { z = new_native_character(cur_f, cur_c); p = get_node(GLYPH_NODE_SIZE); NODE_type(p) = WHATSIT_NODE; mem[p].b16.s0 = GLYPH_NODE; mem[p + 4].b16.s2 = cur_f; mem[p + 4].b16.s1 = get_native_glyph(z, 0); set_native_glyph_metrics(p, 1); free_node(z, mem[z + 4].b16.s3); delta = get_ot_math_ital_corr(cur_f, mem[p + 4].b16.s1); if ((mem[q + 1].b32.s1 == MATH_TEXT_CHAR) && (!((font_area[cur_f] == OTGR_FONT_FLAG) && (isOpenTypeMathFont(font_layout_engine[cur_f]))) != 0)) delta = 0; if ((mem[q + 3].b32.s1 == EMPTY) && (delta != 0)) { mem[p].b32.s1 = new_kern(delta); delta = 0; } } else if ((cur_i.s3 > 0)) { delta = FONT_CHARINFO_ITALCORR(cur_f, cur_i); p = new_character(cur_f, cur_c); if ((mem[q + 1].b32.s1 == MATH_TEXT_CHAR) && (font_info[SPACE_CODE + param_base[cur_f]].b32.s1 != 0)) delta = 0; if ((mem[q + 3].b32.s1 == EMPTY) && (delta != 0)) { mem[p].b32.s1 = new_kern(delta); delta = 0; } } else p = TEX_NULL; } break; case 0: p = TEX_NULL; break; case 2: p = mem[q + 1].b32.s0; break; case 3: { cur_mlist = mem[q + 1].b32.s0; save_style = cur_style; mlist_penalties = false; mlist_to_hlist(); cur_style = save_style; { if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } p = hpack(mem[TEMP_HEAD].b32.s1, 0, ADDITIONAL); } break; default: confusion("mlist2"); break; } mem[q + 1].b32.s1 = p; if ((mem[q + 3].b32.s1 == EMPTY) && (mem[q + 2].b32.s1 == EMPTY)) goto lab82; make_scripts(q, delta); lab82:/*check_dimensions */ z = hpack(mem[q + 1].b32.s1, 0, ADDITIONAL); if (mem[z + 3].b32.s1 > max_h) max_h = mem[z + 3].b32.s1; if (mem[z + 2].b32.s1 > max_d) max_d = mem[z + 2].b32.s1; free_node(z, BOX_NODE_SIZE); lab80: /*done_with_noad */ r = q; r_type = mem[r].b16.s1; if (r_type == RIGHT_NOAD) { r_type = LEFT_NOAD; cur_style = style; { if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } } lab81: /*done_with_node */ q = LLIST_link(q); } if (r_type == BIN_NOAD) mem[r].b16.s1 = 16 /*ord_noad *//*:755 */ ; p = TEMP_HEAD; mem[p].b32.s1 = TEX_NULL; q = mlist; r_type = 0; cur_style = style; { if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } while (q != TEX_NULL) { t = ORD_NOAD; s = NOAD_SIZE; pen = INF_PENALTY; switch (mem[q].b16.s1) { case OP_NOAD: case OPEN_NOAD: case CLOSE_NOAD: case PUNCT_NOAD: case INNER_NOAD: t = mem[q].b16.s1; break; case BIN_NOAD: { t = BIN_NOAD; pen = INTPAR(bin_op_penalty); } break; case REL_NOAD: { t = REL_NOAD; pen = INTPAR(rel_penalty); } break; case ORD_NOAD: case VCENTER_NOAD: case OVER_NOAD: case UNDER_NOAD: break; case RADICAL_NOAD: s = RADICAL_NOAD_SIZE; break; case ACCENT_NOAD: s = ACCENT_NOAD_SIZE; break; case FRACTION_NOAD: s = FRACTION_NOAD_SIZE; break; case LEFT_NOAD: case RIGHT_NOAD: t = make_left_right(q, style, max_d, max_h); break; case STYLE_NODE: { cur_style = mem[q].b16.s0; s = STYLE_NODE_SIZE; { if (cur_style < SCRIPT_STYLE) cur_size = TEXT_SIZE; else cur_size = SCRIPT_SIZE * ((cur_style - 2) / 2); cur_mu = x_over_n(math_quad(cur_size), 18); } goto lab83; } break; case WHATSIT_NODE: case PENALTY_NODE: case RULE_NODE: case DISC_NODE: case ADJUST_NODE: case INS_NODE: case MARK_NODE: case GLUE_NODE: case KERN_NODE: { mem[p].b32.s1 = q; p = q; q = LLIST_link(q); mem[p].b32.s1 = TEX_NULL; goto done; } break; default: confusion("mlist3"); break; } if (r_type > 0) { const char* offset_table[] = { "02340001", "22*40001", "33**3**3", "44*04004", "00*00000", "02340001", "11*11111", "12341011" }; // The inter-element spacing in math formulas depends on a 8x8 table. // The table indices range from ORD_NOAD to INNER_NOAD. // The chars of this table have the following significance: switch (offset_table[r_type - ORD_NOAD][t - ORD_NOAD]) { case '0': // no space x = 0; break; case '1': // a conditional thin space if (cur_style < SCRIPT_STYLE) x = GLUE_PAR__thin_mu_skip; else x = 0; break; case '2': // a thin space x = GLUE_PAR__thin_mu_skip; break; case '3': // a conditional medium space if (cur_style < SCRIPT_STYLE) x = GLUE_PAR__med_mu_skip; else x = 0; break; case '4': // a conditional thick space if (cur_style < SCRIPT_STYLE) x = GLUE_PAR__thick_mu_skip; else x = 0; break; default: // impossible confusion("mlist4"); break; } if (x != 0) { y = math_glue(eqtb[GLUE_BASE + x].b32.s1, cur_mu); z = new_glue(y); mem[y].b32.s1 = TEX_NULL; mem[p].b32.s1 = z; p = z; mem[z].b16.s0 = x + 1; } } if (mem[q + 1].b32.s1 != TEX_NULL) { mem[p].b32.s1 = mem[q + 1].b32.s1; do { p = LLIST_link(p); } while (!(mem[p].b32.s1 == TEX_NULL)); } if (penalties) { if (mem[q].b32.s1 != TEX_NULL) { if (pen < INF_PENALTY) { r_type = mem[mem[q].b32.s1].b16.s1; if (r_type != PENALTY_NODE) { if (r_type != REL_NOAD) { z = new_penalty(pen); mem[p].b32.s1 = z; p = z; } } } } } if (mem[q].b16.s1 == RIGHT_NOAD) t = OPEN_NOAD; r_type = t; lab83: /*delete_q */ r = q; q = LLIST_link(q); free_node(r, s); done: ; } } static int32_t var_delimiter(int32_t d, int32_t s, scaled_t v) { int32_t b; void *ot_assembly_ptr; internal_font_number f, g; uint16_t c = 0, x, y; int32_t m, n; scaled_t u; scaled_t w; b16x4 q = { 0, 0, 0, 0 }; b16x4 r; int32_t z; bool large_attempt; f = FONT_BASE; w = 0; large_attempt = false; z = (mem[d].b16.s3 % 256); x = (mem[d].b16.s2 + (mem[d].b16.s3 / 256) * 65536L); ot_assembly_ptr = NULL; while (true) { if ((z != 0) || (x != 0)) { z = z + s + 256; do { z = z - 256; g = MATH_FONT(z); if (g != FONT_BASE) { /*734: */ if (((font_area[g] == OTGR_FONT_FLAG) && (usingOpenType(font_layout_engine[g])))) { x = map_char_to_glyph(g, x); f = g; c = x; w = 0; n = 0; do { y = get_ot_math_variant(g, x, n, &u, 0); if (u > w) { c = y; w = u; if (u >= v) goto found; } n = n + 1; } while (!(u < 0)); ot_assembly_ptr = get_ot_assembly_ptr(g, x, 0); if (ot_assembly_ptr != NULL) goto found; } else { y = x; if ((y >= font_bc[g]) && (y <= font_ec[g])) { continue_: q = FONT_CHARACTER_INFO(g, y); if ((q.s3 > 0)) { if (((q.s1) % 4) == EXT_TAG) { f = g; c = y; goto found; } u = FONT_CHARINFO_HEIGHT(g, q) + FONT_CHARINFO_DEPTH(g, q); if (u > w) { f = g; c = y; w = u; if (u >= v) goto found; } if (((q.s1) % 4) == LIST_TAG) { y = q.s0; goto continue_; } } } } } } while (!(z < SCRIPT_SIZE)); } if (large_attempt) goto found; large_attempt = true; z = (mem[d].b16.s1 % 256); x = (mem[d].b16.s0 + (mem[d].b16.s1 / 256) * 65536L); } found: if (f != FONT_BASE) { if (!((font_area[f] == OTGR_FONT_FLAG) && (usingOpenType(font_layout_engine[f])))) { /*736: */ if (((q.s1) % 4) == EXT_TAG) { /*739: */ b = new_null_box(); NODE_type(b) = VLIST_NODE; r = font_info[exten_base[f] + q.s0].b16; c = r.s0; u = height_plus_depth(f, c); w = 0; q = FONT_CHARACTER_INFO(f, effective_char(true, f, c)); mem[b + 1].b32.s1 = FONT_CHARINFO_WIDTH(f, q) + FONT_CHARINFO_ITALCORR(f, q); c = r.s1; if (c != 0) w = w + height_plus_depth(f, c); c = r.s2; if (c != 0) w = w + height_plus_depth(f, c); c = r.s3; if (c != 0) w = w + height_plus_depth(f, c); n = 0; if (u > 0) while (w < v) { w = w + u; n++; if (r.s2 != 0) w = w + u; } c = r.s1; if (c != 0) stack_into_box(b, f, c); c = r.s0; { register int32_t for_end; m = 1; for_end = n; if (m <= for_end) do stack_into_box(b, f, c); while (m++ < for_end); } c = r.s2; if (c != 0) { stack_into_box(b, f, c); c = r.s0; { register int32_t for_end; m = 1; for_end = n; if (m <= for_end) do stack_into_box(b, f, c); while (m++ < for_end); } } c = r.s3; if (c != 0) stack_into_box(b, f, c); mem[b + 2].b32.s1 = w - mem[b + 3].b32.s1; } else b = char_box(f, c) /*:736 */ ; } else { if (ot_assembly_ptr != NULL) b = build_opentype_assembly(f, ot_assembly_ptr, v, 0); else { b = new_null_box(); NODE_type(b) = VLIST_NODE; mem[b + 5].b32.s1 = get_node(GLYPH_NODE_SIZE); NODE_type(mem[b + 5].b32.s1) = WHATSIT_NODE; mem[mem[b + 5].b32.s1].b16.s0 = GLYPH_NODE; mem[mem[b + 5].b32.s1 + 4].b16.s2 = f; mem[mem[b + 5].b32.s1 + 4].b16.s1 = c; set_native_glyph_metrics(mem[b + 5].b32.s1, 1); mem[b + 1].b32.s1 = mem[mem[b + 5].b32.s1 + 1].b32.s1; mem[b + 3].b32.s1 = mem[mem[b + 5].b32.s1 + 3].b32.s1; mem[b + 2].b32.s1 = mem[mem[b + 5].b32.s1 + 2].b32.s1; } } } else { b = new_null_box(); mem[b + 1].b32.s1 = DIMENPAR(null_delimiter_space); } mem[b + 4].b32.s1 = half(mem[b + 3].b32.s1 - mem[b + 2].b32.s1) - axis_height(s); free_ot_assembly(ot_assembly_ptr); return b; } static int32_t char_box(internal_font_number f, int32_t c) { b16x4 q; int32_t b, p; if (((font_area[f] == AAT_FONT_FLAG) || (font_area[f] == OTGR_FONT_FLAG))) { b = new_null_box(); p = new_native_character(f, c); mem[b + 5].b32.s1 = p; mem[b + 3].b32.s1 = mem[p + 3].b32.s1; mem[b + 1].b32.s1 = mem[p + 1].b32.s1; if (mem[p + 2].b32.s1 < 0) mem[b + 2].b32.s1 = 0; else mem[b + 2].b32.s1 = mem[p + 2].b32.s1; } else { q = FONT_CHARACTER_INFO(f, effective_char(true, f, c)); b = new_null_box(); mem[b + 1].b32.s1 = FONT_CHARINFO_WIDTH(f, q) + FONT_CHARINFO_ITALCORR(f, q); mem[b + 3].b32.s1 = FONT_CHARINFO_HEIGHT(f, q); mem[b + 2].b32.s1 = FONT_CHARINFO_DEPTH(f, q); p = get_avail(); mem[p].b16.s0 = c; mem[p].b16.s1 = f; } mem[b + 5].b32.s1 = p; return b; } static void stack_into_box(int32_t b, internal_font_number f, uint16_t c) { int32_t p; p = char_box(f, c); mem[p].b32.s1 = mem[b + 5].b32.s1; mem[b + 5].b32.s1 = p; mem[b + 3].b32.s1 = mem[p + 3].b32.s1; } static scaled_t height_plus_depth(internal_font_number f, uint16_t c) { b16x4 q = FONT_CHARACTER_INFO(f, effective_char(true, f, c)); return FONT_CHARINFO_HEIGHT(f, q) + FONT_CHARINFO_DEPTH(f, q); } static void stack_glyph_into_box(int32_t b, internal_font_number f, int32_t g) { int32_t p, q; p = get_node(GLYPH_NODE_SIZE); NODE_type(p) = WHATSIT_NODE; mem[p].b16.s0 = GLYPH_NODE; mem[p + 4].b16.s2 = f; mem[p + 4].b16.s1 = g; set_native_glyph_metrics(p, 1); if (NODE_type(b) == HLIST_NODE) { q = mem[b + 5].b32.s1; if (q == TEX_NULL) mem[b + 5].b32.s1 = p; else { while (mem[q].b32.s1 != TEX_NULL) q = LLIST_link(q); mem[q].b32.s1 = p; if ((mem[b + 3].b32.s1 < mem[p + 3].b32.s1)) mem[b + 3].b32.s1 = mem[p + 3].b32.s1; if ((mem[b + 2].b32.s1 < mem[p + 2].b32.s1)) mem[b + 2].b32.s1 = mem[p + 2].b32.s1; } } else { mem[p].b32.s1 = mem[b + 5].b32.s1; mem[b + 5].b32.s1 = p; mem[b + 3].b32.s1 = mem[p + 3].b32.s1; if ((mem[b + 1].b32.s1 < mem[p + 1].b32.s1)) mem[b + 1].b32.s1 = mem[p + 1].b32.s1; } } static void stack_glue_into_box(int32_t b, scaled_t min, scaled_t max) { int32_t p, q; q = new_spec(0); mem[q + 1].b32.s1 = min; mem[q + 2].b32.s1 = max - min; p = new_glue(q); if (NODE_type(b) == HLIST_NODE) { q = mem[b + 5].b32.s1; if (q == TEX_NULL) mem[b + 5].b32.s1 = p; else { while (mem[q].b32.s1 != TEX_NULL) q = LLIST_link(q); mem[q].b32.s1 = p; } } else { mem[p].b32.s1 = mem[b + 5].b32.s1; mem[b + 5].b32.s1 = p; mem[b + 3].b32.s1 = mem[p + 3].b32.s1; mem[b + 1].b32.s1 = mem[p + 1].b32.s1; } } static int32_t build_opentype_assembly(internal_font_number f, void *a, scaled_t s, bool horiz) { int32_t b; int32_t n; int32_t i, j; int32_t g; int32_t p; scaled_t s_max, o, oo, prev_o, min_o; bool no_extenders; scaled_t nat, str; b = new_null_box(); if (horiz) NODE_type(b) = HLIST_NODE; else NODE_type(b) = VLIST_NODE; n = -1; no_extenders = true; min_o = ot_min_connector_overlap(f); do { n = n + 1; s_max = 0; prev_o = 0; { register int32_t for_end; i = 0; for_end = ot_part_count(a) - 1; if (i <= for_end) do { if (ot_part_is_extender(a, i)) { no_extenders = false; { register int32_t for_end; j = 1; for_end = n; if (j <= for_end) do { o = ot_part_start_connector(f, a, i); if (min_o < o) o = min_o; if (prev_o < o) o = prev_o; s_max = s_max - o + ot_part_full_advance(f, a, i); prev_o = ot_part_end_connector(f, a, i); } while (j++ < for_end); } } else { o = ot_part_start_connector(f, a, i); if (min_o < o) o = min_o; if (prev_o < o) o = prev_o; s_max = s_max - o + ot_part_full_advance(f, a, i); prev_o = ot_part_end_connector(f, a, i); } } while (i++ < for_end); } } while (!((s_max >= s) || no_extenders)); prev_o = 0; { register int32_t for_end; i = 0; for_end = ot_part_count(a) - 1; if (i <= for_end) do { if (ot_part_is_extender(a, i)) { { register int32_t for_end; j = 1; for_end = n; if (j <= for_end) do { o = ot_part_start_connector(f, a, i); if (prev_o < o) o = prev_o; oo = o; if (min_o < o) o = min_o; if (oo > 0) stack_glue_into_box(b, -(int32_t) oo, -(int32_t) o); g = ot_part_glyph(a, i); stack_glyph_into_box(b, f, g); prev_o = ot_part_end_connector(f, a, i); } while (j++ < for_end); } } else { o = ot_part_start_connector(f, a, i); if (prev_o < o) o = prev_o; oo = o; if (min_o < o) o = min_o; if (oo > 0) stack_glue_into_box(b, -(int32_t) oo, -(int32_t) o); g = ot_part_glyph(a, i); stack_glyph_into_box(b, f, g); prev_o = ot_part_end_connector(f, a, i); } } while (i++ < for_end); } p = mem[b + 5].b32.s1; nat = 0; str = 0; while (p != TEX_NULL) { if (NODE_type(p) == WHATSIT_NODE) { if (horiz) nat = nat + mem[p + 1].b32.s1; else nat = nat + mem[p + 3].b32.s1 + mem[p + 2].b32.s1; } else if (NODE_type(p) == GLUE_NODE) { nat = nat + mem[mem[p + 1].b32.s0 + 1].b32.s1; str = str + mem[mem[p + 1].b32.s0 + 2].b32.s1; } p = LLIST_link(p); } o = 0; if ((s > nat) && (str > 0)) { o = (s - nat); if ((o > str)) o = str; mem[b + 5].b16.s0 = NORMAL; mem[b + 5].b16.s1 = STRETCHING; BOX_glue_set(b) = o / ((double)str); if (horiz) mem[b + 1].b32.s1 = nat + tex_round(str * BOX_glue_set(b)); else mem[b + 3].b32.s1 = nat + tex_round(str * BOX_glue_set(b)); } else if (horiz) mem[b + 1].b32.s1 = nat; else mem[b + 3].b32.s1 = nat; return b; } static int32_t rebox(int32_t b, scaled_t w) { int32_t p; internal_font_number f; scaled_t v; if ((mem[b + 1].b32.s1 != w) && (mem[b + 5].b32.s1 != TEX_NULL)) { if (NODE_type(b) == VLIST_NODE) b = hpack(b, 0, ADDITIONAL); p = mem[b + 5].b32.s1; if (((is_char_node(p))) && (mem[p].b32.s1 == TEX_NULL)) { f = CHAR_NODE_font(p); v = FONT_CHARACTER_WIDTH(f, effective_char(true, f, CHAR_NODE_character(p))); if (v != mem[b + 1].b32.s1) mem[p].b32.s1 = new_kern(mem[b + 1].b32.s1 - v); } free_node(b, BOX_NODE_SIZE); b = new_glue(12); mem[b].b32.s1 = p; while (mem[p].b32.s1 != TEX_NULL) p = LLIST_link(p); mem[p].b32.s1 = new_glue(12); return hpack(b, w, EXACTLY); } else { mem[b + 1].b32.s1 = w; return b; } }