diff options
author | Hans Hagen <pragma@wxs.nl> | 2022-10-14 10:56:48 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2022-10-14 10:56:48 +0200 |
commit | 0aa93a6d31a45d8df2d8516567b98967ce04f183 (patch) | |
tree | 7e1942650512f1994ca56c1eba245973240d4b71 /source/luametatex | |
parent | c161b7d6fe142231346cc1844e6e27c0ab7718c1 (diff) | |
download | context-0aa93a6d31a45d8df2d8516567b98967ce04f183.tar.gz |
2022-10-14 10:15:00
Diffstat (limited to 'source/luametatex')
51 files changed, 1539 insertions, 2405 deletions
diff --git a/source/luametatex/source/README b/source/luametatex/source/README deleted file mode 100644 index 8d63e4393..000000000 --- a/source/luametatex/source/README +++ /dev/null @@ -1,39 +0,0 @@ -LuaMetaTeX - -This is a follow up on the LuaTeX project. The source is considered part of the ConTeXt distribution -and managed by the ConTeXt development team and the ConTeXt user group. That way we can guarantee -that the engine and this TeX macro package work together as expected. The idea is that users can -easily compile the source themselves and that way have a guaranteed long term (minimal) TeX based -installation. Because the management scripts are in Lua, only one binary is needed to serve the -ConTeXt distribution. - -In the source code we try to stay close to the ancestors, LuaTeX, pdfTeX, eTeX and TeX, but in the -meantime due to additions there is quite some diverge. There are new primitives and submechanisms, -there is more control over the inner workings, font handling is mostly delegated to Lua and there -is no built-in backend. The code base is all-inclusive and has no (nor will have) dependencies on -external libraries. - -Performance and memory consumption have been optimized and the additions (compared to LuaTeX) don't -have a negative impact. In spite of the extensions, we consider this a more lightweight version of -its ancestor and want to keep it that way. There are a few optional interfaces to the outside world -but ConTeXt will never depend on them for regular usage. - -Version numbering starts 2.00 so that there is no confusion with LuaTeX where the stable 1.00+ -version numbers now can bump with the yearly TeXlive updates. Backporting features to LuaTeX is yet -undecided (also because the codebase is now too different). The internal MetaPost library is an -enhanced version of the official one that ships with LuaTeX. Here we started with number 3.00 and -to what extend there will be backports to the 2.00+ library is yet unknown. We use Lua 5.4+ and try -to keep up to date with the latest greatest, also because the LuaMetaTeX-ConTeXt combination makes -for nice test enviroment. Starting with LuaMetaTeX version 2.10 the interfaces are considered -stable. Although we will fix bugs as fast as possible, we might end up with the same slow-paced -release cycle as traditional TeX. - -Bugs can be reported to the ConTeXt mailing lists (support or development) or the team members. Such -a report should come with a (MEW) ConTeXt .tex file that illustrates the issue. The code repository -is managed by the ConTeXt user group and its compile farm team (aka contextgarden built bot). - -All kind of aspects of the LuaMetaTeX engine, its development, experiment, ideas and implementation -have been (and are) reported in user group publications aas well as several documents in the ConTeXt -distribution. The mailing list archives and contextgarden wiki are also a source of information. - -Hans Hagen diff --git a/source/luametatex/source/lua/lmtfontlib.c b/source/luametatex/source/lua/lmtfontlib.c index 09429d98a..5004a9710 100644 --- a/source/luametatex/source/lua/lmtfontlib.c +++ b/source/luametatex/source/lua/lmtfontlib.c @@ -73,23 +73,6 @@ static int fontlib_aux_count_hash_items(lua_State *L) */ -/* -# define set_numeric_field_by_index(target,name,dflt) \ - lua_key_rawgeti(name); \ - target = (lua_type(L, -1) == LUA_TNUMBER) ? lmt_roundnumber(L, -1) : dflt ; \ - lua_pop(L, 1); - -# define set_boolean_field_by_index(target,name,dflt) \ - lua_key_rawgeti(name); \ - target = (lua_type(L, -1) == LUA_TBOOLEAN) ? lua_toboolean(L, -1) : dflt ; \ - lua_pop(L, 1); - -# define set_string_field_by_index(target,name) \ - lua_key_rawgeti(name); \ - target = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1) : NULL ; \ - lua_pop(L, 1); -*/ - # define set_numeric_field_by_index(target,name,dflt) \ lua_push_key(name); \ target = (lua_rawget(L, -2) == LUA_TNUMBER) ? lmt_roundnumber(L, -1) : dflt ; \ @@ -219,9 +202,6 @@ static void fontlib_aux_read_lua_math_parameters(lua_State *L, int f) } lua_pop(L, 1); } - set_font_oldmath(f, 0); - } else { - set_font_oldmath(f, 1); } lua_pop(L, 1); } @@ -251,11 +231,6 @@ static void fontlib_aux_store_math_kerns(lua_State *L, int index, charinfo *co, for (lua_Integer l = 1; l <= k; l++) { if (lua_rawgeti(L, -1, l) == LUA_TTABLE) { scaled ht, krn; -// set_numeric_field_by_index(ht, height, min_infinity); -// set_numeric_field_by_index(krn, kern, min_infinity); -// if (krn > min_infinity && ht > min_infinity) { -// tex_add_charinfo_math_kern(co, id, ht, krn); -// } set_numeric_field_by_index(ht, height, 0); set_numeric_field_by_index(krn, kern, 0); if (krn || ht) { @@ -297,6 +272,8 @@ static void fontlib_aux_font_char_from_lua(lua_State *L, halfword f, int i, int tex_char_malloc_mathinfo(co); set_numeric_field_by_index(target, smaller, 0); set_charinfo_smaller(co, target); + set_numeric_field_by_index(target, mirror, 0); + set_charinfo_mirror(co, target); set_numeric_field_by_index(target, vitalic, 0); set_charinfo_vertical_italic(co, target); /* */ @@ -318,12 +295,15 @@ static void fontlib_aux_font_char_from_lua(lua_State *L, halfword f, int i, int set_numeric_field_by_index(target, bottommargin, 0); set_charinfo_bottom_margin(co, target); /* */ - // set_numeric_field_by_index(target, options, 0); - // set_charinfo_options(co, target); - set_numeric_field_by_index(target, topaccent, INT_MIN); - set_charinfo_top_accent(co, target); - set_numeric_field_by_index(target, bottomaccent, INT_MIN); - set_charinfo_bottom_accent(co, target); + set_numeric_field_by_index(target, topovershoot, 0); + set_charinfo_top_overshoot(co, target); + set_numeric_field_by_index(target, bottomovershoot, 0); + set_charinfo_bottom_overshoot(co, target); + /* */ + set_numeric_field_by_index(target, topanchor, INT_MIN); + set_charinfo_top_anchor(co, target); + set_numeric_field_by_index(target, bottomanchor, INT_MIN); + set_charinfo_bottom_anchor(co, target); set_numeric_field_by_index(target, flataccent, INT_MIN); set_charinfo_flat_accent(co, target); set_numeric_field_by_index(target, next, -1); @@ -574,8 +554,6 @@ static int lmt_font_from_lua(lua_State *L, int f) set_font_design_size(f, j); set_numeric_field_by_index(j, size, font_design_size(f)); set_font_size(f, j); - set_boolean_field_by_index(j, oldmath, 0); - set_font_oldmath(f, j); set_boolean_field_by_index(j, compactmath, 0); set_font_compactmath(f, j); set_numeric_field_by_index(j, mathcontrol, 0); @@ -594,12 +572,8 @@ static int lmt_font_from_lua(lua_State *L, int f) set_font_skew_char(f, j); set_boolean_field_by_index(no_math, nomath, 0); fontlib_aux_read_lua_parameters(L, f); - if (no_math) { - set_font_oldmath(f, 1); - } else { + if (! no_math) { fontlib_aux_read_lua_math_parameters(L, f); - set_boolean_field_by_index(j, oldmath, 0); - set_font_oldmath(f, j); } /*tex The characters. */ lua_push_key(characters); @@ -808,8 +782,6 @@ static int fontlib_setfont(lua_State *L) luaL_checktype(L, 2, LUA_TTABLE); if (! tex_is_valid_font(i)) { return luaL_error(L, "font with id %d is not a valid font", i); - // } else if (font_touched(i)) { - // return luaL_error(L, "font with id %d has been accessed already, changing it is forbidden", i); } else { lua_settop(L, 2); lmt_font_from_lua(L, i); diff --git a/source/luametatex/source/lua/lmtinterface.c b/source/luametatex/source/lua/lmtinterface.c index 1aef54563..bc546a9e2 100644 --- a/source/luametatex/source/lua/lmtinterface.c +++ b/source/luametatex/source/lua/lmtinterface.c @@ -82,35 +82,38 @@ void lmt_initialize_interface(void) # define set_group_code_value(n,k) lmt_interface.group_code_values[n] = (value_info) { .lua = lua_key_index(k), .name = lua_key(k), .id = n } - set_group_code_value(bottom_level_group, bottomlevel); - set_group_code_value(simple_group, simple); - set_group_code_value(hbox_group, hbox); - set_group_code_value(adjusted_hbox_group, adjustedhbox); - set_group_code_value(vbox_group, vbox); - set_group_code_value(vtop_group, vtop); - set_group_code_value(align_group, align); - set_group_code_value(no_align_group, noalign); - set_group_code_value(output_group, output); - set_group_code_value(math_group, math); - set_group_code_value(discretionary_group, discretionary); - set_group_code_value(insert_group, insert); - set_group_code_value(vadjust_group, vadjust); - set_group_code_value(vcenter_group, vcenter); - set_group_code_value(math_fraction_group, mathfraction); - set_group_code_value(math_operator_group, mathoperator); - set_group_code_value(math_choice_group, mathchoice); - set_group_code_value(also_simple_group, alsosimple); - set_group_code_value(semi_simple_group, semisimple); - set_group_code_value(math_simple_group, mathsimple); - set_group_code_value(math_shift_group, mathshift); - set_group_code_value(math_fence_group, mathfence); - set_group_code_value(local_box_group, localbox); - set_group_code_value(split_off_group, splitoff); - set_group_code_value(split_keep_group, splitkeep); - set_group_code_value(preamble_group, preamble); - set_group_code_value(align_set_group, alignset); - set_group_code_value(finish_row_group, finishrow); - set_group_code_value(lua_group, lua); + set_group_code_value(bottom_level_group, bottomlevel); + set_group_code_value(simple_group, simple); + set_group_code_value(hbox_group, hbox); + set_group_code_value(adjusted_hbox_group, adjustedhbox); + set_group_code_value(vbox_group, vbox); + set_group_code_value(vtop_group, vtop); + set_group_code_value(align_group, align); + set_group_code_value(no_align_group, noalign); + set_group_code_value(output_group, output); + set_group_code_value(math_group, mathsubformula); + set_group_code_value(math_component_group, mathcomponent); + set_group_code_value(math_stack_group, mathstack); + set_group_code_value(discretionary_group, discretionary); + set_group_code_value(insert_group, insert); + set_group_code_value(vadjust_group, vadjust); + set_group_code_value(vcenter_group, vcenter); + set_group_code_value(math_fraction_group, mathfraction); + set_group_code_value(math_radical_group, mathradical); + set_group_code_value(math_operator_group, mathoperator); + set_group_code_value(math_choice_group, mathchoice); + set_group_code_value(also_simple_group, alsosimple); + set_group_code_value(semi_simple_group, semisimple); + set_group_code_value(math_simple_group, mathsimple); + set_group_code_value(math_shift_group, mathshift); + set_group_code_value(math_fence_group, mathfence); + set_group_code_value(local_box_group, localbox); + set_group_code_value(split_off_group, splitoff); + set_group_code_value(split_keep_group, splitkeep); + set_group_code_value(preamble_group, preamble); + set_group_code_value(align_set_group, alignset); + set_group_code_value(finish_row_group, finishrow); + set_group_code_value(lua_group, lua); lmt_interface.par_context_values = lmt_aux_allocate_value_info(reset_par_context); diff --git a/source/luametatex/source/lua/lmtinterface.h b/source/luametatex/source/lua/lmtinterface.h index e55b03e84..3fd87db2f 100644 --- a/source/luametatex/source/lua/lmtinterface.h +++ b/source/luametatex/source/lua/lmtinterface.h @@ -484,6 +484,7 @@ make_lua_key(L, binradspacing);\ make_lua_key(L, binrelspacing);\ make_lua_key(L, boolean);\ make_lua_key(L, bottomaccent);\ +make_lua_key(L, bottomanchor);\ make_lua_key(L, bottomaccentvariant);\ make_lua_key(L, bothflexible);\ make_lua_key(L, bottom);\ @@ -491,6 +492,7 @@ make_lua_key(L, bottomleft);\ make_lua_key(L, bottomlevel);\ make_lua_key(L, bottommargin);\ make_lua_key(L, bottomright);\ +make_lua_key(L, bottomovershoot);\ make_lua_key(L, boundary);\ make_lua_key(L, box);\ make_lua_key(L, broken);\ @@ -879,11 +881,13 @@ make_lua_key(L, math_style);\ make_lua_key(L, mathtextchar);\ make_lua_key(L, mathchar);\ make_lua_key(L, mathchoice);\ +make_lua_key(L, mathcomponent);\ make_lua_key(L, MathConstants);\ make_lua_key(L, mathcontrol);\ make_lua_key(L, mathdir);\ make_lua_key(L, mathfence);\ make_lua_key(L, mathfraction);\ +make_lua_key(L, mathradical);\ make_lua_key(L, mathkerns);\ make_lua_key(L, MathLeading);\ make_lua_key(L, mathoperator);\ @@ -894,6 +898,8 @@ make_lua_key(L, mathshapekern);\ make_lua_key(L, mathshift);\ make_lua_key(L, mathsimple);\ make_lua_key(L, mathskip);\ +make_lua_key(L, mathstack);\ +make_lua_key(L, mathsubformula);\ make_lua_key(L, mathstyle);\ make_lua_key(L, medmuskip);\ make_lua_key(L, message);\ @@ -911,6 +917,7 @@ make_lua_key(L, middlepunctspacing);\ make_lua_key(L, middleradspacing);\ make_lua_key(L, middlerelspacing);\ make_lua_key(L, MinConnectorOverlap);\ +make_lua_key(L, mirror);\ make_lua_key(L, mkern);\ make_lua_key(L, mode);\ make_lua_key(L, modeline);\ @@ -956,7 +963,6 @@ make_lua_key(L, nucleus);\ make_lua_key(L, number);\ make_lua_key(L, numerator);\ make_lua_key(L, numeratorvariant);\ -make_lua_key(L, oldmath);\ make_lua_key(L, op);\ make_lua_key(L, opbinspacing);\ make_lua_key(L, opclosespacing);\ @@ -1094,6 +1100,7 @@ make_lua_key(L, protected_call);\ make_lua_key(L, protrudechars);\ make_lua_key(L, protrusion);\ make_lua_key(L, properties);\ +make_lua_key(L, proportional);\ make_lua_key(L, ptr);\ make_lua_key(L, punct);\ make_lua_key(L, punctbinspacing);\ @@ -1352,11 +1359,13 @@ make_lua_key(L, tolerant_call);\ make_lua_key(L, tolerant_protected_call);\ make_lua_key(L, top);\ make_lua_key(L, topaccent);\ +make_lua_key(L, topanchor);\ make_lua_key(L, topaccentvariant);\ make_lua_key(L, topleft);\ make_lua_key(L, topmargin);\ make_lua_key(L, topright);\ make_lua_key(L, topskip);\ +make_lua_key(L, topovershoot);\ make_lua_key(L, total);\ make_lua_key(L, tracingparagraphs);\ make_lua_key(L, trailer);\ @@ -1662,32 +1671,6 @@ extern void lmt_initialize_interface(void); # define lmt_toroundnumber lmt_roundnumber # define lmt_touroundnumber lmt_uroundnumber -/* -# define lua_set_string_by_key(L,a,b) \ - lua_pushstring(L, b ? b : ""); \ - lua_setfield(L, -2, a); - -# define lua_set_string_by_index(L,a,b) \ - lua_pushstring(L, b ? b : ""); \ - lua_rawseti(L, -2, a); - -# define lua_set_integer_by_key(L,a,b) \ - lua_pushinteger(L, b); \ - lua_setfield(L, -2, a); - -# define lua_set_integer_by_index(L,a,b) \ - lua_pushinteger(L, b); \ - lua_rawseti(L, -2, a); - -# define lua_set_boolean_by_key(L,a,b) \ - lua_pushboolean(L, b); \ - lua_setfield(L, -2, a); - -# define lua_set_boolean_by_index(L,a,b) \ - lua_pushboolean(L, b); \ - lua_rawseti(L, -2, a); -*/ - inline static void lua_set_string_by_key(lua_State *L, const char *a, const char *b) { lua_pushstring(L, b ? b : ""); diff --git a/source/luametatex/source/lua/lmtnodelib.c b/source/luametatex/source/lua/lmtnodelib.c index ff98a7064..7d9d7bcbe 100644 --- a/source/luametatex/source/lua/lmtnodelib.c +++ b/source/luametatex/source/lua/lmtnodelib.c @@ -715,8 +715,12 @@ static int nodelib_direct_getfam(lua_State *L) case delimiter_node: lua_pushinteger(L, delimiter_small_family(n)); break; - case fraction_noad: case simple_noad: + case radical_noad: + case fraction_noad: + case accent_noad: + case fence_noad: + /*tex Not all are used or useful at the tex end! */ lua_pushinteger(L, noad_family(n)); break; case rule_node: @@ -744,8 +748,12 @@ static int nodelib_direct_setfam(lua_State *L) case delimiter_node: delimiter_small_family(n) = lmt_tohalfword(L, 2); break; - case fraction_noad: case simple_noad: + case radical_noad: + case fraction_noad: + case accent_noad: + case fence_noad: + /*tex Not all are used or useful at the tex end! */ set_noad_family(n, lmt_tohalfword(L, 2)); break; case rule_node: @@ -6557,10 +6565,7 @@ static int nodelib_common_getfield(lua_State *L, int direct, halfword n) break; case insert_node: if (lua_key_eq(s, index)) { - halfword index = lmt_tohalfword(L, 3); - if (tex_valid_insert_id(index)) { - insert_index(n) = index; - } + lua_pushinteger(L, insert_index(n)); } else if (lua_key_eq(s, cost)) { lua_pushinteger(L, insert_float_cost(n)); } else if (lua_key_eq(s, depth)) { @@ -6647,6 +6652,8 @@ static int nodelib_common_getfield(lua_State *L, int direct, halfword n) lua_pushinteger(L, get_noad_left_class(n)); lua_pushinteger(L, get_noad_right_class(n)); return 3; + } else if (lua_key_eq(s, fam)) { + lua_pushinteger(L, noad_family(n)); } else { switch(t) { case simple_noad: @@ -6678,8 +6685,6 @@ static int nodelib_common_getfield(lua_State *L, int direct, halfword n) nodelib_push_direct_or_nil(L, fraction_right_delimiter(n)); } else if (lua_key_eq(s, middle)) { nodelib_push_direct_or_nil(L, fraction_middle_delimiter(n)); - } else if (lua_key_eq(s, fam)) { - lua_pushinteger(L, noad_family(n)); } else { lua_pushnil(L); } @@ -7321,10 +7326,11 @@ static int nodelib_common_setfield(lua_State *L, int direct, halfword n) set_noad_main_class(n, c); set_noad_left_class(n, lmt_opthalfword(L, 4, c)); set_noad_right_class(n, lmt_opthalfword(L, 5, c)); + } else if (lua_key_eq(s, fam)) { + set_noad_family(n, lmt_tohalfword(L, 3)); } else { switch (t) { case simple_noad: - // return nodelib_cantset(L, n, s); break; case radical_noad: if (lua_key_eq(s, left) || lua_key_eq(s, delimiter)) { @@ -7352,8 +7358,6 @@ static int nodelib_common_setfield(lua_State *L, int direct, halfword n) fraction_right_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3); } else if (lua_key_eq(s, middle)) { fraction_middle_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3); - } else if (lua_key_eq(s, fam)) { - set_noad_family(n, lmt_tohalfword(L, 3)); } else { goto CANTSET; } @@ -9856,9 +9860,9 @@ halfword lmt_node_list_from_lua(lua_State *L, int n) */ void lmt_begin_paragraph_callback( - int invmode, + int invmode, int *indented, - int context + int context ) { int callback_id = lmt_callback_defined(begin_paragraph_callback); @@ -9884,7 +9888,7 @@ void lmt_begin_paragraph_callback( } void lmt_paragraph_context_callback( - int context, + int context, int *ignore ) { @@ -9975,14 +9979,14 @@ void lmt_append_line_filter_callback( void lmt_node_filter_callback( int filterid, int extrainfo, - halfword head_node, - halfword *tail_node + halfword head, + halfword *tail ) { - if (head_node) { + if (head) { /*tex We start after head (temp). */ - halfword start_node = node_next(head_node); - if (start_node) { + halfword start = node_next(head); + if (start) { int callback_id = lmt_callback_defined(filterid); if (callback_id > 0) { lua_State *L = lmt_lua_state.lua_instance; @@ -9990,33 +9994,33 @@ void lmt_node_filter_callback( if (lmt_callback_okay(L, callback_id, &top)) { int i; /*tex We make sure we have no prev */ - node_prev(start_node) = null; + node_prev(start) = null; /*tex the action */ - lmt_node_list_to_lua(L, start_node); + lmt_node_list_to_lua(L, start); lmt_push_group_code(L, extrainfo); i = lmt_callback_call(L, 2, 1, top); if (i) { lmt_callback_error(L, top, i); } else { /*tex append to old head */ - halfword start_done = lmt_node_list_from_lua(L, -1); - tex_try_couple_nodes(head_node, start_done); + halfword list = lmt_node_list_from_lua(L, -1); + tex_try_couple_nodes(head, list); /*tex redundant as we set top anyway */ lua_pop(L, 2); /*tex find tail in order to update tail */ - start_node = node_next(head_node); - if (start_node) { + start = node_next(head); + if (start) { /*tex maybe just always slide (harmless and fast) */ - halfword last_node = node_next(start_node); - while (last_node) { - start_node = last_node; - last_node = node_next(start_node); + halfword last = node_next(start); + while (last) { + start = last; + last = node_next(start); } /*tex we're at the end now */ - *tail_node = start_node; + *tail = start; } else { /*tex we're already at the end */ - *tail_node = head_node; + *tail = head; } lmt_callback_wrapup(L, top); } @@ -10032,14 +10036,14 @@ void lmt_node_filter_callback( */ int lmt_linebreak_callback( - int is_broken, - halfword head_node, - halfword *new_head + int isbroken, + halfword head, + halfword *newhead ) { - if (head_node) { - halfword start_node = node_next(head_node); - if (start_node) { + if (head) { + halfword start = node_next(head); + if (start) { int callback_id = lmt_callback_defined(linebreak_filter_callback); if (callback_id > 0) { lua_State *L = lmt_lua_state.lua_instance; @@ -10047,17 +10051,17 @@ int lmt_linebreak_callback( if (callback_id > 0 && lmt_callback_okay(L, callback_id, &top)) { int i; int ret = 0; - node_prev(start_node) = null; - lmt_node_list_to_lua(L, start_node); - lua_pushboolean(L, is_broken); + node_prev(start) = null; + lmt_node_list_to_lua(L, start); + lua_pushboolean(L, isbroken); i = lmt_callback_call(L, 2, 1, top); if (i) { lmt_callback_error(L, top, i); } else { - halfword *p = lua_touserdata(L, -1); - if (p) { - int a = lmt_node_list_from_lua(L, -1); - tex_try_couple_nodes(*new_head, a); + halfword *result = lua_touserdata(L, -1); + if (result) { + halfword list = lmt_node_list_from_lua(L, -1); + tex_try_couple_nodes(*newhead, list); ret = 1; } lmt_callback_wrapup(L, top); @@ -10071,22 +10075,22 @@ int lmt_linebreak_callback( } void lmt_alignment_callback( - halfword head_node, + halfword head, halfword context, - halfword attr_list, + halfword attrlist, halfword preamble ) { - if (head_node || preamble) { + if (head || preamble) { int callback_id = lmt_callback_defined(alignment_filter_callback); if (callback_id > 0) { lua_State *L = lmt_lua_state.lua_instance; int top = 0; if (lmt_callback_okay(L, callback_id, &top)) { int i; - lmt_node_list_to_lua(L, head_node); + lmt_node_list_to_lua(L, head); lmt_push_alignment_context(L, context); - lmt_node_list_to_lua(L, attr_list); + lmt_node_list_to_lua(L, attrlist); lmt_node_list_to_lua(L, preamble); i = lmt_callback_call(L, 4, 0, top); if (i) { @@ -10106,16 +10110,16 @@ void lmt_local_box_callback( halfword rightbox, halfword middlebox, halfword linenumber, - scaled leftskip, - scaled rightskip, - scaled lefthang, - scaled righthang, - scaled indentation, - scaled parinitleftskip, - scaled parinitrightskip, - scaled parfillleftskip, - scaled parfillrightskip, - scaled overshoot + scaled leftskip, + scaled rightskip, + scaled lefthang, + scaled righthang, + scaled indentation, + scaled parinitleftskip, + scaled parinitrightskip, + scaled parfillleftskip, + scaled parfillrightskip, + scaled overshoot ) { if (linebox) { @@ -10160,11 +10164,11 @@ void lmt_local_box_callback( int lmt_append_to_vlist_callback( halfword box, int location, - halfword prev_depth, + halfword prevdepth, halfword *result, - int *next_depth, - int *prev_set, - int *check_depth + int *nextdepth, + int *prevset, + int *checkdepth ) { if (box) { @@ -10176,7 +10180,7 @@ int lmt_append_to_vlist_callback( int i; lmt_node_list_to_lua(L, box); lua_push_key_by_index(location); - lua_pushinteger(L, (int) prev_depth); + lua_pushinteger(L, (int) prevdepth); i = lmt_callback_call(L, 3, 3, top); if (i) { lmt_callback_error(L, top, i); @@ -10193,11 +10197,11 @@ int lmt_append_to_vlist_callback( break; } if (lua_type(L, -2) == LUA_TNUMBER) { - *next_depth = lmt_roundnumber(L, -2); - *prev_set = 1; + *nextdepth = lmt_roundnumber(L, -2); + *prevset = 1; } if (*result && lua_type(L, -1) == LUA_TBOOLEAN) { - *check_depth = lua_toboolean(L, -1); + *checkdepth = lua_toboolean(L, -1); } lmt_callback_wrapup(L, top); return 1; @@ -10214,28 +10218,28 @@ int lmt_append_to_vlist_callback( */ halfword lmt_hpack_filter_callback( - halfword head_node, + halfword head, scaled size, - int pack_type, + int packtype, int extrainfo, - int pack_direction, + int direction, halfword attr ) { - if (head_node) { + if (head) { int callback_id = lmt_callback_defined(hpack_filter_callback); if (callback_id > 0) { lua_State *L = lmt_lua_state.lua_instance; int top = 0; if (lmt_callback_okay(L, callback_id, &top)) { int i; - node_prev(head_node) = null; - lmt_node_list_to_lua(L, head_node); + node_prev(head) = null; + lmt_node_list_to_lua(L, head); lmt_push_group_code(L, extrainfo); lua_pushinteger(L, size); - lmt_push_pack_type(L, pack_type); - if (pack_direction >= 0) { - lua_pushinteger(L, pack_direction); + lmt_push_pack_type(L, packtype); + if (direction >= 0) { + lua_pushinteger(L, direction); } else { lua_pushnil(L); } @@ -10245,13 +10249,13 @@ halfword lmt_hpack_filter_callback( if (i) { lmt_callback_error(L, top, i); } else { - head_node = lmt_node_list_from_lua(L, -1); + head = lmt_node_list_from_lua(L, -1); lmt_callback_wrapup(L, top); } } } } - return head_node; + return head; } extern halfword lmt_packed_vbox_filter_callback( @@ -10282,30 +10286,30 @@ extern halfword lmt_packed_vbox_filter_callback( } halfword lmt_vpack_filter_callback( - halfword head_node, + halfword head, scaled size, - int pack_type, - scaled maxd, + int packtype, + scaled maxdepth, int extrainfo, - int pack_direction, + int direction, halfword attr ) { - if (head_node) { + if (head) { int callback_id = lmt_callback_defined(extrainfo == output_group ? pre_output_filter_callback : vpack_filter_callback); if (callback_id > 0) { lua_State *L = lmt_lua_state.lua_instance; int top = 0; if (lmt_callback_okay(L, callback_id, &top)) { int i; - node_prev(head_node) = null; - lmt_node_list_to_lua(L, head_node); + node_prev(head) = null; + lmt_node_list_to_lua(L, head); lmt_push_group_code(L, extrainfo); lua_pushinteger(L, size); - lmt_push_pack_type(L, pack_type); - lua_pushinteger(L, maxd); - if (pack_direction >= 0) { - lua_pushinteger(L, pack_direction); + lmt_push_pack_type(L, packtype); + lua_pushinteger(L, maxdepth); + if (direction >= 0) { + lua_pushinteger(L, direction); } else { lua_pushnil(L); } @@ -10314,11 +10318,11 @@ halfword lmt_vpack_filter_callback( if (i) { lmt_callback_error(L, top, i); } else { - head_node = lmt_node_list_from_lua(L, -1); + head = lmt_node_list_from_lua(L, -1); lmt_callback_wrapup(L, top); } } } } - return head_node; + return head; } diff --git a/source/luametatex/source/lua/lmtnodelib.h b/source/luametatex/source/lua/lmtnodelib.h index 6894104b2..c32be142d 100644 --- a/source/luametatex/source/lua/lmtnodelib.h +++ b/source/luametatex/source/lua/lmtnodelib.h @@ -18,21 +18,21 @@ extern halfword lmt_check_isdirectornode (lua_State *L, int i, int *isdirect); extern void lmt_initialize_properties (int set_size); extern halfword lmt_hpack_filter_callback( - halfword head_node, + halfword head, scaled size, - int pack_type, + int packtype, int extrainfo, - int d, + int direction, halfword a ); extern halfword lmt_vpack_filter_callback( - halfword head_node, + halfword head, scaled size, - int pack_type, - scaled maxd, + int packtype, + scaled depth, int extrainfo, - int d, + int direction, halfword a ); @@ -44,20 +44,20 @@ extern halfword lmt_packed_vbox_filter_callback( extern void lmt_node_filter_callback( int filterid, int extrainfo, - halfword head_node, - halfword *tail_node + halfword head, + halfword *tail ); extern int lmt_linebreak_callback( - int is_broken, - halfword head_node, - halfword *new_head + int isbroken, + halfword head, + halfword *newhead ); extern void lmt_alignment_callback( - halfword head_node, + halfword head, halfword context, - halfword attr_list, + halfword attrlist, halfword preamble ); @@ -67,26 +67,26 @@ extern void lmt_local_box_callback( halfword rightbox, halfword middlebox, halfword linenumber, - scaled leftskip, - scaled rightskip, - scaled lefthang, - scaled righthang, - scaled indentation, - scaled parinitleftskip, - scaled parinitrightskip, - scaled parfillleftskip, - scaled parfillrightskip, - scaled overshoot + scaled leftskip, + scaled rightskip, + scaled lefthang, + scaled righthang, + scaled indentation, + scaled parinitleftskip, + scaled parinitrightskip, + scaled parfillleftskip, + scaled parfillrightskip, + scaled overshoot ); extern int lmt_append_to_vlist_callback( halfword box, int location, - halfword prev_depth, + halfword prevdepth, halfword *result, - int *next_depth, - int *prev_set, - int *check_depth + int *nextdepth, + int *prevset, + int *checkdepth ); extern void lmt_begin_paragraph_callback( diff --git a/source/luametatex/source/lua/lmttexlib.c b/source/luametatex/source/lua/lmttexlib.c index 12510206a..d44127330 100644 --- a/source/luametatex/source/lua/lmttexlib.c +++ b/source/luametatex/source/lua/lmttexlib.c @@ -1392,27 +1392,6 @@ static int texlib_getdimen(lua_State *L) return 1; } -// static halfword texlib_aux_make_glue(lua_State *L, int top, int slot) -// { -// halfword value = copy_node(zero_glue); -// if (++slot <= top) { -// glue_amount(value) = lmt_toroundnumber(L, slot); -// if (++slot <= top) { -// glue_stretch(value) = lmt_toroundnumber(L, slot); -// if (++slot <= top) { -// glue_shrink(value) = lmt_toroundnumber(L, slot); -// if (++slot <= top) { -// glue_stretch_order(value) = lmt_tohalfword(L, slot); -// if (++slot <= top) { -// glue_shrink_order(value) = lmt_tohalfword(L, slot); -// } -// } -// } -// } -// } -// return value; -// } - static halfword texlib_aux_make_glue(lua_State *L, int top, int slot) { halfword value = tex_copy_node(zero_glue); @@ -2624,6 +2603,7 @@ static int texlib_aux_convert(lua_State *L, int cur_code) case insert_progress_code: /* arg <register int> */ case lua_code: /* arg complex */ case lua_escape_string_code: /* arg token list */ + /* case lua_token_string_code: */ /* arg token list */ case string_code: /* arg token */ case cs_string_code: /* arg token */ case detokenized_code: /* arg token */ @@ -4361,7 +4341,7 @@ static int texlib_runstring(lua_State *L) static int texlib_getmathdir(lua_State *L) { lua_pushinteger(L, math_direction_par); - return 0; + return 1; } static int texlib_setmathdir(lua_State *L) @@ -4824,6 +4804,7 @@ static int texlib_getnoadoptionvalues(lua_State *L) lua_push_key_at_index(L, auto, noad_option_auto); lua_push_key_at_index(L, unrolllist, noad_option_unroll_list); lua_push_key_at_index(L, followedbyspace, noad_option_followed_by_space); + lua_push_key_at_index(L, proportional, noad_option_proportional); return 1; } @@ -4943,6 +4924,7 @@ static int texlib_getmathclassoptionvalues(lua_State *L) lua_set_string_by_index(L, prefer_delimiter_dimensions_class_option, "preferdelimiterdimensions"); lua_set_string_by_index(L, auto_inject_class_option, "autoinject"); lua_set_string_by_index(L, remove_italic_correction_class_option, "removeitaliccorrection"); + lua_set_string_by_index(L, operator_italic_correction_class_option, "operatoritaliccorrection"); return 1; } @@ -5025,6 +5007,20 @@ static int texlib_getfrozenparvalues(lua_State *L) return 1; } +static int texlib_getkerneloptionvalues(lua_State *L) +{ + lua_createtable(L, 2, 6); + lua_set_string_by_index(L, math_kernel_no_italic_correction, "noitaliccorrection"); + lua_set_string_by_index(L, math_kernel_no_left_pair_kern, "noleftpairkern"); + lua_set_string_by_index(L, math_kernel_no_right_pair_kern, "norightpairkern"); + lua_set_string_by_index(L, math_kernel_auto_discretionary, "autodiscretionary"); + lua_set_string_by_index(L, math_kernel_full_discretionary, "fulldiscretionary"); + lua_set_string_by_index(L, math_kernel_ignored_character, "ignoredcharacter"); + lua_set_string_by_index(L, math_kernel_is_large_operator, "islargeoperator"); + lua_set_string_by_index(L, math_kernel_has_italic_shape, "hasitalicshape"); + return 1; +} + static int texlib_getshapingpenaltiesvalues(lua_State *L) { lua_createtable(L, 2, 2); @@ -5035,7 +5031,6 @@ static int texlib_getshapingpenaltiesvalues(lua_State *L) return 1; } - static int texlib_getprimitiveorigins(lua_State *L) { lua_createtable(L, 2, 1); @@ -5163,7 +5158,7 @@ static int texlib_getdiscstatevalues(lua_State *L) static int texlib_getmathcontrolvalues(lua_State *L) { - lua_createtable(L, 2, 19); + lua_createtable(L, 2, 21); lua_set_string_by_index(L, math_control_use_font_control, "usefontcontrol"); lua_set_string_by_index(L, math_control_over_rule, "overrule"); lua_set_string_by_index(L, math_control_under_rule, "underrule"); @@ -5185,6 +5180,8 @@ static int texlib_getmathcontrolvalues(lua_State *L) lua_set_string_by_index(L, math_control_analyze_script_nucleus_char, "analyzescriptnucleuschar"); lua_set_string_by_index(L, math_control_analyze_script_nucleus_list, "analyzescriptnucleuslist"); lua_set_string_by_index(L, math_control_analyze_script_nucleus_box, "analyzescriptnucleusbox"); + lua_set_string_by_index(L, math_control_accent_top_skew_with_offset, "accenttopskewwithoffset"); + lua_set_string_by_index(L, math_control_ignore_kern_dimensions, "ignorekerndimensions"); return 1; } @@ -5484,6 +5481,7 @@ static const struct luaL_Reg texlib_function_list[] = { { "getprimitiveorigins", texlib_getprimitiveorigins }, { "getfrozenparvalues", texlib_getfrozenparvalues }, { "getshapingpenaltiesvalues", texlib_getshapingpenaltiesvalues }, + { "getkerneloptionvalues", texlib_getkerneloptionvalues }, { "getspecialmathclassvalues", texlib_getspecialmathclassvalues }, { "getlargestusedmark", texlib_getlargestusedmark }, { "getoutputactive", texlib_getoutputactive }, diff --git a/source/luametatex/source/lua/lmttokenlib.c b/source/luametatex/source/lua/lmttokenlib.c index 896b22eec..ac69241ba 100644 --- a/source/luametatex/source/lua/lmttokenlib.c +++ b/source/luametatex/source/lua/lmttokenlib.c @@ -3146,9 +3146,9 @@ static int tokenlib_save_lua(lua_State *L) while (1) { --ptr; switch (save_type(ptr)) { - case level_boundary: + case level_boundary_save_type: goto SAVE; - case restore_lua: + case restore_lua_save_type: if (save_value(ptr) == f) { return 0; } else { @@ -3158,7 +3158,7 @@ static int tokenlib_save_lua(lua_State *L) } } SAVE: - tex_save_halfword_on_stack(restore_lua, f); + tex_save_halfword_on_stack(restore_lua_save_type, f); return 0; } diff --git a/source/luametatex/source/luacore/lua54/src/lobject.c b/source/luametatex/source/luacore/lua54/src/lobject.c index a2c006098..03e2798ca 100644 --- a/source/luametatex/source/luacore/lua54/src/lobject.c +++ b/source/luametatex/source/luacore/lua54/src/lobject.c @@ -62,7 +62,7 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, case LUA_OPBOR: return intop(|, v1, v2); case LUA_OPBXOR: return intop(^, v1, v2); case LUA_OPSHL: return luaV_shiftl(v1, v2); - case LUA_OPSHR: return luaV_shiftl(v1, -v2); + case LUA_OPSHR: return luaV_shiftr(v1, v2); case LUA_OPUNM: return intop(-, 0, v1); case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); default: lua_assert(0); return 0; diff --git a/source/luametatex/source/luacore/lua54/src/loslib.c b/source/luametatex/source/luacore/lua54/src/loslib.c index 3e20d622b..854dcf691 100644 --- a/source/luametatex/source/luacore/lua54/src/loslib.c +++ b/source/luametatex/source/luacore/lua54/src/loslib.c @@ -260,9 +260,7 @@ static int getfield (lua_State *L, const char *key, int d, int delta) { res = d; } else { - /* unsigned avoids overflow when lua_Integer has 32 bits */ - if (!(res >= 0 ? (lua_Unsigned)res <= (lua_Unsigned)INT_MAX + delta - : (lua_Integer)INT_MIN + delta <= res)) + if (!(res >= 0 ? res - delta <= INT_MAX : INT_MIN + delta <= res)) return luaL_error(L, "field '%s' is out-of-bound", key); res -= delta; } diff --git a/source/luametatex/source/luacore/lua54/src/lutf8lib.c b/source/luametatex/source/luacore/lua54/src/lutf8lib.c index e7bf098f6..3a5b9bc38 100644 --- a/source/luametatex/source/luacore/lua54/src/lutf8lib.c +++ b/source/luametatex/source/luacore/lua54/src/lutf8lib.c @@ -25,6 +25,9 @@ #define MAXUTF 0x7FFFFFFFu + +#define MSGInvalid "invalid UTF-8 code" + /* ** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits. */ @@ -35,7 +38,8 @@ typedef unsigned long utfint; #endif -#define iscont(p) ((*(p) & 0xC0) == 0x80) +#define iscont(c) (((c) & 0xC0) == 0x80) +#define iscontp(p) iscont(*(p)) /* from strlib */ @@ -65,7 +69,7 @@ static const char *utf8_decode (const char *s, utfint *val, int strict) { int count = 0; /* to count number of continuation bytes */ for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ unsigned int cc = (unsigned char)s[++count]; /* read next byte */ - if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + if (!iscont(cc)) /* not a continuation byte? */ return NULL; /* invalid byte sequence */ res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ } @@ -140,7 +144,7 @@ static int codepoint (lua_State *L) { utfint code; s = utf8_decode(s, &code, !lax); if (s == NULL) - return luaL_error(L, "invalid UTF-8 code"); + return luaL_error(L, MSGInvalid); lua_pushinteger(L, code); n++; } @@ -190,16 +194,16 @@ static int byteoffset (lua_State *L) { "position out of bounds"); if (n == 0) { /* find beginning of current byte sequence */ - while (posi > 0 && iscont(s + posi)) posi--; + while (posi > 0 && iscontp(s + posi)) posi--; } else { - if (iscont(s + posi)) + if (iscontp(s + posi)) return luaL_error(L, "initial position is a continuation byte"); if (n < 0) { while (n < 0 && posi > 0) { /* move back */ do { /* find beginning of previous character */ posi--; - } while (posi > 0 && iscont(s + posi)); + } while (posi > 0 && iscontp(s + posi)); n++; } } @@ -208,7 +212,7 @@ static int byteoffset (lua_State *L) { while (n > 0 && posi < (lua_Integer)len) { do { /* find beginning of next character */ posi++; - } while (iscont(s + posi)); /* (cannot pass final '\0') */ + } while (iscontp(s + posi)); /* (cannot pass final '\0') */ n--; } } @@ -226,15 +230,15 @@ static int iter_aux (lua_State *L, int strict) { const char *s = luaL_checklstring(L, 1, &len); lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2); if (n < len) { - while (iscont(s + n)) n++; /* skip continuation bytes */ + while (iscontp(s + n)) n++; /* go to next character */ } if (n >= len) /* (also handles original 'n' being negative) */ return 0; /* no more codepoints */ else { utfint code; const char *next = utf8_decode(s + n, &code, strict); - if (next == NULL) - return luaL_error(L, "invalid UTF-8 code"); + if (next == NULL || iscontp(next)) + return luaL_error(L, MSGInvalid); lua_pushinteger(L, n + 1); lua_pushinteger(L, code); return 2; @@ -253,7 +257,8 @@ static int iter_auxlax (lua_State *L) { static int iter_codes (lua_State *L) { int lax = lua_toboolean(L, 2); - luaL_checkstring(L, 1); + const char *s = luaL_checkstring(L, 1); + luaL_argcheck(L, !iscontp(s), 1, MSGInvalid); lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict); lua_pushvalue(L, 1); lua_pushinteger(L, 0); diff --git a/source/luametatex/source/luacore/lua54/src/lvm.c b/source/luametatex/source/luacore/lua54/src/lvm.c index 614df0557..73a19ba9b 100644 --- a/source/luametatex/source/luacore/lua54/src/lvm.c +++ b/source/luametatex/source/luacore/lua54/src/lvm.c @@ -765,12 +765,10 @@ lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) { /* number of bits in an integer */ #define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) + /* ** Shift left operation. (Shift right just negates 'y'.) */ -#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) - - lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { if (y < 0) { /* shift right? */ if (y <= -NBITS) return 0; diff --git a/source/luametatex/source/luacore/lua54/src/lvm.h b/source/luametatex/source/luacore/lua54/src/lvm.h index 1bc16f3a5..dba1ad277 100644 --- a/source/luametatex/source/luacore/lua54/src/lvm.h +++ b/source/luametatex/source/luacore/lua54/src/lvm.h @@ -110,6 +110,11 @@ typedef enum { luaC_barrierback(L, gcvalue(t), v); } +/* +** Shift right is the same as shift left with a negative 'y' +*/ +#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) + LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); diff --git a/source/luametatex/source/luametatex.h b/source/luametatex/source/luametatex.h index c2536f461..32fd78f6d 100644 --- a/source/luametatex/source/luametatex.h +++ b/source/luametatex/source/luametatex.h @@ -76,6 +76,7 @@ 2.09.35 : near the end of 2021 (so close to the 2.10 release date) 2.09.55 : in July 2022 (the official release of the new math engine) 2.10.00 : a few days before the ctx 2022 meeting (starting September 19) + 2.10.01 : mid October 2022 At some point the \CONTEXT\ group will be responsible for guaranteeing that the official version is what comes with \CONTEXT\ and that long term support and stabilty is guaranteed and that no @@ -86,9 +87,9 @@ # include "tex/textypes.h" # define luametatex_version 210 -# define luametatex_revision 00 -# define luametatex_version_string "2.10.00" -# define luametatex_development_id 20220918 +# define luametatex_revision 01 +# define luametatex_version_string "2.10.01" +# define luametatex_development_id 20221014 # define luametatex_name_camelcase "LuaMetaTeX" # define luametatex_name_lowercase "luametatex" diff --git a/source/luametatex/source/mp/mpc/mp.c b/source/luametatex/source/mp/mpc/mp.c index 0e9c4bf2d..993bf98fb 100644 --- a/source/luametatex/source/mp/mpc/mp.c +++ b/source/luametatex/source/mp/mpc/mp.c @@ -1882,6 +1882,8 @@ static const char *mp_op_string (int c) case mp_unequal_operation : return "<>"; case mp_concatenate_operation : return "&"; case mp_just_append_operation : return "&&"; + case mp_tolerant_concat_operation : return "&&&"; + case mp_tolerant_append_operation : return "&&&&"; case mp_rotated_operation : return "rotated"; case mp_slanted_operation : return "slanted"; case mp_scaled_operation : return "scaled"; @@ -17230,6 +17232,8 @@ static void mp_do_binary (MP mp, mp_node p, int c) break; case mp_concatenate_operation: case mp_just_append_operation: + case mp_tolerant_concat_operation: + case mp_tolerant_append_operation: if ((mp->cur_exp.type == mp_string_type) && (mp_type(p) == mp_string_type)) { mp_string str = mp_cat(mp, mp_get_value_str(p), cur_exp_str); delete_str_ref(cur_exp_str) ; @@ -21505,7 +21509,7 @@ static int mp_scan_path (MP mp) mp_left_type(pp) = mp_open_knot; mp_right_type(qq) = mp_open_knot; } - if (d == mp_ampersand_command && dd != mp_just_append_operation) { + if (d == mp_ampersand_command && dd != mp_just_append_operation && dd != mp_tolerant_concat_operation && dd != mp_tolerant_append_operation) { if (! (number_equal(path_q->x_coord, pp->x_coord)) || ! (number_equal(path_q->y_coord, pp->y_coord))) { mp_back_error( mp, @@ -21524,6 +21528,22 @@ static int mp_scan_path (MP mp) number_clone(pp->right_given, x); } if (d == mp_ampersand_command) { + if (dd == mp_tolerant_concat_operation || dd == mp_tolerant_append_operation) { + mp_number dx, dy; + set_number_from_subtraction(dx, path_q->x_coord, pp->x_coord); + set_number_from_subtraction(dy, path_q->y_coord, pp->y_coord); + number_abs(dx); + number_abs(dy); + if (number_lessequal(dx, epsilon_t) && number_lessequal(dy, epsilon_t)) { + set_number_half_from_addition(dx, path_q->x_coord, pp->x_coord); + set_number_half_from_addition(dy, path_q->y_coord, pp->y_coord); + number_clone(pp->left_x, dx); + number_clone(path_q->right_x, dx); + number_clone(pp->left_y, dy); + number_clone(path_q->right_y, dy); + } + dd = dd == mp_tolerant_concat_operation ? mp_concatenate_operation : mp_just_append_operation; + } if (dd == mp_just_append_operation) { mp_left_type(pp) = mp_explicit_knot; mp_right_type(path_q) = mp_explicit_knot; @@ -21927,6 +21947,8 @@ void mp_final_cleanup (MP mp) mp_primitive(mp, "mpversion", mp_nullary_command, mp_version_operation); mp_primitive(mp, "&", mp_ampersand_command, mp_concatenate_operation); mp_primitive(mp, "&&", mp_ampersand_command, mp_just_append_operation); + mp_primitive(mp, "&&&", mp_ampersand_command, mp_tolerant_concat_operation); + mp_primitive(mp, "&&&&", mp_ampersand_command, mp_tolerant_append_operation); mp_primitive(mp, "rotated", mp_secondary_binary_command, mp_rotated_operation); mp_primitive(mp, "slanted", mp_secondary_binary_command, mp_slanted_operation); mp_primitive(mp, "scaled", mp_secondary_binary_command, mp_scaled_operation); diff --git a/source/luametatex/source/mp/mpc/mp.h b/source/luametatex/source/mp/mpc/mp.h index 252a625aa..2542bffaa 100644 --- a/source/luametatex/source/mp/mpc/mp.h +++ b/source/luametatex/source/mp/mpc/mp.h @@ -606,6 +606,8 @@ typedef enum mp_name_type_type { mp_unequal_operation, mp_concatenate_operation, mp_just_append_operation, + mp_tolerant_concat_operation, + mp_tolerant_append_operation, mp_rotated_operation, mp_slanted_operation, mp_scaled_operation, diff --git a/source/luametatex/source/mp/mpw/mp.w b/source/luametatex/source/mp/mpw/mp.w index 017cc0fd7..a7a1a9b7d 100644 --- a/source/luametatex/source/mp/mpw/mp.w +++ b/source/luametatex/source/mp/mpw/mp.w @@ -2552,117 +2552,119 @@ use a function call), @d mp_min_of_operation mp_substring_operation @<Operation codes@>= -mp_true_operation, /* operation code for |true| */ -mp_false_operation, /* operation code for |false| */ -mp_null_picture_operation, /* operation code for |nullpicture| */ -mp_null_pen_operation, /* operation code for |nullpen| */ -mp_read_string_operation, /* operation code for |readstring| */ -mp_pen_circle_operation, /* operation code for |pencircle| */ -mp_normal_deviate_operation, /* operation code for |normaldeviate| */ -mp_read_from_operation, /* operation code for |readfrom| */ -mp_close_from_operation, /* operation code for |closefrom| */ -mp_odd_operation, /* operation code for |odd| */ -mp_known_operation, /* operation code for |known| */ -mp_unknown_operation, /* operation code for |unknown| */ -mp_not_operation, /* operation code for |not| */ -mp_decimal_operation, /* operation code for |decimal| */ -mp_reverse_operation, /* operation code for |reverse| */ -mp_uncycle_operation, /* operation code for |uncycle| */ -mp_make_path_operation, /* operation code for |makepath| */ -mp_make_pen_operation, /* operation code for |makepen| */ -mp_make_nep_operation, /* operation code for |makenep| */ -mp_convexed_operation, /* operation code for |convexed| */ -mp_uncontrolled_operation, /* operation code for |uncontrolled| */ -mp_oct_operation, /* operation code for |oct| */ -mp_hex_operation, /* operation code for |hex| */ -mp_ASCII_operation, /* operation code for |ASCII| */ -mp_char_operation, /* operation code for |char| */ -mp_length_operation, /* operation code for |length| */ -mp_turning_operation, /* operation code for |turningnumber| */ -mp_color_model_operation, /* operation code for |colormodel| */ -mp_path_part_operation, /* operation code for |pathpart| */ -mp_pen_part_operation, /* operation code for |penpart| */ -mp_dash_part_operation, /* operation code for |dashpart| */ -mp_prescript_part_operation, /* operation code for |prescriptpart| */ -mp_postscript_part_operation, /* operation code for |postscriptpart| */ -mp_stacking_part_operation, /* operation code for |stackingpart| */ -mp_sqrt_operation, /* operation code for |sqrt| */ -mp_m_exp_operation, /* operation code for |mexp| */ -mp_m_log_operation, /* operation code for |mlog| */ -mp_sin_d_operation, /* operation code for |sind| */ -mp_cos_d_operation, /* operation code for |cosd| */ -mp_floor_operation, /* operation code for |floor| */ -mp_uniform_deviate_operation, /* operation code for |uniformdeviate| */ -mp_ll_corner_operation, /* operation code for |llcorner| */ -mp_lr_corner_operation, /* operation code for |lrcorner| */ -mp_ul_corner_operation, /* operation code for |ulcorner| */ -mp_ur_corner_operation, /* operation code for |urcorner| */ -mp_center_of_operation, /* operation code for |centerof| */ -mp_center_of_mass_operation, /* operation code for |centerofmass| */ -mp_corners_operation, /* operation code for |corners| */ -mp_x_range_operation, /* operation code for |xrange| */ -mp_y_range_operation, /* operation code for |yrange| */ -mp_delta_point_operation, /* operation code for |deltapoint| */ -mp_delta_precontrol_operation, /* operation code for |deltaprecontrol| */ -mp_delta_postcontrol_operation,/* operation code for |deltapostcontrol| */ -mp_delta_direction_operation, /* operation code for |deltadirection| */ -mp_arc_length_operation, /* operation code for |arclength| */ -mp_angle_operation, /* operation code for |angle| */ -mp_cycle_operation, /* operation code for |cycle| */ -mp_no_cycle_operation, /* operation code for |nocycle| */ -mp_filled_operation, /* operation code for |filled| */ -mp_stroked_operation, /* operation code for |stroked| */ -mp_clipped_operation, /* operation code for |clipped| */ -mp_grouped_operation, /* operation code for |bounded| */ -mp_bounded_operation, /* operation code for |grouped| */ -mp_plus_operation, /* operation code for \.+ */ -mp_minus_operation, /* operation code for \.- */ -mp_times_operation, /* operation code for \.* */ -mp_over_operation, /* operation code for \./ */ -mp_power_operation, /* operation code for \.^ */ -mp_pythag_add_operation, /* operation code for |++| */ -mp_pythag_sub_operation, /* operation code for |+-+| */ -mp_or_operation, /* operation code for |or| */ -mp_and_operation, /* operation code for |and| */ -mp_less_than_operation, /* operation code for \.< */ -mp_less_or_equal_operation, /* operation code for |<=| */ -mp_greater_than_operation, /* operation code for \.> */ -mp_greater_or_equal_operation, /* operation code for |>=| */ -mp_equal_operation, /* operation code for \.= */ -mp_unequal_operation, /* operation code for |<>| */ -mp_concatenate_operation, /* operation code for \.\& */ -mp_just_append_operation, /* operation code for \.\&\& */ -mp_rotated_operation, /* operation code for |rotated| */ -mp_slanted_operation, /* operation code for |slanted| */ -mp_scaled_operation, /* operation code for |scaled| */ -mp_shifted_operation, /* operation code for |shifted| */ -mp_transformed_operation, /* operation code for |transformed| */ -mp_uncycled_operation, /* operation code for |uncycled| */ -mp_x_scaled_operation, /* operation code for |xscaled| */ -mp_y_scaled_operation, /* operation code for |yscaled| */ -mp_z_scaled_operation, /* operation code for |zscaled| */ -mp_intertimes_operation, /* operation code for |intersectiontimes| */ -mp_intertimes_list_operation, /* operation code for |intersectiontimeslist| */ -mp_double_dot_operation, /* operation code for improper |..| */ -mp_substring_operation, /* operation code for |substring| */ -mp_subpath_operation, /* operation code for |subpath| */ -mp_direction_time_operation, /* operation code for |directiontime| */ -mp_point_operation, /* operation code for |point| */ -mp_precontrol_operation, /* operation code for |precontrol| */ -mp_postcontrol_operation, /* operation code for |postcontrol| */ -mp_direction_operation, /* operation code for |direction| */ -mp_path_point_operation, /* operation code for |pathpoint| */ -mp_path_precontrol_operation, /* operation code for |pathprecontrol| */ -mp_path_postcontrol_operation, /* operation code for |pathpostcontrol| */ -mp_path_direction_operation, /* operation code for |pathdirection| */ -mp_pen_offset_operation, /* operation code for |penoffset| */ -mp_arc_time_operation, /* operation code for |arctime| */ -mp_arc_point_operation, /* operation code for |arcpoint| */ -mp_arc_point_list_operation, /* operation code for |arcpointlist| */ -mp_subarc_length_operation, /* operation code for |subarclength| */ -mp_version_operation, /* operation code for |mpversion| */ -mp_envelope_operation, /* operation code for |envelope| */ -mp_boundingpath_operation, /* operation code for |boundingpath| */ +mp_true_operation, /* operation code for |true| */ +mp_false_operation, /* operation code for |false| */ +mp_null_picture_operation, /* operation code for |nullpicture| */ +mp_null_pen_operation, /* operation code for |nullpen| */ +mp_read_string_operation, /* operation code for |readstring| */ +mp_pen_circle_operation, /* operation code for |pencircle| */ +mp_normal_deviate_operation, /* operation code for |normaldeviate| */ +mp_read_from_operation, /* operation code for |readfrom| */ +mp_close_from_operation, /* operation code for |closefrom| */ +mp_odd_operation, /* operation code for |odd| */ +mp_known_operation, /* operation code for |known| */ +mp_unknown_operation, /* operation code for |unknown| */ +mp_not_operation, /* operation code for |not| */ +mp_decimal_operation, /* operation code for |decimal| */ +mp_reverse_operation, /* operation code for |reverse| */ +mp_uncycle_operation, /* operation code for |uncycle| */ +mp_make_path_operation, /* operation code for |makepath| */ +mp_make_pen_operation, /* operation code for |makepen| */ +mp_make_nep_operation, /* operation code for |makenep| */ +mp_convexed_operation, /* operation code for |convexed| */ +mp_uncontrolled_operation, /* operation code for |uncontrolled| */ +mp_oct_operation, /* operation code for |oct| */ +mp_hex_operation, /* operation code for |hex| */ +mp_ASCII_operation, /* operation code for |ASCII| */ +mp_char_operation, /* operation code for |char| */ +mp_length_operation, /* operation code for |length| */ +mp_turning_operation, /* operation code for |turningnumber| */ +mp_color_model_operation, /* operation code for |colormodel| */ +mp_path_part_operation, /* operation code for |pathpart| */ +mp_pen_part_operation, /* operation code for |penpart| */ +mp_dash_part_operation, /* operation code for |dashpart| */ +mp_prescript_part_operation, /* operation code for |prescriptpart| */ +mp_postscript_part_operation, /* operation code for |postscriptpart| */ +mp_stacking_part_operation, /* operation code for |stackingpart| */ +mp_sqrt_operation, /* operation code for |sqrt| */ +mp_m_exp_operation, /* operation code for |mexp| */ +mp_m_log_operation, /* operation code for |mlog| */ +mp_sin_d_operation, /* operation code for |sind| */ +mp_cos_d_operation, /* operation code for |cosd| */ +mp_floor_operation, /* operation code for |floor| */ +mp_uniform_deviate_operation, /* operation code for |uniformdeviate| */ +mp_ll_corner_operation, /* operation code for |llcorner| */ +mp_lr_corner_operation, /* operation code for |lrcorner| */ +mp_ul_corner_operation, /* operation code for |ulcorner| */ +mp_ur_corner_operation, /* operation code for |urcorner| */ +mp_center_of_operation, /* operation code for |centerof| */ +mp_center_of_mass_operation, /* operation code for |centerofmass| */ +mp_corners_operation, /* operation code for |corners| */ +mp_x_range_operation, /* operation code for |xrange| */ +mp_y_range_operation, /* operation code for |yrange| */ +mp_delta_point_operation, /* operation code for |deltapoint| */ +mp_delta_precontrol_operation, /* operation code for |deltaprecontrol| */ +mp_delta_postcontrol_operation, /* operation code for |deltapostcontrol| */ +mp_delta_direction_operation, /* operation code for |deltadirection| */ +mp_arc_length_operation, /* operation code for |arclength| */ +mp_angle_operation, /* operation code for |angle| */ +mp_cycle_operation, /* operation code for |cycle| */ +mp_no_cycle_operation, /* operation code for |nocycle| */ +mp_filled_operation, /* operation code for |filled| */ +mp_stroked_operation, /* operation code for |stroked| */ +mp_clipped_operation, /* operation code for |clipped| */ +mp_grouped_operation, /* operation code for |bounded| */ +mp_bounded_operation, /* operation code for |grouped| */ +mp_plus_operation, /* operation code for \.+ */ +mp_minus_operation, /* operation code for \.- */ +mp_times_operation, /* operation code for \.* */ +mp_over_operation, /* operation code for \./ */ +mp_power_operation, /* operation code for \.^ */ +mp_pythag_add_operation, /* operation code for |++| */ +mp_pythag_sub_operation, /* operation code for |+-+| */ +mp_or_operation, /* operation code for |or| */ +mp_and_operation, /* operation code for |and| */ +mp_less_than_operation, /* operation code for \.< */ +mp_less_or_equal_operation, /* operation code for |<=| */ +mp_greater_than_operation, /* operation code for \.> */ +mp_greater_or_equal_operation, /* operation code for |>=| */ +mp_equal_operation, /* operation code for \.= */ +mp_unequal_operation, /* operation code for |<>| */ +mp_concatenate_operation, /* operation code for \.\& */ +mp_just_append_operation, /* operation code for \.\&\& */ +mp_tolerant_concat_operation, /* operation code for \.\&\&\& */ +mp_tolerant_append_operation, /* operation code for \.\&\&\&\& */ +mp_rotated_operation, /* operation code for |rotated| */ +mp_slanted_operation, /* operation code for |slanted| */ +mp_scaled_operation, /* operation code for |scaled| */ +mp_shifted_operation, /* operation code for |shifted| */ +mp_transformed_operation, /* operation code for |transformed| */ +mp_uncycled_operation, /* operation code for |uncycled| */ +mp_x_scaled_operation, /* operation code for |xscaled| */ +mp_y_scaled_operation, /* operation code for |yscaled| */ +mp_z_scaled_operation, /* operation code for |zscaled| */ +mp_intertimes_operation, /* operation code for |intersectiontimes| */ +mp_intertimes_list_operation, /* operation code for |intersectiontimeslist| */ +mp_double_dot_operation, /* operation code for improper |..| */ +mp_substring_operation, /* operation code for |substring| */ +mp_subpath_operation, /* operation code for |subpath| */ +mp_direction_time_operation, /* operation code for |directiontime| */ +mp_point_operation, /* operation code for |point| */ +mp_precontrol_operation, /* operation code for |precontrol| */ +mp_postcontrol_operation, /* operation code for |postcontrol| */ +mp_direction_operation, /* operation code for |direction| */ +mp_path_point_operation, /* operation code for |pathpoint| */ +mp_path_precontrol_operation, /* operation code for |pathprecontrol| */ +mp_path_postcontrol_operation, /* operation code for |pathpostcontrol| */ +mp_path_direction_operation, /* operation code for |pathdirection| */ +mp_pen_offset_operation, /* operation code for |penoffset| */ +mp_arc_time_operation, /* operation code for |arctime| */ +mp_arc_point_operation, /* operation code for |arcpoint| */ +mp_arc_point_list_operation, /* operation code for |arcpointlist| */ +mp_subarc_length_operation, /* operation code for |subarclength| */ +mp_version_operation, /* operation code for |mpversion| */ +mp_envelope_operation, /* operation code for |envelope| */ +mp_boundingpath_operation, /* operation code for |boundingpath| */ @ @c static const char *mp_op_string (int c) @@ -2765,6 +2767,8 @@ static const char *mp_op_string (int c) case mp_unequal_operation : return "<>"; case mp_concatenate_operation : return "&"; case mp_just_append_operation : return "&&"; + case mp_tolerant_concat_operation : return "&&&"; + case mp_tolerant_append_operation : return "&&&&"; case mp_rotated_operation : return "rotated"; case mp_slanted_operation : return "slanted"; case mp_scaled_operation : return "scaled"; @@ -21665,7 +21669,7 @@ static int mp_scan_path (MP mp) Join the partial paths and reset |p| and |q| to the head and tail of the result */ - if (d == mp_ampersand_command && dd != mp_just_append_operation) { + if (d == mp_ampersand_command && dd != mp_just_append_operation && dd != mp_tolerant_concat_operation && dd != mp_tolerant_append_operation) { if (! (number_equal(path_q->x_coord, pp->x_coord)) || ! (number_equal(path_q->y_coord, pp->y_coord))) { mp_back_error( mp, @@ -21687,6 +21691,22 @@ static int mp_scan_path (MP mp) } if (d == mp_ampersand_command) { /* Splice independent paths together */ + if (dd == mp_tolerant_concat_operation || dd == mp_tolerant_append_operation) { + mp_number dx, dy; + set_number_from_subtraction(dx, path_q->x_coord, pp->x_coord); + set_number_from_subtraction(dy, path_q->y_coord, pp->y_coord); + number_abs(dx); + number_abs(dy); + if (number_lessequal(dx, epsilon_t) && number_lessequal(dy, epsilon_t)) { + set_number_half_from_addition(dx, path_q->x_coord, pp->x_coord); + set_number_half_from_addition(dy, path_q->y_coord, pp->y_coord); + number_clone(pp->left_x, dx); + number_clone(path_q->right_x, dx); + number_clone(pp->left_y, dy); + number_clone(path_q->right_y, dy); + } + dd = dd == mp_tolerant_concat_operation ? mp_concatenate_operation : mp_just_append_operation; + } if (dd == mp_just_append_operation) { mp_left_type(pp) = mp_explicit_knot; mp_right_type(path_q) = mp_explicit_knot; @@ -22222,6 +22242,10 @@ mp_primitive(mp, "&", mp_ampersand_command, mp_concatenate_operation); @:!!!}{|\&| primitive@> mp_primitive(mp, "&&", mp_ampersand_command, mp_just_append_operation); @:!!!!!!}{|\&\&| primitive@> +mp_primitive(mp, "&&&", mp_ampersand_command, mp_tolerant_concat_operation); +@:!!!!!!!!!}{|\&\&\&| primitive@> +mp_primitive(mp, "&&&&", mp_ampersand_command, mp_tolerant_append_operation); +@:!!!!!!!!!!!!}{|\&\&\&\&| primitive@> mp_primitive(mp, "rotated", mp_secondary_binary_command, mp_rotated_operation); @:rotated_}{|rotated| primitive@> mp_primitive(mp, "slanted", mp_secondary_binary_command, mp_slanted_operation); @@ -24891,6 +24915,8 @@ static void mp_do_binary (MP mp, mp_node p, int c) break; case mp_concatenate_operation: case mp_just_append_operation: + case mp_tolerant_concat_operation: + case mp_tolerant_append_operation: if ((mp->cur_exp.type == mp_string_type) && (mp_type(p) == mp_string_type)) { mp_string str = mp_cat(mp, mp_get_value_str(p), cur_exp_str); delete_str_ref(cur_exp_str) ; diff --git a/source/luametatex/source/tex/texadjust.c b/source/luametatex/source/tex/texadjust.c index 279af8950..cb2f8c247 100644 --- a/source/luametatex/source/tex/texadjust.c +++ b/source/luametatex/source/tex/texadjust.c @@ -134,12 +134,12 @@ void tex_run_vadjust(void) scaled depthafter = 0; halfword attrlist = null; tex_scan_adjust_keys(&options, &code, &index, &depthbefore, &depthafter, &attrlist); - tex_set_saved_record(saved_adjust_item_location, saved_adjust_location, 0, code); - tex_set_saved_record(saved_adjust_item_options, saved_adjust_options, 0, options); - tex_set_saved_record(saved_adjust_item_index, saved_adjust_index, 0, index); - tex_set_saved_record(saved_adjust_item_attr_list, saved_adjust_attr_list, 0, attrlist); - tex_set_saved_record(saved_adjust_item_depth_before, saved_adjust_depth_before, 0, depthbefore); - tex_set_saved_record(saved_adjust_item_depth_after, saved_adjust_depth_after, 0, depthafter); + tex_set_saved_record(saved_adjust_item_location, adjust_location_save_type, 0, code); + tex_set_saved_record(saved_adjust_item_options, adjust_options_save_type, 0, options); + tex_set_saved_record(saved_adjust_item_index, adjust_index_save_type, 0, index); + tex_set_saved_record(saved_adjust_item_attr_list, adjust_attr_list_save_type, 0, attrlist); + tex_set_saved_record(saved_adjust_item_depth_before, adjust_depth_before_save_type, 0, depthbefore); + tex_set_saved_record(saved_adjust_item_depth_after, adjust_depth_after_save_type, 0, depthafter); lmt_save_state.save_stack_data.ptr += saved_adjust_n_of_items; tex_new_save_level(vadjust_group); tex_scan_left_brace(); diff --git a/source/luametatex/source/tex/texalign.c b/source/luametatex/source/tex/texalign.c index 207895a6d..ac7712870 100644 --- a/source/luametatex/source/tex/texalign.c +++ b/source/luametatex/source/tex/texalign.c @@ -549,12 +549,12 @@ static void tex_aux_scan_align_spec(quarterword c) } /*tex Now we're referenced. We need to preserve this over the group. */ add_attribute_reference(attrlist); - tex_set_saved_record(saved_align_specification, saved_box_spec, mode, amount); + tex_set_saved_record(saved_align_specification, box_spec_save_type, mode, amount); /* We save them but could put them in the state as we do for some anyway. */ - tex_set_saved_record(saved_align_reverse, saved_box_reverse, reverse, 0); - tex_set_saved_record(saved_align_discard, saved_box_discard, noskips ? 0 : discard, 0); - tex_set_saved_record(saved_align_noskips, saved_box_noskips, noskips, 0); - tex_set_saved_record(saved_align_callback, saved_box_callback, callback, 0); + tex_set_saved_record(saved_align_reverse, box_reverse_save_type, reverse, 0); + tex_set_saved_record(saved_align_discard, box_discard_save_type, noskips ? 0 : discard, 0); + tex_set_saved_record(saved_align_noskips, box_noskips_save_type, noskips, 0); + tex_set_saved_record(saved_align_callback, box_callback_save_type, callback, 0); lmt_save_state.save_stack_data.ptr += saved_align_n_of_items; tex_new_save_level(c); if (! brace) { diff --git a/source/luametatex/source/tex/texbuildpage.c b/source/luametatex/source/tex/texbuildpage.c index a0b5882dd..0e2883305 100644 --- a/source/luametatex/source/tex/texbuildpage.c +++ b/source/luametatex/source/tex/texbuildpage.c @@ -177,15 +177,6 @@ void tex_initialize_buildpage(void) |last_node_type| are similar. And finally, |insert_penalties| holds the sum of the penalties associated with all split and floating insertions. -*/ - -void tex_print_page_totals(void) -{ - tex_print_format("%P", page_total, page_stretch, page_filstretch, page_fillstretch, page_filllstretch, page_shrink); -} - -/*tex - Here is a procedure that is called when the |page_contents| is changing from |empty| to |inserts_only| or |box_there|. diff --git a/source/luametatex/source/tex/texbuildpage.h b/source/luametatex/source/tex/texbuildpage.h index 328bed2a1..20d8416f5 100644 --- a/source/luametatex/source/tex/texbuildpage.h +++ b/source/luametatex/source/tex/texbuildpage.h @@ -78,7 +78,6 @@ extern void tex_initialize_buildpage (void); extern void tex_initialize_pagestate (void); extern void tex_build_page (void); extern void tex_resume_after_output (void); -extern void tex_print_page_totals (void); /*tex The tail of the contribution list: */ diff --git a/source/luametatex/source/tex/texcommands.c b/source/luametatex/source/tex/texcommands.c index 3ac1a7b23..f0949b9ab 100644 --- a/source/luametatex/source/tex/texcommands.c +++ b/source/luametatex/source/tex/texcommands.c @@ -229,18 +229,11 @@ void tex_initialize_commands(void) tex_primitive(luatex_command, "localinterlinepenalty", internal_int_cmd, local_interline_penalty_code, internal_int_base); tex_primitive(luatex_command, "luacopyinputnodes", internal_int_cmd, copy_lua_input_nodes_code, internal_int_base); tex_primitive(luatex_command, "mathcheckfencesmode", internal_int_cmd, math_check_fences_mode_code, internal_int_base); - /* tex_primitive(luatex_command, "mathdelimitersmode", internal_int_cmd, math_delimiters_mode_code, internal_int_base); */ - /* tex_primitive(luatex_command, "mathfencesmode", internal_int_cmd, math_fences_mode_code, internal_int_base); */ tex_primitive(luatex_command, "mathslackmode", internal_int_cmd, math_slack_mode_code, internal_int_base); - /* tex_primitive(luatex_command, "mathflattenmode", internal_int_cmd, math_flatten_mode_code, internal_int_base); */ tex_primitive(luatex_command, "mathpenaltiesmode", internal_int_cmd, math_penalties_mode_code, internal_int_base); - /* tex_primitive(luatex_command, "mathrulethicknessmode", internal_int_cmd, math_rule_thickness_mode_code, internal_int_base); */ tex_primitive(luatex_command, "mathscriptsmode", internal_int_cmd, math_scripts_mode_code, internal_int_base); - /* tex_primitive(luatex_command, "mathscriptboxmode", internal_int_cmd, math_script_box_mode_code, internal_int_base); */ - /* tex_primitive(luatex_command, "mathscriptcharmode", internal_int_cmd, math_script_char_mode_code, internal_int_base); */ tex_primitive(luatex_command, "mathsurroundmode", internal_int_cmd, math_skip_mode_code, internal_int_base); tex_primitive(luatex_command, "mathdoublescriptmode", internal_int_cmd, math_double_script_mode_code, internal_int_base); - /* tex_primitive(luatex_command, "mathcontrolmode", internal_int_cmd, math_control_mode_code, internal_int_base); */ tex_primitive(luatex_command, "mathfontcontrol", internal_int_cmd, math_font_control_code, internal_int_base); tex_primitive(luatex_command, "mathdisplaymode", internal_int_cmd, math_display_mode_code, internal_int_base); tex_primitive(luatex_command, "mathdictgroup", internal_int_cmd, math_dict_group_code, internal_int_base); @@ -424,7 +417,6 @@ void tex_initialize_commands(void) tex_primitive(tex_command, "mathchar", math_char_number_cmd, math_char_number_code, 0); tex_primitive(luatex_command, "Umathchar", math_char_number_cmd, math_xchar_number_code, 0); tex_primitive(luatex_command, "Umathdict", math_char_number_cmd, math_dchar_number_code, 0); - /* tex_primitive(luatex_command, "Umathcharnum", math_char_number_cmd, math_uchar_number_code, 0); */ tex_primitive(luatex_command, "Umathclass", math_char_number_cmd, math_class_number_code, 0); tex_primitive(tex_command, "mathchoice", math_choice_cmd, math_choice_code, 0); @@ -668,6 +660,7 @@ void tex_initialize_commands(void) tex_primitive(luatex_command, "formatname", convert_cmd, format_name_code, 0); tex_primitive(luatex_command, "luabytecode", convert_cmd, lua_bytecode_code, 0); tex_primitive(luatex_command, "luaescapestring", convert_cmd, lua_escape_string_code, 0); + /* tex_primitive(luatex_command, "luatokenstring", convert_cmd, lua_token_string_code, 0); */ tex_primitive(luatex_command, "luafunction", convert_cmd, lua_function_code, 0); tex_primitive(luatex_command, "luatexbanner", convert_cmd, luatex_banner_code, 0); tex_primitive(luatex_command, "Uchar", convert_cmd, uchar_code, 0); @@ -700,6 +693,8 @@ void tex_initialize_commands(void) tex_primitive(luatex_command, "ifincsname", if_test_cmd, if_in_csname_code, 0); /* This is obsolete and might be dropped. */ tex_primitive(luatex_command, "ifabsnum", if_test_cmd, if_abs_int_code, 0); tex_primitive(luatex_command, "ifabsdim", if_test_cmd, if_abs_dim_code, 0); + tex_primitive(luatex_command, "ifzeronum", if_test_cmd, if_zero_int_code, 0); + tex_primitive(luatex_command, "ifzerodim", if_test_cmd, if_zero_dim_code, 0); tex_primitive(luatex_command, "ifchknum", if_test_cmd, if_chk_int_code, 0); tex_primitive(luatex_command, "ifchkdim", if_test_cmd, if_chk_dim_code, 0); tex_primitive(luatex_command, "ifcmpnum", if_test_cmd, if_cmp_int_code, 0); @@ -733,11 +728,7 @@ void tex_initialize_commands(void) tex_primitive(tex_command, "atopwithdelims", math_fraction_cmd, math_atop_delimited_code, 0); tex_primitive(tex_command, "over", math_fraction_cmd, math_over_code, 0); tex_primitive(tex_command, "overwithdelims", math_fraction_cmd, math_over_delimited_code, 0); - /* tex_primitive(luatex_command, "skewed", math_fraction_cmd, math_skewed_code, 0); */ /* makes no sense */ - /* tex_primitive(luatex_command, "skewedwithdelims", math_fraction_cmd, math_skewed_delimited_code, 0); */ /* makes no sense */ - /* tex_primitive(luatex_command, "stretched", math_fraction_cmd, math_stretched_code, 0); */ /* makes no sense */ - /* tex_primitive(luatex_command, "stretchedwithdelims", math_fraction_cmd, math_stretched_delimited_code, 0); */ /* makes no sense */ - + tex_primitive(luatex_command, "Uabove", math_fraction_cmd, math_u_above_code, 0); tex_primitive(luatex_command, "Uabovewithdelims", math_fraction_cmd, math_u_above_delimited_code, 0); tex_primitive(luatex_command, "Uatop", math_fraction_cmd, math_u_atop_code, 0); @@ -770,9 +761,7 @@ void tex_initialize_commands(void) tex_primitive(tex_command, "delcode", define_char_code_cmd, delcode_charcode, 0); tex_primitive(luatex_command, "Umathcode", define_char_code_cmd, extmathcode_charcode, 0); - /* tex_primitive(luatex_command, "Umathcodenum", define_char_code_cmd, extmathcodenum_charcode, 0); */ tex_primitive(luatex_command, "Udelcode", define_char_code_cmd, extdelcode_charcode, 0); - /* tex_primitive(luatex_command, "Udelcodenum", define_char_code_cmd, extdelcodenum_charcode, 0); */ tex_primitive(tex_command, "edef", def_cmd, expanded_def_code, 0); tex_primitive(tex_command, "def", def_cmd, def_code, 0); @@ -928,7 +917,9 @@ void tex_initialize_commands(void) tex_primitive(luatex_command, "allscriptstyles", math_style_cmd, all_script_styles, 0); tex_primitive(luatex_command, "allscriptscriptstyles", math_style_cmd, all_script_script_styles, 0); tex_primitive(luatex_command, "allmathstyles", math_style_cmd, all_math_styles, 0); + tex_primitive(luatex_command, "allmainstyles", math_style_cmd, all_main_styles, 0); tex_primitive(luatex_command, "allsplitstyles", math_style_cmd, all_split_styles, 0); + tex_primitive(luatex_command, "allunsplitstyles", math_style_cmd, all_unsplit_styles, 0); tex_primitive(luatex_command, "alluncrampedstyles", math_style_cmd, all_uncramped_styles, 0); tex_primitive(luatex_command, "allcrampedstyles", math_style_cmd, all_cramped_styles, 0); @@ -987,7 +978,6 @@ void tex_initialize_commands(void) /* tex_primitive(tex_command, "stringdef", shorthand_def_cmd, string_def_code, 0); */ tex_primitive(luatex_command, "Umathchardef", shorthand_def_cmd, math_xchar_def_code, 0); tex_primitive(luatex_command, "Umathdictdef", shorthand_def_cmd, math_dchar_def_code, 0); - /* tex_primitive(luatex_command, "Umathcharnumdef", shorthand_def_cmd, math_uchar_def_code, 0); */ tex_primitive(luatex_command, "attributedef", shorthand_def_cmd, attribute_def_code, 0); tex_primitive(luatex_command, "luadef", shorthand_def_cmd, lua_def_code, 0); tex_primitive(luatex_command, "integerdef", shorthand_def_cmd, integer_def_code, 0); @@ -1246,25 +1236,25 @@ void tex_initialize_commands(void) tex_primitive(no_command, "insertedpar", end_paragraph_cmd, inserted_end_paragraph_code, 0); tex_primitive(no_command, "newlinepar", end_paragraph_cmd, new_line_end_paragraph_code, 0); - /* tex_primitive(luatex_command, "linepar", undefined_cs_cmd, 0, 0); */ /*tex A user can define this one.*/ - - tex_primitive(tex_command, "endgroup", end_group_cmd, semi_simple_group_code, 0); - tex_primitive(luatex_command, "endsimplegroup", end_group_cmd, also_simple_group_code, 0); - tex_primitive(luatex_command, "endmathgroup", end_group_cmd, math_simple_group_code, 0); - - tex_primitive(tex_command, "relax", relax_cmd, relax_code, 0); - tex_primitive(luatex_command, "norelax", relax_cmd, no_relax_code, 0); - tex_primitive(no_command, "noexpandrelax", relax_cmd, no_expand_relax_code, 0); - - tex_primitive(tex_command, "fi", if_test_cmd, fi_code, 0); - tex_primitive(no_command, "noif", if_test_cmd, no_if_code, 0); - - tex_primitive(no_command, "always", prefix_cmd, always_code, 0); - - tex_primitive(tex_command, "nullfont", set_font_cmd, null_font, 0); - - tex_primitive(tex_command, "crcr", alignment_cmd, cr_cr_code, 0); - tex_primitive(tex_command, "cr", alignment_cmd, cr_code, 0); + /* tex_primitive(luatex_command, "linepar", undefined_cs_cmd, 0, 0); */ /*tex A user can define this one.*/ + + tex_primitive(tex_command, "endgroup", end_group_cmd, semi_simple_group_code, 0); + tex_primitive(luatex_command, "endsimplegroup", end_group_cmd, also_simple_group_code, 0); + tex_primitive(luatex_command, "endmathgroup", end_group_cmd, math_simple_group_code, 0); + + tex_primitive(tex_command, "relax", relax_cmd, relax_code, 0); + tex_primitive(luatex_command, "norelax", relax_cmd, no_relax_code, 0); + tex_primitive(no_command, "noexpandrelax", relax_cmd, no_expand_relax_code, 0); + + tex_primitive(tex_command, "fi", if_test_cmd, fi_code, 0); + tex_primitive(no_command, "noif", if_test_cmd, no_if_code, 0); + + tex_primitive(no_command, "always", prefix_cmd, always_code, 0); + + tex_primitive(tex_command, "nullfont", set_font_cmd, null_font, 0); + + tex_primitive(tex_command, "crcr", alignment_cmd, cr_cr_code, 0); + tex_primitive(tex_command, "cr", alignment_cmd, cr_code, 0); tex_aux_copy_deep_frozen_from_primitive(deep_frozen_cs_end_group_code, "endgroup"); tex_aux_copy_deep_frozen_from_primitive(deep_frozen_cs_relax_code, "relax"); diff --git a/source/luametatex/source/tex/texcommands.h b/source/luametatex/source/tex/texcommands.h index 66fabb47e..792e23662 100644 --- a/source/luametatex/source/tex/texcommands.h +++ b/source/luametatex/source/tex/texcommands.h @@ -189,8 +189,6 @@ typedef enum tex_command_code { during expansion of this serializer prefix. */ char_given_cmd, /*tex character code defined by |\chardef| */ - // math_char_given_cmd, /*tex math code defined by |\mathchardef| */ - // math_char_xgiven_cmd, /*tex math code defined by |\Umathchardef| or |\Umathcharnumdef| */ some_item_cmd, /*tex most recent item (|\lastpenalty|, |\lastkern|, |\lastskip| and more) */ /*tex The previous command was described as \quotation {the last that cannot be prefixed by @@ -429,35 +427,36 @@ typedef enum auxiliary_codes { # define last_auxiliary_code insert_mode_code typedef enum convert_codes { - number_code, /*tex command code for |\number| */ - to_integer_code, /*tex command code for |\tointeger| (also gobbles |\relax|) */ - to_hexadecimal_code, /*tex command code for |\tohexadecimal| */ - to_scaled_code, /*tex command code for |\toscaled| (also gobbles |\relax|) */ - to_sparse_scaled_code, /*tex command code for |\tosparsescaled| (also gobbles |\relax|) */ - to_dimension_code, /*tex command code for |\todimension| (also gobbles |\relax|) */ - to_sparse_dimension_code, /*tex command code for |\tosparsedimension| */ - to_mathstyle_code, /*tex command code for |\tomathstyle| */ - lua_code, /*tex command code for |\directlua| */ - lua_function_code, /*tex command code for |\luafunction| */ - lua_bytecode_code, /*tex command code for |\luabytecode| */ - expanded_code, /*tex command code for |\expanded| */ - semi_expanded_code, /*tex command code for |\constantexpanded| */ - string_code, /*tex command code for |\string| */ - cs_string_code, /*tex command code for |\csstring| */ - detokenized_code, /*tex command code for |\detokenized| */ - roman_numeral_code, /*tex command code for |\romannumeral| */ - meaning_code, /*tex command code for |\meaning| */ - meaning_full_code, /*tex command code for |\meaningfull| */ - meaning_less_code, /*tex command code for |\meaningless| */ - meaning_asis_code, /*tex command code for |\meaningasis| */ - uchar_code, /*tex command code for |\Uchar| */ - lua_escape_string_code, /*tex command code for |\luaescapestring| */ - font_name_code, /*tex command code for |\fontname| */ - font_specification_code, /*tex command code for |\fontspecification| */ - job_name_code, /*tex command code for |\jobname| */ - format_name_code, /*tex command code for |\AlephVersion| */ - luatex_banner_code, /*tex command code for |\luatexbanner| */ - font_identifier_code, /*tex command code for |tex.fontidentifier| (virtual) */ + number_code, /*tex command code for |\number| */ + to_integer_code, /*tex command code for |\tointeger| (also gobbles |\relax|) */ + to_hexadecimal_code, /*tex command code for |\tohexadecimal| */ + to_scaled_code, /*tex command code for |\toscaled| (also gobbles |\relax|) */ + to_sparse_scaled_code, /*tex command code for |\tosparsescaled| (also gobbles |\relax|) */ + to_dimension_code, /*tex command code for |\todimension| (also gobbles |\relax|) */ + to_sparse_dimension_code, /*tex command code for |\tosparsedimension| */ + to_mathstyle_code, /*tex command code for |\tomathstyle| */ + lua_code, /*tex command code for |\directlua| */ + lua_function_code, /*tex command code for |\luafunction| */ + lua_bytecode_code, /*tex command code for |\luabytecode| */ + expanded_code, /*tex command code for |\expanded| */ + semi_expanded_code, /*tex command code for |\constantexpanded| */ + string_code, /*tex command code for |\string| */ + cs_string_code, /*tex command code for |\csstring| */ + detokenized_code, /*tex command code for |\detokenized| */ + roman_numeral_code, /*tex command code for |\romannumeral| */ + meaning_code, /*tex command code for |\meaning| */ + meaning_full_code, /*tex command code for |\meaningfull| */ + meaning_less_code, /*tex command code for |\meaningless| */ + meaning_asis_code, /*tex command code for |\meaningasis| */ + uchar_code, /*tex command code for |\Uchar| */ + lua_escape_string_code, /*tex command code for |\luaescapestring| */ + /* lua_token_string_code, */ /*tex command code for |\luatokenstring| */ + font_name_code, /*tex command code for |\fontname| */ + font_specification_code, /*tex command code for |\fontspecification| */ + job_name_code, /*tex command code for |\jobname| */ + format_name_code, /*tex command code for |\AlephVersion| */ + luatex_banner_code, /*tex command code for |\luatexbanner| */ + font_identifier_code, /*tex command code for |tex.fontidentifier| (virtual) */ } convert_codes; # define first_convert_code number_code @@ -670,7 +669,6 @@ typedef enum shorthand_def_codes { math_char_def_code, /*tex |\mathchardef| */ math_xchar_def_code, /*tex |\Umathchardef| */ math_dchar_def_code, /*tex |\Umathdictdef| */ - /* math_uchar_def_code, */ /* |\Umathcharnumdef| */ count_def_code, /*tex |\countdef| */ attribute_def_code, /*tex |\attributedef| */ dimen_def_code, /*tex |\dimendef| */ @@ -700,7 +698,6 @@ typedef enum math_char_number_codes { math_char_number_code, /*tex |\mathchar| */ math_xchar_number_code, /*tex |\Umathchar| */ math_dchar_number_code, /*tex |\Umathdict| */ - /* math_uchar_number_code, */ /* |\Umathcharnum| */ math_class_number_code, /*tex |\Umathclass| */ } math_char_number_codes; @@ -1034,14 +1031,11 @@ typedef enum charcode_codes { hmcode_charcode, mathcode_charcode, extmathcode_charcode, - /* extmathcodenum_charcode, */ delcode_charcode, extdelcode_charcode, - /* extdelcodenum_charcode, */ } charcode_codes; # define first_charcode_code catcode_charcode -/*define last_charcode_code extdelcodenum_charcode */ # define last_charcode_code extdelcode_charcode typedef enum math_styles { @@ -1063,7 +1057,9 @@ typedef enum math_styles { all_script_styles, all_script_script_styles, all_math_styles, + all_main_styles, all_split_styles, + all_unsplit_styles, all_uncramped_styles, all_cramped_styles, } math_styles; diff --git a/source/luametatex/source/tex/texconditional.c b/source/luametatex/source/tex/texconditional.c index 95035f43e..b25bdfbbe 100644 --- a/source/luametatex/source/tex/texconditional.c +++ b/source/luametatex/source/tex/texconditional.c @@ -506,6 +506,11 @@ void tex_conditional_if(halfword code, int unless) } } goto RESULT; + case if_zero_int_code: + { + result = tex_scan_int(0, NULL) == 0; + } + goto RESULT; case if_abs_dim_code: case if_dim_code: /*tex @@ -533,6 +538,11 @@ void tex_conditional_if(halfword code, int unless) } } goto RESULT; + case if_zero_dim_code: + { + result = tex_scan_dimen(0, 0, 0, 0, NULL) == 0; + } + goto RESULT; case if_odd_code: /*tex Test if an integer is odd. */ { diff --git a/source/luametatex/source/tex/texconditional.h b/source/luametatex/source/tex/texconditional.h index f3de5dcdb..a0c22cd38 100644 --- a/source/luametatex/source/tex/texconditional.h +++ b/source/luametatex/source/tex/texconditional.h @@ -45,14 +45,19 @@ typedef enum if_test_codes { or_else_code, /*tex |\orelse| */ or_unless_code, /*tex |\orunless| */ - /*tex Here come the \if... codes: */ + /*tex + Here come the \if... codes. Some are just there to minimize tracing and are not faster, + like |\ifzerodim| (we can use |\ifcase| instead but not with |\unless|). + */ if_char_code, /*tex |\if| */ if_cat_code, /*tex |\ifcat| */ - if_abs_int_code, /*tex |\ifabsnum| */ if_int_code, /*tex |\ifnum| */ - if_abs_dim_code, /*tex |\ifabsdim| */ + if_abs_int_code, /*tex |\ifabsnum| */ + if_zero_int_code, /*tex |\ifzeronum|*/ if_dim_code, /*tex |\ifdim| */ + if_abs_dim_code, /*tex |\ifabsdim| */ + if_zero_dim_code, /*tex |\ifzerodim| */ if_odd_code, /*tex |\ifodd| */ if_vmode_code, /*tex |\ifvmode| */ if_hmode_code, /*tex |\ifhmode| */ @@ -93,7 +98,7 @@ typedef enum if_test_codes { if_has_toks_code, /*tex |\ifhastoks| */ if_has_xtoks_code, /*tex |\ifhasxtoks| */ if_has_char_code, /*tex |\ifhaschar| */ - if_insert_code /*tex |\ifinsert| */ + if_insert_code, /*tex |\ifinsert| */ // if_bitwise_and_code, /*tex |\ifbitwiseand| */ } if_test_codes; diff --git a/source/luametatex/source/tex/texdumpdata.c b/source/luametatex/source/tex/texdumpdata.c index 58f9e4442..dfac980c5 100644 --- a/source/luametatex/source/tex/texdumpdata.c +++ b/source/luametatex/source/tex/texdumpdata.c @@ -5,8 +5,8 @@ # include "luametatex.h" dump_state_info lmt_dump_state = { - .format_identifier = 0, - .format_name = 0 + .fingerprint = luametatex_format_fingerprint, + .padding = 0 }; /*tex @@ -54,9 +54,7 @@ dump_state_info lmt_dump_state = { static int tex_aux_report_dump_state(dumpstream f, int pos, const char *what) { int tmp = ftell(f); - tex_print_int(tmp - pos); - tex_print_char(' '); - tex_print_str(what); + tex_print_format("%i %s", tmp - pos, what); fflush(stdout); return tmp; } @@ -94,37 +92,26 @@ static void tex_aux_undump_fingerprint(dumpstream f) static void tex_aux_dump_final_check(dumpstream f) { - dump_int(f, lmt_dump_state.format_identifier); - dump_int(f, lmt_dump_state.format_name); dump_via_int(f, luametatex_format_fingerprint); } static void tex_aux_undump_final_check(dumpstream f) { int x; - undump_int(f, lmt_dump_state.format_identifier); - if (lmt_dump_state.format_identifier < 0 || lmt_dump_state.format_identifier > lmt_string_pool_state.string_pool_data.ptr) { - goto BAD; - } - undump_int(f, lmt_dump_state.format_name); - if (lmt_dump_state.format_name < 0 || lmt_dump_state.format_name > lmt_string_pool_state.string_pool_data.ptr) { - goto BAD; - } undump_int(f, x); if (x == luametatex_format_fingerprint) { return; + } else { + tex_fatal_undump_error("final fingerprint"); } - BAD: - tex_fatal_undump_error("final fingerprint"); } static void tex_aux_create_fmt_name(void) { lmt_print_state.selector = new_string_selector_code; - tex_print_format("%s %i.%i.%i",lmt_fileio_state.fmt_name, year_par, month_par, day_par); - lmt_dump_state.format_identifier = tex_make_string(); - tex_print_str(lmt_fileio_state.job_name); - lmt_dump_state.format_name = tex_make_string(); +// lmt_dump_state.format_identifier = tex_make_string(); +// lmt_dump_state.format_name = tex_make_string(); + tex_print_format("%s %i.%i.%i %s",lmt_fileio_state.fmt_name, year_par, month_par, day_par, lmt_fileio_state.job_name); lmt_print_state.selector = terminal_and_logfile_selector_code; } @@ -221,7 +208,7 @@ void tex_store_fmt_file(void) } tex_print_nlp(); - tex_print_format("Dumping format '%T' in file '%s': ", lmt_dump_state.format_identifier, lmt_fileio_state.fmt_name); + tex_print_format("Dumping format in file '%s': ", lmt_fileio_state.fmt_name); fflush(stdout); tex_compact_tokens(); @@ -322,10 +309,7 @@ int tex_load_fmt_file(void) void tex_initialize_dump_state(void) { - lmt_dump_state.format_name = get_nullstr(); - if (lmt_main_state.run_state == initializing_state) { - lmt_dump_state.format_identifier = tex_maketexstring(" (INITEX)"); - } else { - lmt_dump_state.format_identifier = 0; + if (! lmt_engine_state.dump_name) { + lmt_engine_state.dump_name = lmt_memory_strdup("initex"); } } diff --git a/source/luametatex/source/tex/texdumpdata.h b/source/luametatex/source/tex/texdumpdata.h index 6a9e11a7d..bea80869d 100644 --- a/source/luametatex/source/tex/texdumpdata.h +++ b/source/luametatex/source/tex/texdumpdata.h @@ -55,13 +55,13 @@ */ -# define luametatex_format_fingerprint 670 +# define luametatex_format_fingerprint 674 /* These end up in the string pool. */ typedef struct dump_state_info { - strnumber format_identifier; - strnumber format_name; + int fingerprint; + int padding; } dump_state_info; extern dump_state_info lmt_dump_state; diff --git a/source/luametatex/source/tex/texequivalents.c b/source/luametatex/source/tex/texequivalents.c index 7cc249a2e..291126fff 100644 --- a/source/luametatex/source/tex/texequivalents.c +++ b/source/luametatex/source/tex/texequivalents.c @@ -110,10 +110,7 @@ static void tex_aux_show_eqtb(halfword n); static void tex_aux_diagnostic_trace(halfword p, const char *s) { tex_begin_diagnostic(); - /* print_format ... */ - tex_print_char('{'); - tex_print_str(s); - tex_print_char(' '); + tex_print_format("{%s ", s); tex_aux_show_eqtb(p); tex_print_char('}'); tex_end_diagnostic(); @@ -449,8 +446,8 @@ void tex_new_save_level(quarterword c) /*tex We begin a new level of grouping. */ if (tex_room_on_save_stack()) { save_attribute_state_before(); - tex_set_saved_record(saved_group_line_number, saved_line_number, 0, lmt_input_state.input_line); - tex_set_saved_record(saved_group_level_boundary, level_boundary, cur_group, cur_boundary); + tex_set_saved_record(saved_group_line_number, line_number_save_type, 0, lmt_input_state.input_line); + tex_set_saved_record(saved_group_level_boundary, level_boundary_save_type, cur_group, cur_boundary); /*tex eventually we will have bumped |lmt_save_state.save_stack_data.ptr| by |saved_group_n_of_items|! */ ++lmt_save_state.save_stack_data.ptr; if (cur_level == max_quarterword) { @@ -510,7 +507,7 @@ static int tex_aux_save_value(int id) static int tex_aux_saved_box_spec(halfword *packing, halfword *amount) { - int i = tex_aux_found_save_type(saved_box_spec); + int i = tex_aux_found_save_type(box_spec_save_type); if (i) { *packing = saved_level(i); *amount = saved_value(i); @@ -595,7 +592,21 @@ void tex_show_save_groups(void) case output_group: tex_print_str_esc("output"); goto FOUND2; + // maybe: + // + // case math_group: + // case math_component_group: + // case math_stack_group: + // tex_print_str_esc(lmt_interface.group_code_values[cur_group].name); + // goto FOUND2; case math_group: + tex_print_str_esc("mathsubformula"); + goto FOUND2; + case math_component_group: + tex_print_str_esc("mathcomponent"); + goto FOUND2; + case math_stack_group: + tex_print_str_esc("mathstack"); goto FOUND2; case discretionary_group: tex_print_str_esc("discretionary"); @@ -605,6 +616,10 @@ void tex_show_save_groups(void) tex_print_str_esc("fraction"); tex_aux_show_group_count(tex_aux_save_value(saved_fraction_item_variant)); goto FOUND2; + case math_radical_group: + tex_print_str_esc("radical"); + tex_aux_show_group_count(tex_aux_save_value(radical_degree_done_save_type)); + goto FOUND2; case math_operator_group: tex_print_str_esc("operator"); tex_aux_show_group_count(tex_aux_save_value(saved_operator_item_variant)); @@ -634,10 +649,10 @@ void tex_show_save_groups(void) ++pointer; tex_print_str_esc("begingroup"); goto FOUND2; -//case math_simple_group: -// ++pointer; -// tex_print_str_esc("beginmathgroup"); -// goto FOUND2; + // case math_simple_group: + // ++pointer; + // tex_print_str_esc("beginmathgroup"); + // goto FOUND2; case math_shift_group: if (mode == mmode) { tex_print_char('$'); @@ -873,9 +888,9 @@ static void tex_aux_eq_save(halfword p, quarterword l) { if (tex_room_on_save_stack()) { if (l == level_zero) { - save_type(lmt_save_state.save_stack_data.ptr) = restore_zero; + save_type(lmt_save_state.save_stack_data.ptr) = restore_zero_save_type; } else { - save_type(lmt_save_state.save_stack_data.ptr) = restore_old_value; + save_type(lmt_save_state.save_stack_data.ptr) = restore_old_value_save_type; save_word(lmt_save_state.save_stack_data.ptr) = lmt_hash_state.eqtb[p]; } save_level(lmt_save_state.save_stack_data.ptr) = l; @@ -898,6 +913,8 @@ static void tex_aux_eq_save(halfword p, quarterword l) the case of glue refs that have work by ref count and token lists and node (lists) are always different so there we do no harm. + There is room for some optimization here. + */ inline static int tex_aux_equal_eq(halfword p, singleword cmd, singleword flag, halfword chr) @@ -948,8 +965,8 @@ inline static int tex_aux_equal_eq(halfword p, singleword cmd, singleword flag, case tolerant_protected_call_cmd: case tolerant_semi_protected_call_cmd: /*tex The initial token reference will do as it is unique. */ -// if (eq_value(p) == chr) { - if (eq_value(p) == chr && eq_level(p) == cur_level) { + // if (eq_value(p) == chr) { + if (eq_value(p) == chr && eq_level(p) == cur_level) { tex_delete_token_reference(eq_value(p)); return 1; } else { @@ -960,7 +977,7 @@ inline static int tex_aux_equal_eq(halfword p, singleword cmd, singleword flag, case register_box_reference_cmd: /*tex These are also references. */ if (eq_type(p) == cmd && eq_value(p) == chr && ! chr) { -// if (eq_type(p) == cmd && eq_value(p) == chr && ! chr && eq_level(p) == cur_level) { + // if (eq_type(p) == cmd && eq_value(p) == chr && ! chr && eq_level(p) == cur_level) { return 1; } else { /* play safe */ @@ -979,7 +996,7 @@ inline static int tex_aux_equal_eq(halfword p, singleword cmd, singleword flag, case register_toks_cmd: /*tex Again we have references. */ if (eq_value(p) == chr) { -// if (eq_value(p) == chr && eq_level(p) == cur_level) { + // if (eq_value(p) == chr && eq_level(p) == cur_level) { return 1; } else { return 0; @@ -996,7 +1013,7 @@ inline static int tex_aux_equal_eq(halfword p, singleword cmd, singleword flag, math file). */ if (eq_type(p) == cmd && eq_value(p) == chr) { -// if (eq_type(p) == cmd && eq_value(p) == chr && eq_level(p) == cur_level) { + // if (eq_type(p) == cmd && eq_value(p) == chr && eq_level(p) == cur_level) { return 1; } return 0; @@ -1344,15 +1361,6 @@ void tex_forced_define(int g, halfword p, singleword f, singleword t, halfword e } } -// void forced_define(int l, halfword p, singleword f, singleword t, halfword e) -// { -// eq_destroy(hash_state.eqtb[p]); -// set_eq_level(p, l); -// set_eq_type(p, t); -// set_eq_flag(p, f); -// set_eq_value(p, e); -// } - void tex_word_define(int g, halfword p, halfword w) { if (tex_aux_mutation_permitted(p)) { @@ -1430,7 +1438,7 @@ void tex_forced_word_define(int g, halfword p, singleword f, halfword w) void tex_save_for_after_group(halfword t) { if (cur_level > level_one && tex_room_on_save_stack()) { - save_type(lmt_save_state.save_stack_data.ptr) = insert_tokens; + save_type(lmt_save_state.save_stack_data.ptr) = insert_tokens_save_type; save_level(lmt_save_state.save_stack_data.ptr) = level_zero; save_value(lmt_save_state.save_stack_data.ptr) = t; ++lmt_save_state.save_stack_data.ptr; @@ -1498,9 +1506,9 @@ void tex_unsave(void) while (1) { --lmt_save_state.save_stack_data.ptr; switch (save_type(lmt_save_state.save_stack_data.ptr)) { - case level_boundary: + case level_boundary_save_type: goto DONE; - case restore_old_value: + case restore_old_value_save_type: { halfword p = save_value(lmt_save_state.save_stack_data.ptr); /*tex @@ -1535,7 +1543,7 @@ void tex_unsave(void) } break; } - case insert_tokens: + case insert_tokens_save_type: { /*tex A list starts a new input level (for now). */ halfword p = save_value(lmt_save_state.save_stack_data.ptr); @@ -1548,7 +1556,7 @@ void tex_unsave(void) } break; } - case restore_lua: + case restore_lua_save_type: { /* The same as lua_function_code in |textoken.c|. */ halfword p = save_value(lmt_save_state.save_stack_data.ptr); @@ -1566,7 +1574,7 @@ void tex_unsave(void) a = 1; break; } - case restore_zero: + case restore_zero_save_type: { halfword p = save_value(lmt_save_state.save_stack_data.ptr); if (eq_level(p) == level_one) { @@ -1946,11 +1954,11 @@ void tex_initialize_equivalents(void) int tex_located_save_value(int id) { int i = lmt_save_state.save_stack_data.ptr - 1; - while (save_type(i) != level_boundary) { + while (save_type(i) != level_boundary_save_type) { i--; } while (i < lmt_save_state.save_stack_data.ptr) { - if (save_type(i) == restore_old_value && save_value(i) == id) { + if (save_type(i) == restore_old_value_save_type && save_value(i) == id) { /* if (math_direction_par != save_value(i - 1)) { return 1; diff --git a/source/luametatex/source/tex/texequivalents.h b/source/luametatex/source/tex/texequivalents.h index aaf45d0c1..24a1729f9 100644 --- a/source/luametatex/source/tex/texequivalents.h +++ b/source/luametatex/source/tex/texequivalents.h @@ -526,22 +526,15 @@ typedef enum int_codes { math_eqno_gap_step_code, /*tex factor/1000 used for distance between eq and eqno */ math_display_skip_mode_code, math_scripts_mode_code, - /* math_script_box_mode_code, */ - /* math_script_char_mode_code, */ math_limits_mode_code, math_nolimits_mode_code, math_rules_mode_code, math_rules_fam_code, math_penalties_mode_code, math_check_fences_mode_code, - /* math_delimiters_mode_code, */ - /* math_fences_mode_code, */ - /* math_rule_thickness_mode_code, */ math_slack_mode_code, - /* math_flatten_mode_code, */ math_skip_mode_code, math_double_script_mode_code, - /* math_control_mode_code, */ math_font_control_code, math_display_mode_code, math_dict_group_code, @@ -723,7 +716,7 @@ typedef enum attribute_codes { # define eqtb_indirect_range(n) ((n < internal_glue_base) || ((n > eqtb_size) && (n <= lmt_hash_state.hash_data.top))) # define eqtb_out_of_range(n) ((n >= undefined_control_sequence) && ((n <= eqtb_size) || n > lmt_hash_state.hash_data.top)) -# define eqtb_valid_cs(n) ((n == 0) || (n > lmt_hash_state.hash_data.top) || ((n > frozen_control_sequence) && (n <= eqtb_size))) +# define eqtb_invalid_cs(n) ((n == 0) || (n > lmt_hash_state.hash_data.top) || ((n > frozen_control_sequence) && (n <= eqtb_size))) # define character_in_range(i) (i >= 0 && i <= max_character_code) # define catcode_in_range(i) (i >= 0 && i <= max_category_code) @@ -855,73 +848,79 @@ inline void tex_set_saved_record(halfword ptr, quarterword type, quarterword lev The rather explicit |save_| items indicate a type. They are sometimes used to lookup a specific field (when tracing). + + Todo: less of these, a few more generic ones, like count, dimen, etc */ typedef enum save_types { - restore_old_value, /*tex a value should be restored later */ - restore_zero, /*tex an undefined entry should be restored */ - insert_tokens, - restore_lua, - level_boundary, /*tex the beginning of a group */ + restore_old_value_save_type, /*tex a value should be restored later */ + restore_zero_save_type, /*tex an undefined entry should be restored */ + insert_tokens_save_type, + restore_lua_save_type, + level_boundary_save_type, /*tex the beginning of a group */ + /* */ + line_number_save_type, + /* */ + insert_index_save_type, /* */ - saved_line_number, + discretionary_count_save_type, /* */ - saved_insert_index, + text_direction_save_type, /* */ - saved_discretionary_count, + equation_number_location_save_type, /* */ - saved_text_direction, + choices_count_save_type, /* */ - saved_equation_number_location, + fraction_variant_save_type, + fraction_auto_style_save_type, + fraction_user_style_save_type, /* */ - saved_choices_count, + radical_degree_done_save_type, /* make this better: just types */ + radical_style_save_type, /* */ - saved_fraction_variant, - saved_fraction_auto_style, - saved_fraction_user_style, - saved_operator_variant, + operator_variant_save_type, /* */ - saved_attribute_list, + attribute_list_save_type, /* */ - saved_math_pointer, - saved_math_class, + math_pointer_save_type, + math_class_save_type, /* */ - saved_box_type, - saved_box_context, - saved_box_spec, - saved_box_direction, - saved_box_attr_list, - saved_box_pack, - saved_box_orientation, - saved_box_anchor, - saved_box_geometry, - saved_box_xoffset, - saved_box_yoffset, - saved_box_xmove, - saved_box_ymove, - saved_box_reverse, - saved_box_discard, - saved_box_noskips, - saved_box_callback, - saved_box_container, - saved_box_shift, - saved_box_source, - saved_box_target, - saved_box_axis, - saved_box_class, - saved_box_state, - saved_box_retain, + box_type_save_type, + box_context_save_type, + box_spec_save_type, + box_direction_save_type, + box_attr_list_save_type, + box_pack_save_type, + box_orientation_save_type, + box_anchor_save_type, + box_geometry_save_type, + box_xoffset_save_type, + box_yoffset_save_type, + box_xmove_save_type, + box_ymove_save_type, + box_reverse_save_type, + box_discard_save_type, + box_noskips_save_type, + box_callback_save_type, + box_container_save_type, + box_shift_save_type, + box_source_save_type, + box_target_save_type, + box_axis_save_type, + box_class_save_type, + box_state_save_type, + box_retain_save_type, /* */ - saved_local_box_location, - saved_local_box_index, - saved_local_box_options, + local_box_location_save_type, + local_box_index_save_type, + local_box_options_save_type, /* */ - saved_adjust_location, - saved_adjust_options, - saved_adjust_index, - saved_adjust_attr_list, - saved_adjust_depth_before, - saved_adjust_depth_after, + adjust_location_save_type, + adjust_options_save_type, + adjust_index_save_type, + adjust_attr_list_save_type, + adjust_depth_before_save_type, + adjust_depth_after_save_type, } save_types; /*tex Nota bena: |equiv_value| is the same as |equiv| but sometimes we use that name instead. */ @@ -966,12 +965,15 @@ typedef enum tex_group_codes { no_align_group, /*tex code for |\noalign| */ output_group, /*tex code for output routine */ math_group, /*tex code for, e.g., |\char'136| */ + math_stack_group, + math_component_group, discretionary_group, /*tex code for |\discretionary|' */ insert_group, /*tex code for |\insert| */ vadjust_group, /*tex code for |\vadjust| */ vcenter_group, /*tex code for |\vcenter| */ math_fraction_group, /*tex code for |\over| and friends */ math_operator_group, + math_radical_group, math_choice_group, /*tex code for |\mathchoice| */ also_simple_group, /*tex code for |\begingroup|\unknown|\egroup| */ semi_simple_group, /*tex code for |\begingroup|\unknown|\endgroup| */ @@ -1265,7 +1267,6 @@ extern void tex_forced_word_define (int g, halfword p, singleword flag, halfword # define math_skip_par glue_parameter(math_skip_code) # define math_skip_mode_par count_parameter(math_skip_mode_code) # define math_double_script_mode_par count_parameter(math_double_script_mode_code) -/*define math_control_mode_par count_parameter(math_control_mode_code) */ # define math_font_control_par count_parameter(math_font_control_code) # define math_display_mode_par count_parameter(math_display_mode_code) # define math_dict_group_par count_parameter(math_dict_group_code) @@ -1364,18 +1365,20 @@ extern void tex_forced_word_define (int g, halfword p, singleword flag, halfword # define end_line_char_inactive ((end_line_char_par < 0) || (end_line_char_par > 127)) -# define delimiter_factor_par count_parameter(delimiter_factor_code) -/*define post_binary_penalty_par count_parameter(post_binary_penalty_code) */ +/*tex + We keep these as reference but they are no longer equivalent to regular \TEX\ because we have + class based penalties instead. +*/ + +/*define post_binary_penalty_par count_parameter(post_binary_penalty_code) */ /*define post_relation_penalty_par count_parameter(post_relation_penalty_code) */ -/*define pre_binary_penalty_par count_parameter(pre_binary_penalty_code) */ -/*define pre_relation_penalty_par count_parameter(pre_relation_penalty_code) */ +/*define pre_binary_penalty_par count_parameter(pre_binary_penalty_code) */ +/*define pre_relation_penalty_par count_parameter(pre_relation_penalty_code) */ + +# define delimiter_factor_par count_parameter(delimiter_factor_code) # define math_penalties_mode_par count_parameter(math_penalties_mode_code) # define math_check_fences_par count_parameter(math_check_fences_mode_code) -/*define math_delimiters_mode_par count_parameter(math_delimiters_mode_code) */ -/*define math_fences_mode_par count_parameter(math_fences_mode_code) */ -/*define math_rule_thickness_mode_par count_parameter(math_rule_thickness_mode_code) */ # define math_slack_mode_par count_parameter(math_slack_mode_code) -/*define math_flatten_mode_par count_parameter(math_flatten_mode_code) */ # define null_delimiter_space_par dimen_parameter(null_delimiter_space_code) # define disable_spaces_par count_parameter(disable_spaces_code) # define glyph_options_par count_parameter(glyph_options_code) @@ -1388,8 +1391,6 @@ extern void tex_forced_word_define (int g, halfword p, singleword flag, halfword # define glyph_x_offset_par dimen_parameter(glyph_x_offset_code) # define glyph_y_offset_par dimen_parameter(glyph_y_offset_code) # define math_scripts_mode_par count_parameter(math_scripts_mode_code) -/*define math_script_box_mode_par count_parameter(math_script_box_mode_code) */ -/*define math_script_char_mode_par count_parameter(math_script_char_mode_code) */ # define math_limits_mode_par count_parameter(math_limits_mode_code) # define math_nolimits_mode_par count_parameter(math_nolimits_mode_code) # define math_rules_mode_par count_parameter(math_rules_mode_code) @@ -1457,19 +1458,6 @@ typedef enum shaping_penalties_mode_bits { # define tab_size_par dimen_parameter(tab_size_code) -/*define prev_graf_par cur_list.prev_graf */ -/*define prev_depth_par cur_list.prev_depth */ -/*define space_factor_par cur_list.space_factor */ - -/*define tail_par cur_list.tail */ -/*define head_par cur_list.head */ -/*define mode_par cur_list.mode */ -/*define dirs_par cur_list.dirs */ - -/*define incompleat_noad_par cur_list.incompleat_noad */ -/*define mode_line_par cur_list.mode_line */ -/*define delim_par cur_list.delim */ - # define par_shape_par specification_parameter(par_shape_code) # define inter_line_penalties_par specification_parameter(inter_line_penalties_code) # define club_penalties_par specification_parameter(club_penalties_code) @@ -1479,11 +1467,17 @@ typedef enum shaping_penalties_mode_bits { # define math_forward_penalties_par specification_parameter(math_forward_penalties_code) # define math_backward_penalties_par specification_parameter(math_backward_penalties_code) +/*tex + We keep these three as reference but because they are backend related they are basically + no-ops and ignored. +*/ + /*define h_offset_par dimen_parameter(h_offset_code) */ /*define v_offset_par dimen_parameter(v_offset_code) */ -# define px_dimen_par dimen_parameter(px_dimen_code) /*define mag_par count_parameter(mag_code) */ +# define px_dimen_par dimen_parameter(px_dimen_code) + # define max_dead_cycles_par count_parameter(max_dead_cycles_code) # define output_box_par count_parameter(output_box_code) # define holding_inserts_par count_parameter(holding_inserts_code) @@ -1596,7 +1590,6 @@ typedef enum hyphenation_mode_bits { /*define glue_data_par count_parameter(glue_data_code) */ # define cur_lang_par count_parameter(language_code) -/*define cur_font_par eq_value(current_font_sequence) */ # define cur_font_par count_parameter(font_code) typedef enum normalize_line_mode_bits { diff --git a/source/luametatex/source/tex/texerrors.c b/source/luametatex/source/tex/texerrors.c index 3252d2c50..bcc581f21 100644 --- a/source/luametatex/source/tex/texerrors.c +++ b/source/luametatex/source/tex/texerrors.c @@ -600,105 +600,18 @@ void tex_handle_error_message_only( in ConTeXt but I;'m nor that sure if users really need it. The english is probably the least problematic part of an error so first I will perfect the tracing bit. -*/ - -/* - %c int char - %s *char string - %q *char 'string' - %i int integer - %e backslash (tex escape) - %C int int symbolic representation of cmd chr - %E *char \cs - %S int tex cs string - %M int mode - %T int tex string - %% percent + Todo: a translation callback: |str, 1 => str|, or not. */ extern void tex_handle_error(error_types type, const char *format, ...) { + const char *str = NULL; va_list args; va_start(args, format); /* hm, weird, no number */ - /*tex Todo: a translation callback: |str, 1 => str|. */ tex_aux_start_error(); - while (1) { - int chr = *format++; - switch (chr) { - case '\0': - goto DONE; - case '%': - { - chr = *format++; - switch (chr) { - case '\0': - goto DONE; - case 'c': - tex_print_char(va_arg(args, int)); - break; - case 's': - tex_print_str(va_arg(args, char *)); - break; - case 'q': - tex_print_char('\''); - tex_print_str(va_arg(args, char *)); - tex_print_char('\''); - break; - case 'm': - tex_print_cs_checked(va_arg(args, int)); - break; - case 'i': - tex_print_int(va_arg(args, int)); - break; - case 'e': - tex_print_str_esc(NULL); - break; - case 'C': - { - int cmd = va_arg(args, int); - int val = va_arg(args, int); - tex_print_cmd_chr((singleword) cmd, val); /* inlining doesn't work */ - break; - } - case 'E': - tex_print_str_esc(va_arg(args, char *)); - break; - case 'S': - { - halfword cs = va_arg(args, int); - tex_print_cs(cs); - break; - } - case 'M': - { - halfword mode = va_arg(args, int); - tex_print_str(tex_string_mode(mode)); - break; - } - case 'T': - { - strnumber s = va_arg(args, int); - tex_print_tex_str(s); - break; - } - case '%': - tex_print_char('%'); - break; - default: - /* ignore bad one */ - break; - } - } - break; - default: - tex_print_char(chr); /* todo: utf */ - break; - } - } - DONE: - /*tex Todo: a translation callback: |str, 2 => str|. */ - tex_aux_update_help_text(va_arg(args, char *)); + tex_print_format_args(format, args); + tex_aux_update_help_text(str); tex_aux_do_handle_error_type(type); va_end(args); } diff --git a/source/luametatex/source/tex/texfont.c b/source/luametatex/source/tex/texfont.c index dd63044ec..605d6ff75 100644 --- a/source/luametatex/source/tex/texfont.c +++ b/source/luametatex/source/tex/texfont.c @@ -251,6 +251,7 @@ void tex_char_malloc_mathinfo(charinfo *ci) mi->top_right_math_kern_array = NULL; mi->bottom_right_math_kern_array = NULL; mi->bottom_left_math_kern_array = NULL; + /* zero annyway: */ mi->top_left_kern = 0; mi->top_right_kern = 0; mi->bottom_left_kern = 0; @@ -259,6 +260,9 @@ void tex_char_malloc_mathinfo(charinfo *ci) mi->right_margin = 0; mi->top_margin = 0; mi->bottom_margin = 0; + /* */ + mi->top_overshoot = INT_MIN; + mi->bottom_overshoot = INT_MIN; if (ci->math) { /*tex This seldom or probably never happens. */ tex_set_charinfo_vertical_parts(ci, NULL); @@ -399,28 +403,43 @@ int tex_math_char_exists(halfword f, int c, int size) a little. */ -int tex_get_math_char(halfword f, int c, int size, scaled *scale) +int tex_get_math_char(halfword f, int c, int size, scaled *scale, int direction) { int id = find_charinfo_id(f, c); texfont *tf = lmt_font_state.fonts[f]; - if (id && size && tf->compactmath) { - for (int i=1;i<=size;i++) { + if (id) { + /* */ + if (direction) { charinfo *ci = &tf->chardata[id]; - if (ci->math) { - int s = ci->math->smaller; - if (s && proper_char_index(f, s)) { - id = find_charinfo_id(f, s); - if (id) { - /* todo: trace */ - c = s; + int m = ci->math->mirror; + if (m && proper_char_index(f, m)) { + int mid = find_charinfo_id(f, m); + if (mid) { + id = mid; + c = m; + } + } + } + /* */ + if (size && tf->compactmath) { + for (int i=1;i<=size;i++) { + charinfo *ci = &tf->chardata[id]; + if (ci->math) { + int s = ci->math->smaller; + if (s && proper_char_index(f, s)) { + id = find_charinfo_id(f, s); + if (id) { + /* todo: trace */ + c = s; + } else { + break; + } } else { break; } } else { break; } - } else { - break; } } } @@ -430,11 +449,6 @@ int tex_get_math_char(halfword f, int c, int size, scaled *scale) *scale = 1000; } } - /* - if (! id && ! tf->oldmath) { - c = check_math_char(f, c, size); - } - */ return c; } @@ -688,7 +702,6 @@ void tex_create_null_font(void) int id = tex_new_font(); tex_set_font_name(id, "nullfont"); tex_set_font_original(id, "nullfont"); - /* set_font_touched(id, 1); */ } int tex_is_valid_font(halfword f) @@ -1562,48 +1575,6 @@ void tex_set_cur_font(halfword g, halfword f) update_tex_font(g, f); } -/*tex This prints a scaled real, rounded to five digits. */ - -static char *tex_aux_scaled_to_string(scaled s) -{ - static char result[16]; - int k = 0; - /*tex The amount of allowable inaccuracy: */ - scaled delta; - if (s < 0) { - /*tex Only print the sign, if negative */ - result[k++] = '-'; - s = -s; - } - { - int l = 0; - char digs[8] = { 0 }; - int n = s / unity; - /*tex Process the integer part: */ - do { - digs[l++] = (char) (n % 10); - n = n / 10;; - } while (n > 0); - while (l > 0) { - result[k++] = (char) (digs[--l] + '0'); - } - } - result[k++] = '.'; - s = 10 * (s % unity) + 5; - delta = 10; - do { - if (delta > unity) { - /*tex Round the last digit: */ - s = s + 0100000 - 050000; - } - result[k++] = (char) ('0' + (s / unity)); - s = 10 * (s % unity); - delta = delta * 10; - } while (s > delta); - result[k] = 0; - return (char *) result; -} - /*tex Because we do fonts in \LUA\ we can decide to drop this one and assume a definition using the @@ -1639,29 +1610,23 @@ int tex_tex_def_font(int a) /*tex Put the positive 'at' size into |s|. */ s = tex_scan_dimen(0, 0, 0, 0, NULL); if ((s <= 0) || (s >= 01000000000)) { - char msg[256]; - snprintf(msg, 255, - "Improper 'at' size (%spt), replaced by 10pt", - tex_aux_scaled_to_string(s) - ); tex_handle_error( normal_error_type, - msg, + "Improper 'at' size (%D), replaced by 10pt", + s, + pt_unit, "I can only handle fonts at positive sizes that are less than 2048pt, so I've\n" - "changed what you said to 10pt." ); + "changed what you said to 10pt." + ); s = 10 * unity; } } else if (tex_scan_keyword("scaled")) { s = tex_scan_int(0, NULL); if ((s <= 0) || (s > 32768)) { - char msg[256]; - snprintf(msg, 255, - "Illegal magnification has been changed to 1000 (%d)", - (int) s - ); tex_handle_error( normal_error_type, - msg, + "Illegal magnification has been changed to 1000 (%i)", + s, "The magnification ratio must be between 1 and 32768." ); s = -1000; @@ -1800,27 +1765,27 @@ halfword tex_char_vertical_italic_from_font(halfword f, halfword c) return ci->math ? ci->math->vertical_italic : INT_MIN; } -halfword tex_char_top_accent_from_font(halfword f, halfword c) +halfword tex_char_unchecked_top_anchor_from_font(halfword f, halfword c) { charinfo *ci = tex_aux_char_info(f, c); - return ci->math ? ci->math->top_accent : INT_MIN; + return ci->math ? ci->math->top_anchor : INT_MIN; } halfword tex_char_top_anchor_from_font(halfword f, halfword c) { - scaled n = tex_char_top_accent_from_font(f, c); + scaled n = tex_char_unchecked_top_anchor_from_font(f, c); return n == INT_MIN ? 0 : n; } -halfword tex_char_bot_accent_from_font(halfword f, halfword c) +halfword tex_char_unchecked_bottom_anchor_from_font(halfword f, halfword c) { charinfo *ci = tex_aux_char_info(f, c); - return ci->math ? ci->math->bottom_accent : INT_MIN; + return ci->math ? ci->math->bottom_anchor : INT_MIN; } -halfword tex_char_bot_anchor_from_font(halfword f, halfword c) +halfword tex_char_bottom_anchor_from_font(halfword f, halfword c) { - scaled n = tex_char_bot_accent_from_font(f, c); + scaled n = tex_char_unchecked_bottom_anchor_from_font(f, c); return n == INT_MIN ? 0 : n; } @@ -1890,6 +1855,18 @@ scaled tex_char_bottom_margin_from_font(halfword f, halfword c) return ci->math ? ci->math->bottom_margin : 0; } +scaled tex_char_top_overshoot_from_font(halfword f, halfword c) +{ + charinfo *ci = tex_aux_char_info(f, c); + return ci->math ? ci->math->top_overshoot : 0; +} + +scaled tex_char_bottom_overshoot_from_font(halfword f, halfword c) +{ + charinfo *ci = tex_aux_char_info(f, c); + return ci->math ? ci->math->bottom_overshoot : 0; +} + /* Nodes */ scaled tex_char_width_from_glyph(halfword g) diff --git a/source/luametatex/source/tex/texfont.h b/source/luametatex/source/tex/texfont.h index a13c6e13d..e5365a0be 100644 --- a/source/luametatex/source/tex/texfont.h +++ b/source/luametatex/source/tex/texfont.h @@ -80,15 +80,15 @@ typedef struct extinfo { typedef struct mathinfo { scaled vertical_italic; - scaled top_accent; - scaled bottom_accent; + scaled top_anchor; /* provided by the font, aka topaccent */ + scaled bottom_anchor; /* provided by context */ int smaller; scaled scale; - int flat_accent; - int top_left_math_kerns; - int top_right_math_kerns; - int bottom_right_math_kerns; - int bottom_left_math_kerns; + int flat_accent; /* flac feature code point */ + int top_left_math_kerns; /* size of array */ + int top_right_math_kerns; /* size of array */ + int bottom_right_math_kerns; /* size of array */ + int bottom_left_math_kerns; /* size of array */ extinfo *horizontal_parts; extinfo *vertical_parts; scaled *top_left_math_kern_array; @@ -104,6 +104,10 @@ typedef struct mathinfo { scaled right_margin; scaled top_margin; scaled bottom_margin; + scaled top_overshoot; + scaled bottom_overshoot; + int mirror; + int padding; } mathinfo; typedef struct charinfo { @@ -184,8 +188,6 @@ typedef struct texfont { char *original; /*tex for experimental new thingies */ int compactmath; - /*tex default to false when MathConstants not seen */ - int oldmath; /*tex this controls the engine */ int mathcontrol; int textcontrol; @@ -199,8 +201,6 @@ typedef struct texfont { /*tex all parameters, although only some are used */ int parameter_count; scaled *parameter_base; - /* */ - int padding; /*tex also special */ charinfo *left_boundary; charinfo *right_boundary; @@ -235,8 +235,6 @@ extern font_state_info lmt_font_state; # define font_design_size(a) lmt_font_state.fonts[a]->design_size # define font_first_character(a) lmt_font_state.fonts[a]->first_character # define font_last_character(a) lmt_font_state.fonts[a]->last_character -/*define font_touched(a) font_state.fonts[a]->touched */ -# define font_oldmath(a) lmt_font_state.fonts[a]->oldmath # define font_compactmath(a) lmt_font_state.fonts[a]->compactmath # define font_mathcontrol(a) lmt_font_state.fonts[a]->mathcontrol # define font_textcontrol(a) lmt_font_state.fonts[a]->textcontrol @@ -253,8 +251,6 @@ extern font_state_info lmt_font_state; # define set_font_design_size(a,b) lmt_font_state.fonts[a]->design_size = b # define set_font_first_character(a,b) lmt_font_state.fonts[a]->first_character = b # define set_font_last_character(a,b) lmt_font_state.fonts[a]->last_character = b -/*define set_font_touched(a,b) font_state.fonts[a]->touched = b */ -# define set_font_oldmath(a,b) lmt_font_state.fonts[a]->oldmath = b # define set_font_compactmath(a,b) lmt_font_state.fonts[a]->compactmath = b # define set_font_mathcontrol(a,b) lmt_font_state.fonts[a]->mathcontrol = b # define set_font_textcontrol(a,b) lmt_font_state.fonts[a]->textcontrol = b @@ -408,7 +404,7 @@ extern charinfo *tex_get_charinfo (halfword f, int c); extern int tex_char_exists (halfword f, int c); extern void tex_char_process (halfword f, int c); extern int tex_math_char_exists (halfword f, int c, int size); -extern int tex_get_math_char (halfword f, int c, int size, scaled *scale); +extern int tex_get_math_char (halfword f, int c, int size, scaled *scale, int direction); /*tex @@ -461,9 +457,10 @@ extern int tex_get_math_char (halfword f, int c, int size, scaled *scal # define set_charinfo_bottom_margin(ci,val) if (ci->math) { ci->math->bottom_margin = val; } # define set_charinfo_smaller(ci,val) if (ci->math) { ci->math->smaller = val; } +# define set_charinfo_mirror(ci,val) if (ci->math) { ci->math->mirror = val; } # define set_charinfo_vertical_italic(ci,val) if (ci->math) { ci->math->vertical_italic = val; } -# define set_charinfo_top_accent(ci,val) if (ci->math) { ci->math->top_accent = val; } -# define set_charinfo_bottom_accent(ci,val) if (ci->math) { ci->math->bottom_accent = val; } +# define set_charinfo_top_anchor(ci,val) if (ci->math) { ci->math->top_anchor = val; } +# define set_charinfo_bottom_anchor(ci,val) if (ci->math) { ci->math->bottom_anchor = val; } # define set_charinfo_flat_accent(ci,val) if (ci->math) { ci->math->flat_accent = val; } # define set_charinfo_top_left_kern(ci,val) if (ci->math) { ci->math->top_left_kern = val; } @@ -471,6 +468,9 @@ extern int tex_get_math_char (halfword f, int c, int size, scaled *scal # define set_charinfo_bottom_left_kern(ci,val) if (ci->math) { ci->math->bottom_left_kern = val; } # define set_charinfo_bottom_right_kern(ci,val) if (ci->math) { ci->math->bottom_right_kern = val; } +# define set_charinfo_top_overshoot(ci,val) if (ci->math) { ci->math->top_overshoot = val; } +# define set_charinfo_bottom_overshoot(ci,val) if (ci->math) { ci->math->bottom_overshoot = val; } + /*tex Setters: */ void tex_set_lpcode_in_font (halfword f, halfword c, halfword i); @@ -532,19 +532,22 @@ extern scaled tex_char_width_italic_from_glyph (halfword g); /* x/y sca extern scaledwhd tex_char_whd_from_glyph (halfword g); /* x/y scaled */ +extern halfword tex_char_unchecked_top_anchor_from_font (halfword f, halfword c); +extern halfword tex_char_unchecked_bottom_anchor_from_font (halfword f, halfword c); + extern halfword tex_char_vertical_italic_from_font (halfword f, halfword c); -extern halfword tex_char_top_accent_from_font (halfword f, halfword c); -extern halfword tex_char_bot_accent_from_font (halfword f, halfword c); extern halfword tex_char_flat_accent_from_font (halfword f, halfword c); - extern halfword tex_char_top_anchor_from_font (halfword f, halfword c); -extern halfword tex_char_bot_anchor_from_font (halfword f, halfword c); +extern halfword tex_char_bottom_anchor_from_font (halfword f, halfword c); extern scaled tex_char_left_margin_from_font (halfword f, halfword c); extern scaled tex_char_right_margin_from_font (halfword f, halfword c); extern scaled tex_char_top_margin_from_font (halfword f, halfword c); extern scaled tex_char_bottom_margin_from_font (halfword f, halfword c); +extern scaled tex_char_top_overshoot_from_font (halfword f, halfword c); +extern scaled tex_char_bottom_overshoot_from_font (halfword f, halfword c); + extern extinfo *tex_char_vertical_parts_from_font (halfword f, halfword c); extern extinfo *tex_char_horizontal_parts_from_font (halfword f, halfword c); diff --git a/source/luametatex/source/tex/texinserts.c b/source/luametatex/source/tex/texinserts.c index 874dcf24d..27b979e0f 100644 --- a/source/luametatex/source/tex/texinserts.c +++ b/source/luametatex/source/tex/texinserts.c @@ -443,7 +443,7 @@ void tex_undump_insert_data(dumpstream f) { void tex_run_insert(void) { - tex_set_saved_record(saved_insert_item_index, saved_insert_index, 0, tex_scan_insert_index()); + tex_set_saved_record(saved_insert_item_index, insert_index_save_type, 0, tex_scan_insert_index()); lmt_save_state.save_stack_data.ptr += saved_insert_n_of_items; tex_new_save_level(insert_group); tex_scan_left_brace(); diff --git a/source/luametatex/source/tex/texmaincontrol.c b/source/luametatex/source/tex/texmaincontrol.c index a1983ac4f..a44aa1167 100644 --- a/source/luametatex/source/tex/texmaincontrol.c +++ b/source/luametatex/source/tex/texmaincontrol.c @@ -93,7 +93,7 @@ inline scaled tex_aux_checked_dimen2(scaled v) /*tex These two helpers, of which the second one is still experimental, actually belong in another file so then might be moved. Watch how the first one has the |unsave| call! - */ +*/ static void tex_aux_fixup_directions_and_unsave(void) { @@ -171,7 +171,7 @@ static void tex_aux_out_of_range_error(halfword val, halfword max) runners finish what another started, for instance when we see a left brace, depending on state another runner can kick in. - */ +*/ static void tex_aux_adjust_space_factor(halfword chr) { @@ -414,7 +414,7 @@ static void tex_aux_set_lua_value(int a) { There is a special treatment for spaces when |space_factor <> 1000|. - */ +*/ static void tex_aux_run_math_space(void) { if (! disable_spaces_par) { @@ -797,9 +797,9 @@ static void tex_aux_scan_local_box(int code) { quarterword options = 0; halfword class = 0; tex_scan_local_boxes_keys(&options, &class); - tex_set_saved_record(saved_localbox_item_location, saved_local_box_location, 0, code); - tex_set_saved_record(saved_localbox_item_index, saved_local_box_index, 0, class); - tex_set_saved_record(saved_localbox_item_options, saved_local_box_options, 0, options); + tex_set_saved_record(saved_localbox_item_location, local_box_location_save_type, 0, code); + tex_set_saved_record(saved_localbox_item_index, local_box_index_save_type, 0, class); + tex_set_saved_record(saved_localbox_item_options, local_box_options_save_type, 0, options); lmt_save_state.save_stack_data.ptr += saved_localbox_n_of_items; tex_new_save_level(local_box_group); tex_scan_left_brace(); @@ -811,7 +811,7 @@ static void tex_aux_scan_local_box(int code) { static void tex_aux_finish_local_box(void) { tex_unsave(); - if (saved_type(saved_localbox_item_location - saved_localbox_n_of_items) == saved_local_box_location) { + if (saved_type(saved_localbox_item_location - saved_localbox_n_of_items) == local_box_location_save_type) { halfword p; halfword location = saved_value(saved_localbox_item_location - saved_localbox_n_of_items); quarterword options = (quarterword) saved_value(saved_localbox_item_options - saved_localbox_n_of_items); @@ -2227,7 +2227,7 @@ static void tex_aux_run_discretionary(void) } } DONE: - tex_set_saved_record(saved_discretionary_item_component, saved_discretionary_count, 0, 0); + tex_set_saved_record(saved_discretionary_item_component, discretionary_count_save_type, 0, 0); lmt_save_state.save_stack_data.ptr += saved_discretionary_n_of_items; tex_new_save_level(discretionary_group); tex_scan_left_brace(); @@ -2357,7 +2357,7 @@ static void tex_aux_finish_discretionary(void) p = node_next(cur_list.head); tex_pop_nest(); d = cur_list.tail; - if (saved_type(saved_discretionary_item_component - saved_discretionary_n_of_items) == saved_discretionary_count) { + if (saved_type(saved_discretionary_item_component - saved_discretionary_n_of_items) == discretionary_count_save_type) { switch (saved_value(saved_discretionary_item_component - saved_discretionary_n_of_items)) { case 0: if (n > 0) { @@ -2412,7 +2412,7 @@ static void tex_aux_finish_discretionary(void) default: break; } - tex_set_saved_record(saved_discretionary_item_component - saved_discretionary_n_of_items, saved_discretionary_count, 0, saved_value(saved_discretionary_item_component - saved_discretionary_n_of_items) + 1); + tex_set_saved_record(saved_discretionary_item_component - saved_discretionary_n_of_items, discretionary_count_save_type, 0, saved_value(saved_discretionary_item_component - saved_discretionary_n_of_items) + 1); tex_new_save_level(discretionary_group); tex_scan_left_brace(); tex_push_nest(); @@ -2558,6 +2558,8 @@ static void tex_aux_run_right_brace(void) tex_aux_finish_output(); break; case math_group: + case math_component_group: + case math_stack_group: tex_finish_math_group(); break; case discretionary_group: @@ -2575,6 +2577,9 @@ static void tex_aux_run_right_brace(void) case math_fraction_group: tex_finish_math_fraction(); break; + case math_radical_group: + tex_finish_math_radical(); + break; case math_operator_group: tex_finish_math_operator(); break; @@ -2962,35 +2967,33 @@ static void tex_aux_run_kern(void) static void tex_aux_run_kern(void) { halfword code = cur_chr; - halfword val = tex_scan_dimen(0, 0, 0, 0, NULL); switch (code) { - case normal_kern_code: - break; + /* not yet enabled and maybe it never wil be */ case h_kern_code: - if (cur_mode == mmode) { - break; - } else { - cur_tok = token_val(kern_cmd, normal_kern_code); - tex_aux_run_new_paragraph(); + if (cur_mode == vmode) { + tex_back_input(token_val(kern_cmd, normal_kern_code)); + tex_back_input(token_val(begin_paragraph_cmd, quitvmode_par_code)); return; + } else { + break; } - break; case v_kern_code: - if (cur_mode == mmode) { - break; - } else { - cur_tok = token_val(kern_cmd, normal_kern_code); - tex_aux_run_head_for_vmode(); + if (cur_mode == hmode) { + tex_back_input(token_val(kern_cmd, normal_kern_code)); + tex_back_input(token_val(end_paragraph_cmd, normal_end_paragraph_code)); return; - } - case non_zero_width_kern_code: - if (val) { + } else { break; - } else { - return; } } - tex_tail_append(tex_new_kern_node(val, explicit_kern_subtype)); + { + scaled val = tex_scan_dimen(0, 0, 0, 0, NULL); + if (code == non_zero_width_kern_code && ! val) { + return; + } else { + tex_tail_append(tex_new_kern_node(val, explicit_kern_subtype)); + } + } } static void tex_aux_run_mkern(void) @@ -3548,14 +3551,12 @@ inline static void tex_aux_update_register(int a, int level, halfword index, hal } break; case glue_val_level: -// tex_define(a, index, register_glue_reference_cmd, value); tex_define(a, index, cmd == internal_glue_cmd ? internal_glue_reference_cmd : register_glue_reference_cmd, value); if (is_frozen(a) && cmd == internal_glue_cmd && cur_mode == hmode) { tex_update_par_par(internal_glue_cmd, index - lmt_primitive_state.prim_data[cmd].offset); } break; case mu_val_level: -// tex_define(a, index, register_glue_reference_cmd, value); tex_define(a, index, cmd == internal_glue_cmd ? internal_mu_glue_reference_cmd : register_mu_glue_reference_cmd, value); break; default: @@ -4135,15 +4136,6 @@ static void tex_aux_set_shorthand_def(int a, int force) // tex_define(a, p, math_char_xgiven_cmd, math_packed_character(mval.class_value,mval.family_value,mval.character_value)); break; } - /* - case math_uchar_def_code: - { - mathcodeval mval = tex_scan_mathchar(umathnum_mathcode); - tex_define(a, p, mathspec_cmd, tex_new_math_spec(mval, umathnum_mathcode)); - // tex_define(a, p, math_char_xgiven_cmd, math_packed_character(mval.class_value,mval.family_value,mval.character_value)); - break; - } - */ case count_def_code: { halfword n = tex_scan_int_register_number(); @@ -4780,22 +4772,12 @@ static void tex_aux_set_define_char_code(int a) /* maybe make |a| already a bool case extmathcode_charcode: tex_scan_extdef_math_code((is_global(a)) ? level_one : cur_level, umath_mathcode); break; - /* - case extmathcodenum_charcode: - tex_scan_extdef_math_code((is_global(a)) ? level_one : cur_level, umathnum_mathcode); - break; - */ case delcode_charcode: tex_scan_extdef_del_code((is_global(a)) ? level_one : cur_level, tex_mathcode); break; case extdelcode_charcode: tex_scan_extdef_del_code((is_global(a)) ? level_one : cur_level, umath_mathcode); break; - /* - case extdelcodenum_charcode: - tex_scan_extdef_del_code((is_global(a)) ? level_one : cur_level, umathnum_mathcode); - break; - */ default: break; } @@ -5133,9 +5115,15 @@ static void tex_aux_set_math_parameter(int a) case all_math_styles: tex_set_all_styles(code, value, global_or_local(a), indirect); break; + case all_main_styles: + tex_set_main_styles(code, value, global_or_local(a), indirect); + break; case all_split_styles: tex_set_split_styles(code, value, global_or_local(a), indirect); break; + case all_unsplit_styles: + tex_set_unsplit_styles(code, value, global_or_local(a), indirect); + break; case all_uncramped_styles: tex_set_uncramped_styles(code, value, global_or_local(a), indirect); break; @@ -5492,12 +5480,15 @@ void tex_get_r_token(void) do { tex_get_token(); } while (cur_tok == space_token); - if (eqtb_valid_cs(cur_cs)) { + if (eqtb_invalid_cs(cur_cs)) { if (cur_cs == 0) { tex_back_input(cur_tok); } cur_tok = deep_frozen_protection_token; - /* moved down but this might interfere with input on the console */ + /*tex + Moved down but this might interfere with input on the console which we don't use + anyway. + */ tex_handle_error( insert_error_type, "Missing control sequence inserted", @@ -5506,6 +5497,20 @@ void tex_get_r_token(void) "mixing me up too badly.\n" ); goto RESTART; + // } else if (cur_cmd == cs_name_cmd && cur_chr == cs_name_code) { + // /*tex + // This permits + // |\someassignment\csname foo\endcsname| + // over + // |\expandafter\someassignment\csname foo\endcsname| + // but it actually doesn't happen that frequently so even if we measure a gain of some + // 10\percent on some cases (with millions of iterations) for now I will not enable this + // feature. Of course it is also incompatible but I don't expect anyone to redefine csname + // so it is actually a pretty safe extension. Of course it also reduces tracing. I will + // come back to it when I suspect a performance gain in \CONTEXT\ (or want my code to look + // better). + // */ + // cur_cs = tex_create_csname(); } } @@ -6007,9 +6012,7 @@ static void tex_aux_run_show_whatever(void) tex_begin_diagnostic(); } if (! content) { - tex_print_str("> \\box"); - tex_print_int(n); - tex_print_char('='); + tex_print_format("> \\box%i=",n); } if (r) { tex_show_box(r); @@ -6028,7 +6031,7 @@ static void tex_aux_run_show_whatever(void) } case show_the_code: { - halfword head = tex_the_value_toks(1, NULL, 0); + halfword head = tex_the_value_toks(the_code, NULL, 0); tex_print_nlp(); tex_print_str("> "); tex_show_token_list(head, null, default_token_show_max, 0); @@ -6381,9 +6384,6 @@ void tex_initialize_variables(void) math_pre_display_gap_factor_par = default_pre_display_gap; /* pre_binary_penalty_par = infinite_penalty; */ /* pre_relation_penalty_par = infinite_penalty; */ - /* math_script_box_mode_par = 1; */ - /* math_script_char_mode_par = 1; */ - /* math_flatten_mode_par = 1; */ /*tex We default to ord */ /* obsolete */ math_font_control_par = assumed_math_control; math_eqno_gap_step_par = default_eqno_gap_step; px_dimen_par = one_bp; diff --git a/source/luametatex/source/tex/texmath.c b/source/luametatex/source/tex/texmath.c index d38cbf182..52e200657 100644 --- a/source/luametatex/source/tex/texmath.c +++ b/source/luametatex/source/tex/texmath.c @@ -115,8 +115,6 @@ math_state_info lmt_math_state = { .size = 0, .level = 0, - /* .opentype = 1, */ - /* .padding = 0, */ .par_head = NULL, .fam_head = NULL, .last_left = 0, @@ -300,7 +298,7 @@ static void tex_aux_unsave_math(void) tex_unsave(); lmt_save_state.save_stack_data.ptr -= saved_math_n_of_items; tex_flush_node_list(lmt_dir_state.text_dir_ptr); - if (saved_type(saved_math_item_direction) == saved_text_direction) { + if (saved_type(saved_math_item_direction) == text_direction_save_type) { lmt_dir_state.text_dir_ptr = saved_value(saved_math_item_direction); } else { tex_confusion("unsave math"); @@ -329,9 +327,7 @@ void tex_flush_math(void) static void tex_aux_print_parameter(const char *what, halfword style, halfword param, halfword indirect, halfword value) { tex_begin_diagnostic(); - tex_print_char('{'); - tex_print_str(what); - tex_print_char(' '); + tex_print_format("{%s ", what); if (indirect >= 0 && indirect <= last_math_indirect) { tex_print_str(lmt_interface.math_indirect_values[indirect].name); tex_print_char(' '); @@ -365,7 +361,7 @@ static void tex_aux_print_parameter(const char *what, halfword style, halfword p static void tex_aux_print_fam(const char *what, halfword size, halfword fam) { tex_begin_diagnostic(); - tex_print_format("{%s %C %i=%F}", what, define_family_cmd, size, tex_fam_fnt(fam, size)); + tex_print_format("{%s %C family %i: %F}", what, define_family_cmd, size, fam, tex_fam_fnt(fam, size)); tex_end_diagnostic(); } @@ -384,10 +380,10 @@ void tex_def_fam_fnt(int fam, int size, int fnt, int level) sa_tree_item item; item.int_value = fnt; sa_set_item_4(lmt_math_state.fam_head, fam + (256 * size), item, level); - tex_fixup_math_parameters(fam, size, fnt, level); if (tracing_assigns_par > 1) { tex_aux_print_fam("assigning", size, fam); } + tex_fixup_math_parameters(fam, size, fnt, level); } static void tex_aux_unsave_math_fam_data(int gl) @@ -414,6 +410,7 @@ static void tex_aux_unsave_math_fam_data(int gl) void tex_def_math_parameter(int style, int param, scaled value, int level, int indirect) { sa_tree_item item1, item2; + int different = 1; if (level <= 1) { if (math_parameter_value_type(param) == math_muglue_parameter) { item1 = sa_get_item_8(lmt_math_state.par_head, (param + (math_parameter_max_range * style)), &item2); @@ -423,13 +420,19 @@ void tex_def_math_parameter(int style, int param, scaled value, int level, int i } } } - } - item1.int_value = value; - item2.int_value = indirect; - sa_set_item_8(lmt_math_state.par_head, (param + (math_parameter_max_range * style)), item1, item2, level); - if (tracing_assigns_par > 1) { - tex_aux_print_parameter("assigning", style, param, indirect, value); - } + } else { + /*tex Less tracing at the cost of a lookup. */ + item1 = sa_get_item_8(lmt_math_state.par_head, (param + (math_parameter_max_range * style)), &item2); + different = item1.int_value != value || item2.int_value != indirect; + } + // if (different) { // maybe + item1.int_value = value; + item2.int_value = indirect; + sa_set_item_8(lmt_math_state.par_head, (param + (math_parameter_max_range * style)), item1, item2, level); + if (different && tracing_assigns_par > 1) { + tex_aux_print_parameter("assigning", style, param, indirect, value); + } + // } } // mukern .. there is no mudimen @@ -790,7 +793,7 @@ quarterword tex_aux_set_math_char(halfword target, mathcodeval *mval, mathdictva halfword hmcode = tex_get_hm_code(mval->character_value); kernel_math_character(target) = mval->character_value; if (mval->class_value == math_use_current_family_code) { - kernel_math_family(target) = cur_fam_par_in_range ? cur_fam_par : 0; + kernel_math_family(target) = cur_fam_par_in_range ? cur_fam_par : mval->family_value; node_subtype(target) = ordinary_noad_subtype; } else { kernel_math_family(target) = mval->family_value; @@ -1183,7 +1186,7 @@ static void tex_aux_display_fraction_noad(halfword n, int threshold, int max) static void tex_aux_new_save_level_math(quarterword group) { halfword direction = math_direction_par; - tex_set_saved_record(saved_math_item_direction, saved_text_direction, 0, lmt_dir_state.text_dir_ptr); + tex_set_saved_record(saved_math_item_direction, text_direction_save_type, 0, lmt_dir_state.text_dir_ptr); lmt_save_state.save_stack_data.ptr += saved_math_n_of_items; lmt_dir_state.text_dir_ptr = tex_new_dir(normal_dir_subtype, direction); tex_new_save_level(group); @@ -1269,7 +1272,7 @@ void tex_run_math_initialize(void) void tex_run_math_equation_number(void) { if (tex_in_privileged_mode()) { if (cur_group == math_shift_group) { - tex_set_saved_record(saved_equation_number_item_location, saved_equation_number_location, 0, cur_chr); + tex_set_saved_record(saved_equation_number_item_location, equation_number_location_save_type, 0, cur_chr); lmt_save_state.save_stack_data.ptr += saved_equation_number_n_of_items; tex_aux_enter_ordinary_math(text_style); } else { @@ -1479,28 +1482,6 @@ static delcodeval tex_aux_scan_extdef_del_code(int extcode, int doclass) } } break; - /* - case umathnum_mathcode: - // |\Udelcodenum|: |"FF<21bits>|; the largest numeric value is $2^29-1$, but the top of - // bit 21 can't be used as it contains invalid USV's. - if (doclass) { - tex_confusion("umathnum mathcode"); - } else { - halfword v = tex_scan_int(0, NULL); - d.small.family_value = (short) math_family_part(v); - d.small.character_value = math_character_part(v); - if (d.small.family_value < 0 || d.small.family_value > max_math_family_index || d.small.character_value > max_math_character_code) { - tex_handle_error( - normal_error_type, - "Invalid delimiter code", - "I'm going to use 0 instead of that illegal code value." - ); - d.small.family_value = 0; - d.small.character_value = 0; - } - } - break; - */ default: /*tex Something's gone wrong! */ tex_confusion("unknown extcode, case 1"); @@ -1722,11 +1703,6 @@ static int tex_aux_scan_math(halfword target, halfword style, int usetextfont, h case math_xchar_number_code: mval = tex_scan_mathchar(umath_mathcode); break; - /* - case math_uchar_number_code: - mval = tex_scan_mathchar(umathnum_mathcode); - break; - */ default: tex_confusion("scan math char, case 1"); break; @@ -1760,10 +1736,10 @@ static int tex_aux_scan_math(halfword target, halfword style, int usetextfont, h if (nocomponent) { goto DEFAULT; } else { - tex_set_saved_record(saved_math_group_item_pointer, saved_math_pointer, 0, target); - tex_set_saved_record(saved_math_group_all_class, saved_math_class, 0, unset_noad_class); + tex_set_saved_record(saved_math_group_item_pointer, math_pointer_save_type, 0, target); + tex_set_saved_record(saved_math_group_all_class, math_class_save_type, 0, unset_noad_class); lmt_save_state.save_stack_data.ptr += saved_math_group_n_of_items; - tex_aux_push_math(math_group, style); + tex_aux_push_math(math_component_group, style); if (usetextfont) { tex_set_math_text_font(style, usetextfont); } @@ -1782,8 +1758,8 @@ static int tex_aux_scan_math(halfword target, halfword style, int usetextfont, h tex_back_input(cur_tok); tex_scan_left_brace(); SCAN_SUBFORMULA: - tex_set_saved_record(saved_math_group_item_pointer, saved_math_pointer, 0, target); - tex_set_saved_record(saved_math_group_all_class, saved_math_class, 0, all); + tex_set_saved_record(saved_math_group_item_pointer, math_pointer_save_type, 0, target); + tex_set_saved_record(saved_math_group_all_class, math_class_save_type, 0, all); lmt_save_state.save_stack_data.ptr += saved_math_group_n_of_items; tex_aux_push_math(math_group, style); toks = every_math_atom_par; @@ -2007,11 +1983,6 @@ int tex_scan_math_cmd_val(mathcodeval *mval, mathdictval *dval) *dval = tex_scan_mathdict(); *mval = tex_scan_mathchar(umath_mathcode); break; - /* - case math_uchar_number_code: - *mval = tex_scan_mathchar(umathnum_mathcode); - break; - */ default: /* no message yet */ return 0; @@ -2046,11 +2017,6 @@ int tex_scan_math_code_val(halfword code, mathcodeval *mval, mathdictval *dval) *dval = tex_scan_mathdict(); *mval = tex_scan_mathchar(umath_mathcode); break; - /* - case math_uchar_number_code: - *mval = tex_scan_mathchar(umathnum_mathcode); - break; - */ case math_class_number_code: { halfword family = cur_fam_par; @@ -2197,7 +2163,7 @@ static void tex_aux_math_math_component(halfword target, int append) case 'l': case 'L': if (tex_scan_mandate_keyword("all", 2)) { allclass = (quarterword) tex_scan_math_class_number(0); - if (! valid_math_class_code(subtype)) { + if (! valid_math_class_code(allclass)) { allclass = unset_noad_class; } } @@ -2212,7 +2178,7 @@ static void tex_aux_math_math_component(halfword target, int append) case 'e': case 'E': if (tex_scan_mandate_keyword("leftclass", 2)) { halfword c = tex_scan_math_class_number(0); - if (! valid_math_class_code(subtype)) { + if (! valid_math_class_code(c)) { c = ordinary_noad_subtype; } set_noad_left_class(target, c); @@ -2487,11 +2453,6 @@ static void tex_aux_scan_delimiter(halfword target, int code, int class) case math_xchar_number_code: mval = tex_scan_mathchar(umath_mathcode); break; - /* - case math_uchar_number_code: - mval = tex_scan_mathchar(umathnum_mathcode); - break; - */ default: tex_confusion("scan math char, case 1"); break; @@ -2723,27 +2684,12 @@ void tex_run_math_radical(void) } case root_radical_subtype: case rooted_radical_subtype: - /*tex - The trick with the |node_next(q)| is used by |scan_math| to decide whether it needs to - go on. This code looks a bit weird, is it okay? So, here we directly pick up the two - lists while in choices we go through the somewhat complex \quote {complete} group based - mechanism. - */ { - halfword q = tex_new_node(math_char_node, 0); - node_next(q) = radical; /* trick */ - radical_degree(radical) = q; - if (! tex_aux_scan_math(radical_degree(radical), tex_math_style_variant(style, math_parameter_degree_variant), 0, 0, 0, 0, unset_noad_class, unset_noad_class)) { - /*tex Actually it's always scriptscript I guess. */ - node_next(radical_degree(radical)) = null; - q = tex_new_node(math_char_node, 0); - noad_nucleus(radical) = q; - if (noad_style(radical) != style) { - /* We keep the style in the node for diagnostics. */ - tex_back_input(token_val(math_style_cmd, noad_style(radical))); - } - tex_aux_scan_math(q, tex_math_style_variant(style, math_parameter_radical_variant), 0, 0, 0, 0, unset_noad_class, unset_noad_class); - } + tex_set_saved_record(saved_radical_degree_done, radical_degree_done_save_type, 0, 0); + tex_set_saved_record(saved_radical_style, radical_style_save_type, 0, 0); + lmt_save_state.save_stack_data.ptr += saved_radical_n_of_items; + tex_aux_push_math(math_radical_group, tex_math_style_variant(style, math_parameter_degree_variant)); + tex_scan_left_brace(); break; } default : @@ -2756,6 +2702,29 @@ void tex_run_math_radical(void) } } +void tex_finish_math_radical(void) +{ + halfword whatever = tex_new_node(sub_mlist_node, 0); + tex_aux_unsave_math(); + if (saved_type(saved_radical_degree_done - saved_radical_n_of_items) == radical_degree_done_save_type) { + halfword content = tex_aux_finish_math_list(null); + halfword radical = cur_list.tail; + kernel_math_list(whatever) = content; + if (saved_value(saved_radical_degree_done - saved_radical_n_of_items)) { + noad_nucleus(radical) = whatever; + lmt_save_state.save_stack_data.ptr -= saved_radical_n_of_items; + } else { + halfword style = saved_value(saved_radical_style - saved_radical_n_of_items); + radical_degree(radical) = whatever; + tex_set_saved_record(saved_radical_degree_done - saved_radical_n_of_items, radical_degree_done_save_type, 0, 1); + tex_aux_push_math(math_radical_group, tex_math_style_variant(style, math_parameter_radical_variant)); + tex_scan_left_brace(); + } + } else { + tex_confusion("scan radical"); + } +} + void tex_run_math_accent(void) { mathcodeval t = tex_no_math_code(); @@ -2907,7 +2876,7 @@ void tex_run_math_choice(void) { } DONE: tex_tail_append(n); - tex_set_saved_record(saved_choice_item_count, saved_choices_count, 0, math_pre_break_choice); + tex_set_saved_record(saved_choice_item_count, choices_count_save_type, 0, math_pre_break_choice); lmt_save_state.save_stack_data.ptr += saved_choice_n_of_items; tex_aux_push_math(math_choice_group, cur_list.math_style); tex_scan_left_brace(); @@ -2918,7 +2887,7 @@ void tex_run_math_choice(void) { { halfword n = tex_new_node(choice_node, normal_choice_subtype); tex_tail_append(n); - tex_set_saved_record(saved_choice_item_count, saved_choices_count, 0, math_display_choice); + tex_set_saved_record(saved_choice_item_count, choices_count_save_type, 0, math_display_choice); lmt_save_state.save_stack_data.ptr += saved_choice_n_of_items; tex_aux_push_math(math_choice_group, display_style); tex_scan_left_brace(); @@ -2934,9 +2903,10 @@ void tex_run_math_choice(void) { tex_tail_append(n); noad_nucleus(n) = m; tex_scan_left_brace(); - tex_set_saved_record(0, saved_math_pointer, 0, m); - ++lmt_save_state.save_stack_data.ptr; - tex_aux_push_math(math_group, s); + tex_set_saved_record(saved_math_group_item_pointer, math_pointer_save_type, 0, m); + tex_set_saved_record(saved_math_group_all_class, math_class_save_type, 0, unset_noad_class); + lmt_save_state.save_stack_data.ptr += saved_math_group_n_of_items; + tex_aux_push_math(math_stack_group, s); break; } } @@ -2958,7 +2928,7 @@ void tex_finish_math_choice(void) tex_aux_unsave_math(); content = tex_aux_finish_math_list(null); /* We should just count and not rely on the next hackery test: */ - if (saved_type(saved_choice_item_count - saved_choice_n_of_items) == saved_choices_count) { + if (saved_type(saved_choice_item_count - saved_choice_n_of_items) == choices_count_save_type) { int choice = saved_value(saved_choice_item_count - saved_choice_n_of_items); int style = cur_list.math_style; switch (node_subtype(cur_list.tail)) { @@ -3000,7 +2970,7 @@ void tex_finish_math_choice(void) } break; } - tex_set_saved_record(saved_choice_item_count - saved_choice_n_of_items, saved_choices_count, 0, choice + 1); + tex_set_saved_record(saved_choice_item_count - saved_choice_n_of_items, choices_count_save_type, 0, choice + 1); tex_aux_push_math(math_choice_group, style); tex_scan_left_brace(); } else { @@ -3013,7 +2983,7 @@ void tex_finish_math_fraction(void) halfword content; tex_aux_unsave_math(); content = tex_aux_finish_math_list(null); - if (saved_type(saved_fraction_item_variant - saved_fraction_n_of_items) == saved_fraction_variant) { + if (saved_type(saved_fraction_item_variant - saved_fraction_n_of_items) == fraction_variant_save_type) { halfword over = saved_value(saved_fraction_item_variant - saved_fraction_n_of_items); halfword autostyle = saved_value(saved_fraction_item_autostyle - saved_fraction_n_of_items); halfword userstyle = saved_value(saved_fraction_item_userstyle - saved_fraction_n_of_items); @@ -3028,7 +2998,7 @@ void tex_finish_math_fraction(void) lmt_save_state.save_stack_data.ptr -= saved_fraction_n_of_items; return; } - tex_set_saved_record(saved_fraction_item_variant - saved_fraction_n_of_items, saved_fraction_variant, 0, over + 1); + tex_set_saved_record(saved_fraction_item_variant - saved_fraction_n_of_items, fraction_variant_save_type, 0, over + 1); tex_aux_push_math(math_fraction_group, autostyle); tex_scan_left_brace(); } else { @@ -3041,7 +3011,7 @@ void tex_finish_math_operator(void) halfword content; tex_aux_unsave_math(); content = tex_aux_finish_math_list(null); - if (saved_type(saved_operator_item_variant - saved_operator_n_of_items) == saved_operator_variant) { + if (saved_type(saved_operator_item_variant - saved_operator_n_of_items) == operator_variant_save_type) { halfword over = saved_value(saved_operator_item_variant - saved_operator_n_of_items); halfword fenced = cur_list.tail; switch (over) { @@ -3053,7 +3023,7 @@ void tex_finish_math_operator(void) lmt_save_state.save_stack_data.ptr -= saved_operator_n_of_items; return; } - tex_set_saved_record(saved_operator_item_variant - saved_operator_n_of_items, saved_operator_variant, 0, over + 1); + tex_set_saved_record(saved_operator_item_variant - saved_operator_n_of_items, operator_variant_save_type, 0, over + 1); tex_aux_push_math(math_operator_group, tex_math_style_variant(cur_list.math_style, math_parameter_subscript_variant)); tex_scan_left_brace(); } else { @@ -3469,11 +3439,11 @@ void tex_run_math_fraction(void) But here we can! For practical reasons we accept the rule related options and in principle we cold do with one command. */ - case math_u_atop_code: - case math_u_atop_delimited_code: case math_u_above_code: case math_u_above_delimited_code: goto OPTIONS; + case math_u_atop_code: + case math_u_atop_delimited_code: case math_u_over_code: case math_u_over_delimited_code: ruledone = 1; @@ -3485,7 +3455,7 @@ void tex_run_math_fraction(void) ruledone = 1; OPTIONS: while (1) { - switch (tex_scan_character("acefhnstvACEFHNSTV", 0, 1, 0)) { + switch (tex_scan_character("acefhnpstvACEFHNPSTV", 0, 1, 0)) { case 'a': case 'A': if (tex_scan_mandate_keyword("attr", 1)) { attrlist = tex_scan_attribute(attrlist); @@ -3500,10 +3470,17 @@ void tex_run_math_fraction(void) } break; case 'e': case 'E': + /* not used */ if (tex_scan_mandate_keyword("exact", 1)) { options |= noad_option_exact; } break; + case 'p': case 'P': + /* not used */ + if (tex_scan_mandate_keyword("proportional", 1)) { + options |= noad_option_proportional; + } + break; case 'n': case 'N': /*tex A bit over the top, three steps but a push back is still worse. */ if (tex_scan_character("oO", 0, 0, 0)) { @@ -3589,9 +3566,9 @@ void tex_run_math_fraction(void) In this case we need to pick up two math groups, and after some playing around using a variant of choices made most sense. */ - tex_set_saved_record(saved_fraction_item_variant, saved_fraction_variant, 0, math_numerator_above); - tex_set_saved_record(saved_fraction_item_autostyle, saved_fraction_auto_style, 0, autostyle); - tex_set_saved_record(saved_fraction_item_userstyle, saved_fraction_user_style, 0, userstyle); + tex_set_saved_record(saved_fraction_item_variant, fraction_variant_save_type, 0, math_numerator_above); + tex_set_saved_record(saved_fraction_item_autostyle, fraction_auto_style_save_type, 0, autostyle); + tex_set_saved_record(saved_fraction_item_userstyle, fraction_user_style_save_type, 0, userstyle); lmt_save_state.save_stack_data.ptr += saved_fraction_n_of_items; cur_list.math_flatten = 0; tex_aux_push_math(math_fraction_group, autostyle); @@ -4046,7 +4023,7 @@ void tex_run_math_fence(void) node_next(cur_list.head) = fence; cur_list.tail = fence; cur_list.delim = fence; - tex_set_saved_record(saved_operator_item_variant, saved_operator_variant, 0, math_limits_top); + tex_set_saved_record(saved_operator_item_variant, operator_variant_save_type, 0, math_limits_top); lmt_save_state.save_stack_data.ptr += saved_operator_n_of_items; tex_aux_push_math(math_operator_group, tex_math_style_variant(style, math_parameter_superscript_variant)); tex_scan_left_brace(); @@ -4054,7 +4031,6 @@ void tex_run_math_fence(void) break; case no_fence_side: { - /* halfword n = tex_new_node(simple_noad, math_fences_mode_par ? fenced_noad_subtype : inner_noad_subtype); */ halfword n = tex_new_node(simple_noad, fenced_noad_subtype); halfword l = tex_new_node(sub_mlist_node, 0); tex_tail_append(n); @@ -4508,7 +4484,7 @@ void tex_run_math_shift(void) { tex_aux_unsave_math(); /*tex now |cur_group = math_shift_group| */ lmt_save_state.save_stack_data.ptr -= saved_equation_number_n_of_items; - if (saved_type(saved_equation_number_item_location) == saved_equation_number_location) { + if (saved_type(saved_equation_number_item_location) == equation_number_location_save_type) { atleft = saved_value(saved_equation_number_item_location) == left_location_code; mode = cur_list.mode; p = tex_aux_finish_math_list(null); @@ -4994,6 +4970,13 @@ void tex_set_text_styles(halfword code, halfword value, halfword level, halfword tex_def_math_parameter(cramped_text_style, code, value, level, indirect); } +void tex_set_main_styles(halfword code, halfword value, halfword level, halfword indirect) +{ + for (int style = display_style; style <= cramped_text_style; style++) { + tex_def_math_parameter(style, code, value, level, indirect); + } +} + void tex_set_script_styles(halfword code, halfword value, halfword level, halfword indirect) { tex_def_math_parameter(script_style, code, value, level, indirect); @@ -5035,6 +5018,12 @@ void tex_set_split_styles(halfword code, halfword value, halfword level, halfwor tex_set_script_script_styles(code, 0, level, indirect); } +void tex_set_unsplit_styles(halfword code, halfword value, halfword level, halfword indirect) +{ + tex_set_script_styles (code, value, level, indirect); + tex_set_script_script_styles(code, value, level, indirect); +} + void tex_reset_all_styles(halfword level) { for (int code = math_parameter_atom_pairs_first; code <= math_parameter_atom_pairs_last; code++) { @@ -5263,26 +5252,23 @@ void tex_finalize_math_parameters(void) static void tex_aux_math_parameter_error(int style, int param, const char *name) { - char msg[256] = { 0 }; if (param >= 0) { - snprintf(msg, 256, "Math error: parameter '%s' with id %i in style %d is not set", name, param, style); + tex_handle_error( + normal_error_type, + "Math error: parameter '%s' with id %i in style %i is not set", + name, param, style, + "Sorry, but I can't typeset math unless various parameters have been set. This is\n" + "normally done by loading special math fonts into the math family slots. Your font\n" + "set is lacking at least the parameter mentioned earlier." + ); } else { - snprintf(msg, 256, "Math error: parameter '%s' style %d is not set", name, style); + tex_formatted_error("math", "invalid parameter '%s' in style %i", name, style); } - tex_handle_error( - normal_error_type, - msg, - "Sorry, but I can't typeset math unless various parameters have been set. This is\n" - "normally done by loading special math fonts into the math family slots. Your font\n" - "set is lacking at least the parameter mentioned earlier." - ); return; } /*tex - For the moment this is experimental. - */ inline static scaled tex_aux_max_scale(int style, int param) diff --git a/source/luametatex/source/tex/texmath.h b/source/luametatex/source/tex/texmath.h index 7dbd62b2e..e024a6ba2 100644 --- a/source/luametatex/source/tex/texmath.h +++ b/source/luametatex/source/tex/texmath.h @@ -23,8 +23,6 @@ typedef struct math_state_info { int size; /*tex Size code corresponding to |cur_style|. */ int level; /*tex Maybe we should expose this one. */ - /* int opentype; */ /*tex We just assume opentype now. */ - /* int padding; */ sa_tree par_head; sa_tree fam_head; halfword last_left; @@ -272,6 +270,7 @@ typedef enum math_class_options { prefer_delimiter_dimensions_class_option = 0x0080000, auto_inject_class_option = 0x0100000, remove_italic_correction_class_option = 0x0200000, + operator_italic_correction_class_option = 0x0400000, no_class_options = 0xF000000, } math_class_options; @@ -582,10 +581,12 @@ extern void tex_initialize_math_spacing (void); extern void tex_set_display_styles (halfword code, halfword value, halfword level, halfword indirect); extern void tex_set_text_styles (halfword code, halfword value, halfword level, halfword indirect); +extern void tex_set_main_styles (halfword code, halfword value, halfword level, halfword indirect); extern void tex_set_script_styles (halfword code, halfword value, halfword level, halfword indirect); extern void tex_set_script_script_styles (halfword code, halfword value, halfword level, halfword indirect); extern void tex_set_all_styles (halfword code, halfword value, halfword level, halfword indirect); extern void tex_set_split_styles (halfword code, halfword value, halfword level, halfword indirect); +extern void tex_set_unsplit_styles (halfword code, halfword value, halfword level, halfword indirect); extern void tex_set_uncramped_styles (halfword code, halfword value, halfword level, halfword indirect); extern void tex_set_cramped_styles (halfword code, halfword value, halfword level, halfword indirect); extern void tex_reset_all_styles (halfword level); @@ -652,6 +653,7 @@ extern void tex_run_math_italic_correction (void); extern void tex_finish_math_group (void); extern void tex_finish_math_choice (void); extern void tex_finish_math_fraction (void); +extern void tex_finish_math_radical (void); extern void tex_finish_math_operator (void); extern void tex_finish_display_alignment (halfword head, halfword tail, halfword prevdepth); @@ -677,6 +679,8 @@ typedef enum math_control_codes { math_control_analyze_script_nucleus_char = 0x040000, math_control_analyze_script_nucleus_list = 0x080000, math_control_analyze_script_nucleus_box = 0x100000, + math_control_accent_top_skew_with_offset = 0x200000, + math_control_ignore_kern_dimensions = 0x400000, /* for bad fonts (like xits fence depths) */ } math_control_codes; /*tex This is what we use for \OPENTYPE\ in \CONTEXT: */ @@ -699,6 +703,7 @@ typedef enum math_control_codes { | math_control_analyze_script_nucleus_char \ | math_control_analyze_script_nucleus_list \ | math_control_analyze_script_nucleus_box \ + | math_control_accent_top_skew_with_offset \ ) /*tex @@ -744,11 +749,23 @@ typedef enum saved_fraction_items { saved_fraction_n_of_items = 3, } saved_fraction_items; +typedef enum saved_radical_items { + saved_radical_degree_done = 0, + saved_radical_style = 1, + saved_radical_n_of_items = 2, +} saved_radical_items; + typedef enum saved_operator_items { saved_operator_item_variant = 0, saved_operator_n_of_items = 1, } saved_operator_items; +/*tex + These items are for regular groups, ustacks, atoms and such. We could make dedicated items + but in the end it means duplicatign code and we then also need to redo accents as these + check for the group, in which case we then have to intercept the lot. I might do it anyway. +*/ + typedef enum saved_math_group_items { saved_math_group_item_pointer = 0, saved_math_group_all_class = 1, diff --git a/source/luametatex/source/tex/texmathcodes.c b/source/luametatex/source/tex/texmathcodes.c index 7d80eac19..545013264 100644 --- a/source/luametatex/source/tex/texmathcodes.c +++ b/source/luametatex/source/tex/texmathcodes.c @@ -91,7 +91,7 @@ mathcodeval tex_mathchar_from_spec(int value) return mval; } -void tex_show_mathcode_value(mathcodeval mval, int extcode) +void tex_show_mathcode_value(mathcodeval mval, int extcode) /* todo: format option */ { tex_print_char('"'); if (extcode == tex_mathcode) { @@ -110,9 +110,7 @@ void tex_show_mathcode_value(mathcodeval mval, int extcode) static void tex_aux_show_mathcode(int n) { mathcodeval mval = tex_get_math_code(n); - tex_print_str_esc("Umathcode"); - tex_print_int(n); - tex_print_char('='); + tex_print_format("%eUmathcode%i=", n); tex_show_mathcode_value(mval, umath_mathcode); } @@ -207,9 +205,7 @@ static void tex_aux_undump_mathcode(dumpstream f) static void tex_aux_show_delcode(int n) { delcodeval dval = tex_get_del_code(n); - tex_print_str_esc("Udelcode"); - tex_print_int(n); - tex_print_char('='); + tex_print_format("%eUdelcode=", n); if (tex_has_del_code(dval)) { tex_print_char('"'); print_hex_digit_two(dval.small.family_value); diff --git a/source/luametatex/source/tex/texmlist.c b/source/luametatex/source/tex/texmlist.c index ac51d2c35..ddc3f0a6e 100644 --- a/source/luametatex/source/tex/texmlist.c +++ b/source/luametatex/source/tex/texmlist.c @@ -11,7 +11,7 @@ and extensibles are made from other glyphs, as in traditional \TEX\ fonts. In traditional \TEX\ the italic correction is added to the width of the glyph. This is part of - the engine design and this is also reflected in the widtn metric of the font. In \OPENTYPE\ math + the engine design and this is also reflected in the width metric of the font. In \OPENTYPE\ math this is different. There the italic correction had more explicit usage. The 1.7 spec says: \startitemize @@ -85,6 +85,58 @@ */ +/* + + There is a persistent issue with operators and italic correction. For n_ary ones the italic + correction is used for positioning scripts above or below (shifted horizontally) or + at the right top and bottom (also shifted horizontally). That assumes a proper width that + doesn't need italic correction itself. On the other hand, in the case of arbitrary characters + that want to be operators the italic correction can be part of th ewidth (take the |f| as + example). Now, the most problematic one is the integral and especially in Latin Modern where + it is very slanted. In \CONTEXT\ we use the left operator feature to deal with all this. + + We considered a special class for operators where italic correction is used for positioning + but in the end we rejected that. We now: + + \startitemize + \startitem + asume properly bounded characters (sum, product, integral) and most are upright anyway + \stopitem + \startitem + top and bottom scripts are centered + \stopitem + \startitem + right and left scripts are bound tight to the edge + \stopitem + \startitem + italic correction can be completely ignored + \stopitem + \startitem + top and bottom anchors (set up in the goodie) control optional displacements + \stopitem + \startitem + top right and top left kerns (set up in the goodie) control optional displacements + \stopitem + \stopitemize + + We already did the kerns for some fonts using information in the goodie file, and now we + also use the top and bottom anchors. In fact, the only real exception is Latin Modern, so + instead of messing up the code with exceptions and tricky controls we now have a few lines + in (basically) one goodie file. + + An class option can be set to add italic corrections to operators so in the case of the + integral, where it is used for positioning, it can then be used to calculate anchors, but + that is then done in the goodie file. Keep in mind that these anchors are an engine feature. + + For most math fonts all works out of the box, only fonts with highly asymetrical integral + signs are touched by this, but fonts like that likely need tweaks anyway. + + For the record: the specificaton only talks about possible application so we can basically do + as we like. All works fine for Cambria and the \TEX\ community didn't make sure that better + features were added (like anchors) for their shapes. + +*/ + # include "luametatex.h" /*tex @@ -179,6 +231,10 @@ inline void tex_math_wipe_kerns(kernset *kerns) { kerns->depth = 0; kerns->toptotal = 0; kerns->bottomtotal = 0; + kerns->dimensions = 0; + kerns->font = null_font; + kerns->character = 0; + kerns->padding = 0; } } @@ -192,13 +248,14 @@ inline void tex_math_copy_kerns(kernset *kerns, kernset *parent) { kerns->depth = parent->depth; kerns->toptotal = parent->toptotal; kerns->bottomtotal = parent->bottomtotal; + kerns->dimensions = parent->dimensions; + kerns->font = parent->font; + kerns->character = parent->character; } } /*tex - When the style changes, the following piece of program computes associated information: - */ inline static halfword tex_aux_set_style_to_size(halfword style) @@ -315,21 +372,17 @@ inline static scaled limited_rounded(double d) { } } -// inline static int tex_aux_has_opentype_metrics(halfword f) -// { -// return font_math_parameter_count(f) > 0 && ! font_oldmath(f); -// } - -inline static int tex_aux_math_engine_control(halfword fnt, halfword chr) +inline static int tex_aux_math_engine_control(halfword fnt, halfword control) { - if (fnt && (math_font_control_par & math_control_use_font_control) == math_control_use_font_control) { + // if (fnt && (math_font_control_par & math_control_use_font_control) == math_control_use_font_control) { + if (fnt && (font_mathcontrol(fnt) & math_control_use_font_control) == math_control_use_font_control) { /*tex This is only for old fonts and it might go away eventually. Not all control options relate to a font. */ - return (font_mathcontrol(fnt) & chr) == chr; + return (font_mathcontrol(fnt) & control) == control; } - return (math_font_control_par & chr) == chr; + return (math_font_control_par & control) == control; } /* @@ -397,7 +450,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 glyph = tex_new_glyph_node(subtype, fnt, tex_get_math_char(fnt, chr, lmt_math_state.size, &scale), null); /* todo: data */; + 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); glyph_x_scale(glyph) = glyph_x_scale_par; @@ -517,63 +570,19 @@ static inline int tex_aux_checked_right_kern(halfword list, halfword state, half } } -/*tex We no longer need this one: - - \starttyping - static halfword tex_aux_math_remove_italic_kern(halfword head, scaled *italic, const char *trace) - { - halfword tail = tex_tail_of_node_list(box_list(head)); - if (tail && node_type(tail) == kern_node && node_subtype(tail) == italic_kern_subtype && kern_amount(tail) == *italic) { - tex_aux_trace_kerns(tail, "removing italic kern", trace); - if (head == tail) { - head = null; - } else { - head = node_prev(tail); - node_next(node_prev(tail)) = null; - } - tex_flush_node(tail); - *italic = 0; - } - return head; - } - \starttyping - -*/ - -/*tex We no longer need this one: - - \starttyping - static void tex_aux_normalize_delimiters(halfword l, halfword r) - { - if (box_width(l) == null_delimiter_space_par) { - box_height(l) = box_height(r); - box_depth(l) = box_depth(r); - box_shift_amount(l) = box_shift_amount(r); - } else if (box_width(r) == null_delimiter_space_par) { - box_height(r) = box_height(l); - box_depth(r) = box_depth(l); - box_shift_amount(r) = box_shift_amount(l); - } - } - \starttyping - -*/ - static scaled tex_aux_check_rule_thickness(halfword target, int size, halfword *fam, halfword control, halfword param) { - /* if (math_rule_thickness_mode_par > 0) { */ - halfword family = noad_family(target); - if (family != unused_math_family) { - halfword font = tex_fam_fnt(family, size); - if (tex_aux_math_engine_control(font, control)) { - scaled thickness = tex_get_font_math_parameter(font, size, param); - if (thickness != undefined_math_parameter) { - *fam = family; - return thickness; - } + halfword family = noad_family(target); + if (family != unused_math_family) { + halfword font = tex_fam_fnt(family, size); + if (tex_aux_math_engine_control(font, control)) { + scaled thickness = tex_get_font_math_parameter(font, size, param); + if (thickness != undefined_math_parameter) { + *fam = family; + return thickness; } } - /* } */ + } return undefined_math_parameter; } @@ -585,6 +594,7 @@ static halfword tex_aux_fake_nucleus(quarterword cls) halfword q = tex_new_node(math_char_node, 0); set_noad_classes(n, cls); noad_nucleus(n) = q; + math_kernel_node_set_option(q, math_kernel_ignored_character); return n; } @@ -805,6 +815,9 @@ static halfword tex_aux_underbar(halfword box, scaled gap, scaled height, scaled \startitem accent placement \stopitem \stopitemize + We keep this as reference but oldmath handling has been replaces by options that determine code + paths. We actually assuem that \OPENTRYPE fonts are used anyway. The flag is gone. + In the traditional case an italic kern is always added and the |ic| variable is then passed to the caller. For a while we had an option to add the correction to the width but now we have the control options. So these are the options: @@ -854,43 +867,6 @@ static halfword tex_aux_char_box(halfword fnt, int chr, halfword att, scaled *ic return box; } -/*tex - - When we build an extensible character, it's handy to have the following subroutine, which puts - a given character on top of the characters already in box |b|: - -*/ - -// static scaled tex_aux_stack_into_box(halfword b, halfword f, int c, quarterword subtype, int horiziontal) -// { -// /*tex New node placed into |b|. Italic gets added to width in 8 bit fonts. */ -// halfword boxed = tex_aux_char_box(f, c, get_attribute_list(b), NULL, subtype); -// halfword glyph = box_list(boxed); -// if (horiziontal) { -// halfword list = box_list(b); -// if (list) { -// tex_couple_nodes(tex_tail_of_node_list(list), boxed); -// } else { -// box_list(b) = boxed; -// } -// if (box_height(b) < box_height(boxed)) { -// box_height(b) = box_height(boxed); -// } -// if (box_depth(b) < box_depth(boxed)) { -// box_depth(b) = box_depth(boxed); -// } -// return tex_char_width_from_glyph(glyph); -// } else { -// tex_try_couple_nodes(boxed, box_list(b)); -// box_list(b) = boxed; -// box_height(b) = box_height(boxed); -// if (box_width(b) < box_width(boxed)) { -// box_width(b) = box_width(boxed); -// } -// return tex_char_total_from_glyph(glyph); -// } -// } - /*tex There is no need to deal with an italic correction here. If there is one in an extensible we have a real weird font! So in this version we don't end up with a redicoulous amount of hlists @@ -1204,7 +1180,6 @@ halfword tex_make_extensible(halfword fnt, halfword chr, scaled target, scaled m initial = overlap; } if (advance == 0) { - /*tex for tfm fonts (so no need for scaling) */ advance = tex_aux_math_y_size_scaled(fnt, tex_char_total_from_font(fnt, e->glyph), size); /* todo: combine */ if (advance <= 0) { tex_formatted_error("fonts", "bad vertical extensible character %i in font %i", chr, fnt); @@ -1224,7 +1199,6 @@ halfword tex_make_extensible(halfword fnt, halfword chr, scaled target, scaled m initial = overlap; } if (advance == 0) { - /*tex for tfm fonts (so no need for scaling) */ advance = tex_aux_math_y_size_scaled(fnt, tex_char_total_from_font(fnt, e->glyph), size); /* todo: combine */ if (advance <= 0) { tex_formatted_error("fonts", "bad vertical extensible character %i in font %i", chr, fnt); @@ -1248,7 +1222,7 @@ halfword tex_make_extensible(halfword fnt, halfword chr, scaled target, scaled m for (extinfo *e = extensible; e; e = e->next) { if (e->extender == 0) { scaled progress; - scaled initial = horizontal ? tex_aux_math_x_size_scaled(fnt, e->start_overlap, size) : tex_aux_math_y_size_scaled(fnt,e->start_overlap, size); + scaled initial = horizontal ? tex_aux_math_x_size_scaled(fnt, e->start_overlap, size) : tex_aux_math_y_size_scaled(fnt, e->start_overlap, size); if (overlap < initial) { initial = overlap; } @@ -1542,12 +1516,25 @@ static halfword tex_aux_make_delimiter(halfword target, halfword delimiter, int } } if (! flat) { - /*tex A vertical variant. Todo: add a kern instead. */ + /*tex + We have a vertical variant. Case 1 deals with the fact that fonts can lie about their + dimensions which happens in tfm files where there are a limited number of heights and + depths. However, that doesn't work out well when we want to anchor script later on in + a more sophisticated way. Most \OPENTYPE\ fonts have proper heights and depth but there + are some that don't. Problems can show up when we use kerns (as \CONTEXT\ does via + goodie files) and the relevant class option has been enabled. In order to deal with the + problematic fonts we can disable this via a font option. The natural height and depth + are communicated via extremes and kerns. + + For fonts that have their shapes positioned properly around their axis case 1 doesn't + interfere but could as well be skipped. These shapes can also be used directly in + the input if needed (basically case 1 then becomes case 4). + */ switch (shift) { case 0: box_shift_amount(result) = tex_half_scaled(box_height(result) - box_depth(result)); break; - case 1: + case 1: box_shift_amount(result) = tex_half_scaled(box_height(result) - box_depth(result)); box_shift_amount(result) -= tex_aux_math_axis(size); break; @@ -2049,7 +2036,6 @@ static int tex_aux_fetch(halfword n, const char *where, halfword *f, halfword *c if (node_type(n) == glyph_node) { *f = glyph_font(n); *c = glyph_character(n); - /* lmt_math_state.opentype = tex_aux_has_opentype_metrics(*f); */ if (tex_char_exists(*f, *c)) { return 1; } else { @@ -2059,27 +2045,23 @@ static int tex_aux_fetch(halfword n, const char *where, halfword *f, halfword *c } else { *f = tex_fam_fnt(kernel_math_family(n), lmt_math_state.size); *c = kernel_math_character(n); - if (*f == null_font) { - char msg[256]; - snprintf(msg, 255, "\\%s%d is undefined in %s, font id %d, character %d)", - tex_aux_math_size_string(lmt_math_state.size), kernel_math_family(n), where, *f, *c - ); + if (math_kernel_node_has_option(n, math_kernel_ignored_character)) { + return 1; + } else if (*f == null_font) { tex_handle_error( normal_error_type, - msg, + "\\%s%i is undefined in %s, font id %i, character %i)", + tex_aux_math_size_string(lmt_math_state.size), kernel_math_family(n), where, *f, *c, "Somewhere in the math formula just ended, you used the stated character from an\n" "undefined font family. For example, plain TeX doesn't allow \\it or \\sl in\n" "subscripts. Proceed, and I'll try to forget that I needed that character." ); return 0; + } else if (tex_math_char_exists(*f, *c, lmt_math_state.size)) { + return 1; } else { - /* lmt_math_state.opentype = tex_aux_has_opentype_metrics(*f); */ - if (tex_math_char_exists(*f, *c, lmt_math_state.size)) { - return 1; - } else { - tex_char_warning(*f, *c); - return 0; - } + tex_char_warning(*f, *c); + return 0; } } } @@ -2302,6 +2284,8 @@ static void tex_aux_set_radical_kerns(delimiterextremes *extremes, kernset *kern if (tex_math_has_class_option(radical_noad_subtype, prefer_delimiter_dimensions_class_option)) { kerns->height = extremes->height; kerns->depth = extremes->depth; + kerns->dimensions = 1; + kerns->font = extremes->tfont; } } } @@ -2400,13 +2384,7 @@ static void tex_aux_make_root_radical(halfword target, int style, int size, kern if (width) { scaled before = tex_get_math_x_parameter_checked(style, math_parameter_radical_degree_before); scaled after = tex_get_math_x_parameter_checked(style, math_parameter_radical_degree_after); - /* scaled raise = tex_get_math_y_parameter_checked(style, math_parameter_radical_degree_raise); */ /* no! */ scaled raise = tex_get_math_parameter_checked(style, math_parameter_radical_degree_raise); - /* old: - if (-after > (width + before)) { - after = -(width + before); - } - new: */ if (-after > width) { before += -after - width; } @@ -2572,9 +2550,7 @@ static void tex_aux_make_over_delimiter(halfword target, int style, int size) } /*tex - This has the extensible delimiter |x| as a limit below |nucleus| box |y|. - */ static void tex_aux_make_under_delimiter(halfword target, int style, int size) @@ -2602,9 +2578,7 @@ static void tex_aux_make_under_delimiter(halfword target, int style, int size) } /*tex - This has the extensible delimiter |x| as a limit above |nucleus| box |y|. - */ static void tex_aux_make_delimiter_over(halfword target, int style, int size) @@ -2633,9 +2607,7 @@ static void tex_aux_make_delimiter_over(halfword target, int style, int size) } /*tex - This has the extensible delimiter |y| as a limit below a |nucleus| box |x|. - */ static void tex_aux_make_delimiter_under(halfword target, int style, int size) @@ -2727,7 +2699,7 @@ typedef enum math_accent_location_codes { stretch_accent_code = 8, } math_accent_location_codes; -static int tex_aux_compute_accent_skew(halfword target, int flags, scaled *s, halfword size) +static int tex_aux_compute_accent_skew(halfword target, int flags, scaled *skew, halfword size) { /*tex will be true if a top-accent is placed in |s| */ int absolute = 0; @@ -2742,21 +2714,21 @@ static int tex_aux_compute_accent_skew(halfword target, int flags, scaled *s, ha There is no bot_accent so let's assume that the shift also applies to bottom and overlay accents. */ - *s = tex_char_top_accent_from_font(fnt, chr); - if (*s != INT_MIN) { - *s = tex_aux_math_x_size_scaled(fnt, *s, size); + *skew = tex_char_unchecked_top_anchor_from_font(fnt, chr); + if (*skew != INT_MIN) { + *skew = tex_aux_math_x_size_scaled(fnt, *skew, size); absolute = 1; } else { - *s = 0; + *skew = 0; } } else if (flags & top_accent_code) { - *s = tex_aux_math_x_size_scaled(fnt, tex_get_kern(fnt, chr, font_skew_char(fnt)), size); + *skew = tex_aux_math_x_size_scaled(fnt, tex_get_kern(fnt, chr, font_skew_char(fnt)), size); } else { - *s = 0; + *skew = 0; } if (tracing_math_par >= 2) { tex_begin_diagnostic(); - tex_print_format("[math: accent skew, font %i, chr %x, skew %D, absolute %i]", fnt, chr, *s, pt_unit, absolute); + tex_print_format("[math: accent skew, font %i, chr %x, skew %D, absolute %i]", fnt, chr, *skew, pt_unit, absolute); tex_end_diagnostic(); } break; @@ -2793,11 +2765,11 @@ static int tex_aux_compute_accent_skew(halfword target, int flags, scaled *s, ha if (p && ! node_next(p)) { switch (node_type(p)) { case accent_noad: - absolute = tex_aux_compute_accent_skew(p, flags, s, size); + absolute = tex_aux_compute_accent_skew(p, flags, skew, size); break; case simple_noad: if (! noad_has_following_scripts(p)) { - absolute = tex_aux_compute_accent_skew(p, flags, s, size); + absolute = tex_aux_compute_accent_skew(p, flags, skew, size); } break; } @@ -2812,12 +2784,14 @@ static int tex_aux_compute_accent_skew(halfword target, int flags, scaled *s, ha } return absolute; } + static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, halfword accentchr, int flags, int style, int size, scaled *accenttotal) { /*tex The width and height (without scripts) of base character: */ scaled baseheight = 0; // scaled basedepth = 0; scaled basewidth = 0; + scaled usedwidth = 0; /*tex The space to remove between accent and base: */ scaled delta = 0; scaled overshoot = 0; @@ -2825,11 +2799,14 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal halfword attrlist = node_attr(target); scaled fraction = accent_fraction(target) > 0 ? accent_fraction(target) : 1000; scaled skew = 0; + scaled offset = 0; halfword accent = null; halfword base = null; halfword result = null; halfword nucleus = noad_nucleus(target); halfword stretch = (flags & stretch_accent_code) == stretch_accent_code; + halfword basefnt = null_font; + halfword basechr = 0; /*tex Compute the amount of skew, or set |skew| to an alignment point. This will be true if a top-accent has been determined. @@ -2850,32 +2827,49 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal baseheight = box_height(base); // basedepth = box_depth(base); } - if (! absolute && tex_aux_math_engine_control(accentfnt, math_control_accent_skew_half)) { + if (base) { + halfword list = box_list(base); + if (list && node_type(list) == glyph_node) { + basefnt = glyph_font(list); + basechr = glyph_character(list); + } + } + if (stretch && absolute && (flags & top_accent_code) && tex_aux_math_engine_control(accentfnt, math_control_accent_top_skew_with_offset)) { + /*tex + This assumes a font that has been tuned for it. We used a privately made font (will be + in the \CONTEXT\ distribution) RalphSmithsFormalScript.otf (derived from the type one + font) for experimenting with top accents and these parameters. The idea is to have a + decent accent on the very slanted top (of e.g. A) that sticks out a little at the right + edge but still use glyphs with a proper boundingbox, so no messing around with italic + correction. Eventually this might become a more advanced (general) mechanism. Watch the + formula for calculating the used width. + */ + if (base && basefnt && basechr) { + offset = tex_char_top_overshoot_from_font(basefnt, basechr); + offset = offset == INT_MIN ? 0 : tex_aux_math_x_size_scaled(basefnt, offset, size); + } + usedwidth = 2 * ((skew < (basewidth - skew) ? skew : (basewidth - skew)) + offset); + } else if (! absolute && tex_aux_math_engine_control(accentfnt, math_control_accent_skew_half)) { skew = tex_half_scaled(basewidth); absolute = 1; + usedwidth = basewidth; + } else { + usedwidth = basewidth; } /*tex Todo: |w = w - loffset - roffset| but then we also need to add a few kerns so no hurry with that one. */ - if (stretch && (tex_char_width_from_font(accentfnt, accentchr) < basewidth)) { + if (stretch && (tex_char_width_from_font(accentfnt, accentchr) < usedwidth)) { /*tex Switch to a larger accent if available and appropriate */ scaled target = 0; if (flags & overlay_accent_code) { target = baseheight; } else { - target += basewidth; - if (base) { - /*tex Use larger margins, */ - halfword list = box_list(base); - if (list && node_type(list) == glyph_node) { - halfword basefnt = glyph_font(list); - halfword basechr = glyph_character(list); - if (basefnt && basechr) { - target += tex_aux_math_x_size_scaled(basefnt, tex_char_right_margin_from_font(basefnt, basechr), size); - target += tex_aux_math_x_size_scaled(basefnt, tex_char_left_margin_from_font(basefnt, basechr), size); - } - } + target += usedwidth; + if (base && basefnt && basechr) { + target += tex_aux_math_x_size_scaled(basefnt, tex_char_right_margin_from_font(basefnt, basechr), size); + target += tex_aux_math_x_size_scaled(basefnt, tex_char_left_margin_from_font(basefnt, basechr), size); } } if (fraction > 0) { @@ -2891,7 +2885,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal we don't step. */ halfword overlap = tex_get_math_x_parameter_checked(style, math_parameter_connector_overlap_min); - accent = tex_aux_get_delimiter_box(accentfnt, accentchr, basewidth, overlap, 1, attrlist); + accent = tex_aux_get_delimiter_box(accentfnt, accentchr, usedwidth, overlap, 1, attrlist); accent = register_extensible(accentfnt, accentchr, size, accent, attrlist); break; } else if (! tex_char_has_tag_from_font(accentfnt, accentchr, list_tag)) { @@ -2918,7 +2912,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal } if (! accent) { /*tex Italic gets added to width for traditional fonts (no italic anyway): */ - accent = tex_aux_char_box(accentfnt, accentchr, attrlist, NULL, glyph_math_accent_subtype, basewidth, style); + accent = tex_aux_char_box(accentfnt, accentchr, attrlist, NULL, glyph_math_accent_subtype, basewidth, style); // usedwidth } if (accenttotal) { *accenttotal = box_total(accent); @@ -2931,7 +2925,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal halfword flatchr = tex_char_flat_accent_from_font(accentfnt, accentchr); if (flatchr != INT_MIN && flatchr != accentchr) { tex_flush_node(accent); - accent = tex_aux_char_box(accentfnt, flatchr, attrlist, NULL, glyph_math_accent_subtype, basewidth, style); + accent = tex_aux_char_box(accentfnt, flatchr, attrlist, NULL, glyph_math_accent_subtype, usedwidth, style); if (tracing_math_par >= 2) { tex_begin_diagnostic(); tex_print_format("[math: flattening accent, old %x, new %x]", accentchr, flatchr); @@ -2976,17 +2970,6 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal base = tex_aux_clean_box(nucleus, style, style, math_nucleus_list, 1, NULL); /* keep italic */ delta = delta + box_height(base) - baseheight; baseheight = box_height(base); - } else { - /*tex We have only pure math char nodes here:*/ - // halfword basefnt = tex_fam_fnt(math_family(nucleus), size); - // if (tex_aux_has_opentype_metrics(basefnt)) { - // halfword basechr = math_character(nucleus); - // if (math_kernel_node_has_option(nucleus, math_kernel_no_italic_correction)) { - // italic = 0; - // } else if (tex_aux_math_engine_control(basefnt, math_control_accent_italic_kern)) { - // italic = tex_aux_math_x_style_scaled(basefnt, tex_char_italic_from_font(basefnt, basechr), size); - // } - // } } /*tex The top accents of both characters are aligned. */ { @@ -2997,7 +2980,7 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal /*tex If the accent is extensible just take the center. */ anchor = tex_half_scaled(accentwidth); } else { - anchor = tex_char_top_accent_from_font(accentfnt, accentchr); /* no bot accent key */ + anchor = tex_char_unchecked_top_anchor_from_font(accentfnt, accentchr); /* no bot accent key */ if (anchor != INT_MIN) { anchor = tex_aux_math_y_size_scaled(accentfnt, anchor, size); /* why y and not x */ } else { @@ -3064,14 +3047,6 @@ static void tex_aux_do_make_math_accent(halfword target, halfword accentfnt, hal box_shift_amount(result) = - delta; } box_width(result) += overshoot; - // if (italic) { - // /*tex - // The old font codepath has ic built in, but new font code doesn't so we add - // the correction here. - // */ - // tex_aux_math_insert_italic_kern(result, italic, nucleus, "accent"); - // box_width(result) += italic ; - // } kernel_math_list(nucleus) = result; node_type(nucleus) = sub_box_node; } @@ -3199,6 +3174,8 @@ static void tex_aux_wrap_fraction_result(halfword target, int style, int size, h if (tex_math_has_class_option(fraction_noad_subtype, prefer_delimiter_dimensions_class_option)) { kerns->height = extremes.height; kerns->depth = extremes.depth; + kerns->dimensions = 1; + kerns->font = extremes.tfont; } } /* tex_aux_normalize_delimiters(left, right); */ @@ -3220,16 +3197,24 @@ static void tex_aux_wrap_fraction_result(halfword target, int style, int size, h /*tex The numerator and denominator must be separated by a certain minimum clearance, called |clr| in the following program. The difference between |clr| and the actual clearance is |2 * delta|. + + In the case of a fraction line, the minimum clearance depends on the actual thickness of the + line but we've moved that elsewhere. This gap vs up/down is kindo f weird anyway. */ -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) +static void tex_aux_calculate_fraction_shifts(halfword target, int style, int size, scaled *shift_up, scaled *shift_down, int up, int down) { - scaled clearance = tex_get_math_y_parameter_checked(style, math_parameter_stack_vgap); (void) size; - *shift_up = tex_get_math_y_parameter_checked(style, math_parameter_stack_num_up); - *shift_down = tex_get_math_y_parameter_checked(style, math_parameter_stack_denom_down); + *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); +} + +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) +{ + scaled clearance = tex_get_math_y_parameter_checked(style, math_parameter_stack_vgap); + tex_aux_calculate_fraction_shifts(target, style, size, shift_up, shift_down, math_parameter_stack_num_up, math_parameter_stack_denom_down); *delta = tex_half_scaled(clearance - ((*shift_up - box_depth(numerator)) - (box_height(denominator) - *shift_down))); if (*delta > 0) { *shift_up += *delta; @@ -3237,11 +3222,6 @@ static void tex_aux_calculate_fraction_shifts_stack(halfword target, int style, } } -/*tex - In the case of a fraction line, the minimum clearance depends on the actual thickness of the - line. -*/ - static void tex_aux_calculate_fraction_shifts_normal(halfword target, int style, int size, halfword numerator, halfword denominator, scaled *shift_up, scaled *shift_down, scaled *delta) { scaled axis = tex_aux_math_axis(size); @@ -3249,26 +3229,17 @@ static void tex_aux_calculate_fraction_shifts_normal(halfword target, int style, scaled denominator_clearance = tex_get_math_y_parameter_checked(style, math_parameter_fraction_denom_vgap); scaled delta_up = 0; scaled delta_down = 0; - *shift_up = tex_get_math_y_parameter_checked(style, math_parameter_fraction_num_up); - *shift_down = tex_get_math_y_parameter_checked(style, math_parameter_fraction_denom_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); + tex_aux_calculate_fraction_shifts(target, style, size, shift_up, shift_down, math_parameter_fraction_num_up, math_parameter_fraction_denom_down); /* hm, delta is only set when we have a middle delimiter ... needs checking .. i should write this from scratch */ *delta = tex_half_scaled(tex_aux_math_given_y_scaled(fraction_rule_thickness(target))); - if (has_noad_option_exact(target)) { - delta_up = numerator_clearance - ((*shift_up - box_depth(numerator) ) - (axis + *delta)); - delta_down = denominator_clearance - ((*shift_down - box_height(denominator)) + (axis - *delta)); - } else { - // maybe this is just the old tex code path - scaled rule_thickness = tex_aux_math_given_y_scaled(fraction_rule_thickness(target)); - scaled rule_parameter = tex_get_math_y_parameter_checked(style, math_parameter_fraction_rule); - numerator_clearance = tex_ext_xn_over_d(numerator_clearance, rule_thickness, rule_parameter); - denominator_clearance = tex_ext_xn_over_d(denominator_clearance, rule_thickness, rule_parameter); - delta_up = numerator_clearance - ((*shift_up - box_depth(numerator) ) - (axis + *delta)); - delta_down = denominator_clearance - ((*shift_down - box_height(denominator)) + (axis - *delta)); + delta_up = numerator_clearance - ((*shift_up - box_depth(numerator) ) - (axis + *delta)); + delta_down = denominator_clearance - ((*shift_down - box_height(denominator)) + (axis - *delta)); + if (delta_up > 0) { + *shift_up += delta_up; + } + if (delta_down > 0) { + *shift_down += delta_down; } - *shift_up += delta_up; - *shift_down += delta_down; } static scaled tex_aux_check_fraction_rule(halfword target, int style, int size, int fractiontype, halfword *usedfam) @@ -3285,6 +3256,12 @@ static scaled tex_aux_check_fraction_rule(halfword target, int style, int size, } else if (fractiontype == above_fraction_subtype) { /*tex Bypassed by command. */ preferfont = 0; + if (has_noad_option_proportional(target)) { + /* We replaced the non |exact| code path by this one: */ + scaled text = tex_get_math_y_parameter_checked(text_style, math_parameter_fraction_rule); + scaled here = tex_get_math_y_parameter_checked(style, math_parameter_fraction_rule); + fraction_rule_thickness(target) = tex_ext_xn_over_d(fraction_rule_thickness(target), here, text); + } } else if (fraction_rule_thickness(target)) { /*tex Controlled by optional parameter. */ preferfont = 1; @@ -3296,7 +3273,7 @@ static scaled tex_aux_check_fraction_rule(halfword target, int style, int size, } } if (fraction_rule_thickness(target) == preset_rule_thickness) { - fraction_rule_thickness(target) = tex_get_math_y_parameter_checked(style, math_parameter_fraction_rule); + fraction_rule_thickness(target) = tex_get_math_y_parameter_checked(style, math_parameter_fraction_rule); } if (usedfam) { *usedfam = fam; @@ -3371,7 +3348,7 @@ static halfword tex_aux_make_skewed_fraction(halfword target, int style, int siz shift_up = shift_down; /*tex The |shift_up| value might change later. */ tex_aux_wrap_fraction_parts(target, style, size, &numerator, &denominator, 0); /*tex - Here we don't share code bnecause we're going horizontal. + Here we don't share code because we're going horizontal. */ if (! has_noad_option_noaxis(target)) { shift_up += tex_half_scaled(tex_aux_math_axis(size)); @@ -3582,9 +3559,8 @@ static halfword tex_aux_check_nucleus_complexity ( ); /* - For easy configuration ... fonts are somewhat inconsistent and the - values for italic correction run from 30 to 60\% of the width. - + For easy configuration ... fonts are somewhat inconsistent and the values for italic correction + run from 30 to 60\% of the width. */ static void tex_aux_get_shifts(int mode, int style, scaled delta, scaled *top, scaled *bot) @@ -3623,415 +3599,44 @@ static void tex_aux_get_shifts(int mode, int style, scaled delta, scaled *top, s } } -// static scaled tex_aux_make_op(halfword q, int style, int size, int italic, int forced_no_limits, kernset *kerns) -// { -// /*tex for historic reasons we have two flags .. because we need to adapt to the style */ -// int limits = has_noad_option_limits(q); -// int nolimits = has_noad_option_nolimits(q); -// if (! limits && ! nolimits && (style == display_style || style == cramped_display_style)) { -// nolimits = 0; -// limits = 1; -// noad_options(q) |= noad_option_limits; /* so we can track it */ -// } -// if (forced_no_limits) { -// nolimits = 1; -// } -// if (node_type(noad_nucleus(q)) == math_char_node) { -// halfword x; -// int shiftaxis = 0; -// halfword chr = null; -// halfword fnt = null; -// halfword autoleft = null; -// halfword autoright = null; -// halfword autosize = has_noad_option_auto(q); -// scaled openupheight = has_noad_option_openupheight(q) ? noad_height(q) : 0; -// scaled openupdepth = has_noad_option_openupdepth(q) ? noad_depth(q) : 0; -// if (has_noad_option_adapttoleft(q) && node_prev(q)) { -// autoleft = node_prev(q); -// if (node_type(autoleft) != simple_noad) { -// autoleft = null; -// } else { -// autoleft = noad_new_hlist(autoleft); -// } -// } -// if (has_noad_option_adapttoright(q) && node_next(q)) { -// autoright = noad_nucleus(node_next(q)); -// } -// tex_aux_fetch(noad_nucleus(q), "operator", &fnt, &chr); -// /*tex Nicer is actually to just test for |display_style|. */ -// if ((style < text_style) || autoleft || autoright || autosize) { -// /*tex Try to make it larger in displaystyle. */ -// scaled opsize = tex_get_math_parameter(style, math_parameter_operator_size, NULL); -// if ((autoleft || autoright || autosize) && (opsize == undefined_math_parameter)) { -// opsize = 0; -// } -// if (opsize != undefined_math_parameter) { -// /*tex Creating a temporary delimiter is the cleanest way. */ -// halfword y = tex_new_node(delimiter_node, 0); -// tex_attach_attribute_list_copy(y, noad_nucleus(q)); -// delimiter_small_family(y) = math_family(noad_nucleus(q)); -// delimiter_small_character(y) = math_character(noad_nucleus(q)); -// opsize = tex_aux_math_y_scaled(opsize, style); -// if (autoright) { -// /*tex We look ahead and preroll, |autoright| is a noad. */ -// scaledwhd siz = tex_natural_hsizes(autoright, null, 0.0, 0, 0); -// scaled total = siz.ht + siz.dp; -// if (total > opsize) { -// opsize = total; -// } -// } -// if (autoleft && box_total(autoleft) > opsize) { -// /*tex We look back and check, |autoleft| is a box. */ -// opsize = box_total(autoleft); -// } -// /* we need to check for overflow here */ -// opsize += limited_scaled(openupheight); -// opsize += openupdepth; -// x = tex_aux_make_delimiter(y, text_size, opsize, 0, style, ! has_noad_option_noaxis(q), noad_options(q), NULL, &italic, 0, has_noad_option_nooverflow(q), NULL); -// // if (italic) { -// // if (lmt_math_state.opentype) { -// // /*tex -// // As we never added italic correction we don't need to compensate. The ic -// // is stored in a special field of the node and applied in some occasions. -// // */ -// // } else if (noad_subscr(q) && ! has_noad_option_limits(q)) { /* todo: control option */ -// // /*tex -// // Here we (selectively) remove the italic correction that always gets added -// // in a traditional font. See (**). In \OPENTYPE\ mode we insert italic kerns, -// // but in traditional mode it's width manipulation. This actually makes sense -// // because those fonts have a fake width and the italic correction sets that -// // right. -// // */ -// // box_list(x) = tex_aux_math_remove_italic_kern(box_list(x), &italic, "operator"); -// // box_width(x) -= italic; -// // } -// // } -// } else { -// /*tex -// Where was the weird + 1 coming from? It tweaks the comparison. Anyway, because we -// do a lookup we don't need to scale the |total| and |opsize|. We have a safeguard -// against endless loops. -// */ -// opsize = tex_char_total_from_font(fnt, chr) + openupheight + openupdepth + 1; -// /* -// if (opsize) { -// opsize = tex_aux_math_y_style_scaled(fnt, opsize, size); // we compare unscaled -// } -// */ -// while (tex_char_tag_from_font(fnt, chr) == list_tag && tex_char_total_from_font(fnt, chr) < opsize) { -// halfword rem = tex_char_remainder_from_font(fnt, chr); -// if (chr != rem && tex_char_exists(fnt, rem)) { -// chr = rem; -// math_character(noad_nucleus(q)) = chr; -// } else { -// break; -// } -// } -// if (math_kernel_node_has_option(noad_nucleus(q), math_kernel_no_italic_correction)) { -// italic = 0; -// } else { -// italic = tex_aux_math_x_size_scaled(fnt, tex_char_italic_from_font(fnt, chr), size); -// } -// x = tex_aux_clean_box(noad_nucleus(q), style, style, math_nucleus_list, 0, NULL); -// // if (italic) { -// // if (lmt_math_state.opentype) { -// // /*tex we never added italic correction unless we had a |mlist_to_hlist| call. */ -// // } else if (noad_subscr(q) && ! has_noad_option_limits(q)) { /* todo: control option */ -// // box_list(x) = tex_aux_math_remove_italic_kern(box_list(x), &italic, "operator"); -// // box_width(x) -= italic; -// // } -// // } -// shiftaxis = 1; -// } -// } else { -// /*tex Non display style. */ -// italic = tex_aux_math_x_size_scaled(fnt, tex_char_italic_from_font(fnt, chr), size); -// x = tex_aux_clean_box(noad_nucleus(q), style, style, math_nucleus_list, 0, NULL); -// // if (italic) { -// // if (lmt_math_state.opentype) { -// // /*tex We never added italic correction, but it gets ignored anyway. */ -// // box_width(x) -= italic; -// // } else if (noad_subscr(q) && ! has_noad_option_limits(q)) { /* todo: control option, what does this assume from the font */ -// // /*tex remove italic correction */ -// // box_width(x) -= italic; -// // } -// // } -// box_height(x) += openupheight; -// box_depth(x) += openupdepth; -// shiftaxis = 1; -// } -// if (shiftaxis) { -// /*tex center vertically */ -// box_shift_amount(x) = tex_half_scaled(box_height(x) - box_depth(x)) - tex_aux_math_axis(size); -// } -// if ((node_type(x) == hlist_node) && (openupheight || openupdepth)) { -// box_shift_amount(x) -= openupheight/2; -// box_shift_amount(x) += openupdepth/2; -// } -// node_type(noad_nucleus(q)) = sub_box_node; -// math_list(noad_nucleus(q)) = x; -// } -// if (nolimits) { -// /*tex -// We end up here when there is an explicit directive or when we're in displaymode without -// an explicit directive. If in text mode we want to have this mode driven placement tweak -// we need to use the |\nolimits| directive. Beware: that mode might be changed to a font -// property or option itself. -// */ -// // if (lmt_math_state.opentype) { -// kernset localkerns = { .tr = 0, .br = 0, .tl = 0, .bl = 0 }; -// if (kerns) { -// localkerns.tr = kerns->tr; -// localkerns.br = kerns->br; -// localkerns.tl = kerns->tl; -// localkerns.bl = kerns->bl; -// } -// halfword p = tex_aux_check_nucleus_complexity(q, NULL, style, lmt_math_state.size, &localkerns); -// if (noad_has_scripts(q)) { -// scaled top = 0; /*tex Normally this would be: | delta|. */ -// scaled bot = 0; /*tex Normally this would be: |-delta|. */ -// if (localkerns.tr || localkerns.br) { -// italic = 0; -// } -// tex_aux_get_shifts(math_nolimits_mode_par, style, italic, &top, &bot); -// tex_aux_make_scripts(q, p, 0, style, top, bot, 0, &localkerns); -// } else { -// tex_aux_assign_new_hlist(q, p); -// } -// italic = 0; -// // } else { -// // /*tex similar code as in the caller */ -// // halfword p = tex_aux_check_nucleus_complexity(q, &italic, style, lmt_math_state.size, NULL); -// // if (noad_has_scripts(q)) { -// // tex_aux_make_scripts(q, p, italic, style, 0, 0); -// // } else { -// // tex_aux_assign_new_hlist(q, p); -// // } -// // } -// } else if (limits) { -// /*tex -// -// The following program builds a vlist box |v| for displayed limits. The width of the box -// is not affected by the fact that the limits may be skewed. -// -// We end up here when we have a limits directive or when that property is set because -// we're in displaymode. -// */ -// halfword nucleus = noad_nucleus(q); -// halfword x = tex_aux_clean_box(noad_supscr(q), tex_math_style_variant(style, math_parameter_superscript_variant), style, math_sup_list, 0, NULL); -// halfword y = tex_aux_clean_box(nucleus, style, style, math_nucleus_list, 0, NULL); -// halfword z = tex_aux_clean_box(noad_subscr(q), tex_math_style_variant(style, math_parameter_subscript_variant), style, math_sub_list, 0, NULL); -// halfword result = tex_new_null_box_node(vlist_node, math_modifier_list); -// tex_attach_attribute_list_copy(result, q); -// if (nucleus) { -// switch (node_type(nucleus)) { -// case sub_mlist_node: -// case sub_box_node: -// { -// halfword n = math_list(nucleus); -// if (! n) { -// /* kind of special */ -// } else if (node_type(n) == hlist_node) { -// /*tex just a not scaled char */ -// n = box_list(n); -// while (n) { -// if (node_type(n) == glyph_node && ! tex_has_glyph_option(n, glyph_option_no_italic_correction)) { -// if (tex_aux_math_engine_control(glyph_font(n), math_control_apply_boxed_italic_kern)) { -// italic = tex_aux_math_x_size_scaled(glyph_font(n), tex_char_italic_from_font(glyph_font(n), glyph_character(n)), size); -// } -// } -// n = node_next(n); -// } -// } else { -// /*tex This might need checking. */ -// while (n) { -// if (node_type(n) == fence_noad && noad_italic(n) > italic) { -// /*tex we can have dummies, the period ones */ -// italic = tex_aux_math_given_x_scaled(noad_italic(n)); -// } -// n = node_next(n); -// } -// } -// break; -// } -// case math_char_node: -// { -// halfword fnt = tex_fam_fnt(math_family(nucleus), size); -// halfword chr = math_character(nucleus); -// italic = tex_aux_math_x_size_scaled(fnt, tex_char_italic_from_font(fnt, chr), size); -// break; -// } -// } -// } -// /*tex We're still doing limits. */ -// { -// scaled halfitalic = tex_half_scaled(italic); -// scaled supwidth = box_width(x); -// scaled boxwidth = box_width(y); -// scaled subwidth = box_width(z); -// box_width(result) = boxwidth; -// if (supwidth > boxwidth) { -// boxwidth = supwidth; -// } -// if (subwidth > boxwidth) { -// boxwidth = subwidth; -// } -// box_width(result) = boxwidth; -// x = tex_aux_rebox(x, boxwidth, size); -// y = tex_aux_rebox(y, boxwidth, size); -// z = tex_aux_rebox(z, boxwidth, size); -// /*tex This is only (visually) ok for integrals, but other operators have no italic anyway. */ -// box_shift_amount(x) = halfitalic; -// box_shift_amount(z) = -halfitalic; -// if (math_limits_mode_par >= 1) { -// /*tex -// This option enforces the real dimensions and avoids longer limits to stick out -// which is a traditional \TEX\ feature. It's handy to have this for testing. Nicer -// would be to also adapt the width of the wrapped scripts but these are reboxed -// with centering so we keep that as it is. -// */ -// if (supwidth + halfitalic > boxwidth) { -// box_width(result) += supwidth + halfitalic - boxwidth; -// } -// if (subwidth + halfitalic > boxwidth) { -// box_x_offset(result) = subwidth + halfitalic - boxwidth; -// box_width(result) += box_x_offset(result); -// tex_set_box_geometry(result, offset_geometry); -// } -// } else { -// /*tex We keep the possible left and/or right overshoot of limits. */ -// } -// /*tex Here the target |v| is still empty but we do set the height and depth. */ -// box_height(result) = box_height(y); -// box_depth(result) = box_depth(y); -// } -// /*tex -// -// Attach the limits to |y| and adjust |height(v)|, |depth(v)| to account for -// their presence. -// -// We use |shift_up| and |shift_down| in the following program for the amount of -// glue between the displayed operator |y| and its limits |x| and |z|. -// -// The vlist inside box |v| will consist of |x| followed by |y| followed by |z|, -// with kern nodes for the spaces between and around them; |b| is baseline and |v| -// is the minumum gap. -// -// */ -// if (noad_supscr(q)) { -// scaled bgap = tex_get_math_y_parameter_checked(style, math_parameter_limit_above_bgap); -// scaled vgap = tex_get_math_y_parameter_checked(style, math_parameter_limit_above_vgap); -// scaled vkern = tex_get_math_y_parameter_checked(style, math_parameter_limit_above_kern); -// scaled vshift = bgap - box_depth(x); -// if (vshift < vgap) { -// vshift = vgap; -// } -// if (vshift) { -// halfword kern = tex_new_kern_node(vshift, vertical_math_kern_subtype); -// tex_attach_attribute_list_copy(kern, q); -// tex_couple_nodes(kern, y); -// tex_couple_nodes(x, kern); -// } else { -// tex_couple_nodes(y, x); -// } -// if (vkern) { -// halfword kern = tex_new_kern_node(vkern, vertical_math_kern_subtype); -// tex_attach_attribute_list_copy(kern, q); -// tex_couple_nodes(kern, x); -// box_list(result) = kern; -// } else { -// box_list(result) = x; -// } -// box_height(result) += vkern + box_total(x) + vshift; -// } else { -// box_list(x) = null; -// tex_flush_node(x); -// box_list(result) = y; -// } -// if (noad_subscr(q)) { -// scaled bgap = tex_get_math_y_parameter_checked(style, math_parameter_limit_below_bgap); -// scaled vgap = tex_get_math_y_parameter_checked(style, math_parameter_limit_below_vgap); -// scaled vkern = tex_get_math_y_parameter_checked(style, math_parameter_limit_below_kern); -// scaled vshift = bgap - box_height(z); -// if (vshift < vgap) { -// vshift = vgap; -// } -// if (vshift) { -// halfword kern = tex_new_kern_node(vshift, vertical_math_kern_subtype); -// tex_attach_attribute_list_copy(kern, q); -// tex_couple_nodes(y, kern); -// tex_couple_nodes(kern, z); -// } else { -// tex_couple_nodes(y, z); -// } -// if (vkern) { -// halfword kern = tex_new_kern_node(vkern, vertical_math_kern_subtype); -// tex_attach_attribute_list_copy(kern, q); -// tex_couple_nodes(z, kern); -// } -// box_depth(result) += vkern + box_total(z) + vshift; -// } else { -// box_list(z) = null; -// tex_flush_node(z); -// } -// if (noad_subscr(q)) { -// math_list(noad_subscr(q)) = null; -// tex_flush_node(noad_subscr(q)); -// noad_subscr(q) = null; -// } -// if (noad_supscr(q)) { -// math_list(noad_supscr(q)) = null; -// tex_flush_node(noad_supscr(q)); -// noad_supscr(q) = null; -// } -// tex_aux_assign_new_hlist(q, result); -// // if (lmt_math_state.opentype) { -// italic = 0; -// // } -// } else { -// /*tex -// We end up here when we're not in displaymode and don't have a (no)limits directive. -// */ -// } -// return italic; -// } - -static scaled tex_aux_op_no_limits(halfword target, int style, int size, int italic, kernset *kerns) +static scaled tex_aux_op_no_limits(halfword target, int style, int size, int italic, kernset *kerns, int forceitalics) { kernset localkerns ; - halfword p; + halfword kernel; (void) size; + (void) forceitalics; if (kerns) { tex_math_copy_kerns(&localkerns, kerns); } else { tex_math_wipe_kerns(&localkerns); } - p = tex_aux_check_nucleus_complexity(target, NULL, style, lmt_math_state.size, &localkerns); + kernel = tex_aux_check_nucleus_complexity(target, NULL, style, lmt_math_state.size, &localkerns); if (noad_has_scripts(target)) { - scaled top = 0; /*tex Normally this would be: | delta|. */ - scaled bot = 0; /*tex Normally this would be: |-delta|. */ + scaled topshift = 0; /*tex Normally this would be: | delta|. */ + scaled botshift = 0; /*tex Normally this would be: |-delta|. */ if (localkerns.topright || localkerns.bottomright) { italic = 0; } - tex_aux_get_shifts(math_nolimits_mode_par, style, italic, &top, &bot); - tex_aux_make_scripts(target, p, 0, style, top, bot, 0, &localkerns); + tex_aux_get_shifts(math_nolimits_mode_par, style, italic, &topshift, &botshift); + tex_aux_make_scripts(target, kernel, 0, style, topshift, botshift, 0, &localkerns); } else { - tex_aux_assign_new_hlist(target, p); + tex_aux_assign_new_hlist(target, kernel); } // italic = 0; return 0; } -static scaled tex_aux_op_do_limits(halfword target, int style, int size, int italic, kernset *kerns) +static scaled tex_aux_op_do_limits(halfword target, int style, int size, int italic, kernset *kerns, int forceitalics) { halfword nucleus = noad_nucleus(target); - halfword x = tex_aux_clean_box(noad_supscr(target), tex_math_style_variant(style, math_parameter_superscript_variant), style, math_sup_list, 0, NULL); - halfword y = tex_aux_clean_box(nucleus, style, style, math_nucleus_list, 0, NULL); - halfword z = tex_aux_clean_box(noad_subscr(target), tex_math_style_variant(style, math_parameter_subscript_variant), style, math_sub_list, 0, NULL); + halfword superscript = tex_aux_clean_box(noad_supscr(target), tex_math_style_variant(style, math_parameter_superscript_variant), style, math_sup_list, 0, NULL); + halfword kernel = tex_aux_clean_box(nucleus, style, style, math_nucleus_list, forceitalics, NULL); + halfword subscript = tex_aux_clean_box(noad_subscr(target), tex_math_style_variant(style, math_parameter_subscript_variant), style, math_sub_list, 0, NULL); halfword result = tex_new_null_box_node(vlist_node, math_modifier_list); (void) kerns; tex_attach_attribute_list_copy(result, target); if (nucleus) { + // todo: get rid of redundant italic calculation ... it is still a mess .. maybe use noad_italic .. then this whole branch can go switch (node_type(nucleus)) { case sub_mlist_node: case sub_box_node: @@ -4072,11 +3677,27 @@ static scaled tex_aux_op_do_limits(halfword target, int style, int size, int ita } } /*tex We're still doing limits. */ - { + if (noad_supscr(target) || noad_subscr(target)) { + scaled supwidth = box_width(superscript); + scaled boxwidth = box_width(kernel); + scaled subwidth = box_width(subscript); scaled halfitalic = tex_half_scaled(italic); - scaled supwidth = box_width(x); - scaled boxwidth = box_width(y); - scaled subwidth = box_width(z); + halfword topshift = halfitalic; + halfword bottomshift = halfitalic; + if (kerns && ! halfitalic) { + halfword fnt = kerns->font; + halfword chr = kerns->character; + if (fnt && chr) { + scaled t = tex_aux_math_x_size_scaled(fnt, tex_char_top_anchor_from_font(fnt, chr), size); + scaled b = tex_aux_math_x_size_scaled(fnt, tex_char_bottom_anchor_from_font(fnt, chr), size); + if (t) { + topshift = t - boxwidth; + } + if (b) { + bottomshift = boxwidth - b; + } + } + } box_width(result) = boxwidth; if (supwidth > boxwidth) { boxwidth = supwidth; @@ -4085,12 +3706,12 @@ static scaled tex_aux_op_do_limits(halfword target, int style, int size, int ita boxwidth = subwidth; } box_width(result) = boxwidth; - x = tex_aux_rebox(x, boxwidth, size); - y = tex_aux_rebox(y, boxwidth, size); - z = tex_aux_rebox(z, boxwidth, size); + superscript = tex_aux_rebox(superscript, boxwidth, size); + kernel = tex_aux_rebox(kernel, boxwidth, size); + subscript = tex_aux_rebox(subscript, boxwidth, size); /*tex This is only (visually) ok for integrals, but other operators have no italic anyway. */ - box_shift_amount(x) = halfitalic; - box_shift_amount(z) = -halfitalic; + box_shift_amount(superscript) = topshift; + box_shift_amount(subscript) = -bottomshift; if (math_limits_mode_par >= 1) { /*tex This option enforces the real dimensions and avoids longer limits to stick out @@ -4098,11 +3719,11 @@ static scaled tex_aux_op_do_limits(halfword target, int style, int size, int ita would be to also adapt the width of the wrapped scripts but these are reboxed with centering so we keep that as it is. */ - if (supwidth + halfitalic > boxwidth) { - box_width(result) += supwidth + halfitalic - boxwidth; + if (supwidth + topshift > boxwidth) { + box_width(result) += supwidth + topshift - boxwidth; } - if (subwidth + halfitalic > boxwidth) { - box_x_offset(result) = subwidth + halfitalic - boxwidth; + if (subwidth + bottomshift > boxwidth) { + box_x_offset(result) = subwidth + bottomshift - boxwidth; box_width(result) += box_x_offset(result); tex_set_box_geometry(result, offset_geometry); } @@ -4110,8 +3731,12 @@ static scaled tex_aux_op_do_limits(halfword target, int style, int size, int ita /*tex We keep the possible left and/or right overshoot of limits. */ } /*tex Here the target |v| is still empty but we do set the height and depth. */ - box_height(result) = box_height(y); - box_depth(result) = box_depth(y); + box_height(result) = box_height(kernel); + box_depth(result) = box_depth(kernel); + } else { + box_width(result) = box_width(kernel); + box_height(result) = box_height(kernel); + box_depth(result) = box_depth(kernel); } /*tex @@ -4126,61 +3751,61 @@ static scaled tex_aux_op_do_limits(halfword target, int style, int size, int ita is the minumum gap. */ - if (noad_supscr(target)) { + if (noad_supscr(target)) { scaled bgap = tex_get_math_y_parameter_checked(style, math_parameter_limit_above_bgap); scaled vgap = tex_get_math_y_parameter_checked(style, math_parameter_limit_above_vgap); scaled vkern = tex_get_math_y_parameter_checked(style, math_parameter_limit_above_kern); - scaled vshift = bgap - box_depth(x); + scaled vshift = bgap - box_depth(superscript); if (vshift < vgap) { vshift = vgap; } if (vshift) { halfword kern = tex_new_kern_node(vshift, vertical_math_kern_subtype); tex_attach_attribute_list_copy(kern, target); - tex_couple_nodes(kern, y); - tex_couple_nodes(x, kern); + tex_couple_nodes(kern, kernel); + tex_couple_nodes(superscript, kern); } else { - tex_couple_nodes(y, x); + tex_couple_nodes(kernel, superscript); } if (vkern) { halfword kern = tex_new_kern_node(vkern, vertical_math_kern_subtype); tex_attach_attribute_list_copy(kern, target); - tex_couple_nodes(kern, x); + tex_couple_nodes(kern, superscript); box_list(result) = kern; } else { - box_list(result) = x; + box_list(result) = superscript; } - box_height(result) += vkern + box_total(x) + vshift; + box_height(result) += vkern + box_total(superscript) + vshift; } else { - box_list(x) = null; - tex_flush_node(x); - box_list(result) = y; + box_list(superscript) = null; + tex_flush_node(superscript); + box_list(result) = kernel; } if (noad_subscr(target)) { scaled bgap = tex_get_math_y_parameter_checked(style, math_parameter_limit_below_bgap); scaled vgap = tex_get_math_y_parameter_checked(style, math_parameter_limit_below_vgap); scaled vkern = tex_get_math_y_parameter_checked(style, math_parameter_limit_below_kern); - scaled vshift = bgap - box_height(z); + scaled vshift = bgap - box_height(subscript); if (vshift < vgap) { vshift = vgap; } if (vshift) { halfword kern = tex_new_kern_node(vshift, vertical_math_kern_subtype); tex_attach_attribute_list_copy(kern, target); - tex_couple_nodes(y, kern); - tex_couple_nodes(kern, z); + tex_couple_nodes(kernel, kern); + tex_couple_nodes(kern, subscript); } else { - tex_couple_nodes(y, z); + tex_couple_nodes(kernel, subscript); } if (vkern) { halfword kern = tex_new_kern_node(vkern, vertical_math_kern_subtype); tex_attach_attribute_list_copy(kern, target); - tex_couple_nodes(z, kern); + tex_couple_nodes(subscript, kern); } - box_depth(result) += vkern + box_total(z) + vshift; + box_depth(result) += vkern + box_total(subscript) + vshift; } else { - box_list(z) = null; - tex_flush_node(z); + box_list(subscript) = null; + tex_flush_node(subscript); } if (noad_subscr(target)) { kernel_math_list(noad_subscr(target)) = null; @@ -4202,9 +3827,9 @@ static scaled tex_aux_op_do_limits(halfword target, int style, int size, int ita we have more fance fence support now. */ -static void tex_aux_op_wrapup(halfword target, int style, int size, int italic, kernset *kerns) +static scaled tex_aux_op_wrapup(halfword target, int style, int size, int italic, kernset *kerns, int forceitalics) { - halfword x; + halfword box; int shiftaxis = 0; halfword chr = null; halfword fnt = null; @@ -4256,7 +3881,7 @@ static void tex_aux_op_wrapup(halfword target, int style, int size, int italic, /* we need to check for overflow here */ opsize += limited_scaled(openupheight); opsize += openupdepth; - x = tex_aux_make_delimiter(target, y, text_size, opsize, 0, style, ! has_noad_option_noaxis(target), NULL, &italic, 0, has_noad_option_nooverflow(target), NULL, 0); + box = tex_aux_make_delimiter(target, y, text_size, opsize, 0, style, ! has_noad_option_noaxis(target), NULL, &italic, 0, has_noad_option_nooverflow(target), NULL, 0); } else { /*tex Where was the weird + 1 coming from? It tweaks the comparison. Anyway, because we @@ -4278,36 +3903,56 @@ static void tex_aux_op_wrapup(halfword target, int style, int size, int italic, break; } } - if (math_kernel_node_has_option(noad_nucleus(target), math_kernel_no_italic_correction)) { + if (math_kernel_node_has_option(noad_nucleus(target), math_kernel_no_italic_correction) && ! forceitalics) { italic = 0; - } else { + } else { italic = tex_aux_math_x_size_scaled(fnt, tex_char_italic_from_font(fnt, chr), size); } - x = tex_aux_clean_box(noad_nucleus(target), style, style, math_nucleus_list, 0, NULL); + box = tex_aux_clean_box(noad_nucleus(target), style, style, math_nucleus_list, 0, NULL); shiftaxis = 1; } } else { /*tex Non display style. */ italic = tex_aux_math_x_size_scaled(fnt, tex_char_italic_from_font(fnt, chr), size); - x = tex_aux_clean_box(noad_nucleus(target), style, style, math_nucleus_list, 0, NULL); - box_height(x) += openupheight; - box_depth(x) += openupdepth; + box = tex_aux_clean_box(noad_nucleus(target), style, style, math_nucleus_list, 0, NULL); + box_height(box) += openupheight; + box_depth(box) += openupdepth; shiftaxis = 1; } if (shiftaxis) { /*tex center vertically */ - box_shift_amount(x) = tex_half_scaled(box_height(x) - box_depth(x)) - tex_aux_math_axis(size); + box_shift_amount(box) = tex_half_scaled(box_height(box) - box_depth(box)) - tex_aux_math_axis(size); } - if ((node_type(x) == hlist_node) && (openupheight || openupdepth)) { - box_shift_amount(x) -= openupheight/2; - box_shift_amount(x) += openupdepth/2; + if ((node_type(box) == hlist_node) && (openupheight || openupdepth)) { + box_shift_amount(box) -= openupheight/2; + box_shift_amount(box) += openupdepth/2; + } + if (forceitalics && italic && box_list(box)) { + /*tex + This features is provided in case one abuses operators in weird ways and expects italic + correction to be part of the width. Maybe it should be an kernel option so that it can + be controlled locally. Now here we enter fuzzy specification teritory. For n-ary + operators we are supposed to use the italic correction for placements of vertical and + horizontal scripts (limits an nolimits) but when we patch the width that gets messy (we + now need to need to backtrack twice times half the correction). The bad news is that + there is no way to see if we have a n-ary unless we add a new class and only for the + lone slanted integrals in lm. So, instead we just zero the correction now. After all, + we can use a fence instead for these n-ary's. Actually there are probably not that many + slanted operators, so it' smore about using a letter as such. So, |italiic *= 2| became + |italic = 0|. + */ + tex_aux_math_insert_italic_kern(tex_tail_of_node_list(box_list(box)), italic, noad_nucleus(target), "operator"); + box_width(box) += italic; + italic = 0; } node_type(noad_nucleus(target)) = sub_box_node; - kernel_math_list(noad_nucleus(target)) = x; + kernel_math_list(noad_nucleus(target)) = box; + return italic; } static scaled tex_aux_make_op(halfword target, int style, int size, int italic, int limits_mode, kernset *kerns) { + int forceitalics = node_subtype(target) == operator_noad_subtype && tex_math_has_class_option(operator_noad_subtype, operator_italic_correction_class_option); if (limits_mode == limits_horizontal_mode) { /*tex We enforce this and it can't be overruled! */ } else if (! has_noad_option_limits(target) && ! has_noad_option_nolimits(target) && (style == display_style || style == cramped_display_style)) { @@ -4319,7 +3964,7 @@ static scaled tex_aux_make_op(halfword target, int style, int size, int italic, limits_mode = limits_vertical_mode; } if (node_type(noad_nucleus(target)) == math_char_node) { - tex_aux_op_wrapup(target, style, size, italic, kerns); + italic = tex_aux_op_wrapup(target, style, size, italic, kerns, forceitalics); } switch (limits_mode) { case limits_horizontal_mode: @@ -4329,7 +3974,7 @@ static scaled tex_aux_make_op(halfword target, int style, int size, int italic, we need to use the |\nolimits| directive. Beware: that mode might be changed to a font property or option itself. */ - return tex_aux_op_no_limits(target, style, size, italic, kerns); /* italic becomes zero */ + return tex_aux_op_no_limits(target, style, size, italic, kerns, forceitalics); /* italic becomes zero */ case limits_vertical_mode: /*tex @@ -4337,12 +3982,13 @@ static scaled tex_aux_make_op(halfword target, int style, int size, int italic, we're in displaymode. The following program builds a vlist box |v| for displayed limits. The width of the box is not affected by the fact that the limits may be skewed. */ - return tex_aux_op_do_limits(target, style, size, italic, kerns); /* italic becomes zero */ + return tex_aux_op_do_limits(target, style, size, italic, kerns, forceitalics); /* italic becomes zero */ default: /*tex - We end up here when we're not in displaymode and don't have a (no)limits directive. + We end up here when we're not in displaymode and don't have a (no)limits directive. + When called the wrong way we loose the nucleus. */ - return italic; /* italic is retained */ + return italic; /* italic is retained, happens very seldom */ } } @@ -4360,133 +4006,6 @@ static scaled tex_aux_make_op(halfword target, int style, int size, int italic, */ -/* How about: ord_noad_type_limits */ - -// inline static int tex_aux_is_simple_char_noad(halfword p) /* only old school characters */ -// { -// return (node_type(p) == simple_noad) && (node_type(noad_nucleus(p)) == math_char_node && tex_math_has_class_option(node_subtype(p), check_ligature_class_option)); -// } -// -// inline static int tex_aux_have_same_nucleus_fam(halfword p, halfword q) -// { -// return math_family(noad_nucleus(p)) == math_family(noad_nucleus(q)); -// } -// -// static void tex_aux_make_ord(halfword q, halfword size) -// { -// /*tex The left-side character for lig/kern testing. */ -// RESTART: -// /*tex We can end up here again after a ligature is built. */ -// if (! noad_has_following_scripts(q) && node_type(noad_nucleus(q)) == math_char_node) { -// halfword p = node_next(q); -// /*tex */ -// if (p && tex_aux_is_simple_char_noad(p) && tex_aux_have_same_nucleus_fam(p, q)) { -// halfword chr = null; -// halfword fnt = null; -// node_type(noad_nucleus(q)) = math_text_char_node; -// tex_aux_fetch(noad_nucleus(q), "ordinal", &fnt, &chr); -// if (tex_aux_math_engine_control(fnt, math_control_apply_ordinary_italic_kern)) { -// /* -// We don't have other kerns in opentype math fonts. There are however these -// staircase kerns that are dealt with elsewhere. But for new math fonts we do -// need to add italic correction. -// */ -// if (math_kernel_node_has_option(noad_nucleus(q), math_kernel_no_italic_correction)) { -// /* go on */ -// } else { -// scaled kern = tex_aux_math_x_size_scaled(fnt, tex_char_italic_from_font(fnt, math_character(noad_nucleus(q))), size); -// if (kern) { -// tex_aux_math_insert_italic_kern(q, kern, q, "ord"); -// } -// } -// } else if (tex_aux_math_engine_control(fnt, math_control_check_ligature_and_kern)) { -// if (tex_has_kern(fnt, chr) || tex_has_ligature(fnt, chr)) { -// /*tex -// -// Here we construct ligatures, quite unlikely in new math fonts so maybe we -// should just not go here for such fonts. -// -// If character |a| has a kern with |cur_c|, attach the kern after~|q|; or if -// it has a ligature with |cur_c|, combine noads |q| and~|p| appropriately; -// then |return| if the cursor has moved past a noad, or |goto restart|. -// -// Note that a ligature between an |ord_noad| and another kind of noad is -// replaced by an |ord_noad|, when the two noads collapse into one. -// -// We could make a parenthesis (say) change shape when it follows certain -// letters. Presumably a font designer will define such ligatures only when -// this convention makes sense. -// -// */ -// halfword nxt = math_character(noad_nucleus(p)); -// halfword slot; -// int type = tex_valid_ligature(chr, nxt, &slot); -// if (type >= 0) { -// switch (type) { -// case 1: /*tex \type{=:|} */ -// case 5: /*tex \type{=:|>} */ -// math_character(noad_nucleus(q)) = slot; -// break; -// case 2: /*tex \type{|=:} */ -// case 6: /*tex \type{|=:>} */ -// math_character(noad_nucleus(p)) = slot; -// break; -// case 3: /*tex \type{|=:|} */ -// case 7: /*tex \type{|=:|>} */ -// case 11: /*tex \type{|=:|>>} */ -// { -// halfword r = tex_new_node(simple_noad, ordinary_noad_subtype); -// halfword s = tex_new_node(math_char_node, 0); -// tex_attach_attribute_list_copy(r, q); -// tex_attach_attribute_list_copy(s, q); -// noad_nucleus(r) = s; -// math_character(noad_nucleus(r)) = slot; -// math_family(noad_nucleus(r)) = math_family(noad_nucleus(q)); -// tex_couple_nodes(q, r); -// tex_couple_nodes(r, p); -// if (type < 11) { -// node_type(noad_nucleus(r)) = math_char_node; -// } else { -// /*tex prevent combination */ -// node_type(noad_nucleus(r)) = math_text_char_node; -// } -// } -// break; -// default: /*tex |=:| */ -// tex_try_couple_nodes(q, node_next(p)); -// math_character(noad_nucleus(q)) = slot; -// noad_subscr(q) = noad_subscr(p); -// noad_supscr(q) = noad_supscr(p); -// noad_subscr(p) = null ; -// noad_supscr(p) = null ; -// tex_flush_node(p); -// break; -// } -// if (type > 3) { -// return; -// } else { -// node_type(noad_nucleus(q)) = math_char_node; -// goto RESTART; /*tex Inefficient but we never see this branch anyway. */ -// } -// } -// { -// // scaled kern = tex_aux_math_x_size_scaled(fnt, tex_valid_kern(chr, nxt), size); -// halfword nxtchr = null; -// halfword nxtfnt = null; -// tex_aux_fetch(noad_nucleus(p), "ordinal", &nxtfnt, &nxtchr); -// scaled kern = tex_get_kern(fnt, chr, nxtchr); -// if (kern) { -// tex_aux_math_insert_font_kern(q, kern, q, "ord"); -// return; -// } -// } -// } -// } -// } -// } -// } - - // $ \mathord {a} $ : ord -> nucleus -> mathchar // $ \mathord {ab} $ : ord -> nucleus -> submlist -> ord + ord @@ -4517,7 +4036,7 @@ static halfword tex_aux_check_ord(halfword current, halfword size, halfword next case sub_mlist_node: { // I'm not that motivated for this and it should be an engine option anyway then. - + // // halfword head = math_list(nucleus); // halfword tail = tex_tail_of_node_list(head); // // doesn't work @@ -5181,7 +4700,9 @@ static int tex_aux_get_sub_kern(halfword kernel, scriptdata *sub, scaled shift_d some freedom in dealing with them. This code is now a bit too complex due to some (probably by now) redundant analysis so at some - point I will rewrite it. + point I will rewrite it. Anyway, normally we don't end up in the next one because italic + correction already has been dealt with and thereby is zerood. In fact, if we end up here I need + to check why! */ @@ -5191,7 +4712,7 @@ inline static scaled tex_aux_insert_italic_now(halfword target, halfword kernel, case math_char_node: case math_text_char_node: { - halfword fam = noad_family(noad_nucleus(target)); + halfword fam = kernel_math_family(noad_nucleus(target)); if (fam != unused_math_family) { halfword fnt = tex_fam_fnt(fam, lmt_math_state.size); if (! tex_aux_math_engine_control(fnt, math_control_apply_script_italic_kern)) { @@ -5315,13 +4836,16 @@ static void tex_aux_make_scripts(halfword target, halfword kernel, scaled italic */ tex_aux_assign_new_hlist(target, kernel); kernelsize = tex_natural_hsizes(kernel, null, 0.0, 0, 0); - if (kerns) { - /* todo: option */ - if (kerns->height) { - kernelsize.ht = kerns->height; - } - if (kerns->depth) { - kernelsize.dp = kerns->depth; + if (kerns && kerns->dimensions) { + if (tex_aux_math_engine_control(kerns->font, math_control_ignore_kern_dimensions)) { + /* hack for bad xits fence depth */ + } else { + if (kerns->height) { + kernelsize.ht = kerns->height; + } + if (kerns->depth) { + kernelsize.dp = kerns->depth; + } } } switch (node_type(kernel)) { @@ -5609,7 +5133,8 @@ static void tex_aux_make_scripts(halfword target, halfword kernel, scaled italic } /* */ if (postsupdata.box) { - tex_aux_get_math_sup_shifts(postsupdata.box, style, &shift_up); + /* Do we still want to chain these sups or should we combine it? */ + tex_aux_get_math_sup_shifts(postsupdata.box, style, &shift_up); /* maybe only in else branch */ if (postsubdata.box) { tex_aux_get_math_sup_sub_shifts(postsupdata.box, postsubdata.box, style, &shift_up, &shift_down); tex_aux_get_sup_kern(kernel, &postsupdata, shift_up, supshift, &supkern, kerns); @@ -5705,6 +5230,7 @@ static void tex_aux_make_scripts(halfword target, halfword kernel, scaled italic } if (presubdata.box) { if (presupdata.box) { + /* Do we still want to chain these sups or should we combine it? */ tex_aux_get_math_sup_shifts(presupdata.box, style, &shift_up); tex_aux_get_math_sup_sub_shifts(presupdata.box, presubdata.box, style, &shift_up, &shift_down); prekern = box_width(presupdata.box); @@ -5834,7 +5360,7 @@ static halfword tex_aux_make_left_right(halfword target, int style, scaled max_d halfword lst; scaled delta = height + depth; tmp = tex_aux_make_delimiter(target, fence_delimiter_list(target), size, delta, 0, style, 0, &stack, &ic, 0, has_noad_option_nooverflow(target), extremes, 0); -/* do extremes here */ + /* do extremes here */ noad_italic(target) = ic; /*tex Beware, a stacked delimiter has a shift but no corrected height/depth (yet). @@ -5919,8 +5445,12 @@ static halfword tex_aux_make_left_right(halfword target, int style, scaled max_d if (tex_math_has_class_option(fenced_noad_subtype, prefer_delimiter_dimensions_class_option)) { kerns.height = extremes->height; kerns.depth = extremes->depth; + kerns.dimensions = 1; + kerns.font = extremes->tfont; + kerns.character = extremes->tchar; } } + /* returns italic, so maybe noad_italic(target) = ... */ tex_aux_make_op(target, style, size, ic, limits_unknown_mode, &kerns); /* otherwise a leak: */ kernel_math_list(s) = null; @@ -6156,10 +5686,6 @@ halfword tex_math_spacing_glue(halfword ltype, halfword rtype, halfword style) there. The delta parameter can have a value already. When it keeps it value the caller can add is as italic correction. However, when we have no scripts we do it here. - Also, in some cases a new glyph is made while we alredy have one. The fetch routine also sets - |lmt_math_state.opentype| so we can use it here. The complexity of the muxed machinery makes - this complexity test also complex. - */ static halfword tex_aux_check_nucleus_complexity(halfword target, scaled *italic, halfword style, halfword size, kernset *kerns) @@ -6295,15 +5821,19 @@ static halfword tex_aux_check_nucleus_complexity(halfword target, scaled *italic halfword list = kernel_math_list(nucleus); halfword package = null; halfword fenced = node_type(target) == simple_noad && node_subtype(target) == fenced_noad_subtype; + halfword last = fenced ? tex_tail_of_node_list(list) : null; int unpack = tex_math_has_class_option(node_subtype(target), unpack_class_option) || has_noad_option_unpacklist(target); - // todo: check has_noad_option_unpacklist vs hpack later - // halfword result = tex_mlist_to_hlist(list, fenced || has_noad_option_unpacklist(q), style, unset_noad_class, unset_noad_class); /*tex Here we're nesting. */ halfword result = tex_mlist_to_hlist(list, unpack, style, unset_noad_class, unset_noad_class, kerns); /*tex Here we're nesting. */ tex_aux_set_current_math_size(style); package = tex_hpack(result, 0, packing_additional, direction_unknown, holding_none_option); if (fenced) { node_subtype(package) = math_fence_list; - // } else if (has_noad_option_unpacklist(q)) { + if (list && node_type(list) == fence_noad && noad_analyzed(list) != unset_noad_class) { + set_noad_left_class(target, noad_analyzed(list)); + } + if (last && node_type(last) == fence_noad && noad_analyzed(last) != unset_noad_class) { + set_noad_right_class(target, noad_analyzed(last)); + } } else if (unpack) { node_subtype(package) = math_list_list; } else if (noad_class_main(target) == unset_noad_class) { @@ -6420,6 +5950,7 @@ static int tex_aux_make_fenced(halfword current, halfword current_style, halfwor if (nucleus) { halfword list = kernel_math_list(nucleus); if (list && node_type(list) == fence_noad && node_subtype(list) == left_operator_side) { + /* maybe use this more: */ fenceclasses->main = noad_class_main(list); fenceclasses->left = noad_class_left(list); fenceclasses->right = noad_class_right(list); @@ -6482,6 +6013,8 @@ static void tex_aux_finish_fenced(halfword current, halfword main_style, scaled if (tex_math_has_class_option(fenced_noad_subtype, prefer_delimiter_dimensions_class_option)) { kerns->height = extremes.height; kerns->depth = extremes.depth; + kerns->dimensions = 1; + kerns->font = extremes.tfont; } break; case right_fence_side: @@ -6623,8 +6156,7 @@ static void tex_aux_show_math_list(const char *fmt, halfword list) static void tex_aux_wrapup_nucleus_and_add_scripts(halfword current, halfword nxt, int current_style, halfword *italic, kernset *kerns) { - halfword p; - p = tex_aux_check_nucleus_complexity(current, italic, current_style, lmt_math_state.size, kerns); + halfword p = tex_aux_check_nucleus_complexity(current, italic, current_style, lmt_math_state.size, kerns); if (p && noad_source(current)) { switch (node_type(p)) { case hlist_node: @@ -6779,6 +6311,11 @@ static void tex_mlist_to_hlist_preroll_radicals(mliststate *state) } } +/*tex + At some point this will all change to well defined kernel/script/talic handling but then we no + longer are compatible. It depends on fonts being okay. We already have some dead brances. +*/ + static void tex_mlist_to_hlist_preroll_dimensions(mliststate *state) { halfword current = state->mlist; @@ -6854,7 +6391,7 @@ static void tex_mlist_to_hlist_preroll_dimensions(mliststate *state) noad_options(current) |= noad_option_no_limits; } } - PROCESS: + PROCESS: if ( // node_subtype(q) == operator_noad_subtype // || has_noad_option_limits(current) || has_noad_option_nolimits(current) @@ -6873,7 +6410,7 @@ static void tex_mlist_to_hlist_preroll_dimensions(mliststate *state) } /* tex_math_has_class_option(node_subtype(current),keep_correction_class_code) */ if (node_subtype(current) != operator_noad_subtype) { - italic = 0; + italic = 0; } if (fenceclasses.main != unset_noad_class) { noad_class_main(current) = fenceclasses.main; @@ -6962,52 +6499,7 @@ static void tex_mlist_to_hlist_preroll_dimensions(mliststate *state) superscript should be moved right with respect to a subscript when both are present. */ tex_aux_wrapup_nucleus_and_add_scripts(current, nxt, current_style, &italic, &localkerns); - // { - // kernset kerns; - // halfword p; - // tex_math_copy_kerns(&kerns, &localkerns); - // p = tex_aux_check_nucleus_complexity(current, &italic, current_style, lmt_math_state.size, &kerns); - // if (p && noad_source(current)) { - // switch (node_type(p)) { - // case hlist_node: - // case vlist_node: - // if (! box_source_anchor(p)) { - // box_source_anchor(p) = noad_source(current); - // tex_set_box_geometry(p, anchor_geometry); - // } - // break; - // default: - // /*tex Todo: maybe pack and assign! */ - // break; - // } - // } - // if (noad_has_scripts(current)) { - // scaled drop = 0; - // if (node_type(current) == accent_noad && noad_has_superscripts(current)) { - // drop = tex_get_math_y_parameter_default(current_style, math_parameter_accent_superscript_drop, 0); - // drop += scaledround(localkerns.toptotal * tex_get_math_parameter_default(current_style, math_parameter_accent_superscript_percent, 0) / 100.0); - // } - // tex_aux_make_scripts(current, p, italic, current_style, 0, 0, drop, &kerns); - // } else { - // /*tex - // Adding italic correction here is kind of fuzzy because some characters already have - // that built in. However, we also add it in the scripts so if it's optional here it - // also should be there. The compexity tester can have added it in which case delta - // is zero. - // */ - // if (nxt && italic) { - // if (node_type(nxt) == simple_noad && tex_math_has_class_option(node_subtype(nxt), no_italic_correction_class_option)) { - // italic = 0; - // } - // if (italic) { - // /* If we want it as option we need the fontor store it in the noad. */ - // tex_aux_math_insert_italic_kern(p, italic, current, "final"); - // } - // } - // tex_aux_assign_new_hlist(current, p); - // } - // } - CHECK_DIMENSIONS: + CHECK_DIMENSIONS: { scaledwhd siz = tex_natural_hsizes(noad_new_hlist(current), null, normal_glue_multiplier, normal_glue_sign, normal_glue_sign); if (siz.ht > state->max_height) { @@ -7017,7 +6509,7 @@ static void tex_mlist_to_hlist_preroll_dimensions(mliststate *state) state->max_depth = siz.dp; } } - DONE_WITH_NODE: + DONE_WITH_NODE: if ((node_type(current) == simple_noad) && noad_new_hlist(current)) { if (has_noad_option_phantom(current) || has_noad_option_void(current)) { noad_new_hlist(current) = tex_aux_make_list_phantom(noad_new_hlist(current), has_noad_option_void(current), get_attribute_list(current)); @@ -7060,6 +6552,7 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) int recent_subtype = ordinary_noad_subtype; halfword current_style = state->main_style; halfword fenced = null; + halfword packedfence = null; halfword recent_left_slack = 0; halfword recent_right_slack = 0; halfword recent_class_overload = unset_noad_class; @@ -7132,6 +6625,9 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) goto RESTART; } } else { + /*tex + Here we have a wrapped list of left, middle, right and content nodes. + */ current_subtype = node_subtype(current); current_left_slack = noad_left_slack(current); current_right_slack = noad_right_slack(current); @@ -7139,17 +6635,14 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) switch (current_subtype) { case fenced_noad_subtype: { - // halfword list = noad_new_hlist(current); - // if (list && ! noad_nucleus(current) && ! noad_has_scripts(current)) { // scripts test will go - fenced = current; - if (get_noad_right_class(fenced) != unset_noad_class) { - current_subtype = get_noad_left_class(fenced); - } else if (get_noad_main_class(fenced) != unset_noad_class) { // needs testing by MS - current_subtype = get_noad_main_class(fenced); - } else { - current_subtype = open_noad_subtype; /* safeguard, see comment above */ - } - // } + fenced = current; + if (get_noad_right_class(fenced) != unset_noad_class) { + current_subtype = get_noad_left_class(fenced); + } else if (get_noad_main_class(fenced) != unset_noad_class) { // needs testing by MS + current_subtype = get_noad_main_class(fenced); + } else { + current_subtype = open_noad_subtype; /* safeguard, see comment above */ + } break; } default: @@ -7230,9 +6723,10 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) current_subtype = fraction_noad_subtype; /* inner_noad_type */ break; case fence_noad: + /*tex Here we have a left, right, middle */ current_type = simple_noad; /*tex Same kind of fields. */ current_subtype = noad_analyzed(current); - fenced = current; + packedfence = current; break; case style_node: tex_aux_make_style(current, ¤t_style, ¤t_mu); @@ -7481,7 +6975,8 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) /* curious */ } else if (node_type(l) == hlist_node && box_source_anchor(l)) { tex_couple_nodes(p, l); - } else if (fenced) { + } else if (packedfence) { + /*tex This branch probably can go away, see below. */ /*tex Watch out: we can have |[prescripts] [fencelist] [postscripts]| */ if (tex_math_has_class_option(fenced_noad_subtype, unpack_class_option)) { p = tex_aux_unroll_noad(p, l, math_fence_list); @@ -7518,6 +7013,7 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state) fenced = null; } noad_new_hlist(current) = null; + packedfence = null; } /*tex Append any |new_hlist| entries for |q|, and any appropriate penalties. We insert a @@ -7612,7 +7108,7 @@ halfword tex_mlist_to_hlist(halfword mlist, int penalties, int main_style, int b state.penalties = penalties; state.main_style = main_style; state.beginclass = beginclass == unset_noad_class ? math_begin_class : beginclass; - state.endclass = endclass == unset_noad_class ? math_end_class : endclass;; + state.endclass = endclass == unset_noad_class ? math_end_class : endclass; state.kerns = kerns; state.scale = glyph_scale_par; state.max_height = 0; diff --git a/source/luametatex/source/tex/texmlist.h b/source/luametatex/source/tex/texmlist.h index 1cb2a6cc7..720c85b4d 100644 --- a/source/luametatex/source/tex/texmlist.h +++ b/source/luametatex/source/tex/texmlist.h @@ -6,14 +6,18 @@ # define LMT_MLIST_H typedef struct kernset { - scaled topright; - scaled bottomright; - scaled topleft; - scaled bottomleft; - scaled height; - scaled depth; - scaled toptotal; - scaled bottomtotal; + scaled topright; + scaled bottomright; + scaled topleft; + scaled bottomleft; + scaled height; + scaled depth; + scaled toptotal; + scaled bottomtotal; + halfword dimensions; + halfword font; + halfword character; + halfword padding; } kernset; extern void tex_run_mlist_to_hlist (halfword p, halfword penalties, halfword style, int beginclass, int endclass); diff --git a/source/luametatex/source/tex/texnodes.c b/source/luametatex/source/tex/texnodes.c index 45e04dfd2..c627a07cb 100644 --- a/source/luametatex/source/tex/texnodes.c +++ b/source/luametatex/source/tex/texnodes.c @@ -2313,9 +2313,7 @@ static void tex_aux_show_attr_list(halfword p) tex_print_int(v); } } else { - tex_print_int(k); - tex_print_char('='); - tex_print_int(v); + tex_print_format("%i=%i", k, v); }; p = node_next(p); if (p) { @@ -2330,18 +2328,14 @@ void tex_print_name(halfword n, const char* what) { tex_print_str_esc(what); if (tracing_nodes_par > 0) { - tex_print_char('<'); - tex_print_int(n); - tex_print_char('>'); + tex_print_format("<%i>", n); } } static void tex_aux_print_subtype_and_attributes_str(halfword p, const char *n) { if (show_node_details_par > 0) { - tex_print_char('['); - tex_print_str(n); - tex_print_char(']'); + tex_print_format("[%s]",n); } if (show_node_details_par > 1 && tex_nodetype_has_attributes(node_type(p))) { tex_aux_show_attr_list(p); @@ -2415,9 +2409,7 @@ static void tex_print_node_and_details(halfword p) static void tex_aux_print_subtype_and_attributes_int(halfword p, halfword n) { if (show_node_details_par > 0) { \ - tex_print_char('['); - tex_print_int(n); - tex_print_char(']'); + tex_print_format("[%i]", n); } if (show_node_details_par > 1 && tex_nodetype_has_attributes(node_type(p))) { tex_aux_show_attr_list(p); @@ -2476,23 +2468,19 @@ void tex_aux_show_dictionary(halfword p, halfword properties, halfword group, ha lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "Nddddd->R", p, properties, group, index, font, character, &s); tex_restore_cur_string(u); if (s) { - tex_print_str(", "); - tex_print_str(s); + tex_print_format(", %s", s); lmt_memory_free(s); return; } } if (properties) { - tex_print_str(", properties "); - tex_print_qhex(properties); + tex_print_format(", properties %x", properties); } if (group) { - tex_print_str(", group "); - tex_print_qhex(group); + tex_print_format(", group %x", group); } if (index) { - tex_print_str(", index "); - tex_print_qhex(index); + tex_print_format(", index %x", index); } } @@ -2537,120 +2525,87 @@ void tex_show_node_list(halfword p, int threshold, int max) } /* effective */ if (whd.wd) { - tex_print_str(", wd "); - tex_print_dimension(whd.wd, pt_unit); + tex_print_format(", wd %D", whd.wd, pt_unit); } if (whd.ht) { - tex_print_str(", ht "); - tex_print_dimension(whd.ht, pt_unit); + tex_print_format(", ht %D", whd.ht, pt_unit); } if (whd.dp) { - tex_print_str(", dp "); - tex_print_dimension(whd.dp, pt_unit); + tex_print_format(", dp %D", whd.dp, pt_unit); } if (whd.ic) { - tex_print_str(", ic "); - tex_print_dimension(whd.ic, pt_unit); + tex_print_format(", ic %D", whd.ic, pt_unit); } /* */ if (get_glyph_language(p)) { - tex_print_str(", language (n="); - tex_print_int(get_glyph_language(p)); - tex_print_str(",l="); - tex_print_int(get_glyph_lhmin(p)); - tex_print_str(",r="); - tex_print_int(get_glyph_rhmin(p)); - tex_print_char(')'); + tex_print_format(", language (n=%i,l=%i,r=%i)", get_glyph_language(p), get_glyph_lhmin(p), get_glyph_rhmin(p)); } if (get_glyph_script(p)) { - tex_print_str(", script "); - tex_print_int(get_glyph_script(p)); + tex_print_format(", script %i", get_glyph_script(p)); } if (get_glyph_hyphenate(p)) { - tex_print_str(", hyphenationmode "); - tex_print_qhex(get_glyph_hyphenate(p)); + tex_print_format(", hyphenationmode %x", get_glyph_hyphenate(p)); } if (glyph_x_offset(p)) { - tex_print_str(", xoffset "); - tex_print_dimension(glyph_x_offset(p), pt_unit); + tex_print_format(", xoffset %D", glyph_x_offset(p), pt_unit); } if (glyph_y_offset(p)) { - tex_print_str(", yoffset "); - tex_print_dimension(glyph_y_offset(p), pt_unit); + tex_print_format(", yoffset %D", glyph_y_offset(p), pt_unit); } if (glyph_left(p)) { - tex_print_str(", left "); - tex_print_dimension(glyph_left(p), pt_unit); + tex_print_format(", left %D", glyph_left(p), pt_unit); } if (glyph_right(p)) { - tex_print_str(", right "); - tex_print_dimension(glyph_right(p), pt_unit); + tex_print_format(", right %D", glyph_right(p), pt_unit); } if (glyph_raise(p)) { - tex_print_str(", raise "); - tex_print_dimension(glyph_raise(p), pt_unit); + tex_print_format(", raise %D", glyph_raise(p), pt_unit); } if (glyph_expansion(p)) { - tex_print_str(", expansion "); - tex_print_int(glyph_expansion(p)); + tex_print_format(", expansion %i", glyph_expansion(p)); } if (glyph_scale(p) && glyph_scale(p) != 1000) { - tex_print_str(", scale "); - tex_print_int(glyph_scale(p)); + tex_print_format(", scale %i", glyph_scale(p)); } if (glyph_x_scale(p) && glyph_x_scale(p) != 1000) { - tex_print_str(", xscale "); - tex_print_int(glyph_x_scale(p)); + tex_print_format(", xscale %i", glyph_x_scale(p)); } if (glyph_y_scale(p) && glyph_y_scale(p) != 1000) { - tex_print_str(", yscale "); - tex_print_int(glyph_y_scale(p)); + tex_print_format(", yscale %i", glyph_y_scale(p)); } if (glyph_data(p)) { - tex_print_str(", data "); - tex_print_int(glyph_data(p)); + tex_print_format(", data %i", glyph_data(p)); } if (glyph_state(p)) { - tex_print_str(", state "); - tex_print_int(glyph_state(p)); + tex_print_format(", state %i", glyph_state(p)); } if (glyph_options(p)) { - tex_print_str(", options "); - tex_print_qhex(glyph_options(p)); + tex_print_format(", options %x", glyph_options(p)); } if (glyph_discpart(p)) { - tex_print_str(", discpart "); - tex_print_int(glyph_discpart(p)); + tex_print_format(", discpart %i", glyph_discpart(p)); } tex_aux_show_dictionary(p, glyph_properties(p), glyph_group(p), glyph_index(p), glyph_font(p), glyph_character(p)); } - tex_print_str(", font "); - /* this could be a callback */ - tex_print_font_identifier(glyph_font(p)); /* for now consistent with others, might change */ - tex_print_str(", glyph "); - tex_print_char_identifier(glyph_character(p)); + tex_print_format(", font %F, glyph %U", glyph_font(p), glyph_character(p)); break; case hlist_node: case vlist_node: case unset_node: /*tex Display box |p|. */ if (box_width(p)) { - tex_print_str(", width "); - tex_print_dimension(box_width(p), pt_unit); + tex_print_format(", width %D", box_width(p), pt_unit); } if (box_height(p)) { - tex_print_str(", height "); - tex_print_dimension(box_height(p), pt_unit); + tex_print_format(", height %D", box_height(p), pt_unit); } if (box_depth(p)) { - tex_print_str(", depth "); - tex_print_dimension(box_depth(p), pt_unit); + tex_print_format(", depth %D", box_depth(p), pt_unit); } if (node_type(p) == unset_node) { /*tex Display special fields of the unset node |p|. */ if (box_span_count(p)) { - tex_print_str(", columns "); - tex_print_int(box_span_count(p) + 1); + tex_print_format(", columns %i", box_span_count(p) + 1); } if (box_glue_stretch(p)) { tex_print_str(", stretch "); @@ -2691,8 +2646,7 @@ void tex_show_node_list(halfword p, int threshold, int max) } } if (box_shift_amount(p) != 0) { - tex_print_str(", shifted "); - tex_print_dimension(box_shift_amount(p), pt_unit); + tex_print_format(", shifted %D", box_shift_amount(p), pt_unit); } if (valid_direction(box_dir(p))) { tex_print_str(", direction "); @@ -2703,41 +2657,30 @@ void tex_show_node_list(halfword p, int threshold, int max) } } if (box_geometry(p)) { - tex_print_str(", geometry "); - tex_print_qhex(box_geometry(p)); + tex_print_format(", geometry %x", box_geometry(p)); if (tex_has_box_geometry(p, orientation_geometry)) { - tex_print_str(", orientation "); - tex_print_qhex(box_orientation(p)); + tex_print_format(", orientation %x", box_orientation(p)); } if (tex_has_box_geometry(p, offset_geometry)) { - tex_print_str(", offset("); - tex_print_dimension(box_x_offset(p), pt_unit); - tex_print_char(','); - tex_print_dimension(box_y_offset(p), pt_unit); - tex_print_char(')'); + tex_print_format(", offset(%D,%D)", box_x_offset(p), pt_unit, box_y_offset(p), pt_unit); } if (tex_has_box_geometry(p, anchor_geometry)) { if (box_anchor(p)) { - tex_print_str(", anchor "); - tex_print_qhex(box_anchor(p)); + tex_print_format(", anchor %x", box_anchor(p)); } if (box_source_anchor(p)) { - tex_print_str(", source "); - tex_print_int(box_source_anchor(p)); + tex_print_format(", source %i", box_source_anchor(p)); } if (box_target_anchor(p)) { - tex_print_str(", target "); - tex_print_int(box_target_anchor(p)); + tex_print_format(", target %i", box_target_anchor(p)); } } } if (box_index(p)) { - tex_print_str(", index "); - tex_print_int(box_index(p)); + tex_print_format(", index %i", box_index(p)); } if (box_package_state(p)) { - tex_print_str(", state "); - tex_print_int(box_package_state(p)); + tex_print_format(", state %i", box_package_state(p)); } } tex_print_node_list(box_pre_adjusted(p), "preadjusted", threshold, max); @@ -2749,59 +2692,50 @@ void tex_show_node_list(halfword p, int threshold, int max) case rule_node: /*tex Display rule |p|. */ if (rule_width(p)) { - tex_print_str(", width "); - tex_print_rule_dimen(rule_width(p)); + tex_print_format(", width %R", rule_width(p)); } if (rule_height(p)) { - tex_print_str(", height "); - tex_print_rule_dimen(rule_height(p)); + tex_print_format(", height %R", rule_height(p)); } if (rule_depth(p)) { - tex_print_str(", depth "); - tex_print_rule_dimen(rule_depth(p)); + tex_print_format(", depth %R", rule_depth(p)); } if (rule_left(p)) { - tex_print_str(", left / top "); - tex_print_rule_dimen(rule_left(p)); + tex_print_format(", left / top %R", rule_left(p)); } if (rule_right(p)) { - tex_print_str(", right / bottom "); - tex_print_rule_dimen(rule_right(p)); + tex_print_format(", right / bottom %R", rule_right(p)); } if (rule_x_offset(p)) { - tex_print_str(", xoffset "); - tex_print_rule_dimen(rule_x_offset(p)); + tex_print_format(", xoffset %R", rule_x_offset(p)); } if (rule_y_offset(p)) { - tex_print_str(", yoffset "); - tex_print_rule_dimen(rule_y_offset(p)); + tex_print_format(", yoffset %R", rule_y_offset(p)); } if (rule_font(p)) { if (rule_font(p) < 0 || rule_font(p) >= rule_font_fam_offset) { - tex_print_str(", font "); - tex_print_font_identifier(rule_font(p)); + tex_print_format(", font %F", rule_font(p)); } else { - tex_print_str(", family "); - tex_print_int(rule_font(p) - rule_font_fam_offset); + tex_print_format(", family %i", rule_font(p) - rule_font_fam_offset); } } if (rule_character(p)) { - tex_print_str(", character "); - tex_print_char_identifier(rule_character(p)); + tex_print_format(", character %U", rule_character(p)); } break; case insert_node: /*tex Display insertion |p|. The natural size is the sum of height and depth. */ - tex_print_str(", index "); - tex_print_int(insert_index(p)); - tex_print_str(", total height "); - tex_print_dimension(insert_total_height(p), pt_unit); - tex_print_str(", max depth "); - tex_print_dimension(insert_max_depth(p), pt_unit); - tex_print_str(", split glue ("); - tex_print_specnode(insert_split_top(p), no_unit); - tex_print_str("), float cost "); - tex_print_int(insert_float_cost(p)); + tex_print_format( + ", index %i, total height %D, max depth %D, split glue (", + insert_index(p), + insert_total_height(p), pt_unit, + insert_max_depth(p), pt_unit + ); + tex_print_specnode(insert_split_top(p), no_unit); /* todo: formatter for specnode but what CHAR to use */ + tex_print_format( + "), float cost %i", + insert_float_cost(p) + ); tex_print_node_list(insert_list(p), "list", threshold, max); break; case dir_node: @@ -2861,8 +2795,8 @@ void tex_show_node_list(halfword p, int threshold, int max) if (tex_par_state_is_set(p, par_shaping_penalty_code) ) { v = par_shaping_penalty(p) ; if (v > 0) { tex_print_str(", shapingpenalty "); tex_print_int (v); } } } /* local boxes */ - v = tex_get_local_left_width(p) ; if (v) { tex_print_str(", leftboxwidth "); tex_print_dimension(v, pt_unit); } - v = tex_get_local_right_width(p) ; if (v) { tex_print_str(", rightboxwidth "); tex_print_dimension(v, pt_unit); } + v = tex_get_local_left_width(p) ; if (v) { tex_print_format(", leftboxwidth %D", v, pt_unit); } + v = tex_get_local_right_width(p) ; if (v) { tex_print_format(", rightboxwidth %D", v, pt_unit); } tex_print_node_list(par_box_left(p), "leftbox", threshold, max); tex_print_node_list(par_box_right(p), "rightbox", threshold, max); tex_print_node_list(par_box_middle(p), "middlebox", threshold, max); @@ -2870,8 +2804,7 @@ void tex_show_node_list(halfword p, int threshold, int max) break; case boundary_node: if (boundary_data(p)) { - tex_print_str(", data "); - tex_print_int(boundary_data(p)); + tex_print_format(", data %i", boundary_data(p)); } break; case whatsit_node: @@ -2915,27 +2848,22 @@ void tex_show_node_list(halfword p, int threshold, int max) tex_print_specnode(p, node_subtype(p) < conditional_math_glue ? pt_unit : mu_unit); /* was |no_unit : mu_unit| */ } if (glue_data(p)) { - tex_print_str(", data "); - tex_print_int(glue_data(p)); + tex_print_format(", data %i", glue_data(p)); } if (node_subtype(p) == space_skip_glue && glue_font(p)) { - tex_print_str(", font "); - tex_print_int(glue_font(p)); + tex_print_format(", font %i", glue_font(p)); } } break; case kern_node: /*tex Display kern |p| */ - tex_print_str(", amount "); - tex_print_dimension(kern_amount(p), pt_unit); if (node_subtype(p) != explicit_math_kern_subtype) { - tex_print_unit(pt_unit); + tex_print_format(", amount %D", kern_amount(p), pt_unit); if (kern_expansion(p)) { - tex_print_str(", expansion "); - tex_print_int(kern_expansion(p)); + tex_print_format(", expansion %i", kern_expansion(p)); } } else { - tex_print_unit(mu_unit); + tex_print_format(", amount %D", kern_amount(p), mu_unit); } break; case math_node: @@ -2944,38 +2872,31 @@ void tex_show_node_list(halfword p, int threshold, int max) tex_print_str(", glued "); tex_print_specnode(p, no_unit); } else if (math_surround(p)) { - tex_print_str(", surrounded "); - tex_print_dimension(math_surround(p), pt_unit); + tex_print_format(", surrounded %D", math_surround(p), pt_unit); } if (math_penalty(p)) { - tex_print_str(", penalty "); - tex_print_int(math_penalty(p)); + tex_print_format(", penalty %i", math_penalty(p)); } break; case penalty_node: /*tex Display penalty |p|. */ - tex_print_str(", amount "); - tex_print_int(penalty_amount(p)); + tex_print_format(", amount %i", penalty_amount(p)); break; case disc_node: if (disc_class(p) != unset_disc_class) { - tex_print_str(", class "); - tex_print_int(disc_class(p)); + tex_print_format(", class %i", disc_class(p)); } if (disc_options(p)) { - tex_print_str(", options "); - tex_print_qhex(disc_options(p)); + tex_print_format(", options %x", disc_options(p)); } - tex_print_str(", penalty "); - tex_print_int(disc_penalty(p)); + tex_print_format(", penalty %i", disc_penalty(p)); tex_print_node_list(disc_pre_break_head(p), "prebreaklist", threshold, max); tex_print_node_list(disc_post_break_head(p), "postbreaklist", threshold, max); tex_print_node_list(disc_no_break_head(p), "nobreaklist", threshold, max); break; case mark_node: /*tex Display mark |p|. */ - tex_print_str(", index "); - tex_print_int(mark_index(p)); + tex_print_format(", index %i", mark_index(p)); if (node_subtype(p) == reset_mark_value_code) { tex_print_str(", reset"); } else { @@ -2985,20 +2906,16 @@ void tex_show_node_list(halfword p, int threshold, int max) case adjust_node: /*tex Display adjustment |p|. */ if (adjust_options(p)) { - tex_print_str(", options "); - tex_print_qhex(adjust_options(p)); + tex_print_format(", options %x", adjust_options(p)); } if (adjust_index(p)) { - tex_print_str(", index "); - tex_print_int(adjust_index(p)); + tex_print_format(", index %i", adjust_index(p)); } if (has_adjust_option(p, adjust_option_depth_before) && adjust_depth_before(p)) { - tex_print_str(", depthbefore "); - tex_print_dimension(adjust_depth_before(p), pt_unit); + tex_print_format(", depthbefore %D", adjust_depth_before(p), pt_unit); } if (has_adjust_option(p, adjust_option_depth_after) &&adjust_depth_before(p)) { - tex_print_str(", depthafter "); - tex_print_dimension(adjust_depth_after(p), pt_unit); + tex_print_format(", depthafter %D", adjust_depth_after(p), pt_unit); } tex_print_node_list(adjust_list(p), "list", threshold, max); break; diff --git a/source/luametatex/source/tex/texnodes.h b/source/luametatex/source/tex/texnodes.h index f0d20e1e9..a20117ff8 100644 --- a/source/luametatex/source/tex/texnodes.h +++ b/source/luametatex/source/tex/texnodes.h @@ -1588,8 +1588,11 @@ typedef enum simple_choice_subtypes { \LL \stoptabulate - We can use smaller variables for style and class and then have one field available for - other usage so no need to grow. + We can use smaller variables for style and class and then have one field available for other + usage so no need to grow. + + As with other nodes, not all fields are used and|/|or can be set at the tex end but they are + available for usage at the \LUA\ end. Some have been used for experiments and stay around. */ @@ -1680,6 +1683,7 @@ typedef struct noad_classes { noad_class_main(n) = (singleword) unset_noad_class; \ noad_class_left(n) = (singleword) unset_noad_class; \ noad_class_right(n) = (singleword) unset_noad_class; \ + noad_analyzed(n) = (singleword) unset_noad_class; \ } while (0); # define set_noad_classes(n,c) do { \ @@ -1740,8 +1744,7 @@ typedef enum noad_options { noad_option_auto = 0x10000000, noad_option_unroll_list = 0x20000000, noad_option_followed_by_space = 0x40000000, - /* available: */ - noad_option_reserved = 0x80000000, + noad_option_proportional = 0x80000000, } noad_options; # define has_option(a,b) (((a) & (b)) == (b)) @@ -1796,6 +1799,7 @@ inline int has_noad_no_script_option(halfword n, halfword option) # define has_noad_option_void(a) (has_option(noad_options(a), noad_option_void)) # define has_noad_option_unrolllist(a) (has_option(noad_options(a), noad_option_unroll_list)) # define has_noad_option_followedbyspace(a) (has_option(noad_options(a), noad_option_followed_by_space)) +# define has_noad_option_proportional(a) (has_option(noad_options(a), noad_option_proportional)) /*tex In the meantime the codes and subtypes are in sync. The variable component does not really @@ -1995,6 +1999,9 @@ typedef enum math_kernel_options { math_kernel_no_right_pair_kern = 0x0004, math_kernel_auto_discretionary = 0x0008, math_kernel_full_discretionary = 0x0010, + math_kernel_ignored_character = 0x0020, + math_kernel_is_large_operator = 0x0040, + math_kernel_has_italic_shape = 0x0080, } math_kernel_options; # define math_kernel_node_size 5 @@ -2494,7 +2501,7 @@ inline static void tex_attach_attribute_list_attribute(halfword target, halfword if (is_global(a)) { \ int i; \ for (i = (lmt_save_state.save_stack_data.ptr - 1); i >= 0; i--) { \ - if (save_type(i) == saved_attribute_list) { \ + if (save_type(i) == attribute_list_save_type) { \ delete_attribute_reference(save_value(i)); \ save_value(i) = attribute_cache_disabled; \ } \ @@ -2508,7 +2515,7 @@ inline static void tex_attach_attribute_list_attribute(halfword target, halfword # define save_attribute_state_before() do { \ halfword c = current_attribute_state; \ - tex_set_saved_record(saved_attribute_item_list, saved_attribute_list, 0, c); \ + tex_set_saved_record(saved_attribute_item_list, attribute_list_save_type, 0, c); \ lmt_save_state.save_stack_data.ptr += saved_attribute_n_of_items; \ add_attribute_reference(c); \ } while (0) diff --git a/source/luametatex/source/tex/texpackaging.c b/source/luametatex/source/tex/texpackaging.c index 5942c1365..b2286cd71 100644 --- a/source/luametatex/source/tex/texpackaging.c +++ b/source/luametatex/source/tex/texpackaging.c @@ -300,35 +300,35 @@ static void tex_aux_scan_full_spec(quarterword c, quarterword spec_direction, in /*tex Now we're referenced. We need to preserve this over the group. */ add_attribute_reference(attrlist); /* */ - tex_set_saved_record(saved_full_spec_item_context, saved_box_context, 0, context); + tex_set_saved_record(saved_full_spec_item_context, box_context_save_type, 0, context); /*tex Traditionally these two are packed into one record: */ - tex_set_saved_record(saved_full_spec_item_packaging, saved_box_spec, spec_code, spec_amount); + tex_set_saved_record(saved_full_spec_item_packaging, box_spec_save_type, spec_code, spec_amount); /*tex Adjust |text_dir_ptr| for |scan_spec|: */ if (spec_direction != direction_unknown) { - tex_set_saved_record(saved_full_spec_item_direction, saved_box_direction, spec_direction, lmt_dir_state.text_dir_ptr); + tex_set_saved_record(saved_full_spec_item_direction, box_direction_save_type, spec_direction, lmt_dir_state.text_dir_ptr); lmt_dir_state.text_dir_ptr = tex_new_dir(normal_dir_subtype, spec_direction); } else { - tex_set_saved_record(saved_full_spec_item_direction, saved_box_direction, spec_direction, null); + tex_set_saved_record(saved_full_spec_item_direction, box_direction_save_type, spec_direction, null); } /* We could pack some in one record. */ - tex_set_saved_record(saved_full_spec_item_attr_list, saved_box_attr_list, 0, attrlist); - tex_set_saved_record(saved_full_spec_item_only_pack, saved_box_pack, 0, just_pack); - tex_set_saved_record(saved_full_spec_item_orientation, saved_box_orientation, 0, orientation); - tex_set_saved_record(saved_full_spec_item_anchor, saved_box_anchor, 0, anchor); - tex_set_saved_record(saved_full_spec_item_geometry, saved_box_geometry, 0, geometry); - tex_set_saved_record(saved_full_spec_item_xoffset, saved_box_xoffset, 0, xoffset); - tex_set_saved_record(saved_full_spec_item_yoffset, saved_box_yoffset, 0, yoffset); - tex_set_saved_record(saved_full_spec_item_xmove, saved_box_xmove, 0, xmove); - tex_set_saved_record(saved_full_spec_item_ymove, saved_box_ymove, 0, ymove); - tex_set_saved_record(saved_full_spec_item_reverse, saved_box_reverse, 0, reverse); - tex_set_saved_record(saved_full_spec_item_container, saved_box_container, 0, container); - tex_set_saved_record(saved_full_spec_item_shift, saved_box_shift, 0, shift); - tex_set_saved_record(saved_full_spec_item_source, saved_box_source, 0, source); - tex_set_saved_record(saved_full_spec_item_target, saved_box_target, 0, target); - tex_set_saved_record(saved_full_spec_item_axis, saved_box_axis, 0, axis); - tex_set_saved_record(saved_full_spec_item_class, saved_box_class, 0, mainclass); - tex_set_saved_record(saved_full_spec_item_state, saved_box_state, 0, state); - tex_set_saved_record(saved_full_spec_item_retain, saved_box_retain, 0, retain); + tex_set_saved_record(saved_full_spec_item_attr_list, box_attr_list_save_type, 0, attrlist); + tex_set_saved_record(saved_full_spec_item_only_pack, box_pack_save_type, 0, just_pack); + tex_set_saved_record(saved_full_spec_item_orientation, box_orientation_save_type, 0, orientation); + tex_set_saved_record(saved_full_spec_item_anchor, box_anchor_save_type, 0, anchor); + tex_set_saved_record(saved_full_spec_item_geometry, box_geometry_save_type, 0, geometry); + tex_set_saved_record(saved_full_spec_item_xoffset, box_xoffset_save_type, 0, xoffset); + tex_set_saved_record(saved_full_spec_item_yoffset, box_yoffset_save_type, 0, yoffset); + tex_set_saved_record(saved_full_spec_item_xmove, box_xmove_save_type, 0, xmove); + tex_set_saved_record(saved_full_spec_item_ymove, box_ymove_save_type, 0, ymove); + tex_set_saved_record(saved_full_spec_item_reverse, box_reverse_save_type, 0, reverse); + tex_set_saved_record(saved_full_spec_item_container, box_container_save_type, 0, container); + tex_set_saved_record(saved_full_spec_item_shift, box_shift_save_type, 0, shift); + tex_set_saved_record(saved_full_spec_item_source, box_source_save_type, 0, source); + tex_set_saved_record(saved_full_spec_item_target, box_target_save_type, 0, target); + tex_set_saved_record(saved_full_spec_item_axis, box_axis_save_type, 0, axis); + tex_set_saved_record(saved_full_spec_item_class, box_class_save_type, 0, mainclass); + tex_set_saved_record(saved_full_spec_item_state, box_state_save_type, 0, state); + tex_set_saved_record(saved_full_spec_item_retain, box_retain_save_type, 0, retain); lmt_save_state.save_stack_data.ptr += saved_full_spec_n_of_items; tex_new_save_level(c); if (! brace) { @@ -2287,13 +2287,13 @@ halfword tex_vpack(halfword p, scaled h, int m, scaled l, singleword pack_direct return r; } -halfword tex_filtered_vpack(halfword p, scaled h, int m, scaled l, int grp, halfword pack_direction, int just_pack, halfword attr, int state, int retain) +halfword tex_filtered_vpack(halfword p, scaled h, int m, scaled maxdepth, int grp, halfword direction, int just_pack, halfword attr, int state, int retain) { halfword q = p; if (! just_pack) { - q = lmt_vpack_filter_callback(q, h, m, l, grp, pack_direction, attr); + q = lmt_vpack_filter_callback(q, h, m, maxdepth, grp, direction, attr); } - q = tex_vpack(q, h, m, l, checked_direction_value(pack_direction), retain); + q = tex_vpack(q, h, m, maxdepth, checked_direction_value(direction), retain); if (q && normalize_par_mode_permitted(normalize_par_mode_par, flatten_v_leaders_mode) && ! is_box_package_state(state, package_u_leader_delayed)) { tex_flatten_leaders(q, NULL); } @@ -2376,7 +2376,7 @@ void tex_package(singleword nature) halfword context, spec, dirptr, attrlist, justpack, orientation, anchor, geometry, source, target, axis, mainclass, state, retain; scaled shift; int grp = cur_group; - scaled d = box_max_depth_par; + scaled maxdepth = box_max_depth_par; halfword boxnode = null; /*tex Aka |cur_box|. */ tex_unsave(); lmt_save_state.save_stack_data.ptr -= saved_full_spec_n_of_items; @@ -2405,7 +2405,7 @@ void tex_package(singleword nature) box_package_state(boxnode) = hbox_package_state; } else { boxnode = tex_filtered_vpack(node_next(cur_list.head), spec, saved_level(saved_full_spec_item_packaging), - d, grp, saved_level(saved_full_spec_item_direction), justpack, attrlist, state, retain); + maxdepth, grp, saved_level(saved_full_spec_item_direction), justpack, attrlist, state, retain); if (nature == vtop_code) { /*tex @@ -2414,21 +2414,21 @@ void tex_package(singleword nature) |hlist_node|, |vlist_node|, or |rule_node|; otherwise the |\vtop| height is zero. */ - scaled h = 0; - halfword p = box_list(boxnode); - if (p) { - switch (node_type(p)) { + scaled height = 0; + halfword list = box_list(boxnode); + if (list) { + switch (node_type(list)) { case hlist_node: case vlist_node: - h = box_height(p); + height = box_height(list); break; case rule_node: - h = rule_height(p); + height = rule_height(list); break; } } - box_depth(boxnode) = box_total(boxnode) - h; - box_height(boxnode) = h; + box_depth(boxnode) = box_total(boxnode) - height; + box_height(boxnode) = height; box_package_state(boxnode) = vtop_package_state; } else { box_package_state(boxnode) = vbox_package_state; @@ -3360,7 +3360,7 @@ void tex_begin_box(int boxcontext, scaled shift) break; } mode = code - vtop_code; - tex_set_saved_record(saved_full_spec_item_context, saved_box_context, 0, boxcontext); + tex_set_saved_record(saved_full_spec_item_context, box_context_save_type, 0, boxcontext); switch (abs(cur_list.mode)) { case vmode: spec_direction = dir_lefttoright; diff --git a/source/luametatex/source/tex/texpackaging.h b/source/luametatex/source/tex/texpackaging.h index 75d3d1653..b96d31353 100644 --- a/source/luametatex/source/tex/texpackaging.h +++ b/source/luametatex/source/tex/texpackaging.h @@ -114,7 +114,7 @@ extern scaled tex_left_marginkern (halfword p); extern scaled tex_right_marginkern (halfword p); extern halfword tex_filtered_hpack (halfword p, halfword qt, scaled w, int m, int grp, halfword d, int just_pack, halfword attr, int state, int retain); -extern halfword tex_filtered_vpack (halfword p, scaled h, int m, scaled l, int grp, halfword d, int just_pack, halfword attr, int state, int retain); +extern halfword tex_filtered_vpack (halfword p, scaled h, int m, scaled maxdepth, int grp, halfword direction, int just_pack, halfword attr, int state, int retain); extern scaledwhd tex_natural_hsizes (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order); extern scaledwhd tex_natural_vsizes (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order); diff --git a/source/luametatex/source/tex/texprinting.c b/source/luametatex/source/tex/texprinting.c index 005c2a3c8..9a7c1d729 100644 --- a/source/luametatex/source/tex/texprinting.c +++ b/source/luametatex/source/tex/texprinting.c @@ -150,48 +150,6 @@ void tex_print_ln(void) */ -// void tex_print_char(int s) -// { -// if (s < 0 || s > 255) { -// tex_formatted_warning("print", "weird character %i", s); -// } else if (s == new_line_char_par && (lmt_print_state.selector < pseudo_selector_code)) { -// tex_print_ln(); -// } else { -// switch (lmt_print_state.selector) { -// case no_print_selector_code: -// break; -// case terminal_selector_code: -// fputc(s, stdout); -// ++lmt_print_state.terminal_offset; -// break; -// case logfile_selector_code: -// fputc(s, lmt_print_state.logfile); -// ++lmt_print_state.logfile_offset; -// break; -// case terminal_and_logfile_selector_code: -// fputc(s, stdout); -// fputc(s, lmt_print_state.logfile); -// ++lmt_print_state.terminal_offset; -// ++lmt_print_state.logfile_offset; -// break; -// case pseudo_selector_code: -// if (lmt_print_state.tally < lmt_print_state.trick_count) { -// lmt_print_state.trick_buffer[lmt_print_state.tally % lmt_error_state.line_limits.size] = (unsigned char) s; -// } -// ++lmt_print_state.tally; -// break; -// case new_string_selector_code: -// tex_append_char((unsigned char) s); -// break; -// case luabuffer_selector_code: -// lmt_char_to_buffer((char) s); -// break; -// default: -// break; -// } -// } -// } - void tex_print_char(int s) { if (s < 0 || s > 255) { @@ -462,7 +420,7 @@ void tex_print_banner(void) stdout, "%s %s\n", lmt_engine_state.luatex_banner, - str_string(lmt_dump_state.format_identifier) + lmt_engine_state.dump_name ); } @@ -470,13 +428,12 @@ void tex_print_log_banner(void) { fprintf( lmt_print_state.logfile, - "engine: %s, format id: %s, time stamp: %d-%d-%d %d:%d, startup file: %s, job name: %s, dump name: %s", + "engine: %s, format id: %s, time stamp: %d-%d-%d %d:%d, startup file: %s, job name: %s", lmt_engine_state.luatex_banner, - str_string(lmt_dump_state.format_identifier), + lmt_engine_state.dump_name, year_par, month_par > 12 ? 0 : month_par, day_par, time_par / 60, time_par % 60, lmt_engine_state.startup_filename ? lmt_engine_state.startup_filename : "-", - lmt_engine_state.startup_jobname ? lmt_engine_state.startup_jobname : "-", - lmt_engine_state.dump_name ? lmt_engine_state.dump_name : "-" + lmt_engine_state.startup_jobname ? lmt_engine_state.startup_jobname : "-" ); } @@ -518,29 +475,6 @@ void tex_print_str_esc(const char *s) } } -/*tex - An array of digits in the range |0..15| is printed by |print_the_digs|. These digits are in the - reverse order: |dig[k-1]|$\,\ldots\,$|dig[0]|! -*/ - -// inline static void tex_print_decimal_digits(const unsigned char *digits, int k) -// { -// while (k-- > 0) { -// tex_print_char('0' + digits[k]); -// } -// } - -// inline static void tex_print_hexadecimal_digits(const unsigned char *digits, int k) -// { -// while (k-- > 0) { -// if (digits[k] < 10) { -// tex_print_char('0' + digits[k]); -// } else { -// tex_print_char('A' - 10 + digits[k]); -// } -// } -// } - /*tex The following procedure, which prints out the decimal representation of a given integer |n|, @@ -550,28 +484,6 @@ void tex_print_str_esc(const char *s) */ -// void tex_print_int(int n) -// { -// /*tex In the end a 0..9 fast path works out best. */ -// if (n >= 0 && n <= 9) { -// tex_print_char('0' + n); -// } else { -// /*tex index to current digit; we assume that $|n|<10^{23}$ */ -// int k = 0; -// unsigned char digits[24]; -// if (n < 0) { -// tex_print_char('-'); -// n = -n; -// } -// do { -// digits[k] = (unsigned char) (n % 10); -// n = n / 10; -// ++k; -// } while (n != 0); -// tex_print_decimal_digits(digits, k); -// } -// } - void tex_print_int(int n) { /*tex In the end a 0..9 fast path works out best; using |sprintf| is slower. */ @@ -695,19 +607,6 @@ void tex_print_sparse_dimension(scaled s, int unit) as an unsigned. */ -// void tex_print_hex(int n) -// { -// /*tex index to current digit; we assume that $0\L n<16^{22}$ */ -// int k = 0 ; -// unsigned char digits[24]; -// do { -// digits[k] = n % 16; -// n = n / 16; -// ++k; -// } while (n != 0); -// tex_print_hexadecimal_digits(digits, k); -// } - void tex_print_hex(int sn) { unsigned int n = (unsigned int) sn; @@ -989,6 +888,9 @@ void tex_print_mathspec(int p) 6 <id: bar @ ..> xyz \stoptyping + This is no longer the case: we now always print a full specification. The |\tracingfonts| + register will be dropped. + */ void tex_print_char_identifier(halfword c) // todo: use string_print_format @@ -1249,21 +1151,19 @@ void tex_print_levels(void) */ -extern void tex_print_format(const char *format, ...) +const char *tex_print_format_args(const char *format, va_list args) { - va_list args; - va_start(args, format); /* hm, weird, no number */ while (1) { int chr = *format++; switch (chr) { case '\0': - goto DONE; + return va_arg(args, char *); case '%': { chr = *format++; switch (chr) { case '\0': - goto DONE; + return va_arg(args, char *); case 'c': tex_print_char(va_arg(args, int)); break; @@ -1384,6 +1284,19 @@ extern void tex_print_format(const char *format, ...) } break; } + case 'Q': + { + scaled s = va_arg(args, scaled); + int u = va_arg(args, int); + tex_print_spec(s, u); + break; + } + case 'R': + { + halfword d = va_arg(args, int); + tex_print_rule_dimen(d); + break; + } case 'S': { halfword cs = va_arg(args, int); @@ -1424,13 +1337,19 @@ extern void tex_print_format(const char *format, ...) break; } } - DONE: +} + +void tex_print_format(const char *format, ...) +{ + va_list args; + va_start(args, format); /* hm, weird, no number */ + tex_print_format_args(format, args); va_end(args); } /*tex - Group codes were introcued in \ETEX\ but have been extended in the meantime in \LUATEX\ and + Group codes were introduced in \ETEX\ but have been extended in the meantime in \LUATEX\ and later again in \LUAMETATEX. We might have (even) more granularity in the future. Todo: combine this with an array of struct(id,name,lua) ... a rainy day + stack of new cd's job. diff --git a/source/luametatex/source/tex/texprinting.h b/source/luametatex/source/tex/texprinting.h index 61b7e45a2..b323b1ae5 100644 --- a/source/luametatex/source/tex/texprinting.h +++ b/source/luametatex/source/tex/texprinting.h @@ -50,64 +50,47 @@ typedef enum spec_units { */ -extern void tex_print_ln (void); /* always forces a newline */ -extern void tex_print_char (int s); -extern void tex_print_tex_str (int s); -extern void tex_print_tex_str_esc (strnumber s); -extern void tex_print_nlp (void); /* flushes a line if we're doing one */ -extern void tex_print_banner (void); -extern void tex_print_log_banner (void); -extern void tex_print_version_banner (void); -////// void tex_print_digits (const unsigned char *digits, int k); -extern void tex_print_int (int n); -extern void tex_print_hex (int n); -extern void tex_print_uhex (int n); -extern void tex_print_qhex (int n); -extern void tex_print_roman_int (int n); -extern void tex_print_current_string (void); -extern void tex_print_cs_checked (halfword p); /*tex Also does the |IMPOSSIBLE| etc. */ -extern void tex_print_cs (halfword p); /*tex Only does the undefined case. */ -extern void tex_print_cs_name (halfword p); /*tex Only prints known ones. */ -extern void tex_print_str (const char *s); -extern void tex_print_str_esc (const char *s); -extern void tex_print_dimension (scaled d, int unit); /*tex prints a dimension with pt */ -extern void tex_print_sparse_dimension (scaled d, int unit); /*tex prints a dimension with pt */ -extern void tex_print_unit (int unit); /*tex prints a glue component */ -extern void tex_print_glue (scaled d, int order, int unit); /*tex prints a glue component */ -extern void tex_print_spec (int p, int unit); /*tex prints a glue specification */ -extern void tex_print_fontspec (int p); -extern void tex_print_mathspec (int p); -extern void tex_print_font_identifier (halfword f); -extern void tex_print_font_specifier (halfword e); /*tex this is an eq table entry */ -extern void tex_print_font (halfword f); -extern void tex_print_char_identifier (halfword c); -extern void tex_print_token_list (const char *s, halfword p); /*tex prints token list data in braces */ -extern void tex_print_rule_dimen (scaled d); /*tex prints dimension in rule node */ -extern void tex_print_group (int e); -extern void tex_print_format (const char *format, ...); /*tex similar to the one we use for errors */ -extern void tex_begin_diagnostic (void); -extern void tex_print_levels (void); -extern void tex_end_diagnostic (void); -extern void tex_show_box (halfword p); -extern void tex_short_display (halfword p); /*tex prints highlights of list |p| */ - -extern void tex_print_message (const char *s); - - -/* -# define single_letter(A) \ - ((str_length(A)==1)|| \ - ((str_length(A)==4)&&*(str_string(A))>=0xF0)|| \ - ((str_length(A)==3)&&*(str_string(A))>=0xE0)|| \ - ((str_length(A)==2)&&*(str_string(A))>=0xC0)) - -# define is_active_cs(a) \ - (a && str_length(a)>3 && \ - ( *str_string(a) == 0xEF) && \ - (*(str_string(a)+1) == 0xBF) && \ - (*(str_string(a)+2) == 0xBF)) - -*/ +extern void tex_print_ln (void); /* always forces a newline */ +extern void tex_print_char (int s); +extern void tex_print_tex_str (int s); +extern void tex_print_tex_str_esc (strnumber s); +extern void tex_print_nlp (void); /* flushes a line if we're doing one */ +extern void tex_print_banner (void); +extern void tex_print_log_banner (void); +extern void tex_print_version_banner (void); +extern void tex_print_int (int n); +extern void tex_print_hex (int n); +extern void tex_print_uhex (int n); +extern void tex_print_qhex (int n); +extern void tex_print_roman_int (int n); +extern void tex_print_current_string (void); +extern void tex_print_cs_checked (halfword p); /*tex Also does the |IMPOSSIBLE| etc. */ +extern void tex_print_cs (halfword p); /*tex Only does the undefined case. */ +extern void tex_print_cs_name (halfword p); /*tex Only prints known ones. */ +extern void tex_print_str (const char *s); +extern void tex_print_str_esc (const char *s); +extern void tex_print_dimension (scaled d, int unit); /*tex prints a dimension with pt */ +extern void tex_print_sparse_dimension (scaled d, int unit); /*tex prints a dimension with pt */ +extern void tex_print_unit (int unit); /*tex prints a glue component */ +extern void tex_print_glue (scaled d, int order, int unit); /*tex prints a glue component */ +extern void tex_print_spec (int p, int unit); /*tex prints a glue specification */ +extern void tex_print_fontspec (int p); +extern void tex_print_mathspec (int p); +extern void tex_print_font_identifier (halfword f); +extern void tex_print_font_specifier (halfword e); /*tex this is an eq table entry */ +extern void tex_print_font (halfword f); +extern void tex_print_char_identifier (halfword c); +extern void tex_print_token_list (const char *s, halfword p); /*tex prints token list data in braces */ +extern void tex_print_rule_dimen (scaled d); /*tex prints dimension in rule node */ +extern void tex_print_group (int e); +extern void tex_print_format (const char *format, ...); /*tex similar to the one we use for errors */ +extern const char *tex_print_format_args (const char *format, va_list args); +extern void tex_begin_diagnostic (void); +extern void tex_print_levels (void); +extern void tex_end_diagnostic (void); +extern void tex_show_box (halfword p); +extern void tex_short_display (halfword p); /*tex prints highlights of list |p| */ +extern void tex_print_message (const char *s); inline static int tex_single_letter(strnumber s) { diff --git a/source/luametatex/source/tex/texscanning.c b/source/luametatex/source/tex/texscanning.c index 8f2dfa050..5dd34b3b6 100644 --- a/source/luametatex/source/tex/texscanning.c +++ b/source/luametatex/source/tex/texscanning.c @@ -168,60 +168,44 @@ inline static void tex_aux_downgrade_cur_val(int level, int succeeded, int negat and they don't downgrade, nor negate which saves a little testing. */ break; - // case int_val_level: - // case attr_val_level: - // case dimen_val_level: - // while (cur_val_level > level) { - // --cur_val_level; - // } - // if (negative) { - // negate(cur_val); - // } - // break; - // case glue_val_level: - // case mu_val_level: - // while (cur_val_level > level) { - // tex_aux_downgrade_cur_val(); /* cleaner is inline */ - // } - // if (succeeded == 1) { - // cur_val = new_glue_spec_node(cur_val); - // } - // if (negative) { - // negate(glue_amount(cur_val)); - // negate(glue_stretch(cur_val)); - // negate(glue_shrink(cur_val)); - // } - // break; - // default: - // /* this can't happen */ - // return 0; - default: - /*tex There is no real need for it being a loop, a test would do. */ - while (cur_val_level > level) { - /*tex Convert |cur_val| to a lower level. */ - switch (cur_val_level) { - case glue_val_level: - cur_val = glue_amount(cur_val); - break; - case mu_val_level : - tex_aux_mu_error(1); - break; - } - --cur_val_level; - } - if (cur_val_level == glue_val_level || cur_val_level == mu_val_level) { - if (succeeded == 1) { - cur_val = tex_new_glue_spec_node(cur_val); - } - if (negative) { - glue_amount(cur_val) = -glue_amount(cur_val); - glue_stretch(cur_val) = -glue_stretch(cur_val); - glue_shrink(cur_val) = -glue_shrink(cur_val); - } - } else if (negative) { - cur_val = -cur_val; - } - break; + case int_val_level: + case attr_val_level: + case dimen_val_level: + while (cur_val_level > level) { + --cur_val_level; + } + if (negative) { + cur_val = -cur_val; + } + break; + default: + /*tex There is no real need for it being a loop, a test would do. */ + while (cur_val_level > level) { + /*tex Convert |cur_val| to a lower level. */ + switch (cur_val_level) { + case glue_val_level: + case mu_val_level : + cur_val = glue_amount(cur_val); + break; + // case mu_val_level : + // tex_aux_mu_error(1); + // break; + } + --cur_val_level; + } + if (cur_val_level == glue_val_level || cur_val_level == mu_val_level) { + if (succeeded == 1) { + cur_val = tex_new_glue_spec_node(cur_val); + } + if (negative) { + glue_amount(cur_val) = -glue_amount(cur_val); + glue_stretch(cur_val) = -glue_stretch(cur_val); + glue_shrink(cur_val) = -glue_shrink(cur_val); + } + } else if (negative) { + cur_val = -cur_val; + } + break; } } @@ -1077,12 +1061,10 @@ static void tex_aux_set_cur_val_by_define_char_cmd(int chr) break; case mathcode_charcode: case extmathcode_charcode: - /* case extmathcodenum_charcode: */ chr = tex_get_math_code_number(index); break; case delcode_charcode: case extdelcode_charcode: - /* case extdelcodenum_charcode: */ chr = tex_get_del_code_number(index); break; default: @@ -1358,7 +1340,6 @@ static halfword tex_aux_scan_something_internal(halfword cmd, halfword chr, int if (tex_aux_valid_tok_level(level)) { cur_val = cur_chr; cur_val_level = font_val_level; - /* set_font_touched(cur_chr, 1); */ return cur_val; } else { break; @@ -3280,7 +3261,6 @@ halfword tex_scan_font_identifier(halfword *spec) case define_font_cmd: return cur_font_par; case set_font_cmd: - /* set_font_touched(cur_chr, 1); */ return cur_chr; case fontspec_cmd: { @@ -3295,7 +3275,6 @@ halfword tex_scan_font_identifier(halfword *spec) halfword siz = cur_chr; halfword fam = tex_scan_math_family_number(); halfword fnt = tex_fam_fnt(fam, siz); - /* set_font_touched(fnt, 1); */ return fnt; } case register_int_cmd: diff --git a/source/luametatex/source/tex/textoken.c b/source/luametatex/source/tex/textoken.c index 0d2415233..0bb0f3e45 100644 --- a/source/luametatex/source/tex/textoken.c +++ b/source/luametatex/source/tex/textoken.c @@ -169,7 +169,7 @@ void tex_compact_tokens(void) memset((void *) mapper, -1, ((size_t) lmt_token_memory_state.tokens_data.allocated) * sizeof(halfword)); memoryword *tokens = lmt_token_memory_state.tokens; /* also reset available */ - for (int cs = 0; cs < (eqtb_size + lmt_hash_state.hash_data.ptr); cs++) { + for (int cs = 0; cs < (eqtb_size + lmt_hash_state.hash_data.ptr + 1); cs++) { switch (eq_type(cs)) { case call_cmd: case protected_call_cmd: @@ -2114,27 +2114,24 @@ halfword tex_string_to_toks(const char *ss) |lua_str_toks| is almost identical, but it also escapes the three symbols that \LUA\ considers special while scanning a literal string. - - This changes the string |str_pool[b .. pool_ptr]| to a token list: - */ static halfword lmt_str_toks(lstring b) /* returns head */ { - /*tex index into string */ unsigned char *k = (unsigned char *) b.s; - /*tex tail of the token list */ - halfword h = null; - halfword p = null; + halfword head = null; + halfword tail = head; while (k < (unsigned char *) b.s + b.l) { - /*tex token being appended */ halfword t = aux_str2uni(k); k += utf8_size(t); if (t == ' ') { t = space_token; } else { if ((t == '\\') || (t == '"') || (t == '\'') || (t == 10) || (t == 13)) { - p = tex_store_new_token(p, escape_token); + tail = tex_store_new_token(tail, escape_token); + if (! head) { + head = tail; + } if (t == 10) { t = 'n'; } else if (t == 13) { @@ -2143,12 +2140,12 @@ static halfword lmt_str_toks(lstring b) /* returns head */ } t += other_token; } - p = tex_store_new_token(p, t); - if (! h) { - h = p; + tail = tex_store_new_token(tail, t); + if (! head) { + head = tail; } } - return h; + return head; } /*tex @@ -2801,20 +2798,36 @@ void tex_run_convert_tokens(halfword code) break; } case lua_escape_string_code: + /* case lua_token_string_code: */ /* for now rejected: could also be keyword */ { - lstring escstr; - int l = 0; - int e = lmt_token_state.in_lua_escape; + /* tex + If I would need it I could probably add support for catcode tables and verbose + serialization. Maybe we can use some of the other (more efficient) helpers when + we have a detokenize variant. We make sure that the escape character is a + backslash because these conversions can occur anywhere and are very much + related to \LUA\ calls. (Maybe it makes sense to pass it a argument to the + serializer.) + + A |\luatokenstring| primitive doesn't really make sense because \LUATEX\ lacks + it and |\luaescapestring| is a compatibility primitive. + */ + lstring str; + int length = 0; + int saved_in_lua_escape = lmt_token_state.in_lua_escape; + halfword saved_escape_char = escape_char_par; full_scanner_status saved_full_status = tex_save_full_scanner_status(); - halfword result = tex_scan_toks_expand(0, NULL, 0); + halfword result = tex_scan_toks_expand(0, NULL, 0); + /* halfword result = tex_scan_toks_expand(0, NULL, code == lua_token_string_code); */ lmt_token_state.in_lua_escape = 1; - escstr.s = (unsigned char *) tex_tokenlist_to_tstring(result, 0, &l, 0, 0, 0); - escstr.l = (unsigned) l; - lmt_token_state.in_lua_escape = e; + escape_char_par = '\\'; + str.s = (unsigned char *) tex_tokenlist_to_tstring(result, 0, &length, 0, 0, 0); + str.l = (unsigned) length; + lmt_token_state.in_lua_escape = saved_in_lua_escape; + escape_char_par = saved_escape_char; tex_delete_token_reference(result); /* boils down to flush_list */ tex_unsave_full_scanner_status(saved_full_status); - if (escstr.l) { - result = lmt_str_toks(escstr); + if (str.l) { + result = lmt_str_toks(str); tex_begin_inserted_list(result); } return; @@ -2855,7 +2868,7 @@ void tex_run_convert_tokens(halfword code) tex_open_log_file(); } push_selector; - tex_print_tex_str(lmt_dump_state.format_name); + tex_print_str(lmt_engine_state.dump_name); pop_selector; break; } @@ -2937,7 +2950,7 @@ strnumber tex_the_convert_string(halfword c, int i) tex_aux_print_job_name(); break; case format_name_code: - tex_print_tex_str(lmt_dump_state.format_name); + tex_print_str(lmt_engine_state.dump_name); break; case luatex_banner_code: tex_print_str(lmt_engine_state.luatex_banner); diff --git a/source/luametatex/source/utilities/auxfile.c b/source/luametatex/source/utilities/auxfile.c index 1aae0e691..0021cb229 100644 --- a/source/luametatex/source/utilities/auxfile.c +++ b/source/luametatex/source/utilities/auxfile.c @@ -254,16 +254,6 @@ } } - // int aux_is_readable(const char *filename) - // { - // struct stat finfo; - // FILE *f; - // return (stat(filename, &finfo) == 0) - // && S_ISREG(finfo.st_mode) - // && ((f = aux_utf8_fopen(filename, "r")) != NULL) - // && ! fclose(f); - // } - int aux_is_readable(const char *filename) { struct _stati64 info; diff --git a/source/luametatex/source/utilities/auxsparsearray.c b/source/luametatex/source/utilities/auxsparsearray.c index d9fa5e453..c3f2c7687 100644 --- a/source/luametatex/source/utilities/auxsparsearray.c +++ b/source/luametatex/source/utilities/auxsparsearray.c @@ -325,13 +325,6 @@ int sa_get_item_n(const sa_tree head, int n) } } -/* -void rawset_sa_item_4(sa_tree head, int n, sa_tree_item v) -{ - head->tree[LMT_SA_H_PART(n)][LMT_SA_M_PART(n)][LMT_SA_L_PART(n)] = v; -} -*/ - void sa_clear_stack(sa_tree a) { if (a) { diff --git a/source/luametatex/source/utilities/auxsparsearray.h b/source/luametatex/source/utilities/auxsparsearray.h index 0a4ce20f1..a1a902c54 100644 --- a/source/luametatex/source/utilities/auxsparsearray.h +++ b/source/luametatex/source/utilities/auxsparsearray.h @@ -57,14 +57,6 @@ typedef struct sparse_state_info { extern sparse_state_info lmt_sparse_state; -/* -typedef struct sa_mathblob { - unsigned int character_value:21; - unsigned int class_value:3; - unsigned int family_value:8; -} sa_mathblob; -*/ - typedef struct sa_mathblob { unsigned int class_value:math_class_bits; unsigned int family_value:math_family_bits; @@ -121,10 +113,6 @@ extern void sa_set_item_1 (sa_tree head, int n, int v, int gl); extern void sa_set_item_2 (sa_tree head, int n, int v, int gl); extern void sa_set_item_4 (sa_tree head, int n, sa_tree_item v, int gl); extern void sa_set_item_8 (sa_tree head, int n, sa_tree_item v1, sa_tree_item v2, int gl); -/* void sa_rawset_item_1 (sa_tree head, int n, sa_tree_item v); */ -/* void sa_rawset_item_2 (sa_tree head, int n, sa_tree_item v); */ -/* void sa_rawset_item_4 (sa_tree head, int n, sa_tree_item v); */ -/* void sa_rawset_item_8 (sa_tree head, int n, sa_tree_item v1, sa_tree_item v2); */ extern sa_tree sa_new_tree (int size, int bytes, sa_tree_item dflt); extern sa_tree sa_copy_tree (sa_tree head); extern void sa_destroy_tree (sa_tree head); diff --git a/source/luametatex/source/utilities/auxunistring.h b/source/luametatex/source/utilities/auxunistring.h index 1e6a997b9..4c5ee3639 100644 --- a/source/luametatex/source/utilities/auxunistring.h +++ b/source/luametatex/source/utilities/auxunistring.h @@ -16,4 +16,3 @@ extern size_t aux_utf8len (const char *text, size_t size); # define buffer_to_unichar(k) aux_str2uni((const unsigned char *)(lmt_fileio_state.io_buffer+k)) # endif - |