diff options
Diffstat (limited to 'source/luametatex/source/tex/texalign.c')
-rw-r--r-- | source/luametatex/source/tex/texalign.c | 351 |
1 files changed, 341 insertions, 10 deletions
diff --git a/source/luametatex/source/tex/texalign.c b/source/luametatex/source/tex/texalign.c index ac7712870..f35bb50b5 100644 --- a/source/luametatex/source/tex/texalign.c +++ b/source/luametatex/source/tex/texalign.c @@ -205,6 +205,19 @@ Todo: lefttabskip righttabskip middletabskip */ +typedef struct alignment_row_state { + halfword orientation; + scaled xoffset; + scaled yoffset; + scaled xmove; + scaled ymove; + halfword shift; + halfword source; + halfword target; + halfword anchor; + halfword attrlist; +} alignment_row_state; + typedef struct alignment_state_info { halfword cur_align; /*tex The current position in the preamble list. */ halfword cur_span; /*tex The start of the currently spanned columns in the preamble list. */ @@ -223,11 +236,14 @@ typedef struct alignment_state_info { halfword no_align_level; halfword no_tab_skips; halfword attr_list; - halfword cell_source; - halfword wrap_source; + halfword cell_source; + halfword wrap_source; /*tex There's also a field in the row_state. */ halfword callback; // halfword reverse; // todo // halfword discard_skips; // todo + halfword row_state_set; + halfword padding; + alignment_row_state row_state; } alignment_state_info ; static alignment_state_info lmt_alignment_state = { @@ -253,8 +269,38 @@ static alignment_state_info lmt_alignment_state = { .callback = 0, // .reverse = 0, // .discard_skips = 0, + .row_state_set = 0, + .padding = 0, + .row_state = { + .attrlist = null, + .orientation = 0, + .xoffset = 0, + .yoffset = 0, + .xmove = 0, + .ymove = 0, + .shift = 0, + .source = 0, + .target = 0, + .anchor = 0, + } }; +static void tex_aux_wipe_row_state(void) +{ + delete_attribute_reference(lmt_alignment_state.row_state.attrlist); + lmt_alignment_state.row_state.attrlist = null; + lmt_alignment_state.row_state.orientation = 0; + lmt_alignment_state.row_state.xoffset = 0; + lmt_alignment_state.row_state.yoffset = 0; + lmt_alignment_state.row_state.xmove = 0; + lmt_alignment_state.row_state.ymove = 0; + lmt_alignment_state.row_state.shift = 0; + lmt_alignment_state.row_state.source = 0; + lmt_alignment_state.row_state.target = 0; + lmt_alignment_state.row_state.anchor = 0; + lmt_alignment_state.row_state_set = 0; +} + /*tex We could as well save these in the alignment stack. */ typedef enum saved_align_items { @@ -313,6 +359,7 @@ static void tex_aux_push_alignment(void) { /*tex The new alignment stack node: */ halfword p = tex_new_node(align_stack_node, 0); + /* todo: just a memory copy */ align_stack_align_ptr(p) = lmt_alignment_state.align_ptr; align_stack_cur_align(p) = lmt_alignment_state.cur_align; align_stack_preamble(p) = preamble; @@ -331,6 +378,18 @@ static void tex_aux_push_alignment(void) align_stack_cur_pre_migrate_tail(p) = lmt_alignment_state.cur_pre_migrate_tail; align_stack_no_tab_skips(p) = lmt_alignment_state.no_tab_skips; align_stack_attr_list(p) = lmt_alignment_state.attr_list; + /* */ + align_stack_row_attrlist(p) = lmt_alignment_state.row_state.attrlist; + align_stack_row_orientation(p) = lmt_alignment_state.row_state.orientation; + align_stack_row_yoffset(p) = lmt_alignment_state.row_state.xoffset; + align_stack_row_xoffset(p) = lmt_alignment_state.row_state.yoffset; + align_stack_row_ymove(p) = lmt_alignment_state.row_state.xmove; + align_stack_row_xmove(p) = lmt_alignment_state.row_state.ymove; + align_stack_row_shift(p) = lmt_alignment_state.row_state.shift; + align_stack_row_source(p) = lmt_alignment_state.row_state.source; + align_stack_row_target(p) = lmt_alignment_state.row_state.target; + align_stack_row_anchor(p) = lmt_alignment_state.row_state.anchor; + /* */ lmt_alignment_state.align_ptr = p; lmt_alignment_state.cur_post_adjust_head = tex_new_temp_node(); lmt_alignment_state.cur_pre_adjust_head = tex_new_temp_node(); @@ -339,6 +398,8 @@ static void tex_aux_push_alignment(void) /* */ lmt_alignment_state.cell_source = 0; lmt_alignment_state.wrap_source = 0; + /* todo: put in align_stack, also wipe attr if needed */ + tex_aux_wipe_row_state(); } static void tex_aux_pop_alignment(void) @@ -367,6 +428,18 @@ static void tex_aux_pop_alignment(void) lmt_alignment_state.cur_pre_migrate_tail = align_stack_cur_pre_migrate_tail(p); lmt_alignment_state.no_tab_skips = align_stack_no_tab_skips(p); lmt_alignment_state.attr_list = align_stack_attr_list(p); + /* */ + lmt_alignment_state.row_state.attrlist = align_stack_row_attrlist(p); + lmt_alignment_state.row_state.orientation = align_stack_row_orientation(p); + lmt_alignment_state.row_state.xoffset = align_stack_row_yoffset(p); + lmt_alignment_state.row_state.yoffset = align_stack_row_xoffset(p); + lmt_alignment_state.row_state.xmove = align_stack_row_ymove(p); + lmt_alignment_state.row_state.ymove = align_stack_row_xmove(p); + lmt_alignment_state.row_state.shift = align_stack_row_shift(p); + lmt_alignment_state.row_state.source = align_stack_row_source(p); + lmt_alignment_state.row_state.target = align_stack_row_target(p); + lmt_alignment_state.row_state.anchor = align_stack_row_anchor(p); + /* */ tex_flush_node(p); } @@ -590,7 +663,154 @@ static void tex_aux_trace_no_align(const char *s) static void tex_aux_run_no_align(void) { - tex_scan_left_brace(); + /* */ + int brace = 0; + int done = lmt_alignment_state.row_state_set; + while (1) { + int add = 0; + AGAIN: + switch (tex_scan_character("atrsoxyATRSOXY", 1, 1, 1)) { + case 0: + goto DONE; + case 't': case 'T': + if (tex_scan_mandate_keyword("target", 1)) { + lmt_alignment_state.row_state.target = tex_scan_int(1, NULL); + done = 1; + } + break; + case 'a': case 'A': + switch (tex_scan_character("ntdNTD", 0, 0, 0)) { + case 'd': case 'D': + if (tex_scan_mandate_keyword("add", 2)) { + add = 1; + goto AGAIN; + } + break; + case 't': case 'T': + if (tex_scan_mandate_keyword("attr", 2)) { + halfword i = tex_scan_attribute_register_number(); + halfword v = tex_scan_int(1, NULL); + if (eq_value(register_attribute_location(i)) != v) { + if (lmt_alignment_state.row_state.attrlist) { + lmt_alignment_state.row_state.attrlist = tex_patch_attribute_list(lmt_alignment_state.row_state.attrlist, i, v); + } else { + lmt_alignment_state.row_state.attrlist = tex_copy_attribute_list_set(tex_current_attribute_list(), i, v); + } + done = 1; + } + } + break; + case 'n': case 'N': + if (tex_scan_mandate_keyword("anchor", 2)) { + switch (tex_scan_character("sS", 0, 0, 0)) { + case 's': case 'S': + lmt_alignment_state.row_state.anchor = tex_scan_anchors(0); + break; + default: + lmt_alignment_state.row_state.anchor = tex_scan_anchor(0); + break; + } + done = 1; + } + break; + default: + tex_aux_show_keyword_error("attr|anchor|add"); + goto DONE; + } + break; + case 'r': case 'R': + if (tex_scan_mandate_keyword("reset", 1)) { + tex_aux_wipe_row_state(); + done = 0; + } + break; + case 's': case 'S': + switch (tex_scan_character("hoHO", 0, 0, 0)) { + case 'h': case 'H': + if (tex_scan_mandate_keyword("shift", 2)) { + lmt_alignment_state.row_state.shift = (add ? lmt_alignment_state.row_state.shift : 0) + + tex_scan_dimen(0, 0, 0, 0, NULL); + done = 1; + } + break; + case 'o': case 'O': + if (tex_scan_mandate_keyword("source", 2)) { + lmt_alignment_state.row_state.source = tex_scan_int(1, NULL); + done = 1; + } + break; + default: + tex_aux_show_keyword_error("shift|source"); + goto DONE; + } + break; + case 'o': case 'O': + if (tex_scan_mandate_keyword("orientation", 1)) { + lmt_alignment_state.row_state.orientation = tex_scan_orientation(0); + done = 1; + } + break; + case 'x': case 'X': + switch (tex_scan_character("omOM", 0, 0, 0)) { + case 'o': case 'O' : + if (tex_scan_mandate_keyword("xoffset", 2)) { + lmt_alignment_state.row_state.xoffset = (add ? lmt_alignment_state.row_state.xoffset : 0) + + tex_scan_dimen(0, 0, 0, 0, NULL); + done = 1; + } + break; + case 'm': case 'M' : + if (tex_scan_mandate_keyword("xmove", 2)) { + lmt_alignment_state.row_state.xmove = (add ? lmt_alignment_state.row_state.xmove : 0) + + tex_scan_dimen(0, 0, 0, 0, NULL); + done = 1; + } + break; + default: + tex_aux_show_keyword_error("xoffset|xmove"); + goto DONE; + } + break; + case 'y': case 'Y': + switch (tex_scan_character("omOM", 0, 0, 0)) { + case 'o': case 'O' : + if (tex_scan_mandate_keyword("yoffset", 2)) { + lmt_alignment_state.row_state.yoffset = (add ? lmt_alignment_state.row_state.yoffset : 0) + + tex_scan_dimen(0, 0, 0, 0, NULL); + done = 1; + } + break; + case 'm': case 'M' : + if (tex_scan_mandate_keyword("ymove", 2)) { + lmt_alignment_state.row_state.ymove = (add ? lmt_alignment_state.row_state.ymove : 0) + + tex_scan_dimen(0, 0, 0, 0, NULL); + done = 1; + } + break; + default: + tex_aux_show_keyword_error("yoffset|ymove"); + goto DONE; + } + break; + case '{': + brace = 1; + goto DONE; + default: + goto DONE; + } + add = 0; + } + DONE: + lmt_alignment_state.row_state_set = done; + if (! lmt_alignment_state.row_state.attrlist) { + /* this alse sets the reference when not yet set */ + lmt_alignment_state.row_state.attrlist = tex_current_attribute_list(); + } + add_attribute_reference(lmt_alignment_state.row_state.attrlist); + /* */ + if (! brace) { + tex_scan_left_brace(); + } tex_new_save_level(no_align_group); ++lmt_alignment_state.no_align_level; tex_aux_trace_no_align("entering"); @@ -598,6 +818,7 @@ static void tex_aux_run_no_align(void) tex_normal_paragraph(no_align_par_context); } } + static int tex_aux_nested_no_align(void) { int state = lmt_alignment_state.no_align_level > 0; @@ -846,7 +1067,7 @@ static void tex_aux_initialize_span(halfword p) if (cur_list.mode == -hmode) { cur_list.space_factor = 1000; } else { - cur_list.prev_depth = ignore_depth; + cur_list.prev_depth = ignore_depth_criterium_par; tex_normal_paragraph(span_par_context); } lmt_alignment_state.cur_span = p; @@ -864,8 +1085,8 @@ static void tex_aux_initialize_span(halfword p) static void tex_aux_initialize_row(void) { tex_push_nest(); - cur_list.mode = (- hmode - vmode) - cur_list.mode; /* weird code */ - if (cur_list.mode == -hmode) { + cur_list.mode = (- hmode - vmode) - cur_list.mode; /* weird code : - 3 - cur_list.mode : so a buogus line */ + if (cur_list.mode == -hmode) { cur_list.space_factor = 0; } else { cur_list.prev_depth = 0; @@ -882,6 +1103,7 @@ static void tex_aux_initialize_row(void) lmt_alignment_state.cur_post_migrate_tail = lmt_alignment_state.cur_post_migrate_head; lmt_alignment_state.cur_pre_migrate_tail = lmt_alignment_state.cur_pre_migrate_head; tex_aux_initialize_span(lmt_alignment_state.cur_align); + /* todo: wipe attr */ } /*tex @@ -1200,12 +1422,114 @@ static void tex_aux_finish_row(void) tex_tail_append(row); cur_list.space_factor = 1000; } + /*tex + Currently this one can be overloaded by the one set on the row via the noalign trickery + which is probably okay. + */ if (lmt_alignment_state.wrap_source) { box_source_anchor(row) = lmt_alignment_state.wrap_source; - tex_set_box_geometry(row, anchor_geometry); + box_geometry(row) |= anchor_geometry; } + /* + This also wipes (list) fields that we might set below, like |xoffset| that is used for + specific alignments purposes. + */ tex_aux_change_list_type(row, unset_node); - tex_attach_attribute_list_attribute(row, lmt_alignment_state.attr_list); + /* */ + tex_attach_attribute_list_attribute(row, lmt_alignment_state.row_state.attrlist ? + lmt_alignment_state.row_state.attrlist : lmt_alignment_state.attr_list); + /*tex + The next blob of code duplicates some of packaging code but because we fetch from different + fields we cannot share. Maybe, when I add this kind of features to other mechanisms (how + about cells!) then the next code will become some helper. + */ + if (lmt_alignment_state.row_state_set) { + halfword orientation = lmt_alignment_state.row_state.orientation; + halfword anchor = lmt_alignment_state.row_state.anchor; + scaled shift = lmt_alignment_state.row_state.shift; + halfword source = lmt_alignment_state.row_state.source; + halfword target = lmt_alignment_state.row_state.target; + scaled xoffset = lmt_alignment_state.row_state.xoffset; + scaled yoffset = lmt_alignment_state.row_state.yoffset; + scaled xmove = lmt_alignment_state.row_state.xmove; + scaled ymove = lmt_alignment_state.row_state.ymove; + singleword geometry = box_geometry(row); + /* */ + if (xoffset || yoffset || xmove || ymove) { + geometry |= offset_geometry; + } + if (orientation) { + geometry |= orientation_geometry; + } + /* */ + if (tex_has_geometry(geometry, offset_geometry) || tex_has_geometry(geometry, orientation_geometry)) { + scaled wd = box_width(row); + scaled ht = box_height(row); + scaled dp = box_depth(row); + if (xmove) { + xoffset = tex_aux_checked_dimen1(xoffset + xmove); + wd = tex_aux_checked_dimen2(wd + xmove); + set_box_package_state(row, package_dimension_size_set); /* safeguard */ + } + if (ymove) { + yoffset = tex_aux_checked_dimen1(yoffset + ymove); + ht = tex_aux_checked_dimen2(ht + ymove); + dp = tex_aux_checked_dimen2(dp - ymove); + } + box_w_offset(row) = wd; + box_h_offset(row) = ht; + box_d_offset(row) = dp; + switch (orientationonly(orientation)) { + case 0 : /* 0 */ + break; + case 2 : /* 180 */ + box_height(row) = dp; + box_depth(row) = ht; + geometry |= orientation_geometry; + break; + case 1 : /* 90 */ + case 3 : /* 270 */ + box_width(row) = ht + dp; + box_height(row) = wd; + box_depth(row) = 0; + geometry |= orientation_geometry; + break; + case 4 : /* 0 */ + box_height(row) = ht + dp; + box_depth(row) = 0; + geometry |= orientation_geometry; + break; + case 5 : /* 180 */ + box_height(row) = 0; + box_depth(row) = ht + dp; + geometry |= orientation_geometry; + break; + default : + break; + } + if (xoffset || yoffset) { + box_x_offset(row) = xoffset; + box_y_offset(row) = yoffset; + geometry |= offset_geometry; + } + } + if (shift) { + box_shift_amount(row) = shift; + } + if (source || target) { + box_source_anchor(row) = source; + box_target_anchor(row) = target; + geometry |= anchor_geometry; + } + box_anchor(row) = anchor; + box_orientation(row) = orientation; + box_geometry(row) = (singleword) geometry; + } + /*tex + We no longer need the row state so best wipe it now! Then we're ready for the next row. + */ + tex_aux_wipe_row_state(); + /* */ if (every_cr_par) { tex_begin_token_list(every_cr_par, every_cr_text); } @@ -1438,10 +1762,12 @@ static void tex_aux_finish_align(void) halfword preptr; halfword colptr; if (cur_list.mode == -vmode) { - tex_aux_change_list_type(rowptr, hlist_node); + /* tex_aux_change_list_type(rowptr, hlist_node); */ /* too much */ + node_type(rowptr) = hlist_node; box_width(rowptr) = box_width(preroll); } else { - tex_aux_change_list_type(rowptr, vlist_node); + /* tex_aux_change_list_type(rowptr, vlist_node); */ /* too much */ + node_type(rowptr) = vlist_node; box_height(rowptr) = box_height(preroll); } node_subtype(rowptr) = align_row_list; @@ -1609,6 +1935,11 @@ static void tex_aux_finish_align(void) if (reverse) { box_list(rowptr) = tex_reversed_node_list(box_list(rowptr)); } + if (has_box_package_state(rowptr, package_dimension_size_set)) { + if (box_w_offset(rowptr) > box_width(rowptr)) { + box_width(rowptr) = box_w_offset(rowptr); + } + } } break; case rule_node: |