View Issue Details

IDProjectCategoryView StatusLast Update
0000233luatexfeature requestpublic2015-11-04 23:21
ReporterTacoAssigned ToHans Hagen 
PrioritynormalSeverityminorReproducibilityhave not tried
Status closedResolutionfixed 
Product Version 
Target VersionFixed in Version0.85.0 
Summary0000233: Math accent overlay needed?
DescriptionSome of the Unicode overlay characters are not accents because they should not be moved vertically. Perhaps this needs a separate primitive for 'overlay accents'
Additional InformationOriginal example:

\startmode[mkiv]
\usetypescript[cambria]
\setupbodyfont[cambria]
\Umathchardef\TESTnot "3 "0 "338
\Umathchardef\TESTleq "3 "0 "2264
\stopmode

\starttext $A \TESTnot\TESTleq B$ \stoptext
Tagsmath

Activities

Khaled Hosny

2011-06-22 16:39

developer  

overlay_accents.diff (9,794 bytes)
diff --git a/source/texk/web2c/luatexdir/tex/mlist.w b/source/texk/web2c/luatexdir/tex/mlist.w
index 4c1f5dc..c765074 100644
--- a/source/texk/web2c/luatexdir/tex/mlist.w
+++ b/source/texk/web2c/luatexdir/tex/mlist.w
@@ -2131,23 +2131,22 @@ respect to the size of the final box.
 @c
 #define TOP_CODE 1
 #define BOT_CODE 2
