Subject: Re: bug#54970: 28.1; Some emoji no longer display

From: Alan Third <[email-masked]>
Date: Mon, 18 Apr 2022 14:19:24 +0100

On Mon, Apr 18, 2022 at 07:29:00AM +0300, Eli Zaretskii wrote:
> > Date: Sun, 17 Apr 2022 21:34:52 +0100
> > From: Alan Third <[email-masked]>
> > 
> > >     case GLYPHLESS_GLYPH:
> > >       if (s->for_overlaps || (s->cmp_from > 0
> > > 			      && ! s->first_glyph->u.cmp.automatic))
> > >         s->background_filled_p = 1;
> > >       else
> > >         ns_maybe_dumpglyphs_background
> > >           (s, s->first_glyph->type == COMPOSITE_GLYPH);
> > >       /* ... */
> > >       /* Not yet implemented.  */
> > >       /* ... */
> > >       break;
> > 
> > To answer my own question: yes. Yes it is.
> > 
> > Patch attached.
> > 
> > It doesn't look to me like it displays quite right, the right hand
> > side of the hex code gets cut off on my Mac and under GNUstep only the
> > first line is displayed, but I can't see any reason for it.
> 
> Can you show screenshots?  I'm not sure I understand the description
> of the display problems that this code yields.
> 
> The font used for the hex code should be a smaller one, and that is
> determined elsewhere in the display code, so maybe that part also
> needs some fix in the NS build?

I've changed my mind about on the Mac. The hex code isn't centred, but
it is readable.

I found a couple of bugs in nsfont.m, which is the GNUstep font
backend, and now the only problem is that the upper and lower text are
drawn in almost the same location. I suspect some error in how the
font backend is calculating the ascent and descent or something. I
don't see what's wrong, though.

Screenshot for GNUstep attached. In this example upper_yoff and
lower_yoff are -14 and -13, respectively.

Po Lu, any ideas?

-- 
Alan Third
>From e2c482042bf45a3f7b924b0f298876d84576df1d Mon Sep 17 00:00:00 2001
From: Alan Third <[email-masked]>
Date: Sun, 17 Apr 2022 21:15:05 +0100
Subject: [PATCH v2] Fix glyphless glyph display on NS (bug#54970)

* src/nsterm.m (ns_draw_glyphless_glyph_string_foreground): New
function.
(ns_draw_glyph_string): Use the new function.
* src/nsfont.m (nsfont_draw): Fix the location the glyphs are drawn,
and also which glyphs are drawn.
---
 src/nsfont.m | 10 +++----
 src/nsterm.m | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/src/nsfont.m b/src/nsfont.m
index f3c8a82930..6915fd217d 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -1176,15 +1176,15 @@ is false when (FROM > 0 || TO < S->nchars).  */
 
   face = s->face;
 
-  r.origin.x = s->x;
+  r.origin.x = x;
   if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p)
     r.origin.x += max (s->face->box_vertical_line_width, 0);
 
-  r.origin.y = s->y;
+  r.origin.y = y;
   r.size.height = FONT_HEIGHT (font);
 
-  for (int i = from; i < to; ++i)
-    c[i] = s->char2b[i];
+  for (int i = 0; i < len; ++i)
+    c[i] = s->char2b[i + from];
 
   /* Fill background if requested.  */
   if (with_background && !isComposite)
@@ -1210,8 +1210,6 @@ is false when (FROM > 0 || TO < S->nchars).  */
     }
 
   /* set up for character rendering */
-  r.origin.y = y;
-
   if (s->hl == DRAW_CURSOR)
     col = FRAME_BACKGROUND_COLOR (s->f);
   else
diff --git a/src/nsterm.m b/src/nsterm.m
index 550f29212e..5a6a4d663b 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3945,6 +3945,81 @@ Function modeled after x_draw_glyph_string_box ().
     }
 }
 
+/* Draw the foreground of glyph string S for glyphless characters.  */
+static void
+ns_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
+{
+  struct glyph *glyph = s->first_glyph;
+  NSGlyph char2b[8];
+  int x, i, j;
+
+  /* If first glyph of S has a left box line, start drawing the text
+     of S to the right of that box line.  */
+  if (s->face && s->face->box != FACE_NO_BOX
+      && s->first_glyph->left_box_line_p)
+    x = s->x + max (s->face->box_vertical_line_width, 0);
+  else
+    x = s->x;
+
+  s->char2b = char2b;
+
+  for (i = 0; i < s->nchars; i++, glyph++)
+    {
+      char buf[7];
+      char *str = NULL;
+      int len = glyph->u.glyphless.len;
+
+      if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
+	{
+	  if (len > 0
+	      && CHAR_TABLE_P (Vglyphless_char_display)
+	      && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
+		  >= 1))
+	    {
+	      Lisp_Object acronym
+		= (! glyph->u.glyphless.for_no_font
+		   ? CHAR_TABLE_REF (Vglyphless_char_display,
+				     glyph->u.glyphless.ch)
+		   : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
+	      if (STRINGP (acronym))
+		str = SSDATA (acronym);
+	    }
+	}
+      else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
+	{
+	  unsigned int ch = glyph->u.glyphless.ch;
+	  eassume (ch <= MAX_CHAR);
+	  sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
+	  str = buf;
+	}
+
+      if (str)
+	{
+	  int upper_len = (len + 1) / 2;
+
+	  /* It is assured that all LEN characters in STR is ASCII.  */
+	  for (j = 0; j < len; j++)
+            char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
+	  s->font->driver->draw (s, 0, upper_len,
+				 x + glyph->slice.glyphless.upper_xoff,
+				 s->ybase + glyph->slice.glyphless.upper_yoff,
+				 false);
+	  s->font->driver->draw (s, upper_len, len,
+				 x + glyph->slice.glyphless.lower_xoff,
+				 s->ybase + glyph->slice.glyphless.lower_yoff,
+				 false);
+	}
+      if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
+        ns_draw_box (NSMakeRect (x, s->ybase - glyph->ascent,
+                                 glyph->pixel_width - 1,
+                                 glyph->ascent + glyph->descent - 1),
+                     1, 1,
+                     [NSColor colorWithUnsignedLong:NS_FACE_FOREGROUND (s->face)],
+                     YES, YES);
+      x += glyph->pixel_width;
+   }
+}
+
 static void
 ns_draw_glyph_string (struct glyph_string *s)
 /* --------------------------------------------------------------------------
@@ -4058,9 +4133,7 @@ Function modeled after x_draw_glyph_string_box ().
       else
         ns_maybe_dumpglyphs_background
           (s, s->first_glyph->type == COMPOSITE_GLYPH);
-      /* ... */
-      /* Not yet implemented.  */
-      /* ... */
+      ns_draw_glyphless_glyph_string_foreground (s);
       break;
 
     default:
-- 
2.35.1