From 3a9e8cb06ee3172025cb388e248c420ee659f879 Mon Sep 17 00:00:00 2001
From: Luigi Scarso <luigi.scarso@gmail.com>
Date: Mon, 17 Mar 2025 20:03:55 +0100
Subject: [PATCH] final solution for italic (H.Hagen)

---
 source/texk/web2c/luatexdir/ChangeLog         |  6 +-
 .../texk/web2c/luatexdir/luatex_svnversion.h  |  2 +-
 source/texk/web2c/luatexdir/tex/commands.c    | 11 ++-
 source/texk/web2c/luatexdir/tex/commands.h    |  2 +-
 source/texk/web2c/luatexdir/tex/equivalents.h |  6 +-
 source/texk/web2c/luatexdir/tex/maincontrol.c |  4 +-
 source/texk/web2c/luatexdir/tex/mlist.c       | 91 ++++++++++++++-----
 7 files changed, 88 insertions(+), 34 deletions(-)

diff --git a/source/texk/web2c/luatexdir/ChangeLog b/source/texk/web2c/luatexdir/ChangeLog
index 1f9455bb2..28017a6ea 100644
--- a/source/texk/web2c/luatexdir/ChangeLog
+++ b/source/texk/web2c/luatexdir/ChangeLog
@@ -1,9 +1,13 @@
+2025-03-17 Luigi Scarso  <luigi.scarso@gmail.com>
+	*  final solution for italic (H.Hagen)
+
+
 2025-03-16 Luigi Scarso  <luigi.scarso@gmail.com>
 	* always use old school tex logic (also for opentype) wrt italics
 	  with exception for large operators in opentyep fonts (no mixed font
           usage); all related control modes removed (H.Hagen)
 
-	
+
 2025-03-15 Luigi Scarso  <luigi.scarso@gmail.com>
 	* italicsmode fix for eight bit fonts (H.Hagen)
 
diff --git a/source/texk/web2c/luatexdir/luatex_svnversion.h b/source/texk/web2c/luatexdir/luatex_svnversion.h
index ddf0547d5..1fa2d58e7 100644
--- a/source/texk/web2c/luatexdir/luatex_svnversion.h
+++ b/source/texk/web2c/luatexdir/luatex_svnversion.h
@@ -1,4 +1,4 @@
 #ifndef luatex_svn_revision_h
 #define luatex_svn_revision_h
-#define luatex_svn_revision 7673
+#define luatex_svn_revision 7674
 #endif
diff --git a/source/texk/web2c/luatexdir/tex/commands.c b/source/texk/web2c/luatexdir/tex/commands.c
index b487c9d7e..8c4389c7c 100644
--- a/source/texk/web2c/luatexdir/tex/commands.c
+++ b/source/texk/web2c/luatexdir/tex/commands.c
@@ -746,7 +746,6 @@ void initialize_commands(void)
     primitive_luatex("pdfextension", extension_cmd, pdf_extension_code, 0);
     primitive_luatex("pdffeedback", feedback_cmd, pdf_feedback_code, 0);
     primitive_luatex("pdfvariable", variable_cmd, pdf_variable_code, 0);
-    primitive_luatex("mathoption", option_cmd, 0, 0);
 
     primitive_luatex("luacopyinputnodes", assign_int_cmd, int_base + copy_lua_input_nodes_code, int_base);
 
@@ -800,13 +799,19 @@ void initialize_etex_commands(void)
     primitive_luatex("matheqnogapstep", assign_int_cmd, int_base + math_eqno_gap_step_code, int_base);
     primitive_luatex("mathdisplayskipmode", assign_int_cmd, int_base + math_display_skip_mode_code, int_base);
     primitive_luatex("mathscriptsmode", assign_int_cmd, int_base + math_scripts_mode_code, int_base);
-    primitive_luatex("mathnolimitsmode", assign_int_cmd, int_base + math_nolimits_mode_code, int_base);
-    primitive_luatex("mathitalicsmode", assign_int_cmd, int_base + math_italics_mode_code, int_base);
     primitive_luatex("mathrulesmode", assign_int_cmd, int_base + math_rules_mode_code, int_base);
     primitive_luatex("matheqdirmode", assign_int_cmd, int_base + math_eq_dir_mode_code, int_base);
     primitive_luatex("mathrulesfam", assign_int_cmd, int_base + math_rules_fam_code, int_base);
     primitive_luatex("synctex", assign_int_cmd, int_base + synctex_code, int_base);
 
+    /* obsolete: */
+
+    primitive_luatex("mathoption", option_cmd, 0, 0);
+    primitive_luatex("mathitalicsmode", assign_int_cmd, int_base + math_italics_mode_code, int_base);
+    primitive_luatex("mathnolimitsmode", assign_int_cmd, int_base + math_nolimits_mode_code, int_base);
+
+    /* */
+
     primitive_etex("currentgrouplevel", last_item_cmd, current_group_level_code, 0);
     primitive_etex("currentgrouptype", last_item_cmd, current_group_type_code, 0);
 