-#define TOP_OR_BOT_MASK ((TOP_CODE) | (BOT_CODE))
-#define STRETCH_ACCENT_CODE 4
+#define OVERLAY_CODE 4
+#define STRETCH_ACCENT_CODE 8
 
 static void do_make_math_accent(pointer q, internal_font_number f, int c,
                                 int flags, int cur_style)
 {
     pointer p, r, x, y;         /* temporary registers for box construction */
     scaled s;                   /* amount to skew the accent to the right */
-    scaled h;                   /* height of character being accented */
-    scaled delta;               /* space to remove between accent and accentee */
+    scaled h;                   /* height of the accentee */
     scaled w;                   /* width of the accentee, not including sub/superscripts */
+    scaled delta;               /* space to remove between accent and accentee */
     boolean s_is_absolute;      /* will be true if a top-accent is placed in |s| */
     extinfo *ext;
     pointer attr_p;
     const int compat_mode = radical_rule(cur_style) == undefined_math_parameter;
-    const int top_or_bot = flags & TOP_OR_BOT_MASK;
-    attr_p = (top_or_bot == TOP_CODE ? accent_chr(q) : bot_accent_chr(q));
+    attr_p = (flags & TOP_CODE ? accent_chr(q) : flags & BOT_CODE ? bot_accent_chr(q) : overlay_accent_chr(q));
     s_is_absolute = false;
     c = cur_c;
     f = cur_f;
@@ -2156,13 +2155,13 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
     if (type(nucleus(q)) == math_char_node) {
         fetch(nucleus(q));
         if (compat_mode) {
-          if (top_or_bot == TOP_CODE) {
+          if (flags & TOP_CODE) {
             s = get_kern(cur_f, cur_c, skew_char(cur_f));
           } else {
             s = 0;
           }
         } else {
-        if (top_or_bot == TOP_CODE) {
+        if (flags & (TOP_CODE | OVERLAY_CODE)) {
             s = char_top_accent(cur_f, cur_c);
             if (s != INT_MIN) {
                 s_is_absolute = true;
@@ -2203,8 +2202,15 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
             int yy = char_remainder(f, c);
             if (!char_exists(f, yy))
                 break;
-            if (char_width(f, yy) > w)
-                break;
+            if (flags & OVERLAY_CODE) {
+                if ((.90 * char_height(f, yy)) > h) { /* make sure the accent is a bit larger than the accentee */
+                   c = yy;
+                   break;
+                }
+            } else {
+                if (char_width(f, yy) > w)
+                   break;
+            }
             c = yy;
         }
       }
@@ -2212,11 +2218,13 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
     if (y == null) {
         y = char_box(f, c, node_attr(attr_p));
     }
-    if (top_or_bot == TOP_CODE) {
+    if (flags & TOP_CODE) {
         if (h < accent_base_height(f))
             delta = h;
         else
             delta = accent_base_height(f);
+    } else if (flags & OVERLAY_CODE) {
+        delta = half(height(y)+depth(y)+height(x)+depth(x)); /* center the accent vertically around the accentee */
     } else {
         delta = 0;              /* hm */
     }
@@ -2240,7 +2248,7 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
     }
     if (s_is_absolute) {
         scaled sa;
-        if (top_or_bot == TOP_CODE)
+        if (flags & (TOP_CODE | OVERLAY_CODE))
             sa = char_top_accent(f, c);
         else
             sa = char_bot_accent(f, c);
@@ -2256,7 +2264,7 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
         }
     }
     width(y) = 0;
-    if (top_or_bot == TOP_CODE) {
+    if (flags & (TOP_CODE | OVERLAY_CODE)) {
         p = new_kern(-delta);
         vlink(p) = x;
         vlink(y) = p;
@@ -2274,7 +2282,7 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
     reset_attributes(r, node_attr(q));
     width(r) = width(x);
     y = r;
-    if (top_or_bot == TOP_CODE) {
+    if (flags & TOP_CODE) {
         if (height(y) < h) {
             /* Make the height of box |y| equal to |h| */
             p = new_kern(h - height(y));
@@ -2283,7 +2291,7 @@ static void do_make_math_accent(pointer q, internal_font_number f, int c,
             list_ptr(y) = p;
             height(y) = h;
         }
-    } else {
+    } else if (flags & BOT_CODE) {
         shift_amount(y) = -(h - height(y));
     }
     math_list(nucleus(q)) = y;
@@ -2311,6 +2319,14 @@ static void make_math_accent(pointer q, int cur_style)
         flush_node(bot_accent_chr(q));
         bot_accent_chr(q) = null;
     }
+    if (overlay_accent_chr(q) != null) {
+        fetch(overlay_accent_chr(q));
+        if (char_exists(cur_f, cur_c)) {
+          do_make_math_accent(q, cur_f, cur_c, OVERLAY_CODE | STRETCH_ACCENT_CODE, cur_style);
+        }
+        flush_node(overlay_accent_chr(q));
+        overlay_accent_chr(q) = null;
+    }
 }
 
 @ The |make_fraction| procedure is a bit different because it sets
diff --git a/source/texk/web2c/luatexdir/tex/texmath.w b/source/texk/web2c/luatexdir/tex/texmath.w
index bcde1ee..25d86fc 100644
--- a/source/texk/web2c/luatexdir/tex/texmath.w
+++ b/source/texk/web2c/luatexdir/tex/texmath.w
@@ -721,8 +721,10 @@ void display_normal_noad(pointer p)
            } else {
                tprint_esc("Umathaccent");
            }
-       } else {
+       } else if (bot_accent_chr(p) != null) {
            tprint_esc("Umathaccent bottom");
+       } else {
+           tprint_esc("Umathaccent overlay");
        }
        switch (subtype(p)) {
        case 0:
@@ -733,8 +735,10 @@ void display_normal_noad(pointer p)
             } else {
                 print_fam_and_char(accent_chr(p));
             }
-        } else {
+        } else if (bot_accent_chr(p) != null) {
             print_fam_and_char(bot_accent_chr(p));
+        } else {
+            print_fam_and_char(overlay_accent_chr(p));
         }
         break;
        case 1:
@@ -1582,8 +1586,7 @@ void math_radical(void)
 void math_ac(void)
 {
     halfword q;
-    mathcodeval t = { 0, 0, 0, 0 }, b = {
-    0, 0, 0, 0};
+    mathcodeval t = { 0, 0, 0, 0 }, b = { 0, 0, 0, 0 }, o = { 0, 0, 0, 0 };
     if (cur_cmd == accent_cmd) {
         const char *hlp[] = {
             "I'm changing \\accent to \\mathaccent here; wish me luck.",
@@ -1615,6 +1618,8 @@ void math_ac(void)
              subtype(tail) = 2;
            }
 	   b = scan_mathchar(xetex_mathcode);
+	} else if (scan_keyword("overlay")) {
+	   o = scan_mathchar(xetex_mathcode);
 	} else {
 	   t = scan_mathchar(xetex_mathcode);
 	}
@@ -1646,6 +1651,15 @@ void math_ac(void)
         else
             math_fam(bot_accent_chr(tail)) = b.family_value;
     }
+    if (!(o.character_value == 0 && o.family_value == 0)) {
+        q = new_node(math_char_node, 0);
+        overlay_accent_chr(tail) = q;
+        math_character(overlay_accent_chr(tail)) = o.character_value;
+        if ((o.class_value == var_code) && fam_in_range)
+            math_fam(overlay_accent_chr(tail)) = cur_fam;
+        else
+            math_fam(overlay_accent_chr(tail)) = o.family_value;
+    }
     q = new_node(math_char_node, 0);
     nucleus(tail) = q;
     (void) scan_math(nucleus(tail), cramped_style(m_style));
diff --git a/source/texk/web2c/luatexdir/tex/texnodes.h b/source/texk/web2c/luatexdir/tex/texnodes.h
index ddbcb41..50449d3 100644
--- a/source/texk/web2c/luatexdir/tex/texnodes.h
+++ b/source/texk/web2c/luatexdir/tex/texnodes.h
@@ -381,9 +381,10 @@ typedef enum {
 /* accent noads */
 /* like a regular noad, but with two extra fields. */
 
-#  define accent_noad_size 5    /*number of |mem| words in an accent noad */
+#  define accent_noad_size 6    /*number of |mem| words in an accent noad */
 #  define accent_chr(a) vinfo((a)+4)    /* the |accent_chr| field of an accent noad */
 #  define bot_accent_chr(a) vlink((a)+4)        /* the |bot_accent_chr| field of an accent noad */
+#  define overlay_accent_chr(a) vinfo((a)+5)    /* the |overlay_accent_chr| field of an accent noad */
 
 /* left and right noads */
 
diff --git a/source/texk/web2c/luatexdir/tex/texnodes.w b/source/texk/web2c/luatexdir/tex/texnodes.w
index a661dcf..ef990b9 100644
--- a/source/texk/web2c/luatexdir/tex/texnodes.w
+++ b/source/texk/web2c/luatexdir/tex/texnodes.w
@@ -610,6 +610,8 @@ halfword copy_node(const halfword p)
             accent_chr(r) = s;
             s = copy_node_list(bot_accent_chr(p));
             bot_accent_chr(r) = s;
+            s = copy_node_list(overlay_accent_chr(p));
+            overlay_accent_chr(r) = s;
         } else if (type(p) == radical_noad) {
             s = copy_node(left_delimiter(p));
             left_delimiter(r) = s;
@@ -1055,6 +1057,7 @@ void flush_node(halfword p)
         if (type(p) == accent_noad) {
             flush_node_list(accent_chr(p));
             flush_node_list(bot_accent_chr(p));
+            flush_node_list(overlay_accent_chr(p));
         } else if (type(p) == radical_noad) {
             flush_node(left_delimiter(p));
             flush_node_list(degree(p));
@@ -1297,6 +1300,7 @@ void check_node(halfword p)
         dorangetest(p, supscr(p), var_mem_max);
         dorangetest(p, accent_chr(p), var_mem_max);
         dorangetest(p, bot_accent_chr(p), var_mem_max);
+        dorangetest(p, overlay_accent_chr(p), var_mem_max);
         break;
     case fence_noad:
         dorangetest(p, delimiter(p), var_mem_max);
overlay_accents.diff (9,794 bytes)

Khaled Hosny

2011-06-22 16:42

developer   ~0000882

Last edited: 2011-06-22 16:53

View 2 revisions

This patch adds a new "overlay" keyword to "\Umathaccent" and some heuristics to place those overlays in a good way. The accents grow by default, it shouldn't be hard to add "fixed" support but I didn't want to mess with the subtype thing. The test file is best tried with XITS git master. Placement over \sum and like is broken, seems another manifestation of 0000507 and the fix there don't seem to be enough.

Khaled Hosny

2011-06-22 16:43

developer  

overlay_test.tex (1,812 bytes)

Khaled Hosny

2011-06-22 16:54

developer  

overlay_test.pdf (3,368 bytes)

Hans Hagen

2015-11-04 23:21

manager   ~0001517

adapted to current state

\Umathaccent
    [top|bottom|overlay]
    [fixed]
    [fraction <number>]
    <delimiter>
    {content}

Issue History

Date Modified Username Field Change
2009-05-27 16:57 Taco New Issue
2011-06-22 16:39 Khaled Hosny File Added: overlay_accents.diff
2011-06-22 16:42 Khaled Hosny Note Added: 0000882
2011-06-22 16:43 Khaled Hosny File Added: overlay_test.tex
2011-06-22 16:53 Khaled Hosny Note Edited: 0000882 View Revisions
2011-06-22 16:54 Khaled Hosny File Added: overlay_test.pdf
2012-04-09 04:40 Khaled Hosny Tag Attached: math
2015-10-24 21:31 Hans Hagen Assigned To => Hans Hagen
2015-10-24 21:31 Hans Hagen Status new => assigned
2015-11-04 23:21 Hans Hagen Note Added: 0001517
2015-11-04 23:21 Hans Hagen Status assigned => closed
2015-11-04 23:21 Hans Hagen Resolution open => fixed
2015-11-04 23:21 Hans Hagen Fixed in Version => 0.85.0