>From b04c8add7a333eb810d4dd81cc3d1240ce58031c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Fabian=20Kr=C3=BCger?= Date: Tue, 16 Feb 2021 14:36:06 +0100 Subject: [PATCH 3/3] Fix double break in nested discretionary --- source/texk/web2c/luatexdir/tex/linebreak.c | 52 ++++++++++++++------- source/texk/web2c/luatexdir/tex/texnodes.h | 3 +- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/source/texk/web2c/luatexdir/tex/linebreak.c b/source/texk/web2c/luatexdir/tex/linebreak.c index f09e34e2e..4b32a426d 100644 --- a/source/texk/web2c/luatexdir/tex/linebreak.c +++ b/source/texk/web2c/luatexdir/tex/linebreak.c @@ -879,7 +879,8 @@ static int line_diff; double_hyphen_demerits, \ final_hyphen_demerits, \ first_p, \ - cur_p \ + cur_p, \ + null \ ); \ if (type(cur_p)!=math_node) \ active_width[1] += width(cur_p); \ @@ -1276,7 +1277,8 @@ static void ext_try_break( int line_penalty, int last_line_fit, int double_hyphen_demerits, - int final_hyphen_demerits, halfword first_p, halfword cur_p + int final_hyphen_demerits, halfword first_p, halfword cur_p, + halfword init_p ) { /*tex runs through the active list */ @@ -1314,6 +1316,8 @@ static void ext_try_break( scaled g = 0; /*tex distance from current active node */ scaled cur_active_width[10] = { 0 }; + /*tex if cur_p == init_p != null, the line length between init_disc and select_disc */ + scaled init_select_width; /*tex Make sure that |pi| is in the proper range; */ if (pi >= inf_penalty) { /*tex this breakpoint is inhibited by infinite penalty */ @@ -1374,6 +1378,11 @@ static void ext_try_break( no_break_yet = false; do_all_eight(set_break_width_to_background); compute_break_width(break_type, line_break_dir, adjust_spacing, cur_p); + if (init_p != null && init_p == cur_p) { + scaled line_width[10] = { 0 }; + add_to_widths(vlink_pre_break(vlink(cur_p)), line_break_dir, adjust_spacing, line_width); + init_select_width = background[1] + line_width[1]; + } } /*tex @@ -1451,6 +1460,8 @@ static void ext_try_break( active_short(q) = best_pl_short[fit_class]; active_glue(q) = best_pl_glue[fit_class]; } + if (init_p != null && init_p == cur_p) + active_select_width(q) = init_select_width; vlink(q) = r; vlink(prev_r) = q; prev_r = q; @@ -1516,7 +1527,10 @@ static void ext_try_break( */ artificial_demerits = false; - shortfall = line_width - cur_active_width[1]; + if (init_p != null && break_node(r) != null && cur_break(break_node(r)) == init_p) + shortfall = line_width - active_select_width(r); + else + shortfall = line_width - cur_active_width[1]; if (break_node(r) == null) shortfall -= init_internal_left_box_width; else @@ -2236,7 +2250,8 @@ void ext_do_line_break( double_hyphen_demerits, final_hyphen_demerits, first_p, - cur_p + cur_p, + null ); } } @@ -2288,7 +2303,7 @@ void ext_do_line_break( tracing_paragraphs, protrude_chars, line_penalty, last_line_fit, double_hyphen_demerits, - final_hyphen_demerits, first_p, cur_p); + final_hyphen_demerits, first_p, cur_p, null); } else { add_to_widths(s, line_break_dir, adjust_spacing, disc_width); do_one_seven_eight(add_disc_width_to_active_width); @@ -2298,19 +2313,24 @@ void ext_do_line_break( tracing_paragraphs, protrude_chars, line_penalty, last_line_fit, double_hyphen_demerits, - final_hyphen_demerits, first_p, cur_p); + final_hyphen_demerits, first_p, cur_p, + subtype(cur_p) == init_disc ? cur_p : null); if (subtype(cur_p) == init_disc) { /*tex The breakpoint after the one we added above - should be special since it's corresponding + is special since it's corresponding disc_width depends on whether the previous - breakpoint will be taken. This isn't handled - yet, so we assume the more common case: Only - one of the breakpoints is used, therefore - |disc_width| is the |pre_break| of the break - in INIT's |no_break|. This is stored in - SELECT's |no_break|. + breakpoint will be taken. Since this would need + adjustments in multiple places, we avoid it by + exploiting the fact that we actually know how long + the line is going to be in that case: The length of + the background plus the SELECT's |pre_break|. + This length is stored in the active nodes for the + INIT since this allows to avoid the computation if + there is no feasible break at INIT. + To trigger this mechanism, we have to pass the + corresponding INIT to ext_try_break. */ actual_penalty = (int) disc_penalty(vlink(cur_p)); /*tex Go back to the starting situation. */ @@ -2329,7 +2349,7 @@ void ext_do_line_break( protrude_chars, line_penalty, last_line_fit, double_hyphen_demerits, final_hyphen_demerits, first_p, - vlink(cur_p)); + vlink(cur_p), cur_p); } do_one_seven_eight(sub_disc_width_from_active_width); } @@ -2343,7 +2363,7 @@ void ext_do_line_break( tracing_paragraphs, protrude_chars, line_penalty, last_line_fit, double_hyphen_demerits, final_hyphen_demerits, - first_p, cur_p); + first_p, cur_p, null); break; case boundary_node: case whatsit_node: @@ -2385,7 +2405,7 @@ void ext_do_line_break( adjust_spacing, par_shape_ptr, adj_demerits, tracing_paragraphs, protrude_chars, line_penalty, last_line_fit, double_hyphen_demerits, - final_hyphen_demerits, first_p, cur_p); + final_hyphen_demerits, first_p, cur_p, null); if (vlink(active) != active) { /*tex Find an active node with fewest demerits; */ r = vlink(active); diff --git a/source/texk/web2c/luatexdir/tex/texnodes.h b/source/texk/web2c/luatexdir/tex/texnodes.h index 9742ca496..3a1c5ff77 100644 --- a/source/texk/web2c/luatexdir/tex/texnodes.h +++ b/source/texk/web2c/luatexdir/tex/texnodes.h @@ -976,13 +976,14 @@ typedef enum { /* node sused in the parbuilder */ -# define active_node_size 4 /*number of words in extended active nodes */ +# define active_node_size 5 /*number of words in extended active nodes */ # define fitness subtype /*|very_loose_fit..tight_fit| on final line for this break */ # define break_node(a) vlink((a)+1) /*pointer to the corresponding passive node */ # define line_number(a) vinfo((a)+1) /*line that begins at this breakpoint */ # define total_demerits(a) varmem[(a)+2].cint /* the quantity that \TeX\ minimizes */ # define active_short(a) vinfo(a+3) /* |shortfall| of this line */ # define active_glue(a) vlink(a+3) /*corresponding glue stretch or shrink */ +# define active_select_width(a) vlink(a+4) /*if this break is a init_disc, the width of the following line when broken at select_disc */ # define passive_node_size 7 # define cur_break(a) vlink((a)+1) /*in passive node, points to position of this breakpoint */ -- 2.30.1