diff --git a/source/texk/web2c/luatexdir/tex/commands.h b/source/texk/web2c/luatexdir/tex/commands.h
index 7a08bf653..96610e900 100644
--- a/source/texk/web2c/luatexdir/tex/commands.h
+++ b/source/texk/web2c/luatexdir/tex/commands.h
@@ -135,7 +135,7 @@ typedef enum {
     message_cmd,                          /* send to user ( \.{\\message}, \.{\\errmessage} ) */
     normal_cmd,                           /* general extensions to \TeX\ that don't fit into a category */
     extension_cmd,                        /* extensions to \TeX\ ( \.{\\write}, \.{\\special}, etc.~) */
-    option_cmd,
+    option_cmd,                           /* obsolete */
     lua_function_call_cmd,
     lua_bytecode_call_cmd,
     lua_call_cmd,
diff --git a/source/texk/web2c/luatexdir/tex/equivalents.h b/source/texk/web2c/luatexdir/tex/equivalents.h
index de56f6f97..5ac1871ab 100644
--- a/source/texk/web2c/luatexdir/tex/equivalents.h
+++ b/source/texk/web2c/luatexdir/tex/equivalents.h
@@ -278,10 +278,10 @@ the |number_regs| \.{\\dimen} registers.
 #  define math_eqno_gap_step_code 87                                    /* factor/1000 used for distance between eq and eqno */
 #  define math_display_skip_mode_code 88
 #  define math_scripts_mode_code 89
-#  define math_nolimits_mode_code 90
+#  define math_nolimits_mode_code 90 /* obsolete */
 #  define math_rules_mode_code 91
 #  define math_rules_fam_code 92
-#  define math_italics_mode_code 93
+#  define math_italics_mode_code 93 /* obsolete */
 #  define synctex_code 94                                               /* is synctex file generation enabled ?  */
 #  define shape_mode_code 95
 #  define first_valid_language_code 96
@@ -672,8 +672,6 @@ extern halfword last_cs_name;
 #define disable_kern_par                   int_par(disable_kern_code)
 #define disable_space_par                  int_par(disable_space_code)
 #define math_scripts_mode_par              int_par(math_scripts_mode_code)
-#define math_nolimits_mode_par             int_par(math_nolimits_mode_code)
-#define math_italics_mode_par              int_par(math_italics_mode_code)
 #define math_rules_mode_par                int_par(math_rules_mode_code)
 #define math_rules_fam_par                 int_par(math_rules_fam_code)
 
diff --git a/source/texk/web2c/luatexdir/tex/maincontrol.c b/source/texk/web2c/luatexdir/tex/maincontrol.c
index 4eacd1d28..0b3dfe445 100644
--- a/source/texk/web2c/luatexdir/tex/maincontrol.c
+++ b/source/texk/web2c/luatexdir/tex/maincontrol.c
@@ -706,7 +706,7 @@ static void run_normal (void) {
 /*tex
 
 This is experimental and not used for production, only for testing and writing
-macros (some options stay). It's now obsolete. We keep the cmd_code because it 
+macros (some options stay). It's now obsolete. We keep the cmd_code becuase it 
 looks like hard coded numbers are used in macro packages. 
 
 */
@@ -980,7 +980,7 @@ static void init_main_control (void) {
     any_mode(xray_cmd, show_whatever);
     any_mode(normal_cmd, run_normal);
     any_mode(extension_cmd, run_extension);
-    any_mode(option_cmd, run_option);
+    any_mode(option_cmd, run_option); /* obsolete */
 
     any_mode(lua_function_call_cmd, lua_function_call);
     any_mode(lua_bytecode_call_cmd, lua_bytecode_call);
diff --git a/source/texk/web2c/luatexdir/tex/mlist.c b/source/texk/web2c/luatexdir/tex/mlist.c
index d93d36e52..5ca4e2abc 100644
--- a/source/texk/web2c/luatexdir/tex/mlist.c
+++ b/source/texk/web2c/luatexdir/tex/mlist.c
@@ -19,16 +19,18 @@ LuaTeX; if not, see <http://www.gnu.org/licenses/>.
 
 /*tex
 
-    These are now obsolete: 
-    
+    These are now obsolete:
+
     \starttyping
     \Umathnolimitsupfactor
     \Umathnolimitsubfactor
-    \mathnolimitsmode 
-    \mathitalicssmode 
+    \mathnolimitsmode
+    \mathitalicssmode
     \mathoption
     \stoptyping
 
+*/
+
 /*tex
 
     In traditional \TeX\ the italic correction is added to the width of the
@@ -70,25 +72,69 @@ LuaTeX; if not, see <http://www.gnu.org/licenses/>.
     italics. Axis are another area of concern, as it looks like opentype math
     fonts often already apply that shift.
 
-    The first public font that we tested was Latin Modern. Here again italic 
-    correction is present. The same is true for later fonts, like Pagella. This 
-    presents a problem: we need to add the correction but then also ignore it 
-    when we have a large operator that has limits or no limits, something that 
-    needs to be known explicitly. We used to have a few modes to control this, 
-    one that controlled the anchoring of sub scripts, as these depend on the 
-    italic correction, and one for dealing with the operators. In the end we 
-    decided to ditch these because there is no way to consistently set up the 
-    engine, we now just accept the fact that fonts are a mixed bag: traditional 
-    width plus italic as well as italic used for limits. However, for opentype 
-    fonts we have a code path that compensates for the width.
+*/
+
+/*tex
+
+    This is the state per early 2025:
+
+    When we started with \OPENTYPE\ math (2005) there was only cambria. The only
+    way to test with e.g. Computer Modern was to make a virtual font. One of the
+    complications we ran into is italic correction and because the specification
+    explicitly binds italic correction to (1) a sequence of text (!) glyphs and
+    (2) anchoring limits (as there's only a top anchor and no bttom anchor
+    field), we ended up with a split code path. This is also due to the fact that
+    when Latin Modern showed up, we wanted to make sure that it rendered okay.
+
+    However, when the \TEX\ Gyre fonts were introduced, and other fonts used
+    those as template, the heuristics for Latin Modern were sub optimal so we
+    introduced ways to control the distance between super and subscript as well
+    as limit anchoring for large operators (these cannot really be identified).
+    Keep in mind that the italic correction in large operators is not used as
+    correction but for anchoring while the \TEX\ machinery always adds italic
+    correction to the width and selectively removes it. There is also the fact
+    that we don't know to what extend users mix \OPENTYPE\ fonts with traditional
+    ones.
+
+    In the end we decided to just drop that control, and assume that \OPENTYPE\
+    math fonts are expected to behave like traditional \TEX\ fonts, or: just
+    forget about what the specification says about italic correction. As a side
+    note: in \CONTEXT\ we already moved on and started treating fonts (in the
+    \LUAMETATEX\ default setup) as glyph providers and forget about italic
+    correction and the on the average unreliable and often wrong staircase kerns.
+    There we take whatever information fits our purpose and assume fonts to be a
+    mixed bag.
+
+    The result is that math renders similar to traditional (eight bit) rendering
+    but that Latin Modern can look kind of bad but as (non \CONTEXT) users are
+    accustomed to correcting spacing manually (with |\,| and |\!| etc.) that is
+    what is expected. We just fix the fonts runtime.
+
+    So, we ditched the control options, went for a hard coded traditional font
+    approach and likely will never look back: this is what one gets,
+    irrespectable of the specification. A side effect is that in some cases
+    \CONTEXT\ users will get worse results but because most already switched to
+    \LUAMETATEX\ the impact is not that large.
+
+    In 2005 and following years no one could have predicted that the majority of
+    math fonts would be designed as traditional \TEX\ fonts and less like the
+    reference Cambria font and that anchoring scripts would therefore be italic
+    correction driven (also for non italic shapes). So, in retrospect one can
+    argue that following the specification was a waste of time although it
+    eventually lead to detailed control over these things in the follow up
+    engine. However, there we might eventually completely remove all traces of
+    italic correction because we don't need it, but that's another story and
+    only relevant for \CONTEXT\ \LMTX.
 
 */
 
 /*tex
+
     These macros are used to determine if we need to pick up parameters from the
     opentype table or the traditional parameter array. We noticed that some macro
     packages set both tables so we cannot use that for determining if we have a new
     or old font. It's a bit guesswork especially when it comes to italics.
+
 */
 
 #define is_new_mathfont(A)   ((font_math_params(A) > 0))
@@ -3123,7 +3169,7 @@ static scaled make_op(pointer q, int cur_style)
     /*tex dimensions for box calculation */
     scaled shift_up, shift_down;
     boolean axis_shift = false;
-    int opentype = assume_new_math(cur_f);
+    int opentype = 0;
     scaled ok_size;
     if ((subtype(q) == op_noad_type_normal) && (cur_style < text_style)) {
         subtype(q) = op_noad_type_limits;
@@ -3190,11 +3236,12 @@ static scaled make_op(pointer q, int cur_style)
         type(nucleus(q)) = sub_box_node;
         math_list(nucleus(q)) = x;
     }
+    opentype = assume_new_math(cur_f);
     /*tex we now handle op_nod_type_no_limits here too */
     if (subtype(q) == op_noad_type_no_limits) {
         /*tex similar code then the caller (before CHECK_DIMENSIONS) */
         p = check_nucleus_complexity(q, &delta, cur_style, NULL);
-        if (opentype) { 
+        if (opentype) {
             width(p) -= delta;
         }
         if ((subscr(q) == null) && (supscr(q) == null)) {
@@ -3228,14 +3275,14 @@ static scaled make_op(pointer q, int cur_style)
         x = rebox(x, width(v));
         y = rebox(y, width(v));
         z = rebox(z, width(v));
-        shift_amount(x) = half(delta); /* sup */
-        shift_amount(z) = -shift_amount(x);
+        shift_amount(x) = half(delta);      /* sup */
+        shift_amount(z) = -shift_amount(x); /* sub */
         /*tex v is the still empty target */
         height(v) = height(y);
         depth(v) = depth(y);
-        if (opentype) { 
-            width(v) -= delta; 
-            delta = 0;
+        if (opentype) {
+            width(v) -= delta;
+         // delta = 0;
         }
         /*tex
 
-- 
GitLab