1
4
5# include "luametatex.h"
6
7
8
9
67
68linebreak_state_info lmt_linebreak_state = {
69 .just_box = 0,
70 .last_line_fill = 0,
71 .no_shrink_error_yet = 0,
72 .second_pass = 0,
73 .final_pass = 0,
74 .threshold = 0,
75 .adjust_spacing = 0,
76 .adjust_spacing_step = 0,
77 .adjust_spacing_shrink = 0,
78 .adjust_spacing_stretch = 0,
79 .max_stretch_ratio = 0,
80 .max_shrink_ratio = 0,
81 .current_font_step = 0,
82 .passive = 0,
83 .printed_node = 0,
84 .pass_number = 0,
85 .active_width = { 0 },
86 .background = { 0 },
87 .break_width = { 0 },
88
89
90 .internal_penalty_interline = 0,
91 .internal_penalty_broken = 0,
92 .internal_left_box = null,
93 .internal_left_box_width = 0,
94 .internal_left_box_init = 0,
95 .internal_left_box_width_init = 0,
96 .internal_right_box = null,
97 .internal_right_box_width = 0,
98 .internal_middle_box = null,
99 .disc_width = { 0 },
100 .minimal_demerits = { 0 },
101 .minimum_demerits = 0,
102 .easy_line = 0,
103 .last_special_line = 0,
104 .first_width = 0,
105 .second_width = 0,
106 .first_indent = 0,
107 .second_indent = 0,
108 .best_bet = 0,
109 .fewest_demerits = 0,
110 .best_line = 0,
111 .actual_looseness = 0,
112 .line_difference = 0,
113 .do_last_line_fit = 0,
114 .fill_width = { 0 },
115 .dir_ptr = 0,
116 .warned = 0,
117 .calling_back = 0,
118 .saved_threshold = 0,
119 .line_break_dir = 0,
120 .checked_expansion = -1,
121};
122
123
127
128typedef enum fill_orders {
129 fi_order = 0,
130 fil_order = 1,
131 fill_order = 2,
132 filll_order = 3,
133} fill_orders;
134
135
147
148void tex_line_break_prepare(
149 halfword par,
150 halfword *tail,
151 halfword *parinit_left_skip_glue,
152 halfword *parinit_right_skip_glue,
153 halfword *parfill_left_skip_glue,
154 halfword *parfill_right_skip_glue,
155 halfword *final_line_penalty
156)
157{
158
159 if (node_type(par) == par_node) {
160 if (tracing_linebreak_lists) {
161 tex_begin_diagnostic();
162 tex_print_format("[linebreak: prepare, before]");
163 tex_show_box(par);
164 tex_end_diagnostic();
165 }
166 *tail = *tail ? *tail : tex_tail_of_node_list(par);
167 *final_line_penalty = tex_new_penalty_node(infinite_penalty, line_penalty_subtype);
168 *parfill_left_skip_glue = tex_new_glue_node(tex_get_par_par(par, par_par_fill_left_skip_code), par_fill_left_skip_glue);
169 *parfill_right_skip_glue = tex_new_glue_node(tex_get_par_par(par, par_par_fill_right_skip_code), par_fill_right_skip_glue);
170 *parinit_left_skip_glue = null;
171 *parinit_right_skip_glue = null;
172 if (par != *tail && node_type(*tail) == glue_node && ! tex_is_par_init_glue(*tail)) {
173 halfword prev = node_prev(*tail);
174 node_next(prev) = null;
175 tex_flush_node(*tail);
176 *tail = prev;
177 }
178 tex_attach_attribute_list_copy(*final_line_penalty, par);
179 tex_attach_attribute_list_copy(*parfill_left_skip_glue, par);
180 tex_attach_attribute_list_copy(*parfill_right_skip_glue, par);
181 tex_try_couple_nodes(*tail, *final_line_penalty);
182 tex_try_couple_nodes(*final_line_penalty, *parfill_left_skip_glue);
183 tex_try_couple_nodes(*parfill_left_skip_glue, *parfill_right_skip_glue);
184 *tail = *parfill_right_skip_glue;
185 if (node_next(par)) {
186 halfword p = par;
187 halfword n = node_next(par);
188 while (node_next(p) && node_type(node_next(p)) == dir_node) {
189 p = node_next(p);
190 }
191 while (n) {
192 if (node_type(n) == glue_node && node_subtype(n) == indent_skip_glue) {
193 *parinit_left_skip_glue = tex_new_glue_node(tex_get_par_par(par, par_par_init_left_skip_code), par_init_left_skip_glue);
194 *parinit_right_skip_glue = tex_new_glue_node(tex_get_par_par(par, par_par_init_right_skip_code), par_init_right_skip_glue);
195 tex_attach_attribute_list_copy(*parinit_left_skip_glue, par);
196 tex_attach_attribute_list_copy(*parinit_right_skip_glue, par);
197 tex_try_couple_nodes(*parinit_right_skip_glue, n);
198 tex_try_couple_nodes(*parinit_left_skip_glue, *parinit_right_skip_glue);
199
200 tex_try_couple_nodes(p, *parinit_left_skip_glue);
201 break;
202 } else {
203 n = node_next(n);
204 }
205 }
206 }
207 if (tracing_linebreak_lists) {
208 tex_begin_diagnostic();
209 tex_print_format("[linebreak: prepare, after]");
210 tex_show_box(par);
211 tex_end_diagnostic();
212 }
213 }
214}
215
216void tex_line_break(int d, int line_break_context)
217{
218 halfword head = node_next(cur_list.head);
219
220 if (node_type(head) == par_node) {
221
222 halfword tail = cur_list.tail;
223 lmt_packaging_state.pack_begin_line = cur_list.mode_line;
224 node_prev(head) = null;
225
226 if (tex_list_has_glyph(head)) {
227 tex_handle_hyphenation(head, tail);
228 head = tex_handle_glyphrun(head, line_break_context, par_dir(head));
229 tail = tex_tail_of_node_list(head);
230 tex_try_couple_nodes(cur_list.head, head);
231 cur_list.tail = tail;
232 }
233
234
235
236
237
238
239
240 node_next(temp_head) = head;
241
242 if (node_type(head) == par_node) {
243
249 halfword start_of_par;
250 halfword par = head;
251 halfword parinit_left_skip_glue = null;
252 halfword parinit_right_skip_glue = null;
253 halfword parfill_left_skip_glue = null;
254 halfword parfill_right_skip_glue = null;
255 halfword final_line_penalty = null;
256 tex_line_break_prepare(par, &tail, &parinit_left_skip_glue, &parinit_right_skip_glue, &parfill_left_skip_glue, &parfill_right_skip_glue, &final_line_penalty);
257 cur_list.tail = tail;
258
262 lmt_node_filter_callback(pre_linebreak_filter_callback, line_break_context, temp_head, &(cur_list.tail));
263
266 lmt_linebreak_state.last_line_fill = cur_list.tail;
267 tex_pop_nest();
268 start_of_par = cur_list.tail;
269 lmt_linebreak_state.calling_back = 1;
270 if (lmt_linebreak_callback(d, temp_head, &(cur_list.tail))) {
271
277 halfword box_search = cur_list.tail;
278 lmt_linebreak_state.just_box = null;
279 if (box_search) {
280 do {
281 if (node_type(box_search) == hlist_node) {
282 lmt_linebreak_state.just_box = box_search;
283 }
284 box_search = node_next(box_search);
285 } while (box_search);
286 }
287 if (! lmt_linebreak_state.just_box) {
288 tex_handle_error(
289 succumb_error_type,
290 "Invalid linebreak_filter",
291 "A linebreaking routine should return a non-empty list of nodes and at least one\n"
292 "of those has to be a \\hbox. Sorry, I cannot recover from this."
293 );
294 }
295 } else {
296 line_break_properties properties = {
297 .initial_par = par,
298 .display_math = d,
299 .tracing_paragraphs = tracing_paragraphs_par,
300 .paragraph_dir = par_dir(par),
301 .parfill_left_skip = parfill_left_skip_glue,
302 .parfill_right_skip = parfill_right_skip_glue,
303 .parinit_left_skip = parinit_left_skip_glue,
304 .parinit_right_skip = parinit_right_skip_glue,
305 .tolerance = tex_get_par_par(par, par_tolerance_code),
306 .emergency_stretch = tex_get_par_par(par, par_emergency_stretch_code),
307 .looseness = tex_get_par_par(par, par_looseness_code),
308 .adjust_spacing = tex_get_par_par(par, par_adjust_spacing_code),
309 .protrude_chars = tex_get_par_par(par, par_protrude_chars_code),
310 .adj_demerits = tex_get_par_par(par, par_adj_demerits_code),
311 .double_adj_demerits = tex_get_par_par(par, par_double_adj_demerits_code),
312 .line_penalty = tex_get_par_par(par, par_line_penalty_code),
313 .last_line_fit = tex_get_par_par(par, par_last_line_fit_code),
314 .double_hyphen_demerits = tex_get_par_par(par, par_double_hyphen_demerits_code),
315 .final_hyphen_demerits = tex_get_par_par(par, par_final_hyphen_demerits_code),
316 .hsize = tex_get_par_par(par, par_hsize_code),
317 .left_skip = tex_get_par_par(par, par_left_skip_code),
318 .right_skip = tex_get_par_par(par, par_right_skip_code),
319 .emergency_left_skip = tex_get_par_par(par, par_emergency_left_skip_code),
320 .emergency_right_skip = tex_get_par_par(par, par_emergency_right_skip_code),
321 .pretolerance = tex_get_par_par(par, par_pre_tolerance_code),
322 .hang_indent = tex_get_par_par(par, par_hang_indent_code),
323 .hang_after = tex_get_par_par(par, par_hang_after_code),
324 .par_shape = tex_get_par_par(par, par_par_shape_code),
325 .inter_line_penalty = tex_get_par_par(par, par_inter_line_penalty_code),
326 .inter_line_penalties = tex_get_par_par(par, par_inter_line_penalties_code),
327 .club_penalty = tex_get_par_par(par, par_club_penalty_code),
328 .club_penalties = tex_get_par_par(par, par_club_penalties_code),
329 .widow_penalty = tex_get_par_par(par, par_widow_penalty_code),
330 .widow_penalties = tex_get_par_par(par, par_widow_penalties_code),
331 .display_widow_penalty = tex_get_par_par(par, par_display_widow_penalty_code),
332 .display_widow_penalties = tex_get_par_par(par, par_display_widow_penalties_code),
333 .orphan_penalty = tex_get_par_par(par, par_orphan_penalty_code),
334 .single_line_penalty = tex_get_par_par(par, par_single_line_penalty_code),
335 .orphan_penalties = tex_get_par_par(par, par_orphan_penalties_code),
336 .broken_penalty = tex_get_par_par(par, par_broken_penalty_code),
337 .baseline_skip = tex_get_par_par(par, par_baseline_skip_code),
338 .line_skip = tex_get_par_par(par, par_line_skip_code),
339 .line_skip_limit = tex_get_par_par(par, par_line_skip_limit_code),
340 .adjust_spacing_step = tex_get_par_par(par, par_adjust_spacing_step_code),
341 .adjust_spacing_shrink = tex_get_par_par(par, par_adjust_spacing_shrink_code),
342 .adjust_spacing_stretch = tex_get_par_par(par, par_adjust_spacing_stretch_code),
343 .hyphenation_mode = tex_get_par_par(par, par_hyphenation_mode_code),
344 .shaping_penalties_mode = tex_get_par_par(par, par_shaping_penalties_mode_code),
345 .shaping_penalty = tex_get_par_par(par, par_shaping_penalty_code),
346 .emergency_extra_stretch = tex_get_par_par(par, par_emergency_extra_stretch_code),
347 .par_passes = tex_get_par_par(par, par_par_passes_code),
348 .tracing_passes = tracing_passes_par,
349 .line_break_criterion = line_break_criterion_par,
350 .extra_hyphen_penalty = 0,
351 .optional_found = 0,
352 .line_break_optional = line_break_optional_par,
353 };
354 tex_do_line_break(&properties);
355
358 }
359 lmt_linebreak_state.calling_back = 0;
360 lmt_node_filter_callback(post_linebreak_filter_callback, line_break_context, start_of_par, &(cur_list.tail));
361 lmt_packaging_state.pack_begin_line = 0;
362 return;
363 }
364 }
365 tex_confusion("missing local par node");
366}
367
368
380
381static scaled tex_aux_checked_shrink(halfword p)
382{
383 if (glue_shrink(p) && glue_shrink_order(p) != normal_glue_order) {
384 if (lmt_linebreak_state.no_shrink_error_yet) {
385 lmt_linebreak_state.no_shrink_error_yet = 0;
386 tex_handle_error(
387 normal_error_type,
388 "Infinite glue shrinkage found in a paragraph",
389 "The paragraph just ended includes some glue that has infinite shrinkability,\n"
390 "e.g., '\\hskip 0pt minus 1fil'. Such glue doesn't belong there---it allows a\n"
391 "paragraph of any length to fit on one line. But it's safe to proceed, since the\n"
392 "offensive shrinkability has been made finite."
393 );
394 }
395 glue_shrink_order(p) = normal_glue_order;
396 }
397 return glue_shrink(p);
398}
399
400
429
430# define max_hlist_stack 512
431
432
433
434static void tex_aux_warn_expand_pars(void)
435{
436 if (! lmt_linebreak_state.warned) {
437 tex_normal_warning("font expansion", "using fonts with different limit of expansion in one paragraph is not allowed");
438 lmt_linebreak_state.warned = 1;
439 }
440}
441
442static int tex_aux_check_expand_pars(halfword adjust_spacing_step, halfword f)
443{
444
445 if (! has_font_text_control(f, text_control_expansion)) {
446 return 0;
447 } else if (adjust_spacing_step > 0) {
448 return 1;
449 } else if (lmt_linebreak_state.current_font_step < 0) {
450 lmt_linebreak_state.current_font_step = font_step(f);
451 } else if (lmt_linebreak_state.current_font_step != font_step(f)) {
452 tex_normal_error("font expansion", "using fonts with different step of expansion in one paragraph is not allowed");
453 }
454 {
455 int m = font_max_stretch(f);
456 if (m) {
457 if (lmt_linebreak_state.max_stretch_ratio < 0) {
458 lmt_linebreak_state.max_stretch_ratio = m;
459 } else if (lmt_linebreak_state.max_stretch_ratio > m) {
460 lmt_linebreak_state.max_stretch_ratio = m;
461 tex_aux_warn_expand_pars();
462 }
463 }
464 }
465 {
466 int m = font_max_shrink(f);
467 if (m) {
468 if (lmt_linebreak_state.max_shrink_ratio < 0) {
469 lmt_linebreak_state.max_shrink_ratio = -m;
470 } else if (-lmt_linebreak_state.max_shrink_ratio > -m) {
471 lmt_linebreak_state.max_shrink_ratio = -m;
472 tex_aux_warn_expand_pars();
473 }
474 }
475 }
476 return 1;
477}
478
479
484
485static halfword tex_aux_find_protchar_left(halfword l, int d)
486{
487 int done = 0 ;
488 halfword initial = l;
489 while (node_next(l) && node_type(l) == hlist_node && tex_zero_box_dimensions(l) && ! box_list(l)) {
490
491 l = node_next(l);
492 done = 1 ;
493 }
494 if (! done && node_type(l) == par_node) {
495 l = node_next(l);
496 done = 1 ;
497 }
498 if (! done && d) {
499 while (node_next(l) && ! (node_type(l) == glyph_node || non_discardable(l))) {
500
501 l = node_next(l);
502 }
503 }
504 if (node_type(l) != glyph_node) {
505 halfword t;
506 int run = 1;
507 halfword hlist_stack[max_hlist_stack];
508 int hlist_stack_level = 0;
509 do {
510 t = l;
511 while (run && node_type(l) == hlist_node && box_list(l)) {
512 if (hlist_stack_level >= max_hlist_stack) {
513
514 return initial;
515 } else {
516 hlist_stack[hlist_stack_level++] = l;
517 }
518 l = box_list(l);
519 }
520 while (run && tex_protrusion_skipable(l)) {
521 while (! node_next(l) && hlist_stack_level > 0) {
522
523 if (hlist_stack_level <= 0) {
524
525
526 return initial;
527 } else {
528 l = hlist_stack[--hlist_stack_level];
529 }
530 run = 0;
531 }
532 if (node_next(l) && node_type(l) == boundary_node && node_subtype(l) == protrusion_boundary && (boundary_data(l) == protrusion_skip_next || boundary_data(l) == protrusion_skip_both)) {
533
534 l = node_next(l);
535 }
536 if (node_next(l)) {
537 l = node_next(l);
538 } else if (hlist_stack_level == 0) {
539 run = 0;
540 }
541 }
542 } while (t != l);
543 }
544 return l;
545}
546
547
552
553static halfword tex_aux_find_protchar_right(halfword l, halfword r)
554{
555 if (r) {
556 halfword t;
557 int run = 1;
558 halfword initial = r;
559 halfword hlist_stack[max_hlist_stack];
560 int hlist_stack_level = 0;
561 do {
562 t = r;
563 while (run && node_type(r) == hlist_node && box_list(r)) {
564 if (hlist_stack_level >= max_hlist_stack) {
565
566 return initial;
567 } else {
568 hlist_stack[hlist_stack_level++] = l;
569 }
570 if (hlist_stack_level >= max_hlist_stack) {
571
572 return initial;
573 } else {
574 hlist_stack[hlist_stack_level++] = r;
575 }
576 l = box_list(r);
577 r = l;
578 while (node_next(r)) {
579 halfword s = r;
580 r = node_next(r);
581 node_prev(r) = s;
582 }
583 }
584 while (run && tex_protrusion_skipable(r)) {
585 while (r == l && hlist_stack_level > 0) {
586
587 if (hlist_stack_level <= 0) {
588
589
590 return initial;
591 } else {
592 r = hlist_stack[--hlist_stack_level];
593 }
594
595 if (hlist_stack_level <= 0) {
596
597
598 return initial;
599 } else {
600 l = hlist_stack[--hlist_stack_level];
601 }
602 }
603 if ((r != l) && r) {
604 if (node_prev(r) && node_type(r) == boundary_node && node_subtype(r) == protrusion_boundary && (boundary_data(r) == protrusion_skip_previous || boundary_data(r) == protrusion_skip_both)) {
605
606 r = node_prev(r);
607 }
608 if (node_prev(r)) {
609 r = node_prev(r);
610 } else {
611
612 run = 0;
613 }
614 } else if (r == l && hlist_stack_level == 0) {
615 run = 0;
616 }
617 }
618 } while (t != r);
619 }
620 return r;
621}
622
623
677
678void tex_initialize_active(void)
679{
680 node_type(active_head) = hyphenated_node;
681 active_line_number(active_head) = max_halfword;
682
686 active_fitness(active_head) = very_loose_fit;
687}
688
689
881
882static void tex_aux_clean_up_the_memory(void)
883{
884 halfword q = node_next(active_head);
885 while (q != active_head) {
886 halfword p = node_next(q);
887
888 tex_flush_node(q);
889 q = p;
890 }
891 q = lmt_linebreak_state.passive;
892 while (q) {
893 halfword p = node_next(q);
894
895 tex_flush_node(q);
896 q = p;
897 }
898}
899
900
904
905inline static void tex_aux_add_disc_source_to_target(halfword adjust_spacing, scaled target[], const scaled source[])
906{
907 target[total_advance_amount] += source[total_advance_amount];
908 if (adjust_spacing) {
909 target[font_stretch_amount] += source[font_stretch_amount];
910 target[font_shrink_amount] += source[font_shrink_amount];
911 }
912}
913
914inline static void tex_aux_sub_disc_target_from_source(halfword adjust_spacing, scaled target[], const scaled source[])
915{
916 target[total_advance_amount] -= source[total_advance_amount];
917 if (adjust_spacing) {
918 target[font_stretch_amount] -= source[font_stretch_amount];
919 target[font_shrink_amount] -= source[font_shrink_amount];
920 }
921}
922
923inline static void tex_aux_reset_disc_target(halfword adjust_spacing, scaled *target)
924{
925 target[total_advance_amount] = 0;
926 if (adjust_spacing) {
927 target[font_stretch_amount] = 0;
928 target[font_shrink_amount] = 0;
929 }
930}
931
932
933
934inline static void tex_aux_set_target_to_source(halfword adjust_spacing, scaled target[], const scaled source[])
935{
936
937 for (int i = total_advance_amount; i <= total_shrink_amount; i++) {
938 target[i] = source[i];
939 }
940 if (adjust_spacing) {
941 target[font_stretch_amount] = source[font_stretch_amount];
942 target[font_shrink_amount] = source[font_shrink_amount];
943 }
944}
945
946
967
968inline static void tex_aux_add_to_target_from_delta(halfword adjust_spacing, scaled target[], halfword delta)
969{
970 target[total_advance_amount] += delta_field_total_glue(delta);
971 target[total_stretch_amount] += delta_field_total_stretch(delta);
972 target[total_fi_amount] += delta_field_total_fi_amount(delta);
973 target[total_fil_amount] += delta_field_total_fil_amount(delta);
974 target[total_fill_amount] += delta_field_total_fill_amount(delta);
975 target[total_filll_amount] += delta_field_total_filll_amount(delta);
976 target[total_shrink_amount] += delta_field_total_shrink(delta);
977 if (adjust_spacing) {
978 target[font_stretch_amount] += delta_field_font_stretch(delta);
979 target[font_shrink_amount] += delta_field_font_shrink(delta);
980 }
981}
982
983inline static void tex_aux_sub_delta_from_target(halfword adjust_spacing, scaled target[], halfword delta)
984{
985 target[total_advance_amount] -= delta_field_total_glue(delta);
986 target[total_stretch_amount] -= delta_field_total_stretch(delta);
987 target[total_fi_amount] -= delta_field_total_fi_amount(delta);
988 target[total_fil_amount] -= delta_field_total_fil_amount(delta);
989 target[total_fill_amount] -= delta_field_total_fill_amount(delta);
990 target[total_filll_amount] -= delta_field_total_filll_amount(delta);
991 target[total_shrink_amount] -= delta_field_total_shrink(delta);
992 if (adjust_spacing) {
993 target[font_stretch_amount] -= delta_field_font_stretch(delta);
994 target[font_shrink_amount] -= delta_field_font_shrink(delta);
995 }
996}
997
998inline static void tex_aux_add_to_delta_from_delta(halfword adjust_spacing, halfword target, halfword source)
999{
1000 delta_field_total_glue(target) += delta_field_total_glue(source);
1001 delta_field_total_stretch(target) += delta_field_total_stretch(source);
1002 delta_field_total_fi_amount(target) += delta_field_total_fi_amount(source);
1003 delta_field_total_fil_amount(target) += delta_field_total_fil_amount(source);
1004 delta_field_total_fill_amount(target) += delta_field_total_fill_amount(source);
1005 delta_field_total_filll_amount(target) += delta_field_total_filll_amount(source);
1006 delta_field_total_shrink(target) += delta_field_total_shrink(source);
1007 if (adjust_spacing) {
1008 delta_field_font_stretch(target) += delta_field_font_stretch(source);
1009 delta_field_font_shrink(target) += delta_field_font_shrink(source);
1010 }
1011}
1012
1013inline static void tex_aux_set_delta_from_difference(halfword adjust_spacing, halfword delta, const scaled source_1[], const scaled source_2[])
1014{
1015 delta_field_total_glue(delta) = (source_1[total_advance_amount] - source_2[total_advance_amount]);
1016 delta_field_total_stretch(delta) = (source_1[total_stretch_amount] - source_2[total_stretch_amount]);
1017 delta_field_total_fi_amount(delta) = (source_1[total_fi_amount] - source_2[total_fi_amount]);
1018 delta_field_total_fil_amount(delta) = (source_1[total_fil_amount] - source_2[total_fil_amount]);
1019 delta_field_total_fill_amount(delta) = (source_1[total_fill_amount] - source_2[total_fill_amount]);
1020 delta_field_total_filll_amount(delta) = (source_1[total_filll_amount] - source_2[total_filll_amount]);
1021 delta_field_total_shrink(delta) = (source_1[total_shrink_amount] - source_2[total_shrink_amount]);
1022 if (adjust_spacing) {
1023 delta_field_font_stretch(delta) = (source_1[font_stretch_amount] - source_2[font_stretch_amount]);
1024 delta_field_font_shrink(delta) = (source_1[font_shrink_amount] - source_2[font_shrink_amount]);
1025 }
1026}
1027
1028inline static void tex_aux_add_delta_from_difference(halfword adjust_spacing, halfword delta, const scaled source_1[], const scaled source_2[])
1029{
1030 delta_field_total_glue(delta) += (source_1[total_advance_amount] - source_2[total_advance_amount]);
1031 delta_field_total_stretch(delta) += (source_1[total_stretch_amount] - source_2[total_stretch_amount]);
1032 delta_field_total_fi_amount(delta) += (source_1[total_fi_amount] - source_2[total_fi_amount]);
1033 delta_field_total_fil_amount(delta) += (source_1[total_fil_amount] - source_2[total_fil_amount]);
1034 delta_field_total_fill_amount(delta) += (source_1[total_fill_amount] - source_2[total_fill_amount]);
1035 delta_field_total_filll_amount(delta) += (source_1[total_filll_amount] - source_2[total_filll_amount]);
1036 delta_field_total_shrink(delta) += (source_1[total_shrink_amount] - source_2[total_shrink_amount]);
1037 if (adjust_spacing) {
1038 delta_field_font_stretch(delta) += (source_1[font_stretch_amount] - source_2[font_stretch_amount]);
1039 delta_field_font_shrink(delta) += (source_1[font_shrink_amount] - source_2[font_shrink_amount]);
1040 }
1041}
1042
1043
1063
1064static void tex_aux_add_to_widths(halfword s, int adjust_spacing, int adjust_spacing_step, scaled widths[])
1065{
1066
1067 while (s) {
1068 switch (node_type(s)) {
1069 case glyph_node:
1070 widths[total_advance_amount] += tex_glyph_width(s);
1071 if (adjust_spacing && ! tex_has_glyph_option(s, glyph_option_no_expansion) && tex_aux_check_expand_pars(adjust_spacing_step, glyph_font(s))) {
1072 lmt_packaging_state.previous_char_ptr = s;
1073 widths[font_stretch_amount] += tex_char_stretch(s);
1074 widths[font_shrink_amount] += tex_char_shrink(s);
1075 };
1076 break;
1077 case hlist_node:
1078 case vlist_node:
1079 widths[total_advance_amount] += box_width(s);
1080 break;
1081 case rule_node:
1082 widths[total_advance_amount] += rule_width(s);
1083 break;
1084 case glue_node:
1085 widths[total_advance_amount] += glue_amount(s);
1086 widths[total_stretch_amount + glue_stretch_order(s)] += glue_stretch(s);
1087 widths[total_shrink_amount] += glue_shrink(s);
1088 break;
1089 case kern_node:
1090 widths[total_advance_amount] += kern_amount(s);
1091 if (adjust_spacing == adjust_spacing_full && node_subtype(s) == font_kern_subtype) {
1092 halfword n = node_prev(s);
1093 if (n && node_type(n) == glyph_node && ! tex_has_glyph_option(node_next(s), glyph_option_no_expansion)) {
1094 widths[font_stretch_amount] += tex_kern_stretch(s);
1095 widths[font_shrink_amount] += tex_kern_shrink(s);
1096 }
1097 }
1098 break;
1099 case disc_node:
1100 break;
1101 default:
1102
1103 break;
1104 }
1105 s = node_next(s);
1106 }
1107}
1108
1109
1116
1117static void tex_aux_sub_from_widths(halfword s, int adjust_spacing, int adjust_spacing_step, scaled widths[])
1118{
1119 while (s) {
1120
1121 switch (node_type(s)) {
1122 case glyph_node:
1123 widths[total_advance_amount] -= tex_glyph_width(s);
1124 if (adjust_spacing && ! tex_has_glyph_option(s, glyph_option_no_expansion) && tex_aux_check_expand_pars(adjust_spacing_step, glyph_font(s))) {
1125 lmt_packaging_state.previous_char_ptr = s;
1126 widths[font_stretch_amount] -= tex_char_stretch(s);
1127 widths[font_shrink_amount] -= tex_char_shrink(s);
1128 }
1129 break;
1130 case hlist_node:
1131 case vlist_node:
1132 widths[total_advance_amount] -= box_width(s);
1133 break;
1134 case rule_node:
1135 widths[total_advance_amount] -= rule_width(s);
1136 break;
1137 case glue_node:
1138 widths[total_advance_amount] -= glue_amount(s);
1139 widths[total_stretch_amount + glue_stretch_order(s)] -= glue_stretch(s);
1140 widths[total_shrink_amount] -= glue_shrink(s);
1141 break;
1142 case kern_node:
1143 widths[total_advance_amount] -= kern_amount(s);
1144 if (adjust_spacing == adjust_spacing_full && node_subtype(s) == font_kern_subtype) {
1145 halfword n = node_prev(s);
1146 if (n && node_type(n) == glyph_node && ! tex_has_glyph_option(node_next(s), glyph_option_no_expansion)) {
1147 widths[font_stretch_amount] -= tex_kern_stretch(s);
1148 widths[font_shrink_amount] -= tex_kern_shrink(s);
1149 }
1150 }
1151 break;
1152 case disc_node:
1153 break;
1154 default:
1155
1156 break;
1157 }
1158 s = node_next(s);
1159 }
1160}
1161
1162
1182
1183static void tex_aux_compute_break_width(int break_type, int adjust_spacing, int adjust_spacing_step, halfword p)
1184{
1185
1191 halfword s = p;
1192 if (p) {
1193 switch (break_type) {
1194 case hyphenated_node:
1195 case delta_node:
1196 case passive_node:
1197
1218 tex_aux_sub_from_widths(disc_no_break_head(p), adjust_spacing, adjust_spacing_step, lmt_linebreak_state.break_width);
1219 tex_aux_add_to_widths(disc_post_break_head(p), adjust_spacing, adjust_spacing_step, lmt_linebreak_state.break_width);
1220 tex_aux_add_disc_source_to_target(adjust_spacing, lmt_linebreak_state.break_width, lmt_linebreak_state.disc_width);
1221 if (disc_post_break_head(p)) {
1222 s = null;
1223 } else {
1224
1225 s = node_next(p);
1226 }
1227 break;
1228 }
1229 }
1230 while (s) {
1231 switch (node_type(s)) {
1232 case glue_node:
1233
1234 lmt_linebreak_state.break_width[total_advance_amount] -= glue_amount(s);
1235 lmt_linebreak_state.break_width[total_stretch_amount + glue_stretch_order(s)] -= glue_stretch(s);
1236 lmt_linebreak_state.break_width[total_shrink_amount] -= glue_shrink(s);
1237 break;
1238 case penalty_node:
1239 break;
1240 case kern_node:
1241 if (node_subtype(s) == explicit_kern_subtype || node_subtype(s) == italic_kern_subtype) {
1242 lmt_linebreak_state.break_width[total_advance_amount] -= kern_amount(s);
1243 break;
1244 } else {
1245 return;
1246 }
1247 case math_node:
1248 if (tex_math_glue_is_zero(s)) {
1249 lmt_linebreak_state.break_width[total_advance_amount] -= math_surround(s);
1250 } else {
1251 lmt_linebreak_state.break_width[total_advance_amount] -= math_amount(s);
1252 lmt_linebreak_state.break_width[total_stretch_amount + math_stretch_order(s)] -= math_stretch(s);
1253 lmt_linebreak_state.break_width[total_shrink_amount] -= math_shrink(s);
1254 }
1255 break;
1256 default:
1257 return;
1258 };
1259 s = node_next(s);
1260 }
1261}
1262
1263static void tex_aux_initialize_show_break_node(int callback_id)
1264{
1265 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "d->", initialize_show_breaks_context);
1266}
1267
1268static void tex_aux_start_show_break_node(int callback_id, int pass)
1269{
1270 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "dd->", start_show_breaks_context, pass);
1271}
1272
1273static void tex_aux_stop_show_break_node(int callback_id)
1274{
1275 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "d->", stop_show_breaks_context);
1276}
1277
1278static void tex_aux_collect_show_break_node(int callback_id)
1279{
1280 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "d->", collect_show_breaks_context);
1281}
1282
1283static void tex_aux_line_show_break_node(int callback_id)
1284{
1285 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "dNdddd->", line_show_breaks_context,
1286 lmt_linebreak_state.just_box, lmt_packaging_state.last_badness, lmt_packaging_state.last_overshoot,
1287 lmt_packaging_state.total_shrink[normal_glue_order], lmt_packaging_state.total_stretch[normal_glue_order]
1288 );
1289}
1290
1291static void tex_aux_delete_break_node(halfword active, halfword passive, int callback_id)
1292{
1293 (void) active;
1294 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "dd->", delete_show_breaks_context,
1295 passive_serial(passive)
1296 );
1297}
1298
1299static void tex_aux_wrapup_show_break_node(int callback_id)
1300{
1301 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "d->", wrapup_show_breaks_context);
1302}
1303
1304static void tex_aux_show_break_node(halfword active, halfword passive, int callback_id, int pass, halfword *demerits)
1305{
1306 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "ddddddddNddd->r", report_show_breaks_context,
1307 pass,
1308 passive_serial(passive),
1309 passive_prev_break(passive) ? passive_serial(passive_prev_break(passive)) : 0,
1310 active_line_number(active) - 1,
1311 node_type(active),
1312 active_fitness(active),
1313 active_total_demerits(active),
1314 passive_cur_break(passive),
1315 active_short(active),
1316 active_glue(active),
1317 active_line_width(active),
1318 demerits
1319 );
1320}
1321
1322static void tex_aux_list_break_node(halfword passive, int callback_id)
1323{
1324 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "dd->", list_show_breaks_context,
1325 passive_serial(passive)
1326 );
1327}
1328
1329static void tex_aux_print_break_node(halfword active, halfword passive)
1330{
1331
1332 tex_print_format(
1333 "%l[break: serial %i, line %i.%i,%s demerits %i, ",
1334 passive_serial(passive),
1335 active_line_number(active) - 1,
1336 active_fitness(active),
1337 node_type(active) == hyphenated_node ? " hyphenated, " : "",
1338 active_total_demerits(active)
1339 );
1340 if (lmt_linebreak_state.do_last_line_fit) {
1341
1342 tex_print_format(
1343 " short %p, %s %p, ",
1344 active_short(active),
1345 passive_cur_break(passive) ? "glue" : "active",
1346 active_glue(active)
1347 );
1348 }
1349 tex_print_format(
1350 "previous %i]",
1351 passive_prev_break(passive) ? passive_serial(passive_prev_break(passive)) : null
1352 );
1353}
1354
1355static const char *tex_aux_node_name(halfword current)
1356{
1357 if (current) {
1358
1359 switch (node_type(current)) {
1360 case penalty_node : return "penalty";
1361 case disc_node : return "discretionary";
1362 case kern_node : return "kern";
1363 case glue_node : return "glue";
1364 default : return "math";
1365 }
1366 } else {
1367 return "par";
1368 }
1369}
1370
1371static void tex_aux_print_feasible_break(halfword current, halfword breakpoint, halfword badness, halfword penalty, halfword d, halfword artificial_demerits, const line_break_properties *properties)
1372{
1373 (void) properties;
1374
1375 if (lmt_linebreak_state.printed_node != current) {
1376
1377 tex_print_nlp();
1378 if (current) {
1379 halfword save_link = node_next(current);
1380 node_next(current) = null;
1381 tex_short_display(node_next(lmt_linebreak_state.printed_node));
1382 node_next(current) = save_link;
1383 } else {
1384 tex_short_display(node_next(lmt_linebreak_state.printed_node));
1385 }
1386 lmt_linebreak_state.printed_node = current;
1387 }
1388 tex_print_format(
1389 "%l[break: feasible, trigger %s, serial %i, badness %B, penalty %i, demerits %B]",
1390 tex_aux_node_name(current),
1391 active_break_node(breakpoint) ? passive_serial(active_break_node(breakpoint)) : 0,
1392 badness,
1393 penalty,
1394 artificial_demerits ? awful_bad : d
1395 );
1396}
1397
1398
1399
1400
1404
1405static void tex_aux_post_line_break(const line_break_properties *properties, halfword line_break_dir, int callback_id, halfword quality);
1406
1407
1459
1460
1471
1472halfword tex_badness(scaled t, scaled s)
1473{
1474
1475 if (t == 0) {
1476 return 0;
1477 } else if (s <= 0) {
1478 return infinite_bad;
1479 } else {
1480
1481 if (t <= large_width_excess) {
1482 t = (t * 297) / s;
1483 } else if (s >= small_stretchability) {
1484 t = t / (s / 297);
1485 } else {
1486
1491 return infinite_bad;
1492 }
1493 if (t > 1290) {
1494
1495 return infinite_bad;
1496 } else {
1497
1498
1499
1500
1501 return (t * t * t + 131072) / 262144;
1502 }
1503 }
1504}
1505
1506inline static void tex_split_line_break_criterion(halfword criterion, halfword *semi_tight, halfword *decent, halfword *semi_loose, halfword *loose) {
1507 *semi_tight = (criterion >> 24) & 0x7F;
1508 *decent = (criterion >> 16) & 0x7F;
1509 *semi_loose = (criterion >> 8) & 0x7F;
1510 *loose = criterion & 0x7F;
1511 if (! *semi_tight) {
1512 *semi_tight = semi_tight_criterion;
1513 }
1514 if (! *decent) {
1515 *decent = decent_criterion;
1516 }
1517 if (! *semi_loose) {
1518 *semi_loose = semi_loose_criterion;
1519 }
1520 if (! *loose) {
1521 *loose = loose_criterion;
1522 }
1523}
1524
1525inline static halfword tex_normalized_loose_badness(halfword b, halfword loose, halfword semi_loose, halfword decent)
1526{
1527 if (b > loose) {
1528 return very_loose_fit;
1529 } else if (b > semi_loose) {
1530 return semi_loose_fit;
1531 } else if (b > decent) {
1532 return loose_fit;
1533 } else {
1534 return decent_fit;
1535 }
1536}
1537
1538inline static halfword tex_normalized_tight_badness(halfword b, halfword decent, halfword semi_tight)
1539{
1540 if (b > semi_tight) {
1541 return semi_tight_fit;
1542 } else if (b > decent) {
1543 return tight_fit;
1544 } else {
1545 return decent_fit;
1546 }
1547}
1548
1549static void tex_check_protrusion_shortfall(halfword breakpoint, halfword first, halfword current, halfword *shortfall)
1550{
1551
1552
1553
1554 halfword other = null;
1555 halfword left = active_break_node(breakpoint) ? passive_cur_break(active_break_node(breakpoint)) : first;
1556 if (current) {
1557 other = node_prev(current);
1558 if (node_next(other) != current) {
1559 tex_normal_error("linebreak", "the node list is messed up");
1560 }
1561 }
1562
1569 if (current && node_type(current) == disc_node && disc_pre_break_head(current)) {
1570
1574 other = disc_pre_break_tail(current);
1575 } else {
1576 other = tex_aux_find_protchar_right(left, other);
1577 }
1578 if (other && node_type(other) == glyph_node) {
1579 *shortfall += tex_char_protrusion(other, right_margin_kern_subtype);
1580 }
1581
1582 if (left && node_type(left) == disc_node && disc_post_break_head(left)) {
1583
1584 other = disc_post_break_head(left);
1585 } else {
1586 other = tex_aux_find_protchar_left(left, 1);
1587 }
1588 if (other && node_type(other) == glyph_node) {
1589 *shortfall += tex_char_protrusion(other, left_margin_kern_subtype);
1590 }
1591
1592}
1593
1594static void tex_aux_set_quality(halfword active, halfword passive, scaled shrt, scaled glue, scaled width, halfword badness)
1595{
1596 halfword quality = 0;
1597 halfword deficiency = 0;
1598 active_short(active) = shrt;
1599 active_glue(active) = glue;
1600 active_line_width(active) = width;
1601 if (shrt < 0) {
1602 shrt = -shrt;
1603 if (shrt > glue) {
1604 quality = par_is_overfull;
1605 deficiency = shrt - glue;
1606 }
1607 } else if (shrt > 0) {
1608 if (shrt > glue) {
1609 quality = par_is_underfull;
1610 deficiency = shrt - glue;
1611 }
1612 }
1613 passive_quality(passive) = quality;
1614 passive_deficiency(passive) = deficiency;
1615 passive_badness(passive) = badness;
1616 active_quality(active) = quality;
1617 active_deficiency(active) = deficiency;
1618 active_badness(active) = badness;
1619}
1620
1621static void tex_aux_try_break(
1622 const line_break_properties *properties,
1623 halfword penalty,
1624 halfword break_type,
1625 halfword first_p,
1626 halfword cur_p,
1627 int callback_id,
1628 int pass
1629)
1630{
1631
1632 halfword previous = active_head;
1633
1634 halfword before_previous = null;
1635
1636 scaled current_active_width[n_of_glue_amounts] = { 0 };
1637
1640 halfword best_place[n_of_finess_values];
1641 halfword best_place_line[n_of_finess_values];
1642 scaled best_place_short[n_of_finess_values];
1643 scaled best_place_glue[n_of_finess_values];
1644
1647
1648 halfword badness = 0;
1649
1650 int demerits = 0;
1651
1652 scaled glue = 0;
1653
1654 scaled shortfall = 0;
1655
1656 halfword old_line = 0;
1657
1658 bool no_break_yet = true;
1659
1660 int current_stays_active;
1661
1662 halfword fit_class;
1663
1664 int artificial_demerits;
1665
1666 scaled line_width = 0;
1667
1668 halfword line = 0;
1669
1673 halfword semi_tight, decent, semi_loose, loose;
1674
1675 tex_split_line_break_criterion(properties->line_break_criterion, &semi_tight, &decent, &semi_loose, &loose);
1676
1677
1678 if (penalty >= infinite_penalty) {
1679
1680 return;
1681 } else if (penalty <= -infinite_penalty) {
1682
1683 penalty = eject_penalty;
1684 }
1685 tex_aux_set_target_to_source(properties->adjust_spacing, current_active_width, lmt_linebreak_state.active_width);
1686 while (1) {
1687
1688 halfword current = node_next(previous);
1689
1696 if (node_type(current) == delta_node) {
1697 tex_aux_add_to_target_from_delta(properties->adjust_spacing, current_active_width, current);
1698 before_previous = previous;
1699 previous = current;
1700 continue;
1701 } else {
1702
1703 }
1704
1715 line = active_line_number(current);
1716 if (line > old_line) {
1717
1718 if ((lmt_linebreak_state.minimum_demerits < awful_bad) && ((old_line != lmt_linebreak_state.easy_line) || (current == active_head))) {
1719
1729 if (no_break_yet) {
1730 no_break_yet = false;
1731 tex_aux_set_target_to_source(properties->adjust_spacing, lmt_linebreak_state.break_width, lmt_linebreak_state.background);
1732 tex_aux_compute_break_width(break_type, properties->adjust_spacing, properties->adjust_spacing_step, cur_p);
1733 }
1734
1740 if (node_type(previous) == delta_node) {
1741
1742 tex_aux_add_delta_from_difference(properties->adjust_spacing, previous, lmt_linebreak_state.break_width, current_active_width);
1743 } else if (previous == active_head) {
1744
1745 tex_aux_set_target_to_source(properties->adjust_spacing, lmt_linebreak_state.active_width, lmt_linebreak_state.break_width);
1746 } else {
1747 halfword q = tex_new_node(delta_node, (quarterword) very_loose_fit);
1748 node_next(q) = current;
1749 tex_aux_set_delta_from_difference(properties->adjust_spacing, q, lmt_linebreak_state.break_width, current_active_width);
1750 node_next(previous) = q;
1751 before_previous = previous;
1752 previous = q;
1753 }
1754 if (abs(properties->adj_demerits) >= awful_bad - lmt_linebreak_state.minimum_demerits) {
1755 lmt_linebreak_state.minimum_demerits = awful_bad - 1;
1756 } else {
1757 lmt_linebreak_state.minimum_demerits += abs(properties->adj_demerits);
1758 }
1759 for (halfword fit_class = very_loose_fit; fit_class <= tight_fit; fit_class++) {
1760 if (lmt_linebreak_state.minimal_demerits[fit_class] <= lmt_linebreak_state.minimum_demerits) {
1761
1768
1769 halfword passive = tex_new_node(passive_node, (quarterword) fit_class);
1770 halfword active = tex_new_node((quarterword) break_type, (quarterword) fit_class);
1771 halfword prev_break = best_place[fit_class];
1772
1773 passive_cur_break(passive) = cur_p;
1774 passive_serial(passive) = ++lmt_linebreak_state.pass_number;
1775 passive_prev_break(passive) = prev_break;
1776 passive_pen_inter(passive) = lmt_linebreak_state.internal_penalty_interline;
1777 passive_pen_broken(passive) = lmt_linebreak_state.internal_penalty_broken;
1778 passive_last_left_box(passive) = lmt_linebreak_state.internal_left_box;
1779 passive_last_left_box_width(passive) = lmt_linebreak_state.internal_left_box_width;
1780 if (prev_break) {
1781 passive_left_box(passive) = passive_last_left_box(prev_break);
1782 passive_left_box_width(passive) = passive_last_left_box_width(prev_break);
1783 } else {
1784 passive_left_box(passive) = lmt_linebreak_state.internal_left_box_init;
1785 passive_left_box_width(passive) = lmt_linebreak_state.internal_left_box_width_init;
1786 }
1787 passive_right_box(passive) = lmt_linebreak_state.internal_right_box;
1788 passive_right_box_width(passive) = lmt_linebreak_state.internal_right_box_width;
1789 passive_middle_box(passive) = lmt_linebreak_state.internal_middle_box;
1790
1791 active_break_node(active) = passive;
1792 active_line_number(active) = best_place_line[fit_class] + 1;
1793 active_total_demerits(active) = lmt_linebreak_state.minimal_demerits[fit_class];
1794
1795 tex_aux_set_quality(active, passive, best_place_short[fit_class], best_place_glue[fit_class], line_width, badness);
1796
1797 node_next(passive) = lmt_linebreak_state.passive;
1798 lmt_linebreak_state.passive = passive;
1799
1800 node_next(active) = current;
1801 node_next(previous) = active;
1802 previous = active;
1803
1804 if (callback_id) {
1805 halfword demerits = active_total_demerits(active);
1806 tex_aux_show_break_node(active, passive, callback_id, pass, &demerits);
1807 active_total_demerits(active) = demerits;
1808 }
1809 if (properties->tracing_paragraphs > 0) {
1810 tex_aux_print_break_node(active, passive);
1811 }
1812 }
1813 lmt_linebreak_state.minimal_demerits[fit_class] = awful_bad;
1814 }
1815 lmt_linebreak_state.minimum_demerits = awful_bad;
1816
1823 if (current != active_head) {
1824 halfword delta = tex_new_node(delta_node, (quarterword) very_loose_fit);
1825 node_next(delta) = current;
1826 tex_aux_set_delta_from_difference(properties->adjust_spacing, delta, current_active_width, lmt_linebreak_state.break_width);
1827 node_next(previous) = delta;
1828 before_previous = previous;
1829 previous = delta;
1830 }
1831 }
1832
1841 if (current == active_head) {
1842 return;
1843 } else if (line > lmt_linebreak_state.easy_line) {
1844 old_line = max_halfword - 1;
1845 line_width = lmt_linebreak_state.second_width;
1846 } else {
1847 old_line = line;
1848 if (line > lmt_linebreak_state.last_special_line) {
1851 line_width = lmt_linebreak_state.second_width;
1852 } else if (properties->par_shape) {
1853 line_width = tex_get_specification_width(properties->par_shape, line);
1854 } else {
1855 line_width = lmt_linebreak_state.first_width;
1856 }
1857 }
1858 }
1859
1869 artificial_demerits = 0;
1870 shortfall = line_width - current_active_width[total_advance_amount];
1871 if (active_break_node(current)) {
1872 shortfall -= passive_last_left_box_width(active_break_node(current));
1873 } else {
1874 shortfall -= lmt_linebreak_state.internal_left_box_width_init;
1875 }
1876 shortfall -= lmt_linebreak_state.internal_right_box_width;
1877
1878
1879 if (properties->protrude_chars) {
1880 tex_check_protrusion_shortfall(current, first_p, cur_p, &shortfall);
1881 }
1882
1886 if (shortfall == 0) {
1887
1888 } else if (shortfall > 0) {
1889 halfword total_stretch = current_active_width[font_stretch_amount];
1890
1891 if (total_stretch > 0) {
1892 if (total_stretch > shortfall) {
1893 shortfall = (total_stretch / (lmt_linebreak_state.max_stretch_ratio / lmt_linebreak_state.current_font_step)) / 2;
1894 } else {
1895 shortfall -= total_stretch;
1896 }
1897 }
1898 } else if (shortfall < 0) {
1899 halfword total_shrink = current_active_width[font_shrink_amount];
1900
1901 if (total_shrink > 0) {
1902 if (total_shrink > -shortfall) {
1903 shortfall = - (total_shrink / (lmt_linebreak_state.max_shrink_ratio / lmt_linebreak_state.current_font_step)) / 2;
1904 } else {
1905 shortfall += total_shrink;
1906 }
1907 }
1908 }
1909 if (shortfall > 0) {
1910
1922 if (current_active_width[total_fi_amount] || current_active_width[total_fil_amount] ||
1923 current_active_width[total_fill_amount] || current_active_width[total_filll_amount]) {
1924 if (lmt_linebreak_state.do_last_line_fit) {
1925 if (! cur_p) {
1926
1936 if (active_short(current) == 0 || active_glue(current) <= 0) {
1937
1943 goto NOT_FOUND;
1944 }
1945 if (current_active_width[total_fi_amount] != lmt_linebreak_state.fill_width[fi_order] || current_active_width[total_fil_amount] != lmt_linebreak_state.fill_width[fil_order] ||
1946 current_active_width[total_fill_amount] != lmt_linebreak_state.fill_width[fill_order] || current_active_width[total_filll_amount] != lmt_linebreak_state.fill_width[filll_order]) {
1947
1950 goto NOT_FOUND;
1951 }
1952 if (active_short(current) > 0) {
1953 glue = current_active_width[total_stretch_amount];
1954 } else {
1955 glue = current_active_width[total_shrink_amount];
1956 }
1957 if (glue <= 0) {
1958
1959 goto NOT_FOUND;
1960 }
1961 lmt_scanner_state.arithmic_error = 0;
1962 glue = tex_fract(glue, active_short(current), active_glue(current), max_dimension);
1963 if (properties->last_line_fit < 1000) {
1964 glue = tex_fract(glue, properties->last_line_fit, 1000, max_dimension);
1965 }
1966 if (lmt_scanner_state.arithmic_error) {
1967 glue = (active_short(current) > 0) ? max_dimension : -max_dimension;
1968 }
1969 if (glue > 0) {
1970
1978 if (glue > shortfall) {
1979 glue = shortfall;
1980 }
1981 if (glue > large_width_excess && (current_active_width[total_stretch_amount] < small_stretchability)) {
1982 badness = infinite_bad;
1983 fit_class = very_loose_fit;
1984 } else {
1985 badness = tex_badness(glue, current_active_width[total_stretch_amount]);
1986 fit_class = tex_normalized_loose_badness(badness, loose, semi_loose, decent);
1987 }
1988 goto FOUND;
1989 } else if (glue < 0) {
1990
1996 if (-glue > current_active_width[total_shrink_amount]) {
1997 glue = -current_active_width[total_shrink_amount];
1998 }
1999 badness = tex_badness(-glue, current_active_width[total_shrink_amount]);
2000 fit_class = tex_normalized_tight_badness(badness, decent, semi_tight);
2001 goto FOUND;
2002 }
2003 }
2004 NOT_FOUND:
2005 shortfall = 0;
2006 }
2007 badness = 0;
2008
2009 fit_class = decent_fit;
2010 } else if (shortfall > large_width_excess && current_active_width[total_stretch_amount] < small_stretchability) {
2011 badness = infinite_bad;
2012 fit_class = very_loose_fit;
2013 } else {
2014 badness = tex_badness(shortfall, current_active_width[total_stretch_amount]);
2015 fit_class = tex_normalized_loose_badness(badness, loose, semi_loose, decent);
2016 }
2017 } else {
2018
2026 if (-shortfall > current_active_width[total_shrink_amount]) {
2027 badness = infinite_bad + 1;
2028 } else {
2029 badness = tex_badness(-shortfall, current_active_width[total_shrink_amount]);
2030 }
2031 fit_class = tex_normalized_tight_badness(badness, decent, semi_tight);
2032 }
2033 if (1) {
2034
2035 if (! cur_p) {
2036 shortfall = 0;
2037 glue = 0;
2038 } else if (shortfall > 0) {
2039 glue = current_active_width[total_stretch_amount];
2040 } else if (shortfall < 0) {
2041 glue = current_active_width[total_shrink_amount];
2042 } else {
2043 glue = 0;
2044 }
2045 } else {
2046
2047 }
2048 FOUND:
2049 if ((badness > infinite_bad) || (penalty == eject_penalty)) {
2050
2062 if (lmt_linebreak_state.final_pass && (lmt_linebreak_state.minimum_demerits == awful_bad) && (node_next(current) == active_head) && (previous == active_head)) {
2063
2064 artificial_demerits = 1;
2065 } else if (badness > lmt_linebreak_state.threshold) {
2066 goto DEACTIVATE;
2067 }
2068 current_stays_active = 0;
2069 } else {
2070 previous = current;
2071 if (badness > lmt_linebreak_state.threshold) {
2072 continue;
2073 } else {
2074 current_stays_active = 1;
2075 }
2076 }
2077
2086 if (artificial_demerits) {
2087 demerits = 0;
2088 } else {
2089
2090 int distance = abs(fit_class - (halfword) active_fitness(current));
2091 demerits = properties->line_penalty + badness;
2092 if (abs(demerits) >= infinite_bad) {
2093 demerits = extremely_deplorable;
2094 } else {
2095 demerits = demerits * demerits;
2096 }
2097 if (penalty) {
2098 if (penalty > 0) {
2099 demerits += (penalty * penalty);
2100 } else if (penalty > eject_penalty) {
2101 demerits -= (penalty * penalty);
2102 }
2103 }
2104 if (break_type == hyphenated_node && node_type(current) == hyphenated_node) {
2105 if (cur_p) {
2106 demerits += properties->double_hyphen_demerits;
2107 } else {
2108 demerits += properties->final_hyphen_demerits;
2109 }
2110 }
2111
2117 if (distance > 1) {
2118 demerits += properties->double_adj_demerits ? properties->double_adj_demerits : properties->adj_demerits;
2119 } else if (distance > 0) {
2120 demerits += properties->adj_demerits;
2121 }
2122 }
2123 if (properties->tracing_paragraphs > 0) {
2124 tex_aux_print_feasible_break(cur_p, current, badness, penalty, demerits, artificial_demerits, properties);
2125 }
2126
2127 demerits += active_total_demerits(current);
2128 if (demerits <= lmt_linebreak_state.minimal_demerits[fit_class]) {
2129 lmt_linebreak_state.minimal_demerits[fit_class] = demerits;
2130 best_place[fit_class] = active_break_node(current);
2131 best_place_line[fit_class] = line;
2132
2137 best_place_short[fit_class] = shortfall;
2138 best_place_glue[fit_class] = glue;
2139 if (demerits < lmt_linebreak_state.minimum_demerits) {
2140 lmt_linebreak_state.minimum_demerits = demerits;
2141 }
2142 }
2143
2144 if (current_stays_active) {
2145
2146 continue;
2147 }
2148 DEACTIVATE:
2149
2157 node_next(previous) = node_next(current);
2158 if (callback_id) {
2159 tex_aux_delete_break_node(current, active_break_node(current), callback_id);
2160 }
2161 tex_flush_node(current);
2162 if (previous == active_head) {
2163
2171 current = node_next(active_head);
2172 if (node_type(current) == delta_node) {
2173 tex_aux_add_to_target_from_delta(properties->adjust_spacing, lmt_linebreak_state.active_width, current);
2174 tex_aux_set_target_to_source(properties->adjust_spacing, current_active_width, lmt_linebreak_state.active_width);
2175 node_next(active_head) = node_next(current);
2176 tex_flush_node(current);
2177 }
2178 } else if (node_type(previous) == delta_node) {
2179 current = node_next(previous);
2180 if (current == active_head) {
2181 tex_aux_sub_delta_from_target(properties->adjust_spacing, current_active_width, previous);
2182 node_next(before_previous) = active_head;
2183 tex_flush_node(previous);
2184 previous = before_previous;
2185 } else if (node_type(current) == delta_node) {
2186 tex_aux_add_to_target_from_delta(properties->adjust_spacing, current_active_width, current);
2187 tex_aux_add_to_delta_from_delta(properties->adjust_spacing, previous, current);
2188 node_next(previous) = node_next(current);
2189 tex_flush_node(current);
2190 }
2191 }
2192 }
2193}
2194
2195static halfword tex_aux_inject_orphan_penalty(halfword current, halfword amount, int orphaned)
2196{
2197 halfword previous = node_prev(current);
2198 if (previous && node_type(previous) != penalty_node) {
2199 halfword penalty = tex_new_penalty_node(amount, orphan_penalty_subtype);
2200 tex_couple_nodes(previous, penalty);
2201 tex_couple_nodes(penalty, current);
2202 if (orphaned) {
2203 tex_add_penalty_option(penalty, penalty_option_orphaned);
2204 }
2205 return previous;
2206 } else {
2207 return current;
2208 }
2209}
2210
2211inline static int tex_aux_valid_glue_break(halfword p)
2212{
2213 halfword prv = node_prev(p);
2214 return (prv && prv != temp_head && (node_type(prv) == glyph_node || precedes_break(prv) || precedes_kern(prv) || precedes_dir(prv)));
2215}
2216
2217inline static halfword tex_aux_upcoming_penalty(halfword p) {
2218 halfword n = node_next(p);
2219 return (n && node_type(n) == math_node && node_subtype(n) == begin_inline_math) ? math_penalty(n) : 0;
2220}
2221
2222
2231
2232
2243
2244# define max_prev_graf (max_integer/2)
2245
2246inline static int tex_aux_short_math(halfword m) {
2247 return m && node_subtype(m) == begin_inline_math && math_penalty(m) > 0 && tex_has_math_option(m, math_option_short);
2248}
2249
2250inline static void tex_aux_adapt_short_math_penalty(halfword m, halfword p1, halfword p2, int orphaned) {
2251 if (p1 > math_penalty(m)) {
2252 math_penalty(m) = p1;
2253 if (orphaned) {
2254 tex_add_math_option(m, math_option_orphaned);
2255 }
2256 }
2257 if (p2 > math_penalty(m)) {
2258 math_penalty(m) = p2;
2259 if (orphaned) {
2260 tex_add_math_option(m, math_option_orphaned);
2261 }
2262 }
2263}
2264
2265inline static halfword tex_aux_backtrack_over_math(halfword m)
2266{
2267 if (node_subtype(m) == end_inline_math) {
2268 do {
2269 m = node_prev(m);
2270 } while (m && node_type(m) != math_node);
2271 }
2272 return m;
2273}
2274
2275inline static int tex_aux_emergency(line_break_properties *properties)
2276{
2277 if (properties->emergency_stretch > 0) {
2278 return 1;
2279 } else if (properties->emergency_extra_stretch > 0) {
2280 return 1;
2281 } else if (! (tex_glue_is_zero(properties->emergency_left_skip) && glue_stretch_order(properties->emergency_left_skip) == normal_glue_order && glue_shrink_order(properties->emergency_left_skip) == normal_glue_order)) {
2282 return 1;
2283 } else if (! (tex_glue_is_zero(properties->emergency_right_skip) && glue_stretch_order(properties->emergency_right_skip) == normal_glue_order && glue_shrink_order(properties->emergency_right_skip) == normal_glue_order)) {
2284 return 1;
2285 } else {
2286 return 0;
2287 }
2288}
2289
2290inline static int tex_aux_emergency_skip(halfword s)
2291{
2292 return ! tex_glue_is_zero(s) && glue_stretch_order(s) == normal_glue_order && glue_shrink_order(s) == normal_glue_order;
2293}
2294
2295static const int classification[] = {
2296 very_loose_class,
2297 loose_fit_class,
2298 semi_loose_fit_class,
2299 decent_fit_class,
2300 semi_tight_fit_class,
2301 tight_fit_class,
2302};
2303
2304static scaled tex_check_linebreak_quality(halfword quality, scaled *overfull, scaled *underfull, halfword *verdict, halfword *classified)
2305{
2306 if ((quality & (par_has_glyph | par_has_disc)) == (par_has_glyph | par_has_disc)) {
2307 halfword q = active_break_node(lmt_linebreak_state.best_bet);
2308
2309 switch (active_quality(q)) {
2310 case par_is_overfull:
2311 *overfull = active_deficiency(q);
2312 *underfull = 0;
2313 break;
2314 case par_is_underfull:
2315 *overfull = 0;
2316 *underfull = active_deficiency(q);
2317 break;
2318 default:
2319 *overfull = 0;
2320 *underfull = 0;
2321 break;
2322 }
2323 *verdict = active_badness(q);
2324 *classified |= classification[node_subtype(q)];
2325
2326 q = passive_prev_break(q);
2327 while (q) {
2328 switch (passive_quality(q)) {
2329 case par_is_overfull:
2330 if (passive_deficiency(q) > *overfull) {
2331 *overfull = passive_deficiency(q);
2332 }
2333 break;
2334 case par_is_underfull:
2335 if (passive_deficiency(q) > *underfull) {
2336 *underfull = passive_deficiency(q);
2337 }
2338 break;
2339 }
2340 *classified |= classification[node_subtype(q)];
2341 if (passive_badness(q) > *verdict) {
2342 *verdict = passive_badness(q);
2343 }
2344 q = passive_prev_break(q);
2345 }
2346 if (*verdict > infinite_bad) {
2347 *verdict = infinite_bad;
2348 }
2349 return 1;
2350 } else {
2351 return 0;
2352 }
2353}
2354
2355static void tex_aux_quality_callback(int callback_id, int id, int pass, int subpass, int subpasses, halfword quality)
2356{
2357 scaled overfull = 0;
2358 scaled underfull = 0;
2359 halfword verdict = 0;
2360 halfword classified = 0;
2361 tex_check_linebreak_quality(quality, &overfull, &underfull, &verdict, &classified);
2362 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "ddddddddd->", id, lmt_packaging_state.pack_begin_line, pass, subpass, subpasses, overfull, underfull, verdict, classified);
2363}
2364
2365
2370
2371static void tex_aux_remove_orphan_penalties(line_break_properties *properties)
2372{
2373 halfword current = node_prev(properties->parfill_right_skip);
2374 while (current) {
2375 switch (node_type(current)) {
2376 case glue_node:
2377 case penalty_node:
2378 current = node_prev(current);
2379 break;
2380 default:
2381 goto CHECK;
2382 }
2383 }
2384 CHECK:
2385 while (current) {
2386 halfword prev = node_prev(current);
2387 switch (node_type(current)) {
2388 case penalty_node:
2389 if (node_subtype(current) == orphan_penalty_subtype && tex_has_penalty_option(current, penalty_option_orphaned)) {
2390 tex_try_couple_nodes(prev, node_next(current));
2391 tex_flush_node(current);
2392 }
2393 break;
2394 case math_node:
2395 current = tex_aux_backtrack_over_math(current);
2396 if (tex_aux_short_math(current)) {
2397 if (tex_has_math_option(current, math_option_orphaned)) {
2398 math_penalty(current) = 0;
2399 tex_remove_math_option(current, math_option_orphaned);
2400 }
2401 }
2402 return;
2403 case disc_node:
2404 if (tex_has_disc_option(current, disc_option_orphaned)) {
2405 disc_orphaned(current) = 0;
2406 tex_remove_disc_option(current, disc_option_orphaned);
2407 }
2408 break;
2409 }
2410 current = prev;
2411 }
2412}
2413
2414static void tex_aux_prepare_orphan_penalties(line_break_properties *properties, int orphaned)
2415{
2416 if (properties->orphan_penalties || properties->orphan_penalty || short_inline_orphan_penalty_par) {
2417 halfword current = node_prev(properties->parfill_right_skip);
2418 if (current) {
2419
2420 while (current) {
2421 switch (node_type(current)) {
2422 case glue_node:
2423 case penalty_node:
2424 current = node_prev(current);
2425 break;
2426 default:
2427 goto INJECT;
2428 }
2429 }
2430 INJECT:
2431 if (properties->orphan_penalties) {
2432
2437 int n = specification_count(properties->orphan_penalties);
2438 if (n > 0) {
2439 int skip = 0;
2440 halfword i = 0;
2441 while (current) {
2442 switch (node_type(current)) {
2443 case glue_node:
2444 switch (node_subtype(current)) {
2445 case space_skip_glue:
2446 case xspace_skip_glue:
2447 case zero_space_skip_glue:
2448 if (skip) {
2449 skip = 0;
2450 } else {
2451 current = tex_aux_inject_orphan_penalty(current, tex_get_specification_penalty(properties->orphan_penalties, ++i), 0);
2452 }
2453 if (i == n) {
2454 return;
2455 } else {
2456 break;
2457 }
2458 }
2459 break;
2460 case math_node:
2461 current = tex_aux_backtrack_over_math(current);
2462 if (tex_aux_short_math(current)) {
2463 halfword p = tex_get_specification_penalty(properties->orphan_penalties, ++i);
2464 tex_aux_adapt_short_math_penalty(current, short_inline_orphan_penalty_par, p, 0);
2465 if (i == n) {
2466 return;
2467 } else {
2468 skip = 1;
2469 }
2470 } else {
2471 return;
2472 }
2473 break;
2474 default:
2475 skip = 0;
2476 break;
2477 }
2478 current = node_prev(current);
2479 }
2480 }
2481 } else if (properties->orphan_penalty) {
2482
2489 while (current) {
2490 switch (node_type(current)) {
2491 case glue_node:
2492 switch (node_subtype(current)) {
2493 case space_skip_glue:
2494 case xspace_skip_glue:
2495 case zero_space_skip_glue:
2496 tex_aux_inject_orphan_penalty(current, properties->orphan_penalty, orphaned);
2497 return;
2498 default:
2499
2500 break;
2501 }
2502 break;
2503 case penalty_node:
2504 if (node_subtype(current) == orphan_penalty_subtype) {
2505 return;
2506 }
2507 break;
2508 case math_node:
2509 current = tex_aux_backtrack_over_math(current);
2510 if (tex_aux_short_math(current)) {
2511 tex_aux_adapt_short_math_penalty(current, short_inline_orphan_penalty_par, properties->orphan_penalty, orphaned);
2512 }
2513 return;
2514 case disc_node:
2515
2521 disc_orphaned(current) = properties->orphan_penalty;
2522 if (orphaned) {
2523 tex_add_disc_option(current, disc_option_orphaned);
2524 }
2525 break;
2526 }
2527 current = node_prev(current);
2528 }
2529 } else if (short_inline_orphan_penalty_par) {
2530
2536 while (current) {
2537 switch (node_type(current)) {
2538 case glue_node:
2539 switch (node_subtype(current)) {
2540 case space_skip_glue:
2541 case xspace_skip_glue:
2542 case zero_space_skip_glue:
2543 return;
2544 }
2545 break;
2546 case math_node:
2547 current = tex_aux_backtrack_over_math(current);
2548 if (tex_aux_short_math(current)) {
2549 tex_aux_adapt_short_math_penalty(current, short_inline_orphan_penalty_par, 0, 0);
2550 }
2551 return;
2552
2553 }
2554 current = node_prev(current);
2555 }
2556 }
2557 }
2558 }
2559}
2560
2561inline static int tex_aux_has_expansion(void)
2562{
2563 if (lmt_linebreak_state.checked_expansion == -1) {
2564 halfword current = node_next(temp_head);
2565 while (current) {
2566 if (node_type(current) == glyph_node && has_font_text_control(glyph_font(current), text_control_expansion)) {
2567 lmt_linebreak_state.checked_expansion = 1;
2568 break;
2569 } else {
2570 current = node_next(current);
2571 }
2572 }
2573 lmt_linebreak_state.checked_expansion = 0;
2574 }
2575 return lmt_linebreak_state.checked_expansion;
2576}
2577
2578
2579inline static void tex_aux_set_initial_active(void)
2580{
2581 halfword initial = tex_new_node(unhyphenated_node, (quarterword) decent_fit);
2582 node_next(initial) = active_head;
2583 active_break_node(initial) = null;
2584 active_line_number(initial) = cur_list.prev_graf + 1;
2585 active_total_demerits(initial) = 0;
2586 active_short(initial) = 0;
2587 active_glue(initial) = 0;
2588 active_line_width(initial) = 0;
2589 node_next(active_head) = initial;
2590}
2591
2592inline static void tex_aux_set_local_par_state(halfword current)
2593{
2594 if (current && node_type(current) == par_node) {
2595 node_prev(current) = temp_head;
2596 lmt_linebreak_state.internal_penalty_interline = tex_get_local_interline_penalty(current);
2597 lmt_linebreak_state.internal_penalty_broken = tex_get_local_broken_penalty(current);
2598 lmt_linebreak_state.internal_left_box_init = par_box_left(current);
2599 lmt_linebreak_state.internal_left_box_width_init = tex_get_local_left_width(current);
2600 lmt_linebreak_state.internal_right_box = par_box_right(current);
2601 lmt_linebreak_state.internal_right_box_width = tex_get_local_right_width(current);
2602 lmt_linebreak_state.internal_middle_box = par_box_middle(current);
2603 } else {
2604 lmt_linebreak_state.internal_penalty_interline = 0;
2605 lmt_linebreak_state.internal_penalty_broken = 0;
2606 lmt_linebreak_state.internal_left_box_init = null;
2607 lmt_linebreak_state.internal_left_box_width_init = 0;
2608 lmt_linebreak_state.internal_right_box = null;
2609 lmt_linebreak_state.internal_right_box_width = 0;
2610 lmt_linebreak_state.internal_middle_box = null;
2611 }
2612 lmt_linebreak_state.internal_left_box = lmt_linebreak_state.internal_left_box_init;
2613 lmt_linebreak_state.internal_left_box_width = lmt_linebreak_state.internal_left_box_width_init;
2614}
2615
2616inline static void tex_aux_set_adjust_spacing(line_break_properties *properties)
2617{
2618 if (properties->adjust_spacing) {
2619 lmt_linebreak_state.adjust_spacing = properties->adjust_spacing;
2620 if (properties->adjust_spacing_step > 0) {
2621 lmt_linebreak_state.adjust_spacing_step = properties->adjust_spacing_step;
2622 lmt_linebreak_state.adjust_spacing_shrink = -properties->adjust_spacing_shrink;
2623 lmt_linebreak_state.adjust_spacing_stretch = properties->adjust_spacing_stretch;
2624 } else {
2625 lmt_linebreak_state.adjust_spacing_step = 0;
2626 lmt_linebreak_state.adjust_spacing_shrink = 0;
2627 lmt_linebreak_state.adjust_spacing_stretch = 0;
2628 }
2629 properties->adjust_spacing = tex_checked_font_adjust(
2630 properties->adjust_spacing,
2631 lmt_linebreak_state.adjust_spacing_step,
2632 lmt_linebreak_state.adjust_spacing_shrink,
2633 lmt_linebreak_state.adjust_spacing_stretch
2634 );
2635 } else {
2636 lmt_linebreak_state.adjust_spacing_step = 0;
2637 lmt_linebreak_state.adjust_spacing_shrink = 0;
2638 lmt_linebreak_state.adjust_spacing_stretch = 0;
2639 properties->adjust_spacing = adjust_spacing_off;
2640 }
2641 lmt_linebreak_state.current_font_step = -1;
2642 lmt_linebreak_state.max_shrink_ratio = -1;
2643 lmt_linebreak_state.max_stretch_ratio = -1;
2644}
2645
2646inline static void tex_aux_set_looseness(line_break_properties *properties)
2647{
2648 if (properties->looseness == 0) {
2649 lmt_linebreak_state.easy_line = lmt_linebreak_state.last_special_line;
2650 } else {
2651 lmt_linebreak_state.easy_line = max_halfword;
2652 }
2653}
2654
2655inline static int tex_aux_check_sub_pass(line_break_properties *properties, halfword quality, halfword passes, int subpass, int nofsubpasses, halfword first)
2656{
2657 scaled overfull = 0;
2658 scaled underfull = 0;
2659 halfword verdict = 0;
2660 halfword classified = 0;
2661 if (tex_check_linebreak_quality(quality, &overfull, &underfull, &verdict, &classified)) {
2662 if (overfull > 0 || verdict > 0) {
2663 while (subpass < nofsubpasses) {
2664 scaled features = tex_get_passes_features(passes, ++subpass);
2665 if (features & passes_quit_pass) {
2666 return -1;
2667 } else if (features & passes_skip_pass) {
2668 continue;
2669 } else {
2670 scaled threshold = tex_get_passes_threshold(passes, subpass);
2671 halfword badness = tex_get_passes_badness(passes, subpass);
2672 halfword classes = tex_get_passes_classes(passes, subpass);
2673 int callback = features & passes_callback_set;
2674 bool tracing = properties->tracing_paragraphs > 0 || properties->tracing_passes > 0;
2675 bool details = properties->tracing_passes > 1;
2676 int success = 0;
2677 bool retry = callback ? 1 : (overfull > threshold || verdict > badness || (classes && (classes & classified) != 0));
2678 if (tracing) {
2679 halfword id = tex_get_passes_identifier(passes, 1);
2680 if (callback) {
2681 tex_print_format("[id %i, subpass: %i of %i, overfull %p, underfull %p, verdict %i, classified %x, %s]\n",
2682 id, subpass, nofsubpasses, overfull, underfull, verdict, classified, "callback"
2683 );
2684 } else {
2685 const char *action = retry ? "retry" : "skipped";
2686 if (id < 0) {
2687 id = -id;
2688 }
2689 tex_begin_diagnostic();
2690 if (threshold == max_dimension) {
2691 if (badness == infinite_bad) {
2692 tex_print_format("[id %i, subpass: %i of %i, overfull %p, underfull %p, verdict %i, classified %x, %s]\n",
2693 id, subpass, nofsubpasses, overfull, underfull, verdict, classified, action
2694 );
2695 } else {
2696 tex_print_format("[id %i, subpass: %i of %i, overfull %p, underfull %p, verdict %i, badness %i, classified %x, %s]\n",
2697 id, subpass, nofsubpasses, overfull, underfull, verdict, badness, classified, action
2698 );
2699 }
2700 } else {
2701 if (badness == infinite_bad) {
2702 tex_print_format("[id %i, subpass: %i of %i, overfull %p, underfull %p, verdict %i, threshold %p, classified %x, %s]\n",
2703 id, subpass, nofsubpasses, overfull, underfull, verdict, threshold, classified, action
2704 );
2705 } else {
2706 tex_print_format("[id %i, subpass: %i of %i, overfull %p, underfull %p, verdict %i, threshold %p, badness %i, classified %x, %s]\n",
2707 id, subpass, nofsubpasses, overfull, underfull, verdict, threshold, badness, classified, action
2708 );
2709 }
2710 }
2711 }
2712 }
2713 if (retry) {
2714 halfword v = tex_get_passes_tolerance(passes, subpass);
2715 if (v) {
2716 properties->tolerance = v;
2717 }
2718 lmt_linebreak_state.threshold = properties->tolerance;
2719 v = tex_get_passes_linepenalty(passes, subpass);
2720 if (v) {
2721 properties->line_penalty = v;
2722 }
2723 v = tex_get_passes_orphanpenalty(passes, subpass);
2724 if (v) {
2725 properties->orphan_penalty = v;
2726 }
2727 v = tex_get_passes_extrahyphenpenalty(passes, subpass);
2728 if (v) {
2729 properties->extra_hyphen_penalty = v;
2730 }
2731 v = tex_get_passes_doublehyphendemerits(passes, subpass);
2732 if (v) {
2733 properties->double_hyphen_demerits = v;
2734 }
2735 v = tex_get_passes_finalhyphendemerits(passes, subpass);
2736 if (v) {
2737 properties->final_hyphen_demerits = v;
2738 }
2739 v = tex_get_passes_adjdemerits(passes, subpass);
2740 if (v) {
2741 properties->adj_demerits = v;
2742 }
2743 v = tex_get_passes_linebreakcriterion(passes, subpass);
2744 if (v) {
2745 properties->line_break_criterion = v;
2746 }
2747 v = tex_get_passes_emergencystretch(passes, subpass);
2748 if (v) {
2749 properties->emergency_stretch = v;
2750 }
2751 v = tex_get_passes_looseness(passes, subpass);
2752 if (v) {
2753 properties->looseness = v;
2754 }
2755 v = tex_get_passes_adjustspacingstep(passes, subpass);
2756 if (v) {
2757 properties->adjust_spacing_step = v;
2758 }
2759 v = tex_get_passes_adjustspacingshrink(passes, subpass);
2760 if (v) {
2761 properties->adjust_spacing_shrink = v;
2762 }
2763 v = tex_get_passes_adjustspacingstretch(passes, subpass);
2764 if (v) {
2765 properties->adjust_spacing_stretch = v;
2766 }
2767 v = tex_get_passes_adjustspacing(passes, subpass);
2768 if (v) {
2769 properties->adjust_spacing = v;
2770 }
2771 if (features & passes_optional_set) {
2772 v = tex_get_passes_optional(passes, subpass);
2773 properties->line_break_optional = v;
2774 }
2775
2776 if (features & passes_callback_set) {
2777 halfword callback = tex_get_passes_callback(passes, subpass);
2778 halfword id = tex_get_passes_identifier(passes, 1);
2779 int repeat = 0;
2780 success = lmt_par_pass_callback(
2781 first,
2782 properties, id, callback, features,
2783 overfull, underfull, verdict, classified,
2784 threshold, badness, classes, &repeat
2785 );
2786
2787 if (repeat) {
2788 subpass -= 1;
2789 }
2790 } else {
2791 success = 1;
2792 }
2793
2794 tex_aux_remove_orphan_penalties(properties);
2795 if (features & passes_orphan_penalty_set) {
2796
2797 tex_aux_prepare_orphan_penalties(properties, 1);
2798 }
2799 tex_aux_set_adjust_spacing(properties);
2800 tex_aux_set_looseness(properties);
2801 }
2802 if (details) {
2803 tex_print_format(" tolerance %i\n", properties->tolerance);
2804 tex_print_format(" doublehyphendemerits %i\n", properties->double_hyphen_demerits);
2805 tex_print_format(" finalhyphendemerits %i\n", properties->final_hyphen_demerits);
2806 tex_print_format(" adjdemerits %i\n", properties->adj_demerits);
2807 tex_print_format(" doubleadjdemerits %i\n", properties->double_adj_demerits);
2808 tex_print_format(" emergencystretch %p\n", properties->emergency_stretch);
2809 tex_print_format(" looseness %i\n", properties->looseness);
2810 tex_print_format(" adjustspacing %i\n", properties->adjust_spacing);
2811 tex_print_format(" linepenalty %i\n", properties->line_penalty);
2812 tex_print_format(" orphanpenalty %i\n", properties->orphan_penalty);
2813 tex_print_format(" extrahyphenpenalty %i\n", properties->extra_hyphen_penalty);
2814 tex_print_format(" linebreakoptional %i\n", properties->line_break_optional);
2815 if (properties->adjust_spacing > 0) {
2816 if (properties->adjust_spacing_step >= 0) {
2817 tex_print_format(" adjustspacingstep %i\n", properties->adjust_spacing_step);
2818 }
2819 if (properties->adjust_spacing_shrink >= 0) {
2820 tex_print_format(" adjustspacingshrink %i\n", properties->adjust_spacing_shrink);
2821 }
2822 if (properties->adjust_spacing_stretch >= 0) {
2823 tex_print_format(" adjustspacingstretch %i\n", properties->adjust_spacing_stretch);
2824 }
2825 }
2826 if (properties->line_break_criterion) {
2827 halfword semi_tight, decent, semi_loose, loose;
2828 tex_split_line_break_criterion(properties->line_break_criterion, &semi_tight, &decent, &semi_loose, &loose);
2829 tex_print_format(" linebreakcriterion %X\n", properties->line_break_criterion);
2830 }
2831 }
2832 if (tracing) {
2833 tex_end_diagnostic();
2834 }
2835
2836
2837 if (features & passes_if_adjust_spacing && tex_aux_has_expansion()) {
2838 if (properties->adjust_spacing) {
2839
2840 } else {
2841 success = 0;
2842 }
2843 } else {
2844
2845 }
2846 if (success) {
2847 return subpass;
2848 }
2849 }
2850 }
2851 } else {
2852
2853 }
2854 }
2855 return 0;
2856}
2857
2858
2885
2886inline static void tex_aux_wipe_optionals(line_break_properties *properties, halfword current)
2887{
2888 if (properties->optional_found) {
2889
2890 while (current) {
2891 if (node_type(current) == boundary_node && node_subtype(current) == optional_boundary) {
2892 if (properties->line_break_optional) {
2893 if (! boundary_data(current)) {
2894
2895 current = node_next(current);
2896 continue;
2897 } else if ((boundary_data(current) & properties->line_break_optional) == properties->line_break_optional) {
2898
2899 current = node_next(current);
2900 continue;
2901 }
2902 }
2903 {
2904 halfword first = current;
2905
2906 while (1) {
2907 current = node_next(current);
2908 if (! current) {
2909 return;
2910 } else if (node_type(current) == boundary_node && node_subtype(current) == optional_boundary && ! boundary_data(current) ) {
2911
2912 halfword prev = node_prev(first);
2913 halfword next = node_next(current);
2914 halfword wiped = first;
2915 node_next(current) = null;
2916 tex_try_couple_nodes(prev, next);
2917 tex_flush_node_list(wiped);
2918 current = prev;
2919 break;
2920 }
2921 }
2922 }
2923 }
2924 current = node_next(current);
2925 }
2926 }
2927}
2928
2929inline static halfword tex_aux_break_list(line_break_properties *properties, halfword pass, halfword current, halfword first, int callback_id, int force_check_hyphenation, halfword *quality)
2930{
2931 while (current && (node_next(active_head) != active_head)) {
2932 switch (node_type(current)) {
2933 case glyph_node:
2934
2935 lmt_linebreak_state.active_width[total_advance_amount] += tex_glyph_width(current);
2936 if (properties->adjust_spacing && tex_aux_check_expand_pars(properties->adjust_spacing_step, glyph_font(current))) {
2937 lmt_packaging_state.previous_char_ptr = current;
2938 lmt_linebreak_state.active_width[font_stretch_amount] += tex_char_stretch(current);
2939 lmt_linebreak_state.active_width[font_shrink_amount] += tex_char_shrink(current);
2940 }
2941 *quality |= par_has_glyph;
2942 break;
2943 case hlist_node:
2944 case vlist_node:
2945 lmt_linebreak_state.active_width[total_advance_amount] += box_width(current);
2946 break;
2947 case rule_node:
2948 lmt_linebreak_state.active_width[total_advance_amount] += rule_width(current);
2949 break;
2950 case dir_node:
2951
2952 lmt_linebreak_state.line_break_dir = tex_update_dir_state(current, properties->paragraph_dir);
2953 break;
2954 case par_node:
2955
2956 switch (node_subtype(current)) {
2957 case vmode_par_par_subtype:
2958 case hmode_par_par_subtype:
2959 break;
2960 case local_box_par_subtype:
2961 break;
2962 case parameter_par_subtype:
2963 {
2964 halfword t = current == 1 ? tex_get_local_tolerance(current) : tex_get_local_pre_tolerance(current);
2965 if (t) {
2966 lmt_linebreak_state.threshold = t;
2967 }
2968 lmt_linebreak_state.internal_penalty_interline = tex_get_local_interline_penalty(current);
2969 lmt_linebreak_state.internal_penalty_broken = tex_get_local_broken_penalty(current);
2970 break;
2971 }
2972 }
2973 lmt_linebreak_state.internal_left_box = par_box_left(current);
2974 lmt_linebreak_state.internal_left_box_width = tex_get_local_left_width(current);
2975 lmt_linebreak_state.internal_right_box = par_box_right(current);
2976 lmt_linebreak_state.internal_right_box_width = tex_get_local_right_width(current);
2977 lmt_linebreak_state.internal_middle_box = par_box_middle(current);
2978 break;
2979 case glue_node:
2980
2992 if (tex_has_glue_option(current, glue_option_no_auto_break)) {
2993
2994 } else if (tex_is_par_init_glue(current)) {
2995
2996 } else if (tex_aux_valid_glue_break(current)) {
2997 tex_aux_try_break(properties, tex_aux_upcoming_penalty(current), unhyphenated_node, first, current, callback_id, pass);
2998 }
2999 lmt_linebreak_state.active_width[total_advance_amount] += glue_amount(current);
3000 lmt_linebreak_state.active_width[total_stretch_amount + glue_stretch_order(current)] += glue_stretch(current);
3001 lmt_linebreak_state.active_width[total_shrink_amount] += tex_aux_checked_shrink(current);
3002 switch (node_subtype(current)) {
3003 case space_skip_glue:
3004 case xspace_skip_glue:
3005 case zero_space_skip_glue:
3006 *quality |= par_has_space;
3007 break;
3008 case u_leaders:
3009 *quality |= par_has_uleader;
3010 break;
3011 }
3012 break;
3013 case kern_node:
3014 switch (node_subtype(current)) {
3015 case explicit_kern_subtype:
3016 case italic_kern_subtype:
3017 case right_correction_kern_subtype:
3018 {
3019
3020
3021 halfword nxt = node_next(current);
3022 if (nxt && node_type(nxt) == glue_node && ! tex_aux_upcoming_penalty(nxt) && ! tex_has_glue_option(nxt, glue_option_no_auto_break)) {
3023 tex_aux_try_break(properties, 0, unhyphenated_node, first, current, callback_id, pass);
3024 }
3025 }
3026 break;
3027
3028
3029 case font_kern_subtype:
3030 if (properties->adjust_spacing == adjust_spacing_full) {
3031 lmt_linebreak_state.active_width[font_stretch_amount] += tex_kern_stretch(current);
3032 lmt_linebreak_state.active_width[font_shrink_amount] += tex_kern_shrink(current);
3033 }
3034 break;
3035 }
3036 lmt_linebreak_state.active_width[total_advance_amount] += kern_amount(current);
3037 break;
3038 case disc_node:
3039
3065 {
3066 halfword replace = disc_no_break_head(current);
3067 if (force_check_hyphenation || lmt_linebreak_state.second_pass || (node_subtype(current) != syllable_discretionary_code)) {
3068 halfword actual_penalty = disc_penalty(current) + disc_orphaned(current) + properties->extra_hyphen_penalty;
3069 halfword pre = disc_pre_break_head(current);
3070 tex_aux_reset_disc_target(properties->adjust_spacing, lmt_linebreak_state.disc_width);
3071 if (pre) {
3072
3086 if (replace && node_subtype(current) != mathematics_discretionary_code) {
3087 if (tex_has_disc_option(current, disc_option_prefer_break) || tex_has_disc_option(current, disc_option_prefer_nobreak)) {
3088
3096 switch (node_type(node_next(current))) {
3097 case glue_node:
3098 case penalty_node:
3099 case boundary_node:
3100 {
3101
3105 scaled wpre = tex_natural_hsize(pre, NULL);
3106 scaled wreplace = tex_natural_hsize(replace, NULL);
3107 if (tex_has_disc_option(current, disc_option_prefer_break)) {
3108 halfword post = disc_post_break_head(current);
3109 scaled wpost = post ? tex_natural_hsize(post, NULL) : 0;
3110 if (wpost > 0) {
3111 if (properties->tracing_paragraphs > 1) {
3112 tex_begin_diagnostic();
3113 tex_print_format("[linebreak: favour final prepost over replace, widths %p %p]", wpre + wpost, wreplace);
3114 tex_short_display(node_next(temp_head));
3115 tex_end_diagnostic();
3116 }
3117 } else {
3118 goto REPLACEONLY;
3119 }
3120 } else {
3121 if (wreplace < wpre) {
3122 if (properties->tracing_paragraphs > 1) {
3123 tex_begin_diagnostic();
3124 tex_print_format("[linebreak: favour final replace over pre, widths %p %p]", wreplace, wpre);
3125 tex_short_display(node_next(temp_head));
3126 tex_end_diagnostic();
3127 }
3128 goto REPLACEONLY;
3129 }
3130 }
3131 }
3132 }
3133 }
3134 }
3135 tex_aux_add_to_widths(pre, properties->adjust_spacing, properties->adjust_spacing_step, lmt_linebreak_state.disc_width);
3136 tex_aux_add_disc_source_to_target(properties->adjust_spacing, lmt_linebreak_state.active_width, lmt_linebreak_state.disc_width);
3137 tex_aux_try_break(properties, actual_penalty, hyphenated_node, first, current, callback_id, pass);
3138 tex_aux_sub_disc_target_from_source(properties->adjust_spacing, lmt_linebreak_state.active_width, lmt_linebreak_state.disc_width);
3139 } else {
3140
3141 tex_aux_try_break(properties, actual_penalty, hyphenated_node, first, current, callback_id, pass);
3142 }
3143 }
3144 REPLACEONLY:
3145 if (replace) {
3146 tex_aux_add_to_widths(replace, properties->adjust_spacing, properties->adjust_spacing_step, lmt_linebreak_state.active_width);
3147 }
3148 *quality |= par_has_disc;
3149 break;
3150 }
3151 case penalty_node:
3152 tex_aux_try_break(properties, penalty_amount(current), unhyphenated_node, first, current, callback_id, pass);
3153 break;
3154 case math_node:
3155 {
3156
3160 int finishing = node_subtype(current) == end_inline_math;
3161 if (finishing) {
3162 lmt_linebreak_state.threshold = lmt_linebreak_state.saved_threshold;
3163
3168 } else {
3169 lmt_linebreak_state.saved_threshold = lmt_linebreak_state.threshold;
3170 if (pass == 1) {
3171 if (math_pre_tolerance(current)) {
3172 lmt_linebreak_state.threshold = math_pre_tolerance(current);
3173 }
3174 } else {
3175 if (math_tolerance(current)) {
3176 lmt_linebreak_state.threshold = math_tolerance(current);
3177 }
3178 }
3179 }
3180
3181 if (tex_math_glue_is_zero(current) || tex_ignore_math_skip(current)) {
3182
3187 if (finishing && node_type(node_next(current)) == glue_node) {
3188 tex_aux_try_break(properties, math_penalty(current), unhyphenated_node, first, current, callback_id, pass);
3189 }
3190 lmt_linebreak_state.active_width[total_advance_amount] += math_surround(current);
3191 } else {
3192
3195 if (finishing && tex_aux_valid_glue_break(current)) {
3196 tex_aux_try_break(properties, math_penalty(current), unhyphenated_node, first, current, callback_id, pass);
3197 }
3198 lmt_linebreak_state.active_width[total_advance_amount] += math_amount(current);
3199 lmt_linebreak_state.active_width[total_stretch_amount + math_stretch_order(current)] += math_stretch(current);
3200 lmt_linebreak_state.active_width[total_shrink_amount] += tex_aux_checked_shrink(current);
3201 }
3202 }
3203 break;
3204 case boundary_node:
3205 if (node_subtype(current) == optional_boundary) {
3206 properties->optional_found = 1;
3207 if (properties->line_break_optional) {
3208 if (! boundary_data(current)) {
3209
3210 break;
3211 } else if ((boundary_data(current) & properties->line_break_optional) == properties->line_break_optional) {
3212
3213
3214 break;
3215 }
3216 }
3217
3218 while (1) {
3219 current = node_next(current);
3220 if (! current) {
3221
3222 return null;
3223 } else if (node_type(current) == boundary_node && node_subtype(current) == optional_boundary && ! boundary_data(current)) {
3224
3225 break;
3226 }
3227 }
3228 }
3229 break;
3230 case whatsit_node:
3231 case mark_node:
3232 case insert_node:
3233 case adjust_node:
3234
3235 break;
3236 default:
3237 tex_formatted_error("parbuilder", "weird node %d in paragraph", node_type(current));
3238 }
3239 current = node_next(current);
3240 }
3241 return current;
3242}
3243
3244void tex_do_line_break(line_break_properties *properties)
3245{
3246
3247 int callback_id = lmt_callback_defined(show_break_callback);
3248 int force_check_hyphenation = hyphenation_permitted(properties->hyphenation_mode, force_check_hyphenation_mode);
3249 halfword quality = 0;
3250 (void) (properties->inter_line_penalties);
3251
3252 if ((cur_list.prev_graf > max_prev_graf || cur_list.prev_graf < 0) && normalize_par_mode_permitted(normalize_par_mode_par, limit_prev_graf_mode)) {
3253 tex_formatted_warning("tex", "clipping prev_graf %i to %i", cur_list.prev_graf, max_prev_graf);
3254 cur_list.prev_graf = max_prev_graf;
3255 }
3256 lmt_linebreak_state.line_break_dir = properties->paragraph_dir;
3257
3258 lmt_linebreak_state.fewest_demerits = 0;
3259 lmt_linebreak_state.actual_looseness = 0;
3260 lmt_linebreak_state.minimum_demerits = awful_bad;
3261 lmt_linebreak_state.checked_expansion = -1;
3262 for (int i = very_loose_fit; i <= tight_fit; i++) {
3263 lmt_linebreak_state.minimal_demerits[i] = awful_bad;
3264 }
3265
3268 tex_aux_set_adjust_spacing(properties);
3269
3275 tex_aux_prepare_orphan_penalties(properties, 0);
3276 if (properties->par_shape) {
3277 int n = specification_count(properties->par_shape);
3278 if (n > 0) {
3279 if (specification_repeat(properties->par_shape)) {
3280 lmt_linebreak_state.last_special_line = max_halfword;
3281 } else {
3282 lmt_linebreak_state.last_special_line = n - 1;
3283 }
3284 lmt_linebreak_state.second_indent = tex_get_specification_indent(properties->par_shape, n);
3285 lmt_linebreak_state.second_width = tex_get_specification_width(properties->par_shape, n);
3286 lmt_linebreak_state.second_indent = swap_parshape_indent(properties->paragraph_dir, lmt_linebreak_state.second_indent, lmt_linebreak_state.second_width);
3287 } else {
3288 lmt_linebreak_state.last_special_line = 0;
3289 lmt_linebreak_state.second_width = properties->hsize;
3290 lmt_linebreak_state.second_indent = 0;
3291 }
3292 } else if (properties->hang_indent == 0) {
3293 lmt_linebreak_state.last_special_line = 0;
3294 lmt_linebreak_state.second_width = properties->hsize;
3295 lmt_linebreak_state.second_indent = 0;
3296 } else {
3297 halfword used_hang_indent = swap_hang_indent(properties->paragraph_dir, properties->hang_indent);
3298
3305 lmt_linebreak_state.last_special_line = abs(properties->hang_after);
3306 if (properties->hang_after < 0) {
3307 lmt_linebreak_state.first_width = properties->hsize - abs(used_hang_indent);
3308 if (used_hang_indent >= 0) {
3309 lmt_linebreak_state.first_indent = used_hang_indent;
3310 } else {
3311 lmt_linebreak_state.first_indent = 0;
3312 }
3313 lmt_linebreak_state.second_width = properties->hsize;
3314 lmt_linebreak_state.second_indent = 0;
3315 } else {
3316 lmt_linebreak_state.first_width = properties->hsize;
3317 lmt_linebreak_state.first_indent = 0;
3318 lmt_linebreak_state.second_width = properties->hsize - abs(used_hang_indent);
3319 if (used_hang_indent >= 0) {
3320 lmt_linebreak_state.second_indent = used_hang_indent;
3321 } else {
3322 lmt_linebreak_state.second_indent = 0;
3323 }
3324 }
3325 }
3326 tex_aux_set_looseness(properties);
3327 lmt_linebreak_state.no_shrink_error_yet = 1;
3328 {
3329 halfword l = properties->left_skip;
3330 halfword r = properties->right_skip;
3331 lmt_linebreak_state.background[total_advance_amount] = glue_amount(l) + glue_amount(r);
3332 lmt_linebreak_state.background[total_stretch_amount] = 0;
3333 lmt_linebreak_state.background[total_fi_amount] = 0;
3334 lmt_linebreak_state.background[total_fil_amount] = 0;
3335 lmt_linebreak_state.background[total_fill_amount] = 0;
3336 lmt_linebreak_state.background[total_filll_amount] = 0;
3337 lmt_linebreak_state.background[total_stretch_amount + glue_stretch_order(l)] = glue_stretch(l);
3338 lmt_linebreak_state.background[total_stretch_amount + glue_stretch_order(r)] += glue_stretch(r);
3339 lmt_linebreak_state.background[total_shrink_amount] = tex_aux_checked_shrink(l) + tex_aux_checked_shrink(r);
3340 }
3341 if (properties->adjust_spacing) {
3342 lmt_linebreak_state.background[font_stretch_amount] = 0;
3343 lmt_linebreak_state.background[font_shrink_amount] = 0;
3344 lmt_linebreak_state.max_stretch_ratio = -1;
3345 lmt_linebreak_state.max_shrink_ratio = -1;
3346 lmt_linebreak_state.current_font_step = -1;
3347 lmt_packaging_state.previous_char_ptr = null;
3348 }
3349
3356 lmt_linebreak_state.do_last_line_fit = 0;
3357 if (properties->last_line_fit > 0) {
3358 halfword q = lmt_linebreak_state.last_line_fill;
3359 if (glue_stretch(q) > 0 && glue_stretch_order(q) > normal_glue_order) {
3360 if (lmt_linebreak_state.background[total_fi_amount] == 0 && lmt_linebreak_state.background[total_fil_amount] == 0 &&
3361 lmt_linebreak_state.background[total_fill_amount] == 0 && lmt_linebreak_state.background[total_filll_amount] == 0) {
3362 lmt_linebreak_state.do_last_line_fit = 1;
3363 lmt_linebreak_state.fill_width[fi_order] = 0;
3364 lmt_linebreak_state.fill_width[fil_order] = 0;
3365 lmt_linebreak_state.fill_width[fill_order] = 0;
3366 lmt_linebreak_state.fill_width[filll_order] = 0;
3367 lmt_linebreak_state.fill_width[glue_stretch_order(q) - fi_glue_order] = glue_stretch(q);
3368 }
3369 }
3370 }
3371
3372 if (lmt_linebreak_state.dir_ptr) {
3373 tex_flush_node_list(lmt_linebreak_state.dir_ptr);
3374 lmt_linebreak_state.dir_ptr = null;
3375 }
3376
3377 lmt_linebreak_state.threshold = properties->pretolerance;
3378 if (properties->tracing_paragraphs > 1) {
3379 tex_begin_diagnostic();
3380 tex_print_str("[linebreak: original]");
3381 tex_short_display(node_next(temp_head));
3382 tex_end_diagnostic();
3383 }
3384 if (lmt_linebreak_state.threshold >= 0) {
3385 if (properties->tracing_paragraphs > 0) {
3386 tex_begin_diagnostic();
3387 tex_print_str("[linebreak: first pass]");
3388 }
3389 lmt_linebreak_state.second_pass = 0;
3390 lmt_linebreak_state.final_pass = 0;
3391 } else {
3392 lmt_linebreak_state.threshold = properties->tolerance;
3393 lmt_linebreak_state.second_pass = 1;
3394 lmt_linebreak_state.final_pass = ! tex_aux_emergency(properties);
3395 if (properties->tracing_paragraphs > 0) {
3396 tex_begin_diagnostic();
3397 }
3398 }
3399 if (line_break_passes_par == -1) {
3400 lmt_linebreak_state.final_pass = 1;
3401 }
3402 if (callback_id) {
3403 tex_aux_initialize_show_break_node(callback_id);
3404 }
3405 {
3406 halfword passes = properties->par_passes;
3407 int subpasses = (passes && line_break_passes_par > 0) ? tex_get_specification_count(passes) : 0;
3408 int subpass = 0;
3409 int pass = 0;
3410 while (++pass) {
3411 halfword first = node_next(temp_head);
3412 halfword current = first;
3413 lmt_linebreak_state.saved_threshold = 0;
3414 if (lmt_linebreak_state.threshold > infinite_bad) {
3415 lmt_linebreak_state.threshold = infinite_bad;
3416 }
3417 if (callback_id) {
3418 tex_aux_start_show_break_node(callback_id, pass);
3419 }
3420
3424 tex_aux_set_initial_active();
3425
3429 tex_aux_set_target_to_source(properties->adjust_spacing, lmt_linebreak_state.active_width, lmt_linebreak_state.background);
3430 lmt_linebreak_state.passive = null;
3431 lmt_linebreak_state.printed_node = temp_head;
3432 lmt_linebreak_state.pass_number = 0;
3433 lmt_print_state.font_in_short_display = null_font;
3434 lmt_packaging_state.previous_char_ptr = null;
3435
3439 tex_aux_set_local_par_state(current);
3440
3450 current = tex_aux_break_list(properties, pass, current, first, callback_id, force_check_hyphenation, &quality);
3451 if (! current) {
3452
3468 tex_aux_try_break(properties, eject_penalty, hyphenated_node, first, current, callback_id, pass);
3469 if (node_next(active_head) != active_head) {
3470
3471 {
3472 halfword r = node_next(active_head);
3473 lmt_linebreak_state.fewest_demerits = awful_bad;
3474 do {
3475 if ((node_type(r) != delta_node) && (active_total_demerits(r) < lmt_linebreak_state.fewest_demerits)) {
3476 lmt_linebreak_state.fewest_demerits = active_total_demerits(r);
3477 lmt_linebreak_state.best_bet = r;
3478 }
3479 r = node_next(r);
3480 } while (r != active_head);
3481 }
3482 lmt_linebreak_state.best_line = active_line_number(lmt_linebreak_state.best_bet);
3483
3484 if (pass == 2 && subpass < subpasses) {
3485 int found = tex_aux_check_sub_pass(properties, quality, passes, subpass, subpasses, first);
3486 if (found > 0) {
3487 subpass = found;
3488 --pass;
3489 lmt_linebreak_state.second_pass = 0;
3490 lmt_linebreak_state.final_pass = 0;
3491 goto HERE;
3492 } else if (found < 0) {
3493 goto HERE;
3494 }
3495 }
3496
3497 if (properties->looseness == 0) {
3498 goto DONE;
3499 } else {
3500
3509 halfword r = node_next(active_head);
3510 lmt_linebreak_state.actual_looseness = 0;
3511 do {
3512 if (node_type(r) != delta_node) {
3513 lmt_linebreak_state.line_difference = active_line_number(r) - lmt_linebreak_state.best_line;
3514 if (((lmt_linebreak_state.line_difference < lmt_linebreak_state.actual_looseness) && (properties->looseness <= lmt_linebreak_state.line_difference))
3515 || ((lmt_linebreak_state.line_difference > lmt_linebreak_state.actual_looseness) && (properties->looseness >= lmt_linebreak_state.line_difference))) {
3516 lmt_linebreak_state.best_bet = r;
3517 lmt_linebreak_state.actual_looseness = lmt_linebreak_state.line_difference;
3518 lmt_linebreak_state.fewest_demerits = active_total_demerits(r);
3519 } else if ((lmt_linebreak_state.line_difference == lmt_linebreak_state.actual_looseness) && (active_total_demerits(r) < lmt_linebreak_state.fewest_demerits)) {
3520 lmt_linebreak_state.best_bet = r;
3521 lmt_linebreak_state.fewest_demerits = active_total_demerits(r);
3522 }
3523 }
3524 r = node_next(r);
3525 } while (r != active_head);
3526 lmt_linebreak_state.best_line = active_line_number(lmt_linebreak_state.best_bet);
3527
3528 if ((lmt_linebreak_state.actual_looseness == properties->looseness) || lmt_linebreak_state.final_pass) {
3529 goto DONE;
3530 }
3531 }
3532 }
3533 } else {
3534
3535 }
3536
3537 HERE:
3538 tex_aux_clean_up_the_memory();
3539 if (! lmt_linebreak_state.second_pass) {
3540 if (properties->tracing_paragraphs > 0) {
3541 tex_print_format("%l[linebreak: second pass]"); ;
3542 }
3543 lmt_linebreak_state.threshold = properties->tolerance;
3544 lmt_linebreak_state.second_pass = 1;
3545 lmt_linebreak_state.final_pass = ! tex_aux_emergency(properties);
3546 } else {
3547
3548 halfword el = properties->emergency_left_skip;
3549 halfword er = properties->emergency_right_skip;
3550 if (properties->tracing_paragraphs > 0) {
3551 tex_print_format("%l[linebreak: emergency pass]");
3552 }
3553 lmt_linebreak_state.background[total_stretch_amount] += properties->emergency_stretch;
3554 lmt_linebreak_state.background[total_stretch_amount] += properties->emergency_extra_stretch;
3555 if (tex_aux_emergency_skip(el)) {
3556 properties->left_skip = tex_copy_node(properties->left_skip);
3557 glue_amount(properties->left_skip) += glue_amount(el);
3558 glue_stretch(properties->left_skip) += glue_stretch(el);
3559 glue_shrink(properties->left_skip) += glue_shrink(el);
3560 lmt_linebreak_state.background[total_advance_amount] += glue_amount(el);
3561 lmt_linebreak_state.background[total_stretch_amount] += glue_stretch(el);
3562 lmt_linebreak_state.background[total_shrink_amount] += glue_shrink(el);
3563 }
3564 if (tex_aux_emergency_skip(er)) {
3565 properties->right_skip = tex_copy_node(properties->right_skip);
3566 glue_amount(properties->right_skip) += glue_amount(er);
3567 glue_stretch(properties->right_skip) += glue_stretch(er);
3568 glue_shrink(properties->right_skip) += glue_shrink(er);
3569 lmt_linebreak_state.background[total_advance_amount] += glue_amount(er);
3570 lmt_linebreak_state.background[total_stretch_amount] += glue_stretch(er);
3571 lmt_linebreak_state.background[total_shrink_amount] += glue_shrink(er);
3572 }
3573 lmt_linebreak_state.final_pass = 1;
3574 }
3575 if (callback_id) {
3576 tex_aux_stop_show_break_node(callback_id);
3577 }
3578 }
3579 DONE:
3580 if (properties->tracing_paragraphs > 0) {
3581 tex_end_diagnostic();
3582
3586 }
3587 if (lmt_linebreak_state.do_last_line_fit) {
3588
3592 if (active_short(lmt_linebreak_state.best_bet) == 0) {
3593 lmt_linebreak_state.do_last_line_fit = 0;
3594 } else {
3595 glue_amount(lmt_linebreak_state.last_line_fill) += (active_short(lmt_linebreak_state.best_bet) - active_glue(lmt_linebreak_state.best_bet));
3596 glue_stretch(lmt_linebreak_state.last_line_fill) = 0;
3597 }
3598 }
3599
3605 {
3606 int callback_id = lmt_callback_defined(linebreak_quality_callback);
3607 if (callback_id) {
3608 tex_aux_quality_callback(callback_id, passes ? tex_get_passes_identifier(passes, 1) : 0, pass, subpass, subpasses, quality);
3609 }
3610 }
3611 tex_aux_wipe_optionals(properties, node_next(temp_head));
3612 tex_flush_node_list(lmt_linebreak_state.dir_ptr);
3613 lmt_linebreak_state.dir_ptr = null;
3614
3615 tex_aux_post_line_break(properties, lmt_linebreak_state.line_break_dir, callback_id, quality);
3616
3617 tex_aux_clean_up_the_memory();
3618 }
3619 if (callback_id) {
3620 tex_aux_wrapup_show_break_node(callback_id);
3621 }
3622}
3623
3624void tex_get_linebreak_info(int *f, int *a)
3625{
3626 *f = lmt_linebreak_state.fewest_demerits;
3627 *a = lmt_linebreak_state.actual_looseness;
3628}
3629
3630
3657
3658
3659
3660# define passive_next_break passive_prev_break
3661
3662
3663
3664static void tex_aux_trace_penalty(const char *what, int line, int index, halfword penalty, halfword total)
3665{
3666 if (tracing_penalties_par > 0) {
3667 tex_begin_diagnostic();
3668 tex_print_format("[linebreak: %s penalty, line %i, index %i, adding %i, total %i]", what, line, index, penalty, total);
3669 tex_end_diagnostic();
3670 }
3671}
3672
3673static void tex_aux_post_line_break(const line_break_properties *properties, halfword line_break_dir, int callback_id, halfword quality)
3674{
3675
3676 halfword q, r;
3677 halfword ls = null;
3678 halfword rs = null;
3679
3680 int glue_break;
3681
3682 int shaping = 0;
3683
3684 int disc_break;
3685
3686 int post_disc_break;
3687
3688 scaled cur_width;
3689
3690 scaled cur_indent;
3691
3692 halfword cur_p = null;
3693
3694 halfword cur_line;
3695
3696 int last_line = 0;
3697 int first_line = 0;
3698
3699 lmt_linebreak_state.dir_ptr = cur_list.direction_stack;
3700 (void) quality;
3701
3709 if (callback_id) {
3710 tex_aux_collect_show_break_node(callback_id);
3711 }
3712 q = active_break_node(lmt_linebreak_state.best_bet);
3713 do {
3714 r = q;
3715 q = passive_prev_break(q);
3716 passive_next_break(r) = cur_p;
3717 cur_p = r;
3718 } while (q);
3719 if (callback_id) {
3720 halfword p = cur_p;
3721 while (p) {
3722 tex_aux_list_break_node(p, callback_id);
3723 p = passive_next_break(p);
3724 }
3725 }
3726
3727 cur_line = cur_list.prev_graf + 1;
3728 do {
3729
3740
3743 halfword cur_disc = null;
3744
3747 halfword leftbox = null;
3748 halfword rightbox = null;
3749 halfword middlebox = null;
3750 if (lmt_linebreak_state.dir_ptr) {
3751
3752 for (halfword q = lmt_linebreak_state.dir_ptr; q; q = node_next(q)) {
3753 halfword tmp = tex_new_dir(normal_dir_subtype, dir_direction(q));
3754 halfword nxt = node_next(temp_head);
3755 tex_attach_attribute_list_copy(tmp, nxt ? nxt : temp_head);
3756 tex_couple_nodes(temp_head, tmp);
3757
3758 tex_try_couple_nodes(tmp, nxt);
3759 }
3760 tex_flush_node_list(lmt_linebreak_state.dir_ptr);
3761 lmt_linebreak_state.dir_ptr = null;
3762 }
3763
3770
3771 q = temp_head;
3772 while (q) {
3773 switch (node_type(q)) {
3774 case glyph_node:
3775 goto DONE;
3776 case hlist_node:
3777 if (node_subtype(q) == indent_list) {
3778 break;
3779 } else {
3780 goto DONE;
3781 }
3782 case glue_node:
3783 if (tex_is_par_init_glue(q)) {
3784 break;
3785 } else {
3786 goto DONE;
3787 }
3788 case kern_node:
3789 if (node_subtype(q) == explicit_kern_subtype || node_subtype(q) == italic_kern_subtype) {
3790 break;
3791 } else {
3792 goto DONE;
3793 }
3794 case math_node:
3795 math_surround(q) = 0;
3796 tex_reset_math_glue_to_zero(q);
3797 goto DONE;
3798 default:
3799 if (non_discardable(q)) {
3800 goto DONE;
3801 } else {
3802 break;
3803 }
3804 }
3805 q = node_next(q);
3806 }
3807 DONE:
3808
3809 r = passive_cur_break(cur_p);
3810 q = null;
3811 disc_break = 0;
3812 post_disc_break = 0;
3813 glue_break = 0;
3814 if (r) {
3815 switch (node_type(r)) {
3816 case glue_node:
3817 tex_copy_glue_values(r, properties->right_skip);
3818 node_subtype(r) = right_skip_glue;
3819 glue_break = 1;
3820
3821 q = r;
3822 rs = q;
3823 r = node_prev(r);
3824
3825 break;
3826 case disc_node:
3827 {
3828 halfword prv = node_prev(r);
3829 halfword nxt = node_next(r);
3830 halfword h = disc_no_break_head(r);
3831 if (h) {
3832 tex_flush_node_list(h);
3833 disc_no_break_head(r) = null;
3834 disc_no_break_tail(r) = null;
3835 }
3836 h = disc_pre_break_head(r);
3837 if (h) {
3838 halfword t = disc_pre_break_tail(r);
3839 tex_set_discpart(r, h, t, glyph_discpart_pre);
3840 tex_couple_nodes(prv, h);
3841 tex_couple_nodes(t, r);
3842 disc_pre_break_head(r) = null;
3843 disc_pre_break_tail(r) = null;
3844 }
3845 h = disc_post_break_head(r);
3846 if (h) {
3847 halfword t = disc_post_break_tail(r);
3848 tex_set_discpart(r, h, t, glyph_discpart_post);
3849 tex_couple_nodes(r, h);
3850 tex_couple_nodes(t, nxt);
3851 disc_post_break_head(r) = null;
3852 disc_post_break_tail(r) = null;
3853 post_disc_break = 1;
3854 }
3855 cur_disc = r;
3856 disc_break = 1;
3857 }
3858 break;
3859 case kern_node:
3860 if (node_subtype(r) != right_correction_kern_subtype && node_subtype(r) != left_correction_kern_subtype) {
3861 kern_amount(r) = 0;
3862 }
3863 break;
3864 case math_node :
3865 math_surround(r) = 0;
3866 tex_reset_math_glue_to_zero(r);
3867 break;
3868 }
3869 } else {
3870
3871
3872 r = tex_tail_of_node_list(temp_head);
3873
3874 if (r == properties->parfill_right_skip) {
3875
3876 q = r;
3877
3878 r = node_prev(r);
3879 }
3880
3881 }
3882
3883 line_break_dir = tex_sanitize_dir_state(node_next(temp_head), passive_cur_break(cur_p), properties->paragraph_dir);
3884
3885 r = tex_complement_dir_state(r);
3886
3903 leftbox = tex_use_local_boxes(passive_left_box(cur_p), local_left_box_code);
3904 rightbox = tex_use_local_boxes(passive_right_box(cur_p), local_right_box_code);
3905 middlebox = tex_use_local_boxes(passive_middle_box(cur_p), local_middle_box_code);
3906
3909 if (rightbox) {
3910 halfword nxt = node_next(r);
3911 tex_couple_nodes(r, rightbox);
3912 tex_try_couple_nodes(rightbox, nxt);
3913 r = rightbox;
3914 }
3915 if (middlebox) {
3916
3921 halfword nxt = node_next(r);
3922 tex_couple_nodes(r, middlebox);
3923 tex_try_couple_nodes(middlebox, nxt);
3924 r = middlebox;
3925 }
3926 if (! q) {
3927 q = r;
3928 }
3929 if (q != temp_head && properties->protrude_chars) {
3930 if (line_break_dir == dir_righttoleft && properties->protrude_chars == protrude_chars_advanced) {
3931 halfword p = q;
3932 halfword l = null;
3933
3934 while (p) {
3935 switch (node_type(p)) {
3936 case dir_node:
3937 if (node_subtype(p) != cancel_dir_subtype) {
3938 goto DONE1;
3939 } else {
3940 break;
3941 }
3942 case glue_node:
3943 if (glue_amount(p)) {
3944 goto DONE3;
3945 } else {
3946 break;
3947 }
3948 case glyph_node:
3949 goto DONE1;
3950 default:
3951 goto DONE3;
3952 }
3953 p = node_prev(p);
3954 }
3955 DONE1:
3956
3957 while (p) {
3958 switch (node_type(p)) {
3959 case glyph_node:
3960 l = p ;
3961 break;
3962 case glue_node:
3963 if (glue_amount(p)) {
3964 l = null;
3965 }
3966 break;
3967 case dir_node:
3968 if (dir_direction(p) != dir_righttoleft) {
3969 goto DONE3;
3970 } else {
3971 goto DONE2;
3972 }
3973 case par_node:
3974 goto DONE2;
3975 case temp_node:
3976
3977 break;
3978 default:
3979 l = null;
3980 break;
3981 }
3982 p = node_prev(p);
3983 }
3984 DONE2:
3985
3986 if (l && p) {
3987 scaled w = tex_char_protrusion(l, right_margin_kern_subtype);
3988 halfword k = tex_new_kern_node(-w, right_margin_kern_subtype);
3989 tex_attach_attribute_list_copy(k, l);
3990 tex_couple_nodes(p, k);
3991 tex_couple_nodes(k, l);
3992 }
3993 } else {
3994 scaled w = 0;
3995 halfword p, ptmp;
3996 if (disc_break && (node_type(q) == glyph_node || node_type(q) != disc_node)) {
3997
3998 p = q;
3999 } else {
4000
4001 p = node_prev(q);
4002 }
4003 ptmp = p;
4004 p = tex_aux_find_protchar_right(node_next(temp_head), p);
4005 w = tex_char_protrusion(p, right_margin_kern_subtype);
4006 if (w && lmt_packaging_state.last_rightmost_char) {
4007
4008 halfword k = tex_new_kern_node(-w, right_margin_kern_subtype);
4009 tex_attach_attribute_list_copy(k, p);
4010 tex_try_couple_nodes(k, node_next(ptmp));
4011 tex_couple_nodes(ptmp, k);
4012 if (ptmp == q) {
4013 q = node_next(q);
4014 }
4015 }
4016 }
4017 }
4018 DONE3:
4019
4023 if (glue_break) {
4024
4025 rs = q;
4026 } else {
4027
4028 rs = tex_new_glue_node(properties->right_skip ? properties->right_skip : zero_glue, right_skip_glue);
4029 tex_attach_attribute_list_copy(rs, q);
4030 tex_try_couple_nodes(rs, node_next(q));
4031 tex_couple_nodes(q, rs);
4032 q = rs;
4033 }
4034
4037 r = node_next(q);
4038 node_next(q) = null;
4039 q = node_next(temp_head);
4040 tex_try_couple_nodes(temp_head, r);
4041
4044 if (leftbox) {
4045 halfword nxt = node_next(q);
4046 tex_couple_nodes(leftbox, q);
4047 q = leftbox;
4048 if (nxt && (cur_line == cur_list.prev_graf + 1) && (node_type(nxt) == hlist_node) && ! box_list(nxt)) {
4049
4050 q = node_next(q);
4051 tex_try_couple_nodes(leftbox, node_next(nxt));
4052 tex_try_couple_nodes(nxt, leftbox);
4053 }
4054 }
4055
4058 if (properties->protrude_chars) {
4059 if (line_break_dir == dir_righttoleft && properties->protrude_chars == protrude_chars_advanced) {
4060 halfword p = tex_aux_find_protchar_left(q, 0);
4061 halfword w = tex_char_protrusion(p, left_margin_kern_subtype);
4062 if (w && lmt_packaging_state.last_leftmost_char) {
4063 halfword k = tex_new_kern_node(-w, left_margin_kern_subtype);
4064 tex_attach_attribute_list_copy(k, p);
4065 tex_couple_nodes(k, q);
4066 q = k;
4067 }
4068 } else {
4069 halfword p = tex_aux_find_protchar_left(q, 0);
4070 halfword w = tex_char_protrusion(p, left_margin_kern_subtype);
4071 if (w && lmt_packaging_state.last_leftmost_char) {
4072 halfword k = tex_new_kern_node(-w, left_margin_kern_subtype);
4073 tex_attach_attribute_list_copy(k, p);
4074 tex_couple_nodes(k, q);
4075 q = k;
4076 }
4077 }
4078 }
4079
4082 if (node_type(q) == par_node && ! tex_is_start_of_par_node(q)) {
4083 node_subtype(q) = hmode_par_par_subtype ;
4084 }
4085
4092 ls = tex_new_glue_node(properties->left_skip, left_skip_glue);
4093 tex_attach_attribute_list_copy(ls, q);
4094 tex_couple_nodes(ls, q);
4095 q = ls;
4096
4102 if (cur_line > lmt_linebreak_state.last_special_line) {
4103 cur_width = lmt_linebreak_state.second_width;
4104 cur_indent = lmt_linebreak_state.second_indent;
4105 } else if (properties->par_shape) {
4106 if (specification_count(properties->par_shape)) {
4107 cur_indent = tex_get_specification_indent(properties->par_shape, cur_line);
4108 cur_width = tex_get_specification_width(properties->par_shape, cur_line);
4109 cur_indent = swap_parshape_indent(properties->paragraph_dir, cur_indent, cur_width);
4110 } else {
4111 cur_width = lmt_linebreak_state.first_width;
4112 cur_indent = lmt_linebreak_state.first_indent;
4113 }
4114 } else {
4115 cur_width = lmt_linebreak_state.first_width;
4116 cur_indent = lmt_linebreak_state.first_indent;
4117 }
4118
4136 first_line = rs && (cur_line == 1) && properties->parinit_left_skip && properties->parinit_right_skip;
4137 last_line = ls && (cur_line + 1 == lmt_linebreak_state.best_line) && properties->parfill_left_skip && properties->parfill_right_skip;
4138 if (first_line) {
4139 halfword n = node_next(properties->parinit_left_skip);
4140 while (n) {
4141 if (n == properties->parinit_right_skip) {
4142 tex_couple_nodes(node_prev(n), node_next(n));
4143 tex_couple_nodes(node_prev(rs), n);
4144 tex_couple_nodes(n, rs);
4145 break;
4146 } else {
4147 n = node_next(n);
4148 }
4149 }
4150 if (! n && normalize_line_mode_par) {
4151
4152 tex_normal_warning("tex", "right parinit skip is gone");
4153 }
4154 }
4155 if (last_line) {
4156 halfword n = node_prev(properties->parfill_right_skip);
4157 while (n) {
4158 if (n == properties->parfill_left_skip) {
4159 tex_couple_nodes(node_prev(n), node_next(n));
4160 tex_couple_nodes(n, node_next(ls));
4161 tex_couple_nodes(ls, n);
4162 break;
4163 } else {
4164 n = node_prev(n);
4165 }
4166 }
4167 if (! n && normalize_line_mode_par) {
4168
4169 tex_normal_warning("tex", "left parfill skip is gone");
4170 }
4171 if (first_line && node_next(properties->parfill_right_skip) == properties->parinit_right_skip) {
4172 halfword p = node_prev(properties->parfill_right_skip);
4173 halfword n = node_next(properties->parinit_right_skip);
4174 tex_couple_nodes(p, properties->parinit_right_skip);
4175 tex_couple_nodes(properties->parfill_right_skip, n);
4176 tex_couple_nodes(properties->parinit_right_skip, properties->parfill_right_skip);
4177 }
4178 }
4179
4180 lmt_packaging_state.post_adjust_tail = post_adjust_head;
4181 lmt_packaging_state.pre_adjust_tail = pre_adjust_head;
4182 lmt_packaging_state.post_migrate_tail = post_migrate_head;
4183 lmt_packaging_state.pre_migrate_tail = pre_migrate_head;
4184
4185 if (normalize_line_mode_permitted(normalize_line_mode_par, flatten_discretionaries_mode)) {
4186 int count = 0;
4187 q = tex_flatten_discretionaries(q, &count, 0);
4188 cur_disc = null;
4189 if (properties->tracing_paragraphs > 1) {
4190 tex_begin_diagnostic();
4191 tex_print_format("[linebreak: flatten, line %i, count %i]", cur_line, count);
4192 tex_end_diagnostic();
4193 }
4194 }
4195
4196 shaping = 0;
4197 if (normalize_line_mode_permitted(normalize_line_mode_par, normalize_line_mode)) {
4198 halfword head = q;
4199 halfword tail = rs ? rs : head;
4200 halfword lefthang = 0;
4201 halfword righthang = 0;
4202
4203 while (node_next(tail)) {
4204 tail = node_next(tail);
4205 }
4206 if (properties->par_shape) {
4207 int n = specification_count(properties->par_shape);
4208 if (n > 0) {
4209 if (specification_repeat(properties->par_shape)) {
4210 n = cur_line;
4211 } else {
4212 n = cur_line > n ? n : cur_line;
4213 }
4214 lefthang = tex_get_specification_indent(properties->par_shape, n);
4215 righthang = properties->hsize - lefthang - tex_get_specification_width(properties->par_shape, n);
4216
4217 }
4218 } else if (properties->hang_after) {
4219 if (properties->hang_after > 0 && cur_line > properties->hang_after) {
4220 if (properties->hang_indent < 0) {
4221 righthang = -properties->hang_indent;
4222 }
4223 if (properties->hang_indent > 0) {
4224 lefthang = properties->hang_indent;
4225 }
4226 } else if (properties->hang_after < 0 && cur_line <= -properties->hang_after) {
4227 if (properties->hang_indent < 0) {
4228 righthang = -properties->hang_indent;
4229 }
4230 if (properties->hang_indent > 0) {
4231 lefthang = properties->hang_indent;
4232 }
4233 }
4234 }
4235 shaping = (lefthang || righthang);
4236 lmt_linebreak_state.just_box = tex_hpack(head, cur_width, properties->adjust_spacing ? packing_linebreak : packing_exactly, (singleword) properties->paragraph_dir, holding_none_option, box_limit_line);
4237
4238 if (node_type(tail) != glue_node || node_subtype(tail) != right_skip_glue) {
4239 halfword rs = tex_new_glue_node((properties->right_skip ? properties->right_skip : zero_glue), right_skip_glue);
4240 tex_attach_attribute_list_copy(rs, tail);
4241 tex_try_couple_nodes(rs, node_next(q));
4242 tex_couple_nodes(tail, rs);
4243 tail = rs;
4244 }
4245 {
4246 halfword lh = tex_new_glue_node(zero_glue, left_hang_skip_glue);
4247 halfword rh = tex_new_glue_node(zero_glue, right_hang_skip_glue);
4248 glue_amount(lh) = lefthang;
4249 glue_amount(rh) = righthang;
4250 tex_attach_attribute_list_copy(lh, head);
4251 tex_attach_attribute_list_copy(rh, tail);
4252 tex_try_couple_nodes(lh, head);
4253 tex_try_couple_nodes(tail, rh);
4254 head = lh;
4255 tail = rh;
4256 }
4257
4263 if (normalize_line_mode_permitted(normalize_line_mode_par, clip_width_mode)) {
4264 if (lmt_packaging_state.last_overshoot) {
4265 halfword g = tex_new_glue_node(zero_glue, correction_skip_glue);
4266 glue_amount(g) = -lmt_packaging_state.last_overshoot;
4267 tex_attach_attribute_list_copy(g, rs);
4268 tex_try_couple_nodes(node_prev(rs), g);
4269 tex_try_couple_nodes(g, rs);
4270 }
4271 box_width(lmt_linebreak_state.just_box) = properties->hsize;
4272 }
4273 box_list(lmt_linebreak_state.just_box) = head;
4274 q = head;
4275
4276 if (leftbox || rightbox || middlebox) {
4277 halfword linebox = lmt_linebreak_state.just_box;
4278 lmt_local_box_callback(
4279 linebox, leftbox, rightbox, middlebox, cur_line,
4280 tex_effective_glue(linebox, properties->left_skip),
4281 tex_effective_glue(linebox, properties->right_skip),
4282 lefthang, righthang, cur_indent,
4283 (first_line && properties->parinit_left_skip) ? tex_effective_glue(linebox, properties->parinit_left_skip) : null,
4284 (first_line && properties->parinit_right_skip) ? tex_effective_glue(linebox, properties->parinit_right_skip) : null,
4285 (last_line && properties->parfill_left_skip) ? tex_effective_glue(linebox, properties->parfill_left_skip) : null,
4286 (last_line && properties->parfill_right_skip) ? tex_effective_glue(linebox, properties->parfill_right_skip) : null,
4287 lmt_packaging_state.last_overshoot
4288 );
4289 }
4290 } else {
4291
4292 lmt_linebreak_state.just_box = tex_hpack(q, cur_width, properties->adjust_spacing ? packing_linebreak : packing_exactly, (singleword) properties->paragraph_dir, holding_none_option, box_limit_line);
4293
4294 box_shift_amount(lmt_linebreak_state.just_box) = cur_indent;
4295 }
4296
4297 node_subtype(lmt_linebreak_state.just_box) = line_list;
4298 if (callback_id) {
4299 tex_aux_line_show_break_node(callback_id);
4300 }
4301
4302 if (node_next(contribute_head)) {
4303 if (! lmt_page_builder_state.output_active) {
4304 lmt_append_line_filter_callback(pre_box_append_line_context, 0);
4305 }
4306 }
4307
4308 if (pre_adjust_head != lmt_packaging_state.pre_adjust_tail) {
4309 tex_inject_adjust_list(pre_adjust_head, 1, lmt_linebreak_state.just_box, properties);
4310 }
4311 lmt_packaging_state.pre_adjust_tail = null;
4312
4313 if (pre_migrate_head != lmt_packaging_state.pre_migrate_tail) {
4314 tex_append_list(pre_migrate_head, lmt_packaging_state.pre_migrate_tail);
4315 if (! lmt_page_builder_state.output_active) {
4316 lmt_append_line_filter_callback(pre_migrate_append_line_context, 0);
4317 }
4318 }
4319 lmt_packaging_state.pre_migrate_tail = null;
4320 if (cur_line == 1 && lmt_linebreak_state.best_line == 2 && properties->single_line_penalty) {
4321
4322 halfword r = tex_new_penalty_node(properties->single_line_penalty, single_line_penalty_subtype);
4323
4324 tex_couple_nodes(cur_list.tail, r);
4325 cur_list.tail = r;
4326 }
4327
4328 tex_append_to_vlist(lmt_linebreak_state.just_box, lua_key_index(post_linebreak), properties);
4329 if (! lmt_page_builder_state.output_active) {
4330
4331 lmt_append_line_filter_callback(box_append_line_context, 0);
4332 }
4333
4334 if (post_migrate_head != lmt_packaging_state.post_migrate_tail) {
4335 tex_append_list(post_migrate_head, lmt_packaging_state.post_migrate_tail);
4336 if (! lmt_page_builder_state.output_active) {
4337 lmt_append_line_filter_callback(post_migrate_append_line_context, 0);
4338 }
4339 }
4340 lmt_packaging_state.post_migrate_tail = null;
4341
4342 if (post_adjust_head != lmt_packaging_state.post_adjust_tail) {
4343 tex_inject_adjust_list(post_adjust_head, 1, null, properties);
4344 }
4345 lmt_packaging_state.post_adjust_tail = null;
4346
4355 if (cur_line + 1 != lmt_linebreak_state.best_line) {
4356
4360 halfword pen = 0;
4361 halfword spm = properties->shaping_penalties_mode;
4362 halfword option = 0;
4363 if (! spm) {
4364 shaping = 0;
4365 }
4366 if (tracing_penalties_par > 0) {
4367 tex_begin_diagnostic();
4368 tex_print_format("[linebreak: penalty, line %i, best line %i, prevgraf %i, mode %x (i=%i c=%i w=%i b=%i)]",
4369 cur_line, lmt_linebreak_state.best_line, cur_list.prev_graf, spm,
4370 is_shaping_penalties_mode(spm, inter_line_penalty_shaping),
4371 is_shaping_penalties_mode(spm, club_penalty_shaping),
4372 is_shaping_penalties_mode(spm, widow_penalty_shaping),
4373 is_shaping_penalties_mode(spm, broken_penalty_shaping)
4374 );
4375 tex_end_diagnostic();
4376 }
4377 if (! (shaping && is_shaping_penalties_mode(spm, inter_line_penalty_shaping))) {
4378 halfword p;
4379 q = properties->inter_line_penalties;
4380 if (q) {
4381 r = cur_line;
4382 if (r > specification_count(q)) {
4383 r = specification_count(q);
4384 } else if (r < 1) {
4385 r = 1;
4386 }
4387 p = tex_get_specification_penalty(q, r);
4388 } else if (passive_pen_inter(cur_p)) {
4389 p = passive_pen_inter(cur_p);
4390 } else {
4391 p = properties->inter_line_penalty;
4392 }
4393 if (p) {
4394 pen += p;
4395 tex_aux_trace_penalty("interline", cur_line, r, p, pen);
4396 }
4397 }
4398 if (! (shaping && is_shaping_penalties_mode(spm, club_penalty_shaping))) {
4399 halfword p;
4400 q = properties->club_penalties;
4401 if (q) {
4402
4403 r = cur_line - cur_list.prev_graf;
4404 if (r > specification_count(q)) {
4405 r = specification_count(q);
4406 } else if (r < 1) {
4407 r = 1;
4408 }
4409 p = tex_get_specification_penalty(q, r);
4410 } else if (cur_line == cur_list.prev_graf + 1) {
4411
4412 p = properties->club_penalty;
4413 } else {
4414 p = 0;
4415 }
4416 if (p) {
4417 pen += p;
4418 tex_aux_trace_penalty("club", cur_line, r, p, pen);
4419 if (pen >= infinite_penalty) {
4420 option = penalty_option_clubbed;
4421 }
4422 }
4423 }
4424 if (! (shaping && is_shaping_penalties_mode(spm, widow_penalty_shaping))) {
4425 halfword p;
4426 q = properties->display_math ? properties->display_widow_penalties : properties->widow_penalties;
4427 if (q) {
4428 r = lmt_linebreak_state.best_line - cur_line - 1;
4429 if (r > specification_count(q)) {
4430 r = specification_count(q);
4431 } else if (r < 1) {
4432 r = 1;
4433 }
4434 p = tex_get_specification_penalty(q, r);
4435 } else if (cur_line + 2 == lmt_linebreak_state.best_line) {
4436 p = properties->display_math ? properties->display_widow_penalty : properties->widow_penalty;
4437 } else {
4438 p = 0;
4439 }
4440 if (p) {
4441 pen += p;
4442 tex_aux_trace_penalty("widow", cur_line, r, p, pen);
4443 if (pen >= infinite_penalty) {
4444 option = penalty_option_widowed;
4445 }
4446 }
4447 }
4448 if (disc_break && ! (shaping && is_shaping_penalties_mode(spm, broken_penalty_shaping))) {
4449 halfword p;
4450 if (passive_pen_broken(cur_p) != 0) {
4451 p = passive_pen_broken(cur_p);
4452 } else {
4453 p = properties->broken_penalty;
4454 }
4455 if (p) {
4456 pen += p;
4457 tex_aux_trace_penalty("broken", cur_line, 0, p, pen);
4458 }
4459 }
4460 if (shaping && ! pen) {
4461 pen = properties->shaping_penalty;
4462 if (pen) {
4463 tex_aux_trace_penalty("shaping", cur_line, 0, pen, pen);
4464 }
4465 }
4466 if (pen) {
4467 r = tex_new_penalty_node(pen, linebreak_penalty_subtype);
4468 tex_add_penalty_option(r, option);
4469 tex_couple_nodes(cur_list.tail, r);
4470 cur_list.tail = r;
4471 }
4472 }
4473
4478 ++cur_line;
4479 cur_p = passive_next_break(cur_p);
4480 if (cur_p && ! post_disc_break) {
4481
4489 r = temp_head;
4490
4500
4501 while (1) {
4502 q = node_next(r);
4503 if (node_type(q) == math_node) {
4504 if (node_subtype(q) == begin_inline_math) {
4505
4506 break;
4507 }
4508
4509 math_surround(q) = 0 ;
4510 tex_reset_math_glue_to_zero(q);
4511
4512 }
4513 if (q == passive_cur_break(cur_p)) {
4514 break;
4515 } else if (node_type(q) == glyph_node) {
4516 break;
4517 } else if (node_type(q) == glue_node && (node_subtype(q) == par_fill_left_skip_glue || node_subtype(q) == par_init_left_skip_glue)) {
4518
4519 break;
4520 } else if (node_type(q) == par_node && node_subtype(q) == local_box_par_subtype) {
4521
4522 break;
4523 } else if (non_discardable(q)) {
4524 break;
4525 } else if (node_type(q) == kern_node && ! (node_subtype(q) == explicit_kern_subtype || node_subtype(q) == italic_kern_subtype)) {
4526 break;
4527 }
4528 r = q;
4529 }
4530 if (r != temp_head) {
4531 node_next(r) = null;
4532 tex_flush_node_list(node_next(temp_head));
4533 tex_try_couple_nodes(temp_head, q);
4534 }
4535 }
4536 if (cur_disc) {
4537 tex_try_couple_nodes(node_prev(cur_disc),node_next(cur_disc));
4538 tex_flush_node(cur_disc);
4539 }
4540
4541 } while (cur_p);
4542 if ((cur_line != lmt_linebreak_state.best_line) || (node_next(temp_head))) {
4543 tex_confusion("line breaking");
4544 }
4545
4546 cur_list.prev_graf = lmt_linebreak_state.best_line - 1;
4547 cur_list.direction_stack = lmt_linebreak_state.dir_ptr;
4548 lmt_linebreak_state.dir_ptr = null;
4549}
4550
4551halfword tex_wipe_margin_kerns(halfword head)
4552{
4553
4554 halfword tail = head;
4555 while (1) {
4556 halfword next = node_next(tail);
4557 if (next) {
4558 if (node_type(next) == kern_node && (node_subtype(next) == left_margin_kern_subtype || node_subtype(next) == right_margin_kern_subtype)) {
4559 tex_try_couple_nodes(tail, node_next(next));
4560 tex_flush_node(next);
4561 } else {
4562 tail = next;
4563 }
4564 } else {
4565 return tail;
4566 }
4567 }
4568} |