diff options
Diffstat (limited to 'source/luametatex')
25 files changed, 506 insertions, 319 deletions
diff --git a/source/luametatex/source/lua/lmtfontlib.c b/source/luametatex/source/lua/lmtfontlib.c index f743f960e..042772b32 100644 --- a/source/luametatex/source/lua/lmtfontlib.c +++ b/source/luametatex/source/lua/lmtfontlib.c @@ -263,7 +263,7 @@ static void fontlib_aux_font_char_from_lua(lua_State *L, halfword f, int i, int set_charinfo_depth(co, target); set_numeric_field_by_index(target, italic, 0); set_charinfo_italic(co, target); - set_numeric_field_by_index(target, expansion, 1000); + set_numeric_field_by_index(target, expansion, scaling_factor); set_charinfo_expansion(co, target); set_numeric_field_by_index(target, compression, target); set_charinfo_compression(co, target); @@ -631,15 +631,15 @@ static int lmt_font_from_lua(lua_State *L, int f) if (fstep > 0) { int fstretch = 0; int fshrink = 0; - if (fstep > 100) { - fstep = 100; + if (fstep > max_font_adjust_step) { + fstep = max_font_adjust_step; } set_numeric_field_by_index(fshrink, shrink, 0); set_numeric_field_by_index(fstretch, stretch, 0); if (fshrink < 0) { fshrink = 0; - } else if (fshrink > 500) { - fshrink = 500; + } else if (fshrink > max_font_adjust_shrink_factor) { + fshrink = max_font_adjust_shrink_factor; } fshrink -= (fshrink % fstep); if (fshrink < 0) { @@ -647,8 +647,8 @@ static int lmt_font_from_lua(lua_State *L, int f) } if (fstretch < 0) { fstretch = 0; - } else if (fstretch > 1000) { - fstretch = 1000; + } else if (fstretch > max_font_adjust_stretch_factor) { + fstretch = max_font_adjust_stretch_factor; } fstretch -= (fstretch % fstep); if (fstretch < 0) { diff --git a/source/luametatex/source/lua/lmtnodelib.c b/source/luametatex/source/lua/lmtnodelib.c index 66cf528fc..531d6d857 100644 --- a/source/luametatex/source/lua/lmtnodelib.c +++ b/source/luametatex/source/lua/lmtnodelib.c @@ -1704,19 +1704,19 @@ static int nodelib_direct_setscales(lua_State *L) if (lua_type(L, 2) == LUA_TNUMBER) { glyph_scale(n) = (halfword) lmt_roundnumber(L, 2); if (! glyph_scale(n)) { - glyph_scale(n) = 1000; + glyph_scale(n) = scaling_factor; } } if (lua_type(L, 3) == LUA_TNUMBER) { glyph_x_scale(n) = (halfword) lmt_roundnumber(L, 3); if (! glyph_x_scale(n)) { - glyph_x_scale(n) = 1000; + glyph_x_scale(n) = scaling_factor; } } if (lua_type(L, 4) == LUA_TNUMBER) { glyph_y_scale(n) = (halfword) lmt_roundnumber(L, 4); if (! glyph_y_scale(n)) { - glyph_y_scale(n) = 1000; + glyph_y_scale(n) = scaling_factor; } } } @@ -7134,17 +7134,17 @@ static int nodelib_common_setfield(lua_State *L, int direct, halfword n) } else if (lua_key_eq(s, scale)) { glyph_scale(n) = (halfword) lmt_roundnumber(L, 3); if (! glyph_scale(n)) { - glyph_scale(n) = 1000; + glyph_scale(n) = scaling_factor; } } else if (lua_key_eq(s, xscale)) { glyph_x_scale(n) = (halfword) lmt_roundnumber(L, 3); if (! glyph_x_scale(n)) { - glyph_x_scale(n) = 1000; + glyph_x_scale(n) = scaling_factor; } } else if (lua_key_eq(s, yscale)) { glyph_y_scale(n) = (halfword) lmt_roundnumber(L, 3); if (! glyph_y_scale(n)) { - glyph_y_scale(n) = 1000; + glyph_y_scale(n) = scaling_factor; } } else if (lua_key_eq(s, data)) { glyph_data(n) = lmt_opthalfword(L, 3, unused_attribute_value); diff --git a/source/luametatex/source/lua/lmtstatuslib.c b/source/luametatex/source/lua/lmtstatuslib.c index 921832d8b..38e81c1c4 100644 --- a/source/luametatex/source/lua/lmtstatuslib.c +++ b/source/luametatex/source/lua/lmtstatuslib.c @@ -251,113 +251,121 @@ static int statslib_getconstants(lua_State *L) { lua_createtable(L, 0, 100); - lua_set_integer_by_key(L, "no_catcode_table", no_catcode_table_preset); - lua_set_integer_by_key(L, "default_catcode_table", default_catcode_table_preset); - - lua_set_cardinal_by_key(L,"max_cardinal", max_cardinal); - lua_set_cardinal_by_key(L,"min_cardinal", min_cardinal); - lua_set_integer_by_key(L, "max_integer", max_integer); - lua_set_integer_by_key(L, "min_integer", min_integer); - lua_set_integer_by_key(L, "max_dimen", max_dimen); - lua_set_integer_by_key(L, "min_dimen", min_dimen); - lua_set_integer_by_key(L, "min_data_value", min_data_value); - lua_set_integer_by_key(L, "max_data_value", max_data_value); - lua_set_integer_by_key(L, "max_half_value", max_half_value); - - lua_set_integer_by_key(L, "max_limited_scale", max_limited_scale); - - lua_set_integer_by_key(L, "one_bp", one_bp); - - lua_set_integer_by_key(L, "infinity", max_infinity); - lua_set_integer_by_key(L, "min_infinity", min_infinity); - lua_set_integer_by_key(L, "awful_bad", awful_bad); - lua_set_integer_by_key(L, "infinite_bad", infinite_bad); - lua_set_integer_by_key(L, "infinite_penalty", infinite_penalty); - lua_set_integer_by_key(L, "eject_penalty", eject_penalty); - lua_set_integer_by_key(L, "deplorable", deplorable); - lua_set_integer_by_key(L, "large_width_excess", large_width_excess); - lua_set_integer_by_key(L, "small_stretchability", small_stretchability); - lua_set_integer_by_key(L, "decent_criterion", decent_criterion); - lua_set_integer_by_key(L, "loose_criterion", loose_criterion); - - lua_set_integer_by_key(L, "default_rule", default_rule); - lua_set_integer_by_key(L, "ignore_depth", ignore_depth); - - lua_set_integer_by_key(L, "min_quarterword", min_quarterword); - lua_set_integer_by_key(L, "max_quarterword", max_quarterword); - - lua_set_integer_by_key(L, "min_halfword", min_halfword); - lua_set_integer_by_key(L, "max_halfword", max_halfword); - - lua_set_integer_by_key(L, "null_flag", null_flag); - lua_set_integer_by_key(L, "zero_glue", zero_glue); - lua_set_integer_by_key(L, "unity", unity); - lua_set_integer_by_key(L, "two", two); - lua_set_integer_by_key(L, "null", null); - lua_set_integer_by_key(L, "null_font", null_font); - - lua_set_integer_by_key(L, "unused_attribute_value", unused_attribute_value); - lua_set_integer_by_key(L, "unused_state_value", unused_state_value); - lua_set_integer_by_key(L, "unused_script_value", unused_script_value); - - lua_set_integer_by_key(L, "preset_rule_thickness", preset_rule_thickness); - lua_set_integer_by_key(L, "running_rule", null_flag); - - lua_set_integer_by_key(L, "max_char_code", max_char_code); - lua_set_integer_by_key(L, "min_space_factor", min_space_factor); - lua_set_integer_by_key(L, "max_space_factor", max_space_factor); - lua_set_integer_by_key(L, "default_space_factor", default_space_factor); - lua_set_integer_by_key(L, "default_tolerance", default_tolerance); - lua_set_integer_by_key(L, "default_hangafter", default_hangafter); - lua_set_integer_by_key(L, "default_deadcycles", default_deadcycles); - lua_set_integer_by_key(L, "default_pre_display_gap", default_pre_display_gap); - lua_set_integer_by_key(L, "default_eqno_gap_step", default_eqno_gap_step); - - lua_set_integer_by_key(L, "default_output_box", default_output_box); - - lua_set_integer_by_key(L, "max_n_of_fonts", max_n_of_fonts); - lua_set_integer_by_key(L, "max_n_of_bytecodes", max_n_of_bytecodes); - lua_set_integer_by_key(L, "max_n_of_math_families", max_n_of_math_families); - lua_set_integer_by_key(L, "max_n_of_languages", max_n_of_languages); - lua_set_integer_by_key(L, "max_n_of_catcode_tables", max_n_of_catcode_tables); - /* lua_set_integer_by_key(L, "max_n_of_hjcode_tables", max_n_of_hjcode_tables); */ /* meaningless */ - lua_set_integer_by_key(L, "max_n_of_marks", max_n_of_marks); - - lua_set_integer_by_key(L, "max_character_code", max_character_code); - lua_set_integer_by_key(L, "max_mark_index", max_mark_index); - - lua_set_integer_by_key(L, "max_toks_register_index", max_toks_register_index); - lua_set_integer_by_key(L, "max_box_register_index", max_box_register_index); - lua_set_integer_by_key(L, "max_int_register_index", max_int_register_index); - lua_set_integer_by_key(L, "max_float_register_index", max_posit_register_index); - lua_set_integer_by_key(L, "max_dimen_register_index", max_dimen_register_index); - lua_set_integer_by_key(L, "max_attribute_register_index", max_attribute_register_index); - lua_set_integer_by_key(L, "max_glue_register_index", max_glue_register_index); - lua_set_integer_by_key(L, "max_mu_glue_register_index", max_mu_glue_register_index); - - lua_set_integer_by_key(L, "max_bytecode_index", max_bytecode_index); - lua_set_integer_by_key(L, "max_math_family_index", max_math_family_index); - lua_set_integer_by_key(L, "max_math_class_code", max_math_class_code); - lua_set_integer_by_key(L, "max_function_reference", max_function_reference); - lua_set_integer_by_key(L, "max_category_code", max_category_code); - - lua_set_integer_by_key(L, "max_newline_character", max_newline_character); - - lua_set_integer_by_key(L, "max_size_of_word", max_size_of_word); - - lua_set_integer_by_key(L, "tex_hash_size", hash_size); - lua_set_integer_by_key(L, "tex_hash_prime", hash_prime); - lua_set_integer_by_key(L, "tex_eqtb_size", eqtb_size); - - lua_set_integer_by_key(L, "math_begin_class", math_begin_class); - lua_set_integer_by_key(L, "math_end_class", math_end_class); - lua_set_integer_by_key(L, "unused_math_family", unused_math_family); - lua_set_integer_by_key(L, "unused_math_style", unused_math_style); - lua_set_integer_by_key(L, "assumed_math_control", assumed_math_control); - - lua_set_integer_by_key(L, "undefined_math_parameter", undefined_math_parameter); - - lua_set_integer_by_key(L, "max_calculated_badness", max_calculated_badness); + lua_set_integer_by_key(L, "no_catcode_table", no_catcode_table_preset); + lua_set_integer_by_key(L, "default_catcode_table", default_catcode_table_preset); + + lua_set_cardinal_by_key(L,"max_cardinal", max_cardinal); + lua_set_cardinal_by_key(L,"min_cardinal", min_cardinal); + lua_set_integer_by_key(L, "max_integer", max_integer); + lua_set_integer_by_key(L, "min_integer", min_integer); + lua_set_integer_by_key(L, "max_dimen", max_dimen); + lua_set_integer_by_key(L, "min_dimen", min_dimen); + lua_set_integer_by_key(L, "min_data_value", min_data_value); + lua_set_integer_by_key(L, "max_data_value", max_data_value); + lua_set_integer_by_key(L, "max_half_value", max_half_value); + + lua_set_integer_by_key(L, "max_limited_scale", max_limited_scale); + + lua_set_integer_by_key(L, "one_bp", one_bp); + + lua_set_integer_by_key(L, "infinity", max_infinity); + lua_set_integer_by_key(L, "min_infinity", min_infinity); + lua_set_integer_by_key(L, "awful_bad", awful_bad); + lua_set_integer_by_key(L, "infinite_bad", infinite_bad); + lua_set_integer_by_key(L, "infinite_penalty", infinite_penalty); + lua_set_integer_by_key(L, "eject_penalty", eject_penalty); + lua_set_integer_by_key(L, "deplorable", deplorable); + lua_set_integer_by_key(L, "large_width_excess", large_width_excess); + lua_set_integer_by_key(L, "small_stretchability", small_stretchability); + lua_set_integer_by_key(L, "decent_criterion", decent_criterion); + lua_set_integer_by_key(L, "loose_criterion", loose_criterion); + + lua_set_integer_by_key(L, "default_rule", default_rule); + lua_set_integer_by_key(L, "ignore_depth", ignore_depth); + + lua_set_integer_by_key(L, "min_quarterword", min_quarterword); + lua_set_integer_by_key(L, "max_quarterword", max_quarterword); + + lua_set_integer_by_key(L, "min_halfword", min_halfword); + lua_set_integer_by_key(L, "max_halfword", max_halfword); + + lua_set_integer_by_key(L, "null_flag", null_flag); + lua_set_integer_by_key(L, "zero_glue", zero_glue); + lua_set_integer_by_key(L, "unity", unity); + lua_set_integer_by_key(L, "two", two); + lua_set_integer_by_key(L, "null", null); + lua_set_integer_by_key(L, "null_font", null_font); + + lua_set_integer_by_key(L, "unused_attribute_value", unused_attribute_value); + lua_set_integer_by_key(L, "unused_state_value", unused_state_value); + lua_set_integer_by_key(L, "unused_script_value", unused_script_value); + + lua_set_integer_by_key(L, "preset_rule_thickness", preset_rule_thickness); + lua_set_integer_by_key(L, "running_rule", null_flag); + + lua_set_integer_by_key(L, "max_char_code", max_char_code); + lua_set_integer_by_key(L, "min_space_factor", min_space_factor); + lua_set_integer_by_key(L, "max_space_factor", max_space_factor); + lua_set_integer_by_key(L, "default_space_factor", default_space_factor); + lua_set_integer_by_key(L, "default_tolerance", default_tolerance); + lua_set_integer_by_key(L, "default_hangafter", default_hangafter); + lua_set_integer_by_key(L, "default_deadcycles", default_deadcycles); + lua_set_integer_by_key(L, "default_pre_display_gap", default_pre_display_gap); + lua_set_integer_by_key(L, "default_eqno_gap_step", default_eqno_gap_step); + + lua_set_integer_by_key(L, "default_output_box", default_output_box); + + lua_set_integer_by_key(L, "max_n_of_fonts", max_n_of_fonts); + lua_set_integer_by_key(L, "max_n_of_bytecodes", max_n_of_bytecodes); + lua_set_integer_by_key(L, "max_n_of_math_families", max_n_of_math_families); + lua_set_integer_by_key(L, "max_n_of_languages", max_n_of_languages); + lua_set_integer_by_key(L, "max_n_of_catcode_tables", max_n_of_catcode_tables); + /* lua_set_integer_by_key(L, "max_n_of_hjcode_tables", max_n_of_hjcode_tables); */ /* meaningless */ + lua_set_integer_by_key(L, "max_n_of_marks", max_n_of_marks); + + lua_set_integer_by_key(L, "max_character_code", max_character_code); + lua_set_integer_by_key(L, "max_mark_index", max_mark_index); + + lua_set_integer_by_key(L, "max_toks_register_index", max_toks_register_index); + lua_set_integer_by_key(L, "max_box_register_index", max_box_register_index); + lua_set_integer_by_key(L, "max_int_register_index", max_int_register_index); + lua_set_integer_by_key(L, "max_float_register_index", max_posit_register_index); + lua_set_integer_by_key(L, "max_dimen_register_index", max_dimen_register_index); + lua_set_integer_by_key(L, "max_attribute_register_index", max_attribute_register_index); + lua_set_integer_by_key(L, "max_glue_register_index", max_glue_register_index); + lua_set_integer_by_key(L, "max_mu_glue_register_index", max_mu_glue_register_index); + + lua_set_integer_by_key(L, "max_bytecode_index", max_bytecode_index); + lua_set_integer_by_key(L, "max_math_family_index", max_math_family_index); + lua_set_integer_by_key(L, "max_math_class_code", max_math_class_code); + lua_set_integer_by_key(L, "max_function_reference", max_function_reference); + lua_set_integer_by_key(L, "max_category_code", max_category_code); + + lua_set_integer_by_key(L, "max_newline_character", max_newline_character); + + lua_set_integer_by_key(L, "max_size_of_word", max_size_of_word); + + lua_set_integer_by_key(L, "tex_hash_size", hash_size); + lua_set_integer_by_key(L, "tex_hash_prime", hash_prime); + lua_set_integer_by_key(L, "tex_eqtb_size", eqtb_size); + + lua_set_integer_by_key(L, "math_begin_class", math_begin_class); + lua_set_integer_by_key(L, "math_end_class", math_end_class); + lua_set_integer_by_key(L, "unused_math_family", unused_math_family); + lua_set_integer_by_key(L, "unused_math_style", unused_math_style); + lua_set_integer_by_key(L, "assumed_math_control", assumed_math_control); + + lua_set_integer_by_key(L, "undefined_math_parameter", undefined_math_parameter); + + lua_set_integer_by_key(L, "max_calculated_badness", max_calculated_badness); + + lua_set_integer_by_key(L, "max_math_scaling_factor", max_math_scaling_factor); + lua_set_integer_by_key(L, "math_default_penalty", math_default_penalty); + + lua_set_integer_by_key(L, "max_font_adjust_step", max_font_adjust_step); + lua_set_integer_by_key(L, "max_font_adjust_stretch_factor", max_font_adjust_stretch_factor); + lua_set_integer_by_key(L, "max_font_adjust_shrink_factor", max_font_adjust_shrink_factor); + return 1; } diff --git a/source/luametatex/source/lua/lmttexlib.c b/source/luametatex/source/lua/lmttexlib.c index 4f2ecbb5c..603454bfe 100644 --- a/source/luametatex/source/lua/lmttexlib.c +++ b/source/luametatex/source/lua/lmttexlib.c @@ -1077,21 +1077,21 @@ static const char *texlib_aux_scan_dimen_part(lua_State * L, const char *ss, int goto ATTACH_FRACTION; } SPECIAL: - result = tex_nx_plus_y(result, special, tex_xn_over_d_r(special, fraction, 0200000, &remainder)); + result = tex_nx_plus_y(result, special, tex_xn_over_d_r(special, fraction, 0x10000, &remainder)); goto DONE; CONVERSION: result = tex_xn_over_d_r(result, numerator, denominator, &remainder); - fraction = (numerator * fraction + 0200000 * remainder) / denominator; - result = result + (fraction / 0200000); - fraction = fraction % 0200000; + fraction = (numerator * fraction + 0x10000 * remainder) / denominator; + result = result + (fraction / 0x10000); + fraction = fraction % 0x10000; ATTACH_FRACTION: - if (result >= 040000) { + if (result >= 0x4000) { lmt_scanner_state.arithmic_error = 1; } else { - result = result * 65536 + fraction; + result = result * 0x10000 + fraction; } DONE: - if (lmt_scanner_state.arithmic_error || (abs(result) >= 010000000000)) { + if (lmt_scanner_state.arithmic_error || (abs(result) >= 0x40000000)) { result = max_dimen; luaL_error(L, "dimension too large"); } @@ -3855,15 +3855,15 @@ static int texlib_preparelinebreak(lua_State *L) halfword parinit_right_skip_glue = null; halfword parfill_left_skip_glue = null; halfword parfill_right_skip_glue = null; - halfword final_penalty = null; - tex_line_break_prepare(par, &tail, &parinit_left_skip_glue, &parinit_right_skip_glue, &parfill_left_skip_glue, &parfill_right_skip_glue, &final_penalty); + halfword final_line_penalty = null; + 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); lmt_push_directornode(L, par, direct); lmt_push_directornode(L, tail, direct); lmt_push_directornode(L, parinit_left_skip_glue, direct); lmt_push_directornode(L, parinit_right_skip_glue, direct); lmt_push_directornode(L, parfill_left_skip_glue , direct); lmt_push_directornode(L, parfill_right_skip_glue, direct); - /* lmt_push_directornode(L, final_penalty, direct); */ /*tex Not that relevant to know. */ + /* lmt_push_directornode(L, final_line_penalty, direct); */ /*tex Not that relevant to know. */ return 6; } } @@ -4021,7 +4021,7 @@ static int texlib_linebreak(lua_State *L) get_penalties_par(properties.orphan_penalties, orphanpenalties, tex_get_par_par(par, par_orphan_penalties_code), orphan_penalties_code); if (! prepared) { halfword attr_template = tail; - halfword final_penalty = tex_new_penalty_node(infinite_penalty, line_penalty_subtype); + halfword final_line_penalty = tex_new_penalty_node(infinite_penalty, line_penalty_subtype); /* */ get_glue_par(properties.parfill_left_skip, parfillleftskip, tex_get_par_par(par, par_par_fill_left_skip_code)); get_glue_par(properties.parfill_right_skip, parfillrightskip, tex_get_par_par(par, par_par_fill_right_skip_code)); @@ -4030,11 +4030,11 @@ static int texlib_linebreak(lua_State *L) /* */ properties.parfill_left_skip = tex_new_glue_node(properties.parfill_left_skip, par_fill_left_skip_glue); properties.parfill_right_skip = tex_new_glue_node(properties.parfill_right_skip, par_fill_right_skip_glue); - tex_attach_attribute_list_copy(final_penalty, attr_template); + tex_attach_attribute_list_copy(final_line_penalty, attr_template); tex_attach_attribute_list_copy(properties.parfill_left_skip, attr_template); tex_attach_attribute_list_copy(properties.parfill_right_skip, attr_template); - tex_couple_nodes(tail, final_penalty); - tex_couple_nodes(final_penalty, properties.parfill_left_skip); + tex_couple_nodes(tail, final_line_penalty); + tex_couple_nodes(final_line_penalty, properties.parfill_left_skip); tex_couple_nodes(properties.parfill_left_skip, properties.parfill_right_skip); if (node_next(par)) { /* test can go, also elsewhere */ halfword n = node_next(par); @@ -5178,7 +5178,7 @@ static int texlib_getspecialmathclassvalues(lua_State *L) static int texlib_getmathclassoptionvalues(lua_State *L) { - lua_createtable(L, 2, 20); + lua_createtable(L, 2, 25); lua_set_string_by_index(L, no_pre_slack_class_option, "nopreslack"); lua_set_string_by_index(L, no_post_slack_class_option, "nopostslack"); lua_set_string_by_index(L, left_top_kern_class_option, "lefttopkern"); @@ -5206,6 +5206,9 @@ static int texlib_getmathclassoptionvalues(lua_State *L) lua_set_string_by_index(L, remove_italic_correction_class_option, "removeitaliccorrection"); lua_set_string_by_index(L, operator_italic_correction_class_option, "operatoritaliccorrection"); lua_set_string_by_index(L, short_inline_class_option, "shortinline"); + lua_set_string_by_index(L, push_nesting_class_option, "pushnesting"); + lua_set_string_by_index(L, pop_nesting_class_option, "popnesting"); + lua_set_string_by_index(L, obey_nesting_class_option, "obeynesting"); return 1; } diff --git a/source/luametatex/source/luametatex.h b/source/luametatex/source/luametatex.h index a6e9b5295..68820d24d 100644 --- a/source/luametatex/source/luametatex.h +++ b/source/luametatex/source/luametatex.h @@ -92,7 +92,7 @@ # define luametatex_version 210 # define luametatex_revision 9 # define luametatex_version_string "2.10.09" -# define luametatex_development_id 20230530 +# define luametatex_development_id 20230531 # define luametatex_name_camelcase "LuaMetaTeX" # define luametatex_name_lowercase "luametatex" diff --git a/source/luametatex/source/tex/texarithmetic.c b/source/luametatex/source/tex/texarithmetic.c index d9cf9859d..3a53985d5 100644 --- a/source/luametatex/source/tex/texarithmetic.c +++ b/source/luametatex/source/tex/texarithmetic.c @@ -196,13 +196,13 @@ scaled tex_xn_over_d_r(scaled x, int n, int d, int *remainder) } xx = (unsigned int) x; dd = (unsigned int) d; - t = ((xx % 0100000) * (unsigned int) n); - u = ((xx / 0100000) * (unsigned int) n + (t / 0100000)); - v = (u % dd) * 0100000 + (t % 0100000); - if (u / dd >= 0100000) { + t = ((xx % 0x8000) * (unsigned int) n); + u = ((xx / 0x8000) * (unsigned int) n + (t / 0x8000)); + v = (u % dd) * 0x8000 + (t % 0x8000); + if (u / dd >= 0x8000) { lmt_scanner_state.arithmic_error = 1; } else { - u = 0100000 * (u / dd) + (v / dd); + u = 0x8000 * (u / dd) + (v / dd); } if (positive) { if (remainder) { @@ -245,13 +245,13 @@ scaled tex_xn_over_d(scaled x, int n, int d) } xx = (unsigned int) x; dd = (unsigned int) d; - t = ((xx % 0100000) * (unsigned int) n); - u = ((xx / 0100000) * (unsigned int) n + (t / 0100000)); - v = (u % dd) * 0100000 + (t % 0100000); - if (u / dd >= 0100000) { + t = ((xx % 0x8000) * (unsigned int) n); + u = ((xx / 0x8000) * (unsigned int) n + (t / 0x8000)); + v = (u % dd) * 0x8000 + (t % 0x8000); + if (u / dd >= 0x8000) { lmt_scanner_state.arithmic_error = 1; } else { - u = 0100000 * (u / dd) + (v / dd); + u = 0x8000 * (u / dd) + (v / dd); } if (positive) { return (scaled) u; @@ -306,13 +306,13 @@ scaled tex_round_xn_over_d(scaled x, int n, unsigned int d) positive = ! positive; n = -n; } - t = (unsigned) ((x % 0100000) * n); - u = (unsigned) (((unsigned) (x) / 0100000) * (unsigned) n + (t / 0100000)); - v = (u % d) * 0100000 + (t % 0100000); - if (u / d >= 0100000) { + t = (unsigned) ((x % 0x8000) * n); + u = (unsigned) (((unsigned) (x) / 0x8000) * (unsigned) n + (t / 0x8000)); + v = (u % d) * 0x8000 + (t % 0x8000); + if (u / d >= 0x8000) { scanner_state.arithmic_error = 1; } else { - u = 0100000 * (u / d) + (v / d); + u = 0x8000 * (u / d) + (v / d); } v = v % d; if (2 * v >= d) { diff --git a/source/luametatex/source/tex/texbuildpage.c b/source/luametatex/source/tex/texbuildpage.c index a2d9051db..6773ed52b 100644 --- a/source/luametatex/source/tex/texbuildpage.c +++ b/source/luametatex/source/tex/texbuildpage.c @@ -600,10 +600,10 @@ void tex_build_page(void) box_height(location) = 0; } split_best_insert(location) = null; - if (multiplier == 1000) { + if (multiplier == scaling_factor) { advance = box_height(location); } else { - advance = tex_x_over_n(box_height(location), 1000) * multiplier; + advance = tex_x_over_n(box_height(location), scaling_factor) * multiplier; } advance += glue_amount(distance); update_page_goal(index, 0, advance); /*tex Here gets no height added! */ @@ -633,9 +633,9 @@ void tex_build_page(void) scaled needed = insert_total_height(current); split_last_insert(location) = current; /*tex This much room is left if we shrink the maximum. */ - if (multiplier != 1000) { + if (multiplier != scaling_factor) { /*tex This much room is needed. */ - needed = tex_x_over_n(needed, 1000) * multiplier; + needed = tex_x_over_n(needed, scaling_factor) * multiplier; } if ((needed <= 0 || needed <= delta) && (insert_total_height(current) + box_height(location) <= limit)) { update_page_goal(index, insert_total_height(current), needed); @@ -665,8 +665,8 @@ void tex_build_page(void) height = max_dimen; } else { height = page_goal - page_total - page_depth; - if (multiplier != 1000) { - height = tex_x_over_n(height, multiplier) * 1000; + if (multiplier != scaling_factor) { + height = tex_x_over_n(height, multiplier) * scaling_factor; } } if (height > limit - box_height(location)) { @@ -678,8 +678,8 @@ void tex_build_page(void) if (tracing_pages_par > 0) { tex_aux_display_insertion_split_cost(index, height, penalty); } - if (multiplier != 1000) { - lmt_packaging_state.best_height_plus_depth = tex_x_over_n(lmt_packaging_state.best_height_plus_depth, 1000) * multiplier; + if (multiplier != scaling_factor) { + lmt_packaging_state.best_height_plus_depth = tex_x_over_n(lmt_packaging_state.best_height_plus_depth, scaling_factor) * multiplier; } update_page_goal(index, lmt_packaging_state.best_height_plus_depth, lmt_packaging_state.best_height_plus_depth); node_subtype(location) = insert_split_subtype; @@ -736,7 +736,7 @@ void tex_build_page(void) } else { criterion = deplorable; } - if (lmt_page_builder_state.insert_penalties >= 10000) { + if (lmt_page_builder_state.insert_penalties >= infinite_penalty) { criterion = awful_bad; } { diff --git a/source/luametatex/source/tex/texcommands.c b/source/luametatex/source/tex/texcommands.c index 1423c80d0..ae22f9794 100644 --- a/source/luametatex/source/tex/texcommands.c +++ b/source/luametatex/source/tex/texcommands.c @@ -270,6 +270,8 @@ void tex_initialize_commands(void) tex_primitive(luatex_command, "mathendclass", internal_int_cmd, math_end_class_code, internal_int_base); tex_primitive(luatex_command, "mathleftclass", internal_int_cmd, math_left_class_code, internal_int_base); tex_primitive(luatex_command, "mathrightclass", internal_int_cmd, math_right_class_code, internal_int_base); + tex_primitive(luatex_command, "mathdisplaypenaltyfactor", internal_int_cmd, math_display_penalty_factor_code, internal_int_base); + tex_primitive(luatex_command, "mathinlinepenaltyfactor", internal_int_cmd, math_inline_penalty_factor_code, internal_int_base); tex_primitive(luatex_command, "supmarkmode", internal_int_cmd, sup_mark_mode_code, internal_int_base); tex_primitive(luatex_command, "overloadmode", internal_int_cmd, overload_mode_code, internal_int_base); tex_primitive(luatex_command, "autoparagraphmode", internal_int_cmd, auto_paragraph_mode_code, internal_int_base); @@ -347,6 +349,7 @@ void tex_initialize_commands(void) tex_primitive(luatex_command, "protrusionboundary", boundary_cmd, protrusion_boundary, 0); tex_primitive(luatex_command, "wordboundary", boundary_cmd, word_boundary, 0); tex_primitive(luatex_command, "pageboundary", boundary_cmd, page_boundary, 0); + tex_primitive(luatex_command, "mathboundary", boundary_cmd, math_boundary, 0); /* tex_primitive(luatex_command, "parboundary", boundary_cmd, par_boundary, 0); */ tex_primitive(tex_command, "penalty", penalty_cmd, normal_penalty_code, 0); diff --git a/source/luametatex/source/tex/texdumpdata.h b/source/luametatex/source/tex/texdumpdata.h index c0a55c2fe..94a153374 100644 --- a/source/luametatex/source/tex/texdumpdata.h +++ b/source/luametatex/source/tex/texdumpdata.h @@ -55,7 +55,7 @@ */ -# define luametatex_format_fingerprint 691 +# define luametatex_format_fingerprint 692 /* These end up in the string pool. */ diff --git a/source/luametatex/source/tex/texequivalents.c b/source/luametatex/source/tex/texequivalents.c index 4f8f789b7..036a4a3d5 100644 --- a/source/luametatex/source/tex/texequivalents.c +++ b/source/luametatex/source/tex/texequivalents.c @@ -1535,6 +1535,10 @@ void tex_save_for_after_group(halfword t) void tex_unsave(void) { if (end_of_group_par) { + /*tex + This is not yet always ok, and looks like we can get weird commands (in some group + ending situations)! But I need a better example of a failure. (low priority) + */ tex_begin_inserted_list(tex_get_available_token(token_val(end_local_cmd, 0))); tex_begin_token_list(end_of_group_par, end_of_group_text); if (tracing_nesting_par > 2) { diff --git a/source/luametatex/source/tex/texequivalents.h b/source/luametatex/source/tex/texequivalents.h index 384a17e06..af3d98000 100644 --- a/source/luametatex/source/tex/texequivalents.h +++ b/source/luametatex/source/tex/texequivalents.h @@ -561,6 +561,8 @@ typedef enum int_codes { math_end_class_code, math_left_class_code, math_right_class_code, + math_inline_penalty_factor_code, + math_display_penalty_factor_code, sup_mark_mode_code, par_direction_code, text_direction_code, @@ -1659,6 +1661,8 @@ typedef enum hyphenation_mode_bits { # define math_left_class_par count_parameter(math_left_class_code) # define math_right_class_par count_parameter(math_right_class_code) # define sup_mark_mode_par count_parameter(sup_mark_mode_code) +# define math_display_penalty_factor_par count_parameter(math_display_penalty_factor_code) +# define math_inline_penalty_factor_par count_parameter(math_inline_penalty_factor_code) # define glyph_data_par count_parameter(glyph_data_code) # define glyph_state_par count_parameter(glyph_state_code) diff --git a/source/luametatex/source/tex/texfont.c b/source/luametatex/source/tex/texfont.c index b274b3ae9..33445122b 100644 --- a/source/luametatex/source/tex/texfont.c +++ b/source/luametatex/source/tex/texfont.c @@ -342,7 +342,7 @@ charinfo *tex_get_charinfo(halfword f, int c) if (tglyph >= lmt_font_state.fonts[f]->chardata_size) { tex_font_malloc_charinfo(f, 256); } - lmt_font_state.fonts[f]->chardata[tglyph].expansion = 1000; + lmt_font_state.fonts[f]->chardata[tglyph].expansion = scaling_factor; sa_value.int_value = tglyph; /*tex 1 means global */ sa_set_item_4(lmt_font_state.fonts[f]->characters, c, sa_value, 1); @@ -495,7 +495,7 @@ int tex_get_math_char(halfword f, int c, int size, scaled *scale, int direction) if (scale) { *scale = tex_get_math_font_scale(f, size); if (! *scale) { - *scale = 1000; + *scale = scaling_factor; } } return c; @@ -826,18 +826,18 @@ halfword tex_checked_font_adjust(halfword adjust_spacing, halfword adjust_spacin lmt_font_state.adjust_step = adjust_spacing_step; lmt_font_state.adjust_shrink = adjust_spacing_shrink; lmt_font_state.adjust_stretch = adjust_spacing_stretch; - if (lmt_font_state.adjust_step > 100) { - lmt_font_state.adjust_step = 100; + if (lmt_font_state.adjust_step > max_font_adjust_step) { + lmt_font_state.adjust_step = max_font_adjust_step; } if (lmt_font_state.adjust_shrink < 0) { lmt_font_state.adjust_shrink = 0; - } else if (lmt_font_state.adjust_shrink > 500) { - lmt_font_state.adjust_shrink = 500; + } else if (lmt_font_state.adjust_shrink > max_font_adjust_shrink_factor) { + lmt_font_state.adjust_shrink = max_font_adjust_shrink_factor; } if (lmt_font_state.adjust_stretch < 0) { lmt_font_state.adjust_stretch = 0; - } else if (lmt_font_state.adjust_stretch > 1000) { - lmt_font_state.adjust_stretch = 1000; + } else if (lmt_font_state.adjust_stretch > max_font_adjust_stretch_factor) { + lmt_font_state.adjust_stretch = max_font_adjust_stretch_factor; } return adjust_spacing; } @@ -1651,7 +1651,7 @@ int tex_tex_def_font(int a) /*tex This runs through existing fonts. */ halfword f; /*tex Stated 'at' size, or negative of scaled magnification. */ - scaled s = -1000; + scaled s = -scaling_factor; char *fn; /*tex Here |a| determines if we define global or not. */ if (is_global(a)) { @@ -1665,7 +1665,7 @@ int tex_tex_def_font(int a) if (tex_scan_keyword("at")) { /*tex Put the positive 'at' size into |s|. */ s = tex_scan_dimen(0, 0, 0, 0, NULL); - if ((s <= 0) || (s >= 01000000000)) { + if ((s <= 0) || (s >= 0x8000000)) { tex_handle_error( normal_error_type, "Improper 'at' size (%D), replaced by 10pt", @@ -1678,14 +1678,14 @@ int tex_tex_def_font(int a) } } else if (tex_scan_keyword("scaled")) { s = tex_scan_int(0, NULL); - if ((s <= 0) || (s > 32768)) { + if ((s <= 0) || (s > 0x8000)) { tex_handle_error( normal_error_type, "Illegal magnification has been changed to 1000 (%i)", s, "The magnification ratio must be between 1 and 32768." ); - s = -1000; + s = -scaling_factor; } else { s = -s; } @@ -2021,14 +2021,14 @@ scaled tex_char_width_italic_from_glyph(halfword g) scaled tex_calculated_char_width(halfword f, halfword c, halfword ex) { scaled wd = tex_aux_char_info(f, c)->width; - return ex ? tex_round_xn_over_d(wd, 1000 + ex, 1000) : wd; + return ex ? tex_round_xn_over_d(wd, scaling_factor + ex, scaling_factor) : wd; } scaled tex_calculated_glyph_width(halfword g, halfword ex) { charinfo *ci = tex_aux_char_info(glyph_font(g), glyph_character(g)); scaled wd = tex_aux_glyph_x_scaled(g, ci->width); - return ex ? tex_round_xn_over_d(wd, 1000 + ex, 1000) : wd; + return ex ? tex_round_xn_over_d(wd, scaling_factor + ex, scaling_factor) : wd; } /* Checkers: */ @@ -2101,13 +2101,13 @@ void tex_set_font_original(halfword f, const char *s) scaled tex_get_math_font_scale(halfword f, halfword size) { - scaled scale = 1000; + scaled scale = scaling_factor; switch (size) { case 2: scale = lmt_font_state.fonts[f]->mathscales[2] ? lmt_font_state.fonts[f]->mathscales[2] : glyph_scriptscript_scale_par; break; case 1: scale = lmt_font_state.fonts[f]->mathscales[1] ? lmt_font_state.fonts[f]->mathscales[1] : glyph_script_scale_par; break; case 0: scale = lmt_font_state.fonts[f]->mathscales[0] ? lmt_font_state.fonts[f]->mathscales[0] : glyph_text_scale_par; break; } - return scale ? scale : 1000; + return scale ? scale : scaling_factor; } /*tex diff --git a/source/luametatex/source/tex/texlinebreak.c b/source/luametatex/source/tex/texlinebreak.c index 93a537ca7..48cf470eb 100644 --- a/source/luametatex/source/tex/texlinebreak.c +++ b/source/luametatex/source/tex/texlinebreak.c @@ -147,7 +147,7 @@ void tex_line_break_prepare( halfword *parinit_right_skip_glue, halfword *parfill_left_skip_glue, halfword *parfill_right_skip_glue, - halfword *final_penalty + halfword *final_line_penalty ) { /* too much testing of next */ @@ -159,7 +159,7 @@ void tex_line_break_prepare( tex_end_diagnostic(); } *tail = *tail ? *tail : tex_tail_of_node_list(par); - *final_penalty = tex_new_penalty_node(infinite_penalty, line_penalty_subtype); + *final_line_penalty = tex_new_penalty_node(infinite_penalty, line_penalty_subtype); *parfill_left_skip_glue = tex_new_glue_node(tex_get_par_par(par, par_par_fill_left_skip_code), par_fill_left_skip_glue); *parfill_right_skip_glue = tex_new_glue_node(tex_get_par_par(par, par_par_fill_right_skip_code), par_fill_right_skip_glue); *parinit_left_skip_glue = null; @@ -170,11 +170,11 @@ void tex_line_break_prepare( tex_flush_node(*tail); *tail = prev; } - tex_attach_attribute_list_copy(*final_penalty, par); + tex_attach_attribute_list_copy(*final_line_penalty, par); tex_attach_attribute_list_copy(*parfill_left_skip_glue, par); tex_attach_attribute_list_copy(*parfill_right_skip_glue, par); - tex_try_couple_nodes(*tail, *final_penalty); - tex_try_couple_nodes(*final_penalty, *parfill_left_skip_glue); + tex_try_couple_nodes(*tail, *final_line_penalty); + tex_try_couple_nodes(*final_line_penalty, *parfill_left_skip_glue); tex_try_couple_nodes(*parfill_left_skip_glue, *parfill_right_skip_glue); *tail = *parfill_right_skip_glue; if (node_next(par)) { @@ -247,8 +247,8 @@ void tex_line_break(int d, int line_break_context) halfword parinit_right_skip_glue = null; halfword parfill_left_skip_glue = null; halfword parfill_right_skip_glue = null; - halfword final_penalty = null; - tex_line_break_prepare(par, &tail, &parinit_left_skip_glue, &parinit_right_skip_glue, &parfill_left_skip_glue, &parfill_right_skip_glue, &final_penalty); + halfword final_line_penalty = null; + 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); cur_list.tail = tail; /*tex We start with a prepared list. If you mess with that the linebreak routine might not @@ -1479,9 +1479,9 @@ halfword tex_badness(scaled t, scaled s) } else { /*tex 297*297*297 == 26198073 / 100 => 261981 */ /*tex This is $t^3 / 2^{18}$, rounded to the nearest integer */ - return (t * t * t + 0400000) / 01000000; /* 0400000/01000000 == 1/2 */ + // return (t * t * t + 0400000) / 01000000; /* 0400000/01000000 == 1/2 */ // return (t * t * t + 0x20000) / 0x40000; - // return (t * t * t + 131072) / 262144; + return (t * t * t + 131072) / 262144; } } } @@ -2046,8 +2046,8 @@ static void tex_aux_try_break( } else { /*tex Compute the demerits, |d|, from |r| to |cur_p|. */ demerits = properties->line_penalty + badness; - if (abs(demerits) >= 10000) { - demerits = 100000000; + if (abs(demerits) >= infinite_bad) { + demerits = extremely_deplorable; } else { demerits = demerits * demerits; } diff --git a/source/luametatex/source/tex/texlinebreak.h b/source/luametatex/source/tex/texlinebreak.h index 850d98da0..cf551bebe 100644 --- a/source/luametatex/source/tex/texlinebreak.h +++ b/source/luametatex/source/tex/texlinebreak.h @@ -121,7 +121,7 @@ void tex_line_break_prepare ( halfword *parinit_right_skip_glue, halfword *parfill_left_skip_glue, halfword *parfill_right_skip_glue, - halfword *final_penalty + halfword *final_line_penalty ); extern void tex_line_break ( diff --git a/source/luametatex/source/tex/texmaincontrol.c b/source/luametatex/source/tex/texmaincontrol.c index c51a636b3..29b652ab7 100644 --- a/source/luametatex/source/tex/texmaincontrol.c +++ b/source/luametatex/source/tex/texmaincontrol.c @@ -429,8 +429,8 @@ static void tex_aux_run_space(void) { if (cur_list.space_factor >= 2000) { glue_amount(p) += tex_get_scaled_extra_space(cur_font); } - glue_stretch(p) = tex_xn_over_d(glue_stretch(p), cur_list.space_factor, 1000); - glue_shrink(p) = tex_xn_over_d(glue_shrink(p), 1000, cur_list.space_factor); + glue_stretch(p) = tex_xn_over_d(glue_stretch(p), cur_list.space_factor, scaling_factor); + glue_shrink(p) = tex_xn_over_d(glue_shrink(p), scaling_factor, cur_list.space_factor); } } else if (tex_glue_is_zero(space_skip_par)) { /*tex Find the glue specification for text spaces in the current font. */ @@ -1216,11 +1216,27 @@ static void tex_aux_run_math_boundary(void) { switch (cur_chr) { case user_boundary: { - halfword n = tex_new_node(boundary_node, user_boundary); + halfword n = tex_new_node(boundary_node, cur_chr); boundary_data(n) = tex_scan_int(0, NULL); tex_tail_append(n); break; } + case math_boundary: + { + halfword n = tex_new_node(boundary_node, cur_chr); + boundary_data(n) = tex_scan_int(0, NULL); + switch (boundary_data(n)) { + case 0: case 1: + /* valid */ + break; + case 2: case 3: + /* valid, penalty to add */ + boundary_reserved(n) = tex_scan_int(0, NULL); + break; + } + tex_tail_append(n); + break; + } case protrusion_boundary: case page_boundary: /*tex We just ignore the values. */ @@ -2006,17 +2022,19 @@ static void tex_aux_run_end_job(void) { if ((page_head == lmt_page_builder_state.page_tail) && (cur_list.head == cur_list.tail) && (lmt_page_builder_state.dead_cycles == 0)) { - /*tex this is the only way out */ + /*tex This is the only way out. */ lmt_main_control_state.control_state = goto_return_state; } else { - /*tex we will try to end again after ejecting residual material */ + /*tex + We will try to end again after ejecting residual material and append |\hbox to \hsize + {}\vfill\penalty-'10000000000|. + */ tex_back_input(cur_tok); tex_tail_append(tex_new_null_box_node(hlist_node, unknown_list)); box_width(cur_list.tail) = hsize_par; tex_tail_append(tex_new_glue_node(fill_glue, user_skip_glue)); /* todo: subtype, final_skip_glue? */ - tex_tail_append(tex_new_penalty_node(-010000000000, final_penalty_subtype)); /* -0x40000000 */ + tex_tail_append(tex_new_penalty_node(final_penalty, final_penalty_subtype)); lmt_page_filter_callback(end_page_context, 0); - /*tex append |\hbox to \hsize{}\vfill\penalty-'10000000000| */ tex_build_page(); } } @@ -6697,15 +6715,17 @@ void tex_initialize_variables(void) math_double_script_mode_par = -1, math_glue_mode_par = default_math_glue_mode; hyphenation_mode_par = default_hyphenation_mode; - glyph_scale_par = 1000; - glyph_x_scale_par = 1000; - glyph_y_scale_par = 1000; + glyph_scale_par = scaling_factor; + glyph_x_scale_par = scaling_factor; + glyph_y_scale_par = scaling_factor; glyph_x_offset_par = 0; glyph_y_offset_par = 0; math_begin_class_par = math_begin_class; math_end_class_par = math_end_class; math_left_class_par = unset_noad_class; math_right_class_par = unset_noad_class; + math_display_penalty_factor_par = scaling_factor; + math_inline_penalty_factor_par = scaling_factor; pre_inline_penalty_par = max_integer; post_inline_penalty_par = max_integer; pre_short_inline_penalty_par = max_integer; diff --git a/source/luametatex/source/tex/texmath.c b/source/luametatex/source/tex/texmath.c index 923ffa56e..e93714000 100644 --- a/source/luametatex/source/tex/texmath.c +++ b/source/luametatex/source/tex/texmath.c @@ -120,7 +120,7 @@ math_state_info lmt_math_state = { .last_left = 0, .last_right = 0, .last_atom = 0, - .scale = 1000, + .scale = scaling_factor, }; static int tex_aux_scan_math (halfword p, halfword style, int usetextfont, halfword toks, halfword toks_text, int nocomponent, halfword cls, halfword all); @@ -1410,8 +1410,8 @@ static void tex_aux_enter_display_math(halfword cmd) size = - max_dimen; } else { tex_line_break(1, math_display_group); - // size = tex_actual_box_width(lmt_linebreak_state.just_box, tex_x_over_n(tex_get_font_em_width(cur_font_par), 1000) * math_pre_display_gap_factor_par); - size = tex_actual_box_width(lmt_linebreak_state.just_box, scaledround((tex_get_font_em_width(cur_font_par) / 1000.0) * math_pre_display_gap_factor_par)); + // size = tex_actual_box_width(lmt_linebreak_state.just_box, tex_x_over_n(tex_get_font_em_width(cur_font_par), scaling_factor) * math_pre_display_gap_factor_par); + size = tex_actual_box_width(lmt_linebreak_state.just_box, scaledround((tex_get_font_em_width(cur_font_par) / scaling_factor_double) * math_pre_display_gap_factor_par)); } /*tex Now we are in vertical mode, working on the list that will contain the display. A displayed @@ -3655,8 +3655,8 @@ void tex_run_math_fraction(void) halfword mathclass = fraction_noad_subtype; halfword rulethickness = preset_rule_thickness; int ruledone = 0; - fraction_h_factor(fraction) = 1000; - fraction_v_factor(fraction) = 1000; + fraction_h_factor(fraction) = scaling_factor; + fraction_v_factor(fraction) = scaling_factor; switch (code) { case math_above_code: case math_above_delimited_code: @@ -4553,7 +4553,7 @@ static void tex_aux_finish_displayed_math(int atleft, halfword eqnumber, halfwor if (eqnumber) { number_width = box_width(eqnumber); eqno_width = number_width; - number_plus_gap_width = number_width + tex_round_xn_over_d(math_eqno_gap_step_par, tex_get_math_quad_style(text_style), 1000); + number_plus_gap_width = number_width + tex_round_xn_over_d(math_eqno_gap_step_par, tex_get_math_quad_style(text_style), scaling_factor); node_subtype(eqnumber) = equation_number_list; /*tex attach_current_attribute_list(eqno_box); */ } else { @@ -5200,14 +5200,14 @@ static void tex_aux_define_all_math_parameters(int size, int param, scaled value # define big_operator_spacing5(A) mathex(A,13) /*tex padding above and below displayed limits */ /*tex - Somehow a scale > 1000 results in extreme values. + Somehow a scale > scaling_factor results in extreme values. */ /* inline static int tex_aux_get_font_math_parameter(scaled scale, halfword f, int id) { scaled v = get_font_math_par(f, id); -// return scale == 1000 ? v : round_xn_over_d(v, scale, 1000); +// return scale == scaling_factor ? v : round_xn_over_d(v, scale, scaling_factor); if (v) { double d = 0.001 * scale * v; return (d < 0.0) ? (int) (d - 0.5) : (int) (d + 0.5); @@ -5218,7 +5218,7 @@ inline static int tex_aux_get_font_math_parameter(scaled scale, halfword f, int inline static int tex_aux_get_font_math_quantity(scaled scale, halfword v) { -// return scale == 1000 ? v : round_xn_over_d(v, scale, 1000); +// return scale == scaling_factor ? v : round_xn_over_d(v, scale, scaling_factor); if (v) { double d = 0.001 * scale * v; return (d < 0.0) ? (int) (d - 0.5) : (int) (d + 0.5); @@ -5328,8 +5328,8 @@ void tex_fixup_math_parameters(int fam, int size, int f, int level) /*tex Not all are official \OPENTYPE: */ - tex_aux_define_all_math_parameters(size, math_parameter_x_scale, 1000, level); - tex_aux_define_all_math_parameters(size, math_parameter_y_scale, 1000, level); + tex_aux_define_all_math_parameters(size, math_parameter_x_scale, scaling_factor, level); + tex_aux_define_all_math_parameters(size, math_parameter_y_scale, scaling_factor, level); /*tex Most are zero and have to be set at by the macro package (if at all):. */ @@ -5508,16 +5508,26 @@ static void tex_aux_set_math_atom_rule(halfword left, halfword right, halfword n tex_set_all_styles(math_parameter_rules_pair(left, right), (newleft << 16) + newright, level_one, indirect_math_regular); } +/*tex + + Originally a penalty of 10000 signaled that no penalty has to be included but because we want + to control penalties in nested sequences (like open and close bound sequences) we need to be + able to go up (multiply by a factor) or down (divide by a factor). Therefore we need to be able + to set a penalty to 10000 as a start. so that it will be ignored unless we apply a factor. For + that reason we now use 10001 instead. + +*/ + void tex_initialize_math_spacing(void) { for (int mathclass = 0; mathclass <= max_math_class_code; mathclass++) { tex_set_math_class_default(mathclass, mathclass, no_class_options); /*tex We do this here as there is no real need for yet another initializer. */ - tex_word_define(0, internal_int_location(first_math_pre_penalty_code + mathclass), infinite_penalty); - tex_word_define(0, internal_int_location(first_math_post_penalty_code + mathclass), infinite_penalty); - tex_word_define(0, internal_int_location(first_math_display_pre_penalty_code + mathclass), infinite_penalty); - tex_word_define(0, internal_int_location(first_math_display_post_penalty_code + mathclass), infinite_penalty); + tex_word_define(0, internal_int_location(first_math_pre_penalty_code + mathclass), math_default_penalty); + tex_word_define(0, internal_int_location(first_math_post_penalty_code + mathclass), math_default_penalty); + tex_word_define(0, internal_int_location(first_math_display_pre_penalty_code + mathclass), math_default_penalty); + tex_word_define(0, internal_int_location(first_math_display_post_penalty_code + mathclass), math_default_penalty); } tex_reset_all_styles(level_one); @@ -5658,8 +5668,8 @@ void tex_initialize_math_spacing(void) /* */ - tex_set_all_styles (math_parameter_x_scale, 1000, level_one, indirect_math_regular); - tex_set_all_styles (math_parameter_y_scale, 1000, level_one, indirect_math_regular); + tex_set_all_styles (math_parameter_x_scale, scaling_factor, level_one, indirect_math_regular); + tex_set_all_styles (math_parameter_y_scale, scaling_factor, level_one, indirect_math_regular); /* could be initialize_math_defaults */ @@ -5734,8 +5744,8 @@ static void tex_aux_math_parameter_error(int style, int param, const char *name) inline static scaled tex_aux_max_scale(int style, int param) { scaled scale = tex_get_math_parameter(style, param, NULL); - if (scale > 5000) { - return 5000; + if (scale > max_math_scaling_factor) { + return max_math_scaling_factor; } else if (scale < 0) { return 0; } else { diff --git a/source/luametatex/source/tex/texmath.h b/source/luametatex/source/tex/texmath.h index 65f706a3c..8e847540d 100644 --- a/source/luametatex/source/tex/texmath.h +++ b/source/luametatex/source/tex/texmath.h @@ -246,34 +246,37 @@ typedef enum math_parameters { # define math_default_rules_parameter 0 typedef enum math_class_options { - no_pre_slack_class_option = 0x0000001, - no_post_slack_class_option = 0x0000002, - left_top_kern_class_option = 0x0000004, - right_top_kern_class_option = 0x0000008, - left_bottom_kern_class_option = 0x0000010, - right_bottom_kern_class_option = 0x0000020, - look_ahead_for_end_class_option = 0x0000040, - no_italic_correction_class_option = 0x0000080, - check_ligature_class_option = 0x0000100, - check_italic_correction_class_option = 0x0000200, - check_kern_pair_class_option = 0x0000400, - flatten_class_option = 0x0000800, - omit_penalty_class_option = 0x0001000, - unpack_class_option = 0x0002000, - raise_prime_option = 0x0004000, - // open_fence_class_option = 0x0000100, - // close_fence_class_option = 0x0000200, - // middle_fence_class_option = 0x0000400, - carry_over_left_top_kern_class_option = 0x0008000, - carry_over_right_top_kern_class_option = 0x0010000, - carry_over_left_bottom_kern_class_option = 0x0020000, - carry_over_right_bottom_kern_class_option = 0x0040000, - prefer_delimiter_dimensions_class_option = 0x0080000, - auto_inject_class_option = 0x0100000, - remove_italic_correction_class_option = 0x0200000, - operator_italic_correction_class_option = 0x0400000, - short_inline_class_option = 0x0800000, - no_class_options = 0xF000000, + no_pre_slack_class_option = 0x00000001, + no_post_slack_class_option = 0x00000002, + left_top_kern_class_option = 0x00000004, + right_top_kern_class_option = 0x00000008, + left_bottom_kern_class_option = 0x00000010, + right_bottom_kern_class_option = 0x00000020, + look_ahead_for_end_class_option = 0x00000040, + no_italic_correction_class_option = 0x00000080, + check_ligature_class_option = 0x00000100, + check_italic_correction_class_option = 0x00000200, + check_kern_pair_class_option = 0x00000400, + flatten_class_option = 0x00000800, + omit_penalty_class_option = 0x00001000, + unpack_class_option = 0x00002000, + raise_prime_option = 0x00004000, + // open_fence_class_option = 0x00000100, + // close_fence_class_option = 0x00000200, + // middle_fence_class_option = 0x00000400, + carry_over_left_top_kern_class_option = 0x00008000, + carry_over_right_top_kern_class_option = 0x00010000, + carry_over_left_bottom_kern_class_option = 0x00020000, + carry_over_right_bottom_kern_class_option = 0x00040000, + prefer_delimiter_dimensions_class_option = 0x00080000, + auto_inject_class_option = 0x00100000, + remove_italic_correction_class_option = 0x00200000, + operator_italic_correction_class_option = 0x00400000, + short_inline_class_option = 0x00800000, + push_nesting_class_option = 0x01000000, + pop_nesting_class_option = 0x02000000, + obey_nesting_class_option = 0x04000000, + no_class_options = 0xF0000000, } math_class_options; extern int tex_math_has_class_option(halfword cls, int option); diff --git a/source/luametatex/source/tex/texmlist.c b/source/luametatex/source/tex/texmlist.c index d91ee50ae..13085dca1 100644 --- a/source/luametatex/source/tex/texmlist.c +++ b/source/luametatex/source/tex/texmlist.c @@ -2,6 +2,52 @@ See license.txt in the root of this project. */ + +/*tex + + Before we get to the code is is good to notice that what we have here is an extension of the + math rendering as implemented in \TEX. There are several reason for additions and changes. One + is that we need to support \OPENTYPE\ fonts and after more than a decade struggling with the + fact that many fonts are a mix between what the \OPENTYPE\ specification describes (its + accuracy evolved a bit over time) and what traditional \TEX\ fonts do. Think of the role that + italic correction plays in \TEX\ and kerns in \OPENTYPE\ math. + + In \LUATEX\ this has resulted in a way to control various elements of the engine so that one + can adapt to the font. Here even more properties can be controlled. However, in the end we + decided that fonts are too inconsistent and unlikely to be fixed, so in \CONTEXT\ we settled + on a combination of engine control and patching fonts runtime (aka goodie tweaks). This does + actually mean that in principle we can remove most of the code related to italic correction + and simplify kerning, which makes for cleaner code. We can then also ditch many control + options. It could also make some of the resulting constructs les scomplex (this is something + that might happen eventually anyway). + + In addition to this, the machinery below also has opened up atoms, fractions, accents, fences, + radicals and more beyond what \LUATEX\ already added. We have more classes (including user + ones), more spacing and penalty control, positioning features, etc. Most of that is not + described here but in documents that come with \CONTEXT\ and articles in user group journals. + + It is unlikely that users will set up the engine beyond what a macro package provides, which + should be reasonable defaults. Keep in mind that the math machinery has never be part of + discussing extensions to \TEX\ and that the math subengine was never touched. So, while + \CONTEXT\ users sort of expect this upgrade path, this is not true for other macro packages, + especially when they are considered standard and provide standard behaviour. This means that + we can go a bit further in setting up the engine (by options and parametsrs) in ways that + provide better output. This means that even with the same input, the output that \CONTEXT\ + produces will look different and hopefully somewhat better. + + One can of course wonder why we think the rendering can be improved and part of the answer is + in the fact that we have double linked node lists. This means that we can go back and forward + over the result. Another apects is that we have less constraints in memory and processor + capabilities, so we can carry around more information and spend more time on analysing and + calculations. Nodes are way bigger and the font system is more dynamic, which comes at a + price not possible when original \TEX\ showed up. One can therefore only admire even more + what Don Knuth came up with, which still performs very well, and what is the robust core of + what we see below! + + HH & MS + +*/ + /*tex The code here has to deal with traditional \TEX\ fonts as well as the more modern \OPENTYPE\ @@ -474,7 +520,7 @@ halfword tex_math_font_char_dp(halfword fnt, halfword chr, halfword style) } inline static halfword tex_aux_new_math_glyph(halfword fnt, halfword chr, quarterword subtype) { - halfword scale = 1000; + halfword scale = scaling_factor; halfword glyph = tex_new_glyph_node(subtype, fnt, tex_get_math_char(fnt, chr, lmt_math_state.size, &scale, math_direction_par), null); /* todo: data */; set_glyph_options(glyph, glyph_options_par); glyph_scale(glyph) = tex_aux_math_glyph_scale(scale); @@ -1511,7 +1557,7 @@ static halfword tex_aux_make_delimiter(halfword target, halfword delimiter, int } } goto FOUND; - } else if (count > 1000) { + } else if (count > scaling_factor) { tex_formatted_warning("fonts", "endless loop in extensible character %U of font %F", curchr, curfnt); goto FOUND; } else if (tex_char_has_tag_from_font(curfnt, curchr, list_tag)) { @@ -2964,7 +3010,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal scaled overshoot = 0; extinfo *extended = NULL; halfword attrlist = node_attr(target); - scaled fraction = accent_fraction(target) > 0 ? accent_fraction(target) : 1000; + scaled fraction = accent_fraction(target) > 0 ? accent_fraction(target) : scaling_factor; scaled skew = 0; scaled offset = 0; scaled innery = 0; @@ -3047,7 +3093,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal } } if (fraction > 0) { - target = tex_xn_over_d(target, fraction, 1000); + target = tex_xn_over_d(target, fraction, scaling_factor); } while (1) { if (tex_char_has_tag_from_font(accentfnt, accentchr, extensible_tag)) { @@ -3448,8 +3494,8 @@ static void tex_aux_calculate_fraction_shifts(halfword target, int style, int si (void) size; *shift_up = tex_get_math_y_parameter_checked(style, up); *shift_down = tex_get_math_y_parameter_checked(style, down); - *shift_up = tex_round_xn_over_d(*shift_up, fraction_v_factor(target), 1000); - *shift_down = tex_round_xn_over_d(*shift_down, fraction_v_factor(target), 1000); + *shift_up = tex_round_xn_over_d(*shift_up, fraction_v_factor(target), scaling_factor); + *shift_down = tex_round_xn_over_d(*shift_down, fraction_v_factor(target), scaling_factor); } static void tex_aux_calculate_fraction_shifts_stack(halfword target, int style, int size, halfword numerator, halfword denominator, scaled *shift_up, scaled *shift_down, scaled *delta) @@ -3584,7 +3630,7 @@ static halfword tex_aux_make_skewed_fraction(halfword target, int style, int siz delimiterextremes extremes = { .tfont = null_font, .tchar = 0, .bfont = null_font, .bchar = 0, .height = 0, .depth = 0 }; scaled tolerance = tex_get_math_y_parameter_default(style, math_parameter_skewed_delimiter_tolerance, 0); scaled shift_up = tex_get_math_y_parameter_checked(style, math_parameter_skewed_fraction_vgap); - scaled shift_down = tex_round_xn_over_d(shift_up, fraction_v_factor(target), 1000); + scaled shift_down = tex_round_xn_over_d(shift_up, fraction_v_factor(target), scaling_factor); (void) kerns; shift_up = shift_down; /*tex The |shift_up| value might change later. */ tex_aux_wrap_fraction_parts(target, style, size, &numerator, &denominator, 0); @@ -3598,7 +3644,7 @@ static halfword tex_aux_make_skewed_fraction(halfword target, int style, int siz Construct a hlist box for the fraction, according to |hgap| and |vgap|. */ hgap = tex_get_math_x_parameter_checked(style, math_parameter_skewed_fraction_hgap); - hgap = tex_round_xn_over_d(hgap, fraction_h_factor(target), 1000); + hgap = tex_round_xn_over_d(hgap, fraction_h_factor(target), scaling_factor); { scaled ht = box_height(numerator) + shift_up; scaled dp = box_depth(numerator) - shift_up; @@ -3828,8 +3874,8 @@ static void tex_aux_get_shifts(int mode, int style, scaled delta, scaled *top, s break; case 1: /*tex |MathConstants| driven */ - *top = tex_round_xn_over_d(delta, tex_get_math_parameter_default(style, math_parameter_nolimit_sup_factor, 0), 1000); - *bot = -tex_round_xn_over_d(delta, tex_get_math_parameter_default(style, math_parameter_nolimit_sub_factor, 0), 1000); + *top = tex_round_xn_over_d(delta, tex_get_math_parameter_default(style, math_parameter_nolimit_sup_factor, 0), scaling_factor); + *bot = -tex_round_xn_over_d(delta, tex_get_math_parameter_default(style, math_parameter_nolimit_sub_factor, 0), scaling_factor); break ; case 2: /*tex no correction */ @@ -3849,7 +3895,7 @@ static void tex_aux_get_shifts(int mode, int style, scaled delta, scaled *top, s default : /*tex above 15: for quickly testing values */ *top = 0; - *bot = (mode > 15) ? -tex_round_xn_over_d(delta, mode, 1000) : 0; + *bot = (mode > 15) ? -tex_round_xn_over_d(delta, mode, scaling_factor) : 0; break; } } @@ -6831,6 +6877,11 @@ static void tex_mlist_to_hlist_size_fences(mliststate *state) } } +/*tex + The mathboundary feature, where 0/2 push, 1/3 pop, 2/3 take an penalty delta, is only there for + special testing by MS and me, so don't depend on that for now. +*/ + static void tex_mlist_to_hlist_finalize_list(mliststate *state) { halfword recent = null; /*tex Watch out: can be wiped, so more a signal! */ @@ -6848,6 +6899,10 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) halfword current = state->mlist; halfword p = temp_head; halfword ghost = null; + int boundarylevel = 0; + int boundaryfactor = scaling_factor; + int nestinglevel = 0; + int nestingfactor = scaling_factor; node_next(p) = null; tex_aux_set_current_math_size(current_style); tex_aux_set_current_math_scale(state->scale); @@ -7019,10 +7074,38 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) default: break; } + case boundary_node: + if (node_subtype(current) == math_boundary) { + halfword l = boundary_data(current); + switch(l) { + case 0: + case 2: + boundarylevel++; + if (l == 2) { + boundaryfactor = boundary_reserved(current) ? boundary_reserved(current) : scaling_factor; + } + break; + case 1: + case 3: + if (boundarylevel > 0) { + boundarylevel--; + if (l == 2) { + boundaryfactor = boundary_reserved(current) ? boundary_reserved(current) : scaling_factor; + } + } else { + tex_formatted_warning("math", "invalid math boundary %i nesting", l); + } + break; + default: + tex_formatted_warning("math", "invalid math boundary value"); + /* error */ + break; + } + } + goto PICKUP; // case glyph_node: case disc_node: case hlist_node: - case boundary_node: case whatsit_node: case penalty_node: case rule_node: @@ -7031,6 +7114,7 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) case mark_node: case par_node: case kern_node: + PICKUP: tex_couple_nodes(p, current); p = current; current = node_next(current); @@ -7201,16 +7285,40 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) /*tex Do we still want this check in infinite. */ - if (state->penalties && pre_penalty < infinite_penalty && node_type(last) != penalty_node) { - /*tex no checking of prev node type */ - halfword penalty = tex_new_penalty_node(pre_penalty, math_pre_penalty_subtype); - tex_attach_attribute_list_copy(penalty, current); - tex_couple_nodes(p, penalty); - p = penalty; - if (tracing_math_par >= 2) { - tex_begin_diagnostic(); - tex_print_format("[math: pre penalty, left %n, right %n, amount %i]", recent_subtype, current_subtype, penalty_amount(penalty)); - tex_end_diagnostic(); + if (tex_math_has_class_option(current_subtype, push_nesting_class_option)) { + nestinglevel++; + switch (current_style) { + case display_style: + case cramped_display_style: + nestingfactor = math_display_penalty_factor_par ? math_display_penalty_factor_par : scaling_factor; + break; + default: + nestingfactor = math_inline_penalty_factor_par ? math_inline_penalty_factor_par : scaling_factor; + break; + } + } else if (tex_math_has_class_option(current_subtype, pop_nesting_class_option) && nestinglevel > 0) { + nestinglevel--; + if (nestinglevel == 0) { + nestingfactor = scaling_factor; + } + } + if (state->penalties && node_type(last) != penalty_node && pre_penalty <= infinite_penalty && (! boundarylevel || (boundaryfactor != scaling_factor || nestingfactor != scaling_factor))) { + if (boundaryfactor != scaling_factor) { + pre_penalty = tex_xn_over_d(pre_penalty, boundaryfactor, scaling_factor); + } else if (nestingfactor != scaling_factor && tex_math_has_class_option(current_subtype, obey_nesting_class_option)) { + pre_penalty = tex_xn_over_d(pre_penalty, nestingfactor, scaling_factor); + } + if (pre_penalty < infinite_penalty) { + /*tex no checking of prev node type */ + halfword penalty = tex_new_penalty_node(pre_penalty, math_pre_penalty_subtype); + tex_attach_attribute_list_copy(penalty, current); + tex_couple_nodes(p, penalty); + p = penalty; + if (tracing_math_par >= 2) { + tex_begin_diagnostic(); + tex_print_format("[math: pre penalty, left %n, right %n, amount %i]", recent_subtype, current_subtype, penalty_amount(penalty)); + tex_end_diagnostic(); + } } } if (tex_math_has_class_option(current_subtype, remove_italic_correction_class_option)) { @@ -7298,20 +7406,27 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) We can actually drop the omit check because we pair by class. */ - if (state->penalties && node_next(current) && post_penalty < infinite_penalty) { - halfword recent = node_next(current); - recent_type = node_type(recent); - recent_subtype = node_subtype(recent); - /* todo: maybe also check the mainclass of the recent */ - if ((recent_type != penalty_node) && ! (recent_type == simple_noad && tex_math_has_class_option(recent_subtype, omit_penalty_class_option))) { - halfword penalty = tex_new_penalty_node(post_penalty, math_post_penalty_subtype); - tex_attach_attribute_list_copy(penalty, current); - tex_couple_nodes(p, penalty); - p = penalty; - if (tracing_math_par >= 2) { - tex_begin_diagnostic(); - tex_print_format("[math: post penalty, left %n, right %n, amount %i]", recent_subtype, current_subtype, penalty_amount(penalty)); - tex_end_diagnostic(); + if (state->penalties && node_next(current) && post_penalty <= infinite_penalty && (! boundarylevel || (boundaryfactor != scaling_factor || nestingfactor != scaling_factor))) { + if (boundaryfactor != scaling_factor) { + post_penalty = tex_xn_over_d(post_penalty, boundaryfactor, scaling_factor); + } else if (nestingfactor != scaling_factor && tex_math_has_class_option(current_subtype, obey_nesting_class_option)) { + post_penalty = tex_xn_over_d(post_penalty, nestingfactor, scaling_factor); + } + if (post_penalty < infinite_penalty) { + halfword recent = node_next(current); + recent_type = node_type(recent); + recent_subtype = node_subtype(recent); + /* todo: maybe also check the mainclass of the recent */ + if ((recent_type != penalty_node) && ! (recent_type == simple_noad && tex_math_has_class_option(recent_subtype, omit_penalty_class_option))) { + halfword penalty = tex_new_penalty_node(post_penalty, math_post_penalty_subtype); + tex_attach_attribute_list_copy(penalty, current); + tex_couple_nodes(p, penalty); + p = penalty; + if (tracing_math_par >= 2) { + tex_begin_diagnostic(); + tex_print_format("[math: post penalty, left %n, right %n, amount %i]", recent_subtype, current_subtype, penalty_amount(penalty)); + tex_end_diagnostic(); + } } } } diff --git a/source/luametatex/source/tex/texnesting.c b/source/luametatex/source/tex/texnesting.c index 65e32a333..1f2995942 100644 --- a/source/luametatex/source/tex/texnesting.c +++ b/source/luametatex/source/tex/texnesting.c @@ -337,7 +337,7 @@ void tex_show_activities(void) while (r != page_insert_head) { halfword index = insert_index(r); halfword multiplier = tex_get_insert_multiplier(index); - halfword size = multiplier == 1000 ? insert_total_height(r) : tex_x_over_n(insert_total_height(r), 1000) * multiplier; + halfword size = multiplier == scaling_factor ? insert_total_height(r) : tex_x_over_n(insert_total_height(r), scaling_factor) * multiplier; if (node_type(r) == split_node && node_subtype(r) == insert_split_subtype) { halfword q = page_head; halfword n = 0; diff --git a/source/luametatex/source/tex/texnodes.c b/source/luametatex/source/tex/texnodes.c index 650e0cee2..48a1bd2db 100644 --- a/source/luametatex/source/tex/texnodes.c +++ b/source/luametatex/source/tex/texnodes.c @@ -157,14 +157,15 @@ void lmt_nodelib_initialize(void) { set_value_entry_key(subtypes_glue, g_leaders, gleaders) set_value_entry_key(subtypes_glue, u_leaders, uleaders) - subtypes_boundary = lmt_aux_allocate_value_info(par_boundary); + subtypes_boundary = lmt_aux_allocate_value_info(math_boundary); set_value_entry_key(subtypes_boundary, cancel_boundary, cancel) set_value_entry_key(subtypes_boundary, user_boundary, user) set_value_entry_key(subtypes_boundary, protrusion_boundary, protrusion) set_value_entry_key(subtypes_boundary, word_boundary, word) set_value_entry_key(subtypes_boundary, page_boundary, page) - set_value_entry_key(subtypes_boundary, par_boundary, par) + set_value_entry_key(subtypes_boundary, math_boundary, math) + /* set_value_entry_key(subtypes_boundary, par_boundary, par) */ subtypes_penalty = lmt_aux_allocate_value_info(equation_number_penalty_subtype); @@ -2595,13 +2596,13 @@ void tex_show_node_list(halfword p, int threshold, int max) if (glyph_expansion(p)) { tex_print_format(", expansion %i", glyph_expansion(p)); } - if (glyph_scale(p) && glyph_scale(p) != 1000) { + if (glyph_scale(p) && glyph_scale(p) != scaling_factor) { tex_print_format(", scale %i", glyph_scale(p)); } - if (glyph_x_scale(p) && glyph_x_scale(p) != 1000) { + if (glyph_x_scale(p) && glyph_x_scale(p) != scaling_factor) { tex_print_format(", xscale %i", glyph_x_scale(p)); } - if (glyph_y_scale(p) && glyph_y_scale(p) != 1000) { + if (glyph_y_scale(p) && glyph_y_scale(p) != scaling_factor) { tex_print_format(", yscale %i", glyph_y_scale(p)); } if (glyph_data(p)) { @@ -3371,7 +3372,7 @@ scaled tex_glyph_width_ex(halfword p) } w -= (glyph_left(p) + glyph_right(p)); if (glyph_expansion(p)) { - w = w + tex_ext_xn_over_d(w, 1000000 + glyph_expansion(p), 1000000); + w = w + tex_ext_xn_over_d(w, scaling_factor_squared + glyph_expansion(p), scaling_factor_squared); } return w; } @@ -3442,7 +3443,7 @@ scaledwhd tex_glyph_dimensions_ex(halfword p) whd.dp = 0; } if (whd.wd && glyph_expansion(p)) { - whd.wd = tex_ext_xn_over_d(whd.wd, 1000000 + glyph_expansion(p), 1000000); + whd.wd = tex_ext_xn_over_d(whd.wd, scaling_factor_squared + glyph_expansion(p), scaling_factor_squared); } return whd; } @@ -3478,7 +3479,7 @@ halfword tex_kern_dimension_ex(halfword p) { halfword k = kern_amount(p); if (k && kern_expansion(p)) { - k = tex_ext_xn_over_d(k, 1000000 + kern_expansion(p), 1000000); + k = tex_ext_xn_over_d(k, scaling_factor_squared + kern_expansion(p), scaling_factor_squared); } return k; } diff --git a/source/luametatex/source/tex/texnodes.h b/source/luametatex/source/tex/texnodes.h index 3550e7345..492e220f2 100644 --- a/source/luametatex/source/tex/texnodes.h +++ b/source/luametatex/source/tex/texnodes.h @@ -2147,11 +2147,12 @@ typedef enum boundary_subtypes { protrusion_boundary, /* 1=left, 2=right, 3=both */ word_boundary, page_boundary, + math_boundary, par_boundary, } boundary_subtypes; # define last_boundary_subtype word_boundary -# define last_boundary_code page_boundary +# define last_boundary_code math_boundary # define boundary_node_size 3 # define boundary_data(a) vinfo(a,2) diff --git a/source/luametatex/source/tex/texpackaging.c b/source/luametatex/source/tex/texpackaging.c index 9f66232a7..8d2f0d87a 100644 --- a/source/luametatex/source/tex/texpackaging.c +++ b/source/luametatex/source/tex/texpackaging.c @@ -425,7 +425,7 @@ scaled tex_char_stretch(halfword p) /* todo: move this to texfont.c and make it if (e > 0) { scaled dw = tex_calculated_glyph_width(p, m) - tex_char_width_from_glyph(p); if (dw > 0) { - return tex_round_xn_over_d(dw, e, 1000); + return tex_round_xn_over_d(dw, e, scaling_factor); } } } @@ -444,7 +444,7 @@ scaled tex_char_shrink(halfword p) /* todo: move this to texfont.c and make it m if (e > 0) { scaled dw = tex_char_width_from_glyph(p) - tex_calculated_glyph_width(p, -m); if (dw > 0) { - return tex_round_xn_over_d(dw, e, 1000); + return tex_round_xn_over_d(dw, e, scaling_factor); } } } @@ -462,9 +462,9 @@ scaled tex_kern_stretch(halfword p) if (m > 0) { scaled e = tex_char_ef_from_font(glyph_font(l), glyph_character(l)); if (e > 0) { - scaled dw = w - tex_round_xn_over_d(w, 1000 + m, 1000); + scaled dw = w - tex_round_xn_over_d(w, scaling_factor + m, scaling_factor); if (dw > 0) { - return tex_round_xn_over_d(dw, e, 1000); + return tex_round_xn_over_d(dw, e, scaling_factor); } } } @@ -483,9 +483,9 @@ scaled tex_kern_shrink(halfword p) if (m > 0) { scaled e = tex_char_cf_from_font(glyph_font(l), glyph_character(l)); if (e > 0) { - scaled dw = tex_round_xn_over_d(w, 1000 - m, 1000) - w; + scaled dw = tex_round_xn_over_d(w, scaling_factor - m, scaling_factor) - w; if (dw > 0) { - return tex_round_xn_over_d(dw, e, 1000); + return tex_round_xn_over_d(dw, e, scaling_factor); } } } @@ -507,8 +507,8 @@ static void tex_aux_set_kern_expansion(halfword p, halfword ex_ratio) if (e > 0) { halfword m = font_max_stretch(f); if (m > 0) { - e = tex_ext_xn_over_d(ex_ratio * e, m, 1000000); - kern_expansion(p) = tex_fix_expand_value(f, e) * 1000; + e = tex_ext_xn_over_d(ex_ratio * e, m, scaling_factor_squared); + kern_expansion(p) = tex_fix_expand_value(f, e) * scaling_factor; } } } else if (ex_ratio < 0) { @@ -516,8 +516,8 @@ static void tex_aux_set_kern_expansion(halfword p, halfword ex_ratio) if (e > 0) { halfword m = font_max_shrink(f); if (m > 0) { - e = tex_ext_xn_over_d(ex_ratio * e, m, 1000000); - kern_expansion(p) = tex_fix_expand_value(f, e) * 1000; + e = tex_ext_xn_over_d(ex_ratio * e, m, scaling_factor_squared); + kern_expansion(p) = tex_fix_expand_value(f, e) * scaling_factor; } } } @@ -537,8 +537,8 @@ static void tex_aux_set_glyph_expansion(halfword p, int ex_ratio) if (e > 0) { halfword m = font_max_stretch(f); if (m > 0) { - e = tex_ext_xn_over_d(ex_ratio * e, m, 1000000); - glyph_expansion(p) = tex_fix_expand_value(f, e) * 1000; + e = tex_ext_xn_over_d(ex_ratio * e, m, scaling_factor_squared); + glyph_expansion(p) = tex_fix_expand_value(f, e) * scaling_factor; } } } else if (ex_ratio < 0) { @@ -548,8 +548,8 @@ static void tex_aux_set_glyph_expansion(halfword p, int ex_ratio) if (e > 0) { halfword m = font_max_shrink(f); if (m > 0) { - e = tex_ext_xn_over_d(ex_ratio * e, m, 1000000); - glyph_expansion(p) = tex_fix_expand_value(f, e) * 1000; + e = tex_ext_xn_over_d(ex_ratio * e, m, scaling_factor_squared); + glyph_expansion(p) = tex_fix_expand_value(f, e) * scaling_factor; } } } @@ -1100,10 +1100,10 @@ halfword tex_hpack(halfword p, scaled w, int m, singleword pack_direction, int r /*tex Why not always: */ lmt_packaging_state.previous_char_ptr = null; } else if (m == packing_adapted) { - if (w > 1000) { - w = 1000; - } else if (w < -1000) { - w = -1000; + if (w > scaling_factor) { + w = scaling_factor; + } else if (w < -scaling_factor) { + w = -scaling_factor; } } for (int i = normal_glue_order; i <= filll_glue_order; i++) { @@ -1423,7 +1423,7 @@ halfword tex_hpack(halfword p, scaled w, int m, singleword pack_direction, int r */ halfword o = tex_aux_used_order(lmt_packaging_state.total_stretch); if ((m == packing_expanded) && (o == normal_glue_order) && (font_stretch > 0)) { - lmt_packaging_state.font_expansion_ratio = tex_divide_scaled_n(x, font_stretch, 1000.0); + lmt_packaging_state.font_expansion_ratio = tex_divide_scaled_n(x, font_stretch, scaling_factor_double); goto EXIT; } box_glue_order(r) = o; @@ -1476,7 +1476,7 @@ halfword tex_hpack(halfword p, scaled w, int m, singleword pack_direction, int r */ halfword o = tex_aux_used_order(lmt_packaging_state.total_shrink); if ((m == packing_expanded) && (o == normal_glue_order) && (font_shrink > 0)) { - lmt_packaging_state.font_expansion_ratio = tex_divide_scaled_n(x, font_shrink, 1000.0); + lmt_packaging_state.font_expansion_ratio = tex_divide_scaled_n(x, font_shrink, scaling_factor_double); goto EXIT; } box_glue_order(r) = o; @@ -1491,7 +1491,7 @@ halfword tex_hpack(halfword p, scaled w, int m, singleword pack_direction, int r if (o == normal_glue_order && box_list(r)) { if (lmt_packaging_state.total_shrink[o] < -x) { int overshoot = -x - lmt_packaging_state.total_shrink[normal_glue_order]; - lmt_packaging_state.last_badness = 1000000; + lmt_packaging_state.last_badness = scaling_factor_squared; lmt_packaging_state.last_overshoot = overshoot; /*tex Use the maximum shrinkage */ box_glue_set(r) = 1.0; @@ -1574,7 +1574,7 @@ halfword tex_hpack(halfword p, scaled w, int m, singleword pack_direction, int r } EXIT: if ((m == packing_expanded) && (lmt_packaging_state.font_expansion_ratio != 0)) { - lmt_packaging_state.font_expansion_ratio = fix_int(lmt_packaging_state.font_expansion_ratio, -1000, 1000); + lmt_packaging_state.font_expansion_ratio = fix_int(lmt_packaging_state.font_expansion_ratio, -scaling_factor, scaling_factor); q = box_list(r); box_list(r) = null; tex_flush_node(r); @@ -2237,7 +2237,7 @@ halfword tex_vpack(halfword p, scaled h, int m, scaled l, singleword pack_direct if (o == normal_glue_order && box_list(r)) { if (lmt_packaging_state.total_shrink[o] < -x) { int overshoot = -x - lmt_packaging_state.total_shrink[normal_glue_order]; - lmt_packaging_state.last_badness = 1000000; + lmt_packaging_state.last_badness = scaling_factor_squared; lmt_packaging_state.last_overshoot = overshoot; /*tex Use the maximum shrinkage */ box_glue_set(r) = 1.0; diff --git a/source/luametatex/source/tex/texprinting.c b/source/luametatex/source/tex/texprinting.c index 518f1cf43..f79a47a87 100644 --- a/source/luametatex/source/tex/texprinting.c +++ b/source/luametatex/source/tex/texprinting.c @@ -529,8 +529,8 @@ void tex_print_dimension(scaled s, int unit) s = 10 * (s % unity) + 5; do { if (delta > unity) { - /*tex Round the last digit. */ - s = s + 0100000 - 50000; + /*tex Round the last digit, so: |s + 32768 - 50000| it is. */ + s = s + 0x8000 - 50000; } buffer[i++] = (unsigned char) ('0' + (s / unity)); s = 10 * (s % unity); diff --git a/source/luametatex/source/tex/textextcodes.c b/source/luametatex/source/tex/textextcodes.c index e76329685..73e9f7867 100644 --- a/source/luametatex/source/tex/textextcodes.c +++ b/source/luametatex/source/tex/textextcodes.c @@ -216,7 +216,7 @@ static void tex_aux_free_catcodes(void) # define UCCODEDEFAULT 0 # define SFCODESTACK 8 -# define SFCODEDEFAULT 1000 +# define SFCODEDEFAULT scaling_factor # define HCCODESTACK 8 # define HCCODEDEFAULT 0 diff --git a/source/luametatex/source/tex/textypes.h b/source/luametatex/source/tex/textypes.h index 683ee2e5a..5a4dce7e8 100644 --- a/source/luametatex/source/tex/textypes.h +++ b/source/luametatex/source/tex/textypes.h @@ -162,11 +162,13 @@ extern halfword tex_badness( # define max_infinity 0x7FFFFFFF /*tex the largest positive value that \TEX\ knows */ # define min_infinity -0x7FFFFFFF -# define awful_bad 07777777777 /*tex more than a billion demerits |0x3FFFFFFF| */ + # define awful_bad 0x3FFFFFFF /*tex more than a billion demerits |07777777777| */ # define infinite_bad 10000 /*tex infinitely bad value */ # define infinite_penalty infinite_bad /*tex infinite penalty value */ # define eject_penalty -infinite_penalty /*tex negatively infinite penalty value */ +# define final_penalty -0x40000000 /*tex in the output routine */ # define deplorable 100000 /*tex more than |inf_bad|, but less than |awful_bad| */ +# define extremely_deplorable 100000000 # define large_width_excess 7230584 # define small_stretchability 1663497 # define loose_criterion 99 @@ -213,6 +215,19 @@ extern halfword tex_badness( # define default_output_box 255 +# define scaling_factor 1000 +# define scaling_factor_squared 1000000 +# define scaling_factor_double 1000.0 +//define scaling_multiplier_double 0.001 + +# define max_math_scaling_factor 5000 + +# define max_font_adjust_step 100 +# define max_font_adjust_stretch_factor 1000 +# define max_font_adjust_shrink_factor 500 + +# define math_default_penalty (infinite_penalty+1) + /*tex For practical reasons all these registers were max'd to 64K but that really makes no sense for |