unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Pip Cet <pipcet@gmail.com>
To: "Clément Pit-Claudel" <cpitclaudel@gmail.com>
Cc: Eli Zaretskii <eliz@gnu.org>, Alan Third <alan@idiocy.org>,
	emacs-devel@gnu.org
Subject: Re: Ligatures (was: Unify the Platforms: Cairo+FreeType+Harfbuzz Everywhere (except TTY))
Date: Tue, 19 May 2020 21:43:49 +0000	[thread overview]
Message-ID: <CAOqdjBfevUKGMcoeuG8JPtV5Qs09VMKW-BufHhQFpXq+qbKxTw@mail.gmail.com> (raw)
In-Reply-To: <75a90563-51b4-d3b8-4832-fc0e2542af0d@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1433 bytes --]

On Tue, May 19, 2020 at 2:39 PM Clément Pit-Claudel
<cpitclaudel@gmail.com> wrote:
> On 19/05/2020 09.56, Eli Zaretskii wrote:
> > I don't see anything on or after "a", I see a thin vertical line on
> > the "Z".  is that what is actually displayed?  If so, how do people
> > know the cursor is after "a"??
>
> They don't: "the seven equal slices that Firefox treats it as for selection/editing purposes don't match up to the visual shapes of the sub-glyphs at all well"

And I'm afraid the difference is much more obvious with box cursors
than it is with carets. I'm attaching a screenshot of a patched Emacs
displaying "ffi", with point on the second f, in the "Linux Libertine
Display O" font (using approximately equal slices).

I think this is a bit of a worst-case scenario, a three-letter
ligature in a font using ligatures and overhangs very
enthusiastically. It might be okay for other fonts.

My remaining idea is to stretch characters so we can break up a
ligature without changing its total width. I'm not sure how to do
that, though.

(I'm also attaching the patch, for the morbidly curious; it isn't
clean, readable, or finished in any way, and contains at least one
obvious bug. It's just good enough to produce the screenshot, and
maybe it can serve as a hint as to which files need changing for
ligatures to work; but such changes would have to be done very
differently from the patch.).

[-- Attachment #2: ffi-box-cursor.png --]
[-- Type: image/png, Size: 1067 bytes --]

[-- Attachment #3: 0001-Ligatures.diff --]
[-- Type: text/x-patch, Size: 21370 bytes --]

diff --git a/src/alloc.c b/src/alloc.c
index ebc55857ea..1395f647f4 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -322,7 +322,7 @@ #define PUREBEG (char *) pure
 
 /* If positive, garbage collection is inhibited.  Otherwise, zero.  */
 
-static intptr_t garbage_collection_inhibited;
+static intptr_t garbage_collection_inhibited = 3;
 
 /* The GC threshold in bytes, the last time it was calculated
    from gc-cons-threshold and gc-cons-percentage.  */
diff --git a/src/composite.c b/src/composite.c
index 518502be49..e2bece40c8 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -836,7 +836,7 @@ fill_gstring_body (Lisp_Object gstring)
       LGLYPH_SET_CHAR (g, c);
 
       if (font != NULL)
-        code = font->driver->encode_char (font, LGLYPH_CHAR (g));
+        code = font->driver->encode_char (font, LGLYPH_CHAR (g), NULL);
       else
         code = FONT_INVALID_CODE;
       if (code != FONT_INVALID_CODE)
diff --git a/src/dispextern.h b/src/dispextern.h
index 0b1f3d14ae..2f6b33e74c 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -397,6 +397,15 @@ #define SET_GLYPH_FROM_GLYPH_CODE(glyph, gc)				\
 };
 
 
+struct glyph_context
+{
+  union vectorlike_header header;
+  Lisp_Object string;
+  Lisp_Object position;
+  int i;
+  int n;
+};
+
 /* Glyphs.
 
    Be extra careful when changing this structure!  Esp. make sure that
@@ -567,6 +576,8 @@ #define FACE_ID_BITS	20
     /* Used to compare all bit-fields above in one step.  */
     unsigned val;
   } u;
+
+  struct glyph_context *context;
 };
 
 
diff --git a/src/font.c b/src/font.c
index ab00402b40..8de3c969b9 100644
--- a/src/font.c
+++ b/src/font.c
@@ -3010,7 +3010,7 @@ font_has_char (struct frame *f, Lisp_Object font, int c)
       if (result >= 0)
 	return result;
     }
-  return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
+  return (fontp->driver->encode_char (fontp, c, NULL) != FONT_INVALID_CODE);
 }
 
 
@@ -3023,7 +3023,7 @@ font_encode_char (Lisp_Object font_object, int c)
 
   eassert (FONT_OBJECT_P (font_object));
   font = XFONT_OBJECT (font_object);
-  return font->driver->encode_char (font, c);
+  return font->driver->encode_char (font, c, NULL);
 }
 
 
@@ -4418,7 +4418,7 @@ font_fill_lglyph_metrics (Lisp_Object glyph, struct font *font, unsigned int cod
   struct font_metrics metrics;
 
   LGLYPH_SET_CODE (glyph, code);
-  font->driver->text_extents (font, &code, 1, &metrics);
+  font->driver->text_extents (font, &code, 1, &metrics, NULL);
   LGLYPH_SET_LBEARING (glyph, metrics.lbearing);
   LGLYPH_SET_RBEARING (glyph, metrics.rbearing);
   LGLYPH_SET_WIDTH (glyph, metrics.width);
@@ -4638,7 +4638,7 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
   struct face *face = FACE_FROM_ID (f, face_id);
   if (! face->font)
     return Qnil;
-  unsigned code = face->font->driver->encode_char (face->font, c);
+  unsigned code = face->font->driver->encode_char (face->font, c, NULL);
   if (code == FONT_INVALID_CODE)
     return Qnil;
   Lisp_Object font_object;
@@ -4965,7 +4965,7 @@ DEFUN ("font-get-glyphs", Ffont_get_glyphs, Sfont_get_glyphs, 3, 4, 0,
       unsigned code;
       struct font_metrics metrics;
 
-      code = font->driver->encode_char (font, c);
+      code = font->driver->encode_char (font, c, NULL);
       if (code == FONT_INVALID_CODE)
 	{
 	  ASET (vec, i, Qnil);
@@ -4976,7 +4976,7 @@ DEFUN ("font-get-glyphs", Ffont_get_glyphs, Sfont_get_glyphs, 3, 4, 0,
       LGLYPH_SET_TO (g, i);
       LGLYPH_SET_CHAR (g, c);
       LGLYPH_SET_CODE (g, code);
-      font->driver->text_extents (font, &code, 1, &metrics);
+      font->driver->text_extents (font, &code, 1, &metrics, NULL);
       LGLYPH_SET_WIDTH (g, metrics.width);
       LGLYPH_SET_LBEARING (g, metrics.lbearing);
       LGLYPH_SET_RBEARING (g, metrics.rbearing);
diff --git a/src/font.h b/src/font.h
index 8614e7fa10..952a9fa4c3 100644
--- a/src/font.h
+++ b/src/font.h
@@ -565,6 +565,8 @@ #define FONT_PIXEL_SIZE_QUANTUM 1
 
 #define FONT_INVALID_CODE 0xFFFFFFFF
 
+struct glyph_context;
+
 /* Font driver.  Members specified as "optional" can be NULL.  */
 
 struct font_driver
@@ -645,14 +647,15 @@ #define FONT_INVALID_CODE 0xFFFFFFFF
 
   /* Return a glyph code of FONT for character C (Unicode code point).
      If FONT doesn't have such a glyph, return FONT_INVALID_CODE.  */
-  unsigned (*encode_char) (struct font *font, int c);
+  unsigned (*encode_char) (struct font *font, int c, struct glyph_context *context);
 
   /* Compute the total metrics of the NGLYPHS glyphs specified by
      the font FONT and the sequence of glyph codes CODE, and store the
      result in METRICS.  */
   void (*text_extents) (struct font *font,
 			const unsigned *code, int nglyphs,
-			struct font_metrics *metrics);
+			struct font_metrics *metrics,
+			struct glyph_context *context);
 
 #ifdef HAVE_WINDOW_SYSTEM
 
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 7832d4f5ce..19c2644285 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -323,7 +323,7 @@ ftcrfont_has_char (Lisp_Object font, int c)
 }
 
 static unsigned
-ftcrfont_encode_char (struct font *font, int c)
+ftcrfont_encode_char (struct font *font, int c, struct glyph_context *context)
 {
   struct font_info *ftcrfont_info = (struct font_info *) font;
   unsigned code = FONT_INVALID_CODE;
@@ -331,20 +331,53 @@ ftcrfont_encode_char (struct font *font, int c)
   int utf8len = CHAR_STRING (c, utf8);
   cairo_glyph_t stack_glyph;
   cairo_glyph_t *glyphs = &stack_glyph;
-  int num_glyphs = 1;
 
-  if (cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font, 0, 0,
-					(char *) utf8, utf8len,
-					&glyphs, &num_glyphs,
-					NULL, NULL, NULL)
-      == CAIRO_STATUS_SUCCESS)
+  if (context == NULL)
     {
-      if (glyphs != &stack_glyph)
-	cairo_glyph_free (glyphs);
-      else if (stack_glyph.index)
-	code = stack_glyph.index;
+      context = xmalloc (sizeof *context);
+      context->string = CALLN (Fstring, make_fixnum (c));
+      context->position = make_fixnum (0);
     }
 
+  unsigned int num_glyphs = 0;
+  unsigned int num_clusters = 0;
+  hb_buffer_t *hb_buf = hb_buffer_create ();
+  hb_buffer_set_cluster_level (hb_buf, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
+  hb_buffer_add_utf8 (hb_buf, SDATA (context->string), -1, 0, -1);
+  hb_buffer_set_direction (hb_buf, HB_DIRECTION_LTR);
+  hb_font_t *hb_font = hb_ft_font_create_referenced
+    (cairo_ft_scaled_font_lock_face (ftcrfont_info->cr_scaled_font));
+  hb_shape (hb_font, hb_buf, NULL, 0);
+  hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos
+    (hb_buf, &num_glyphs);
+  hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions
+    (hb_buf, &num_glyphs);
+  int i0, i1;
+  int c0, c1;
+  i0 = 0;
+  for (int i = num_glyphs - 1; i >= 0; i--)
+    {
+      if (glyph_info[i].cluster <= XFIXNUM (context->position))
+	{
+	  i0 = i;
+	  c0 = glyph_info[i].cluster;
+	  break;
+	}
+    }
+  i1 = num_glyphs;
+  for (int i = 0; i < num_glyphs; i++)
+    {
+      if (glyph_info[i].cluster > c0)
+	{
+	  i1 = i;
+	  c1 = glyph_info[i].cluster;
+	  break;
+	}
+    }
+  context->i = XFIXNUM (context->position) - c0;
+  context->n = c1 - c0;
+  code = glyph_info[i0].codepoint;
+
   return code;
 }
 
@@ -352,30 +385,65 @@ ftcrfont_encode_char (struct font *font, int c)
 ftcrfont_text_extents (struct font *font,
                        const unsigned *code,
                        int nglyphs,
-                       struct font_metrics *metrics)
+                       struct font_metrics *metrics,
+		       struct glyph_context *context)
 {
+  struct font_info *ftcrfont_info = (struct font_info *) font;
   int width, i;
 
   block_input ();
-  width = ftcrfont_glyph_extents (font, code[0], metrics);
-  for (i = 1; i < nglyphs; i++)
+
+  if (context == NULL)
     {
-      struct font_metrics m;
-      int w = ftcrfont_glyph_extents (font, code[i], metrics ? &m : NULL);
+      context = xmalloc (sizeof *context);
+      context->string = CALLN (Fstring, make_fixnum (code[0]));
+      context->position = make_fixnum (0);
+    }
 
-      if (metrics)
+  unsigned int num_glyphs = 0;
+  unsigned int num_clusters = 0;
+  hb_buffer_t *hb_buf = hb_buffer_create ();
+  hb_buffer_set_cluster_level (hb_buf, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
+  hb_buffer_set_direction (hb_buf, HB_DIRECTION_LTR);
+  hb_buffer_set_content_type (hb_buf, HB_BUFFER_CONTENT_TYPE_UNICODE);
+  int n = 0;
+  for (const char *p = SDATA (context->string); p <= SDATA (context->string) + SBYTES (context->string);)
+    {
+      int c = string_char_advance (&p);
+      hb_buffer_add (hb_buf, c, n++);
+    }
+  hb_font_t *hb_font = hb_ft_font_create_referenced
+    (cairo_ft_scaled_font_lock_face (ftcrfont_info->cr_scaled_font));
+  hb_shape (hb_font, hb_buf, NULL, 0);
+  hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos
+    (hb_buf, &num_glyphs);
+  hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions
+    (hb_buf, &num_glyphs);
+  int i0, i1;
+  int c0, c1;
+  i0 = 0;
+  for (int i = num_glyphs - 1; i >= 0; i--)
+    {
+      if (glyph_info[i].cluster <= XFIXNUM (context->position))
+	{
+	  i0 = i;
+	  c0 = glyph_info[i].cluster;
+	  break;
+	}
+    }
+  i1 = num_glyphs;
+  for (int i = 0; i < num_glyphs; i++)
+    {
+      if (glyph_info[i].cluster > c0)
 	{
-	  if (width + m.lbearing < metrics->lbearing)
-	    metrics->lbearing = width + m.lbearing;
-	  if (width + m.rbearing > metrics->rbearing)
-	    metrics->rbearing = width + m.rbearing;
-	  if (m.ascent > metrics->ascent)
-	    metrics->ascent = m.ascent;
-	  if (m.descent > metrics->descent)
-	    metrics->descent = m.descent;
+	  i1 = i;
+	  c1 = glyph_info[i].cluster;
+	  break;
 	}
-      width += w;
     }
+  context->i = XFIXNUM (context->position) - c0;
+  context->n = c1 - c0;
+  width = glyph_pos[i0].x_advance / (c1 - c0) / 64;
   unblock_input ();
 
   if (metrics)
@@ -508,6 +576,8 @@ ftcrfont_draw (struct glyph_string *s,
       glyphs[i].index = s->char2b[from + i];
       glyphs[i].x = x;
       glyphs[i].y = y;
+      struct glyph_context *context = s->first_glyph->context;
+      glyphs[i].x -= (context->i * s->width);
       x += (s->padding_p ? 1 : ftcrfont_glyph_extents (s->font,
                                                        glyphs[i].index,
                                                        NULL));
diff --git a/src/hbfont.c b/src/hbfont.c
index 576c5fe7f6..5c3c690281 100644
--- a/src/hbfont.c
+++ b/src/hbfont.c
@@ -578,7 +578,7 @@ hbfont_shape (Lisp_Object lgstring, Lisp_Object direction)
       LGLYPH_SET_CODE (lglyph, info[i].codepoint);
 
       unsigned code = info[i].codepoint;
-      font->driver->text_extents (font, &code, 1, &metrics);
+      font->driver->text_extents (font, &code, 1, &metrics, NULL);
       LGLYPH_SET_WIDTH (lglyph, metrics.width);
       LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
       LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
diff --git a/src/lisp.h b/src/lisp.h
index ad7d67ae69..c4ae954999 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1103,6 +1103,7 @@ DEFINE_GDB_SYMBOL_END (PSEUDOVECTOR_FLAG)
   PVEC_MUTEX,
   PVEC_CONDVAR,
   PVEC_MODULE_FUNCTION,
+  PVEC_GLYPH_CONTEXT,
 
   /* These should be last, for internal_equal and sxhash_obj.  */
   PVEC_COMPILED,
diff --git a/src/xdisp.c b/src/xdisp.c
index cf15f579b5..41a7b4235a 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -27499,14 +27499,15 @@ append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
 
 static struct face *
 get_char_face_and_encoding (struct frame *f, int c, int face_id,
-			    unsigned *char2b, bool display_p)
+			    unsigned *char2b, bool display_p,
+			    struct glyph_context *context)
 {
   struct face *face = FACE_FROM_ID (f, face_id);
   unsigned code = 0;
 
   if (face->font)
     {
-      code = face->font->driver->encode_char (face->font, c);
+      code = face->font->driver->encode_char (face->font, c, context);
 
       if (code == FONT_INVALID_CODE)
 	code = 0;
@@ -27533,7 +27534,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
 
 static struct face *
 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
-			     unsigned *char2b)
+			     unsigned *char2b, struct glyph_context *context)
 {
   struct face *face;
   unsigned code = 0;
@@ -27549,7 +27550,8 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
       if (CHAR_BYTE8_P (glyph->u.ch))
 	code = CHAR_TO_BYTE8 (glyph->u.ch);
       else
-	code = face->font->driver->encode_char (face->font, glyph->u.ch);
+	code = face->font->driver->encode_char (face->font, glyph->u.ch,
+						context);
 
       if (code == FONT_INVALID_CODE)
 	code = 0;
@@ -27565,14 +27567,15 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
    Return true iff FONT has a glyph for C.  */
 
 static bool
-get_char_glyph_code (int c, struct font *font, unsigned *char2b)
+get_char_glyph_code (int c, struct font *font, unsigned *char2b,
+		     struct glyph_context *context)
 {
   unsigned code;
 
   if (CHAR_BYTE8_P (c))
     code = CHAR_TO_BYTE8 (c);
   else
-    code = font->driver->encode_char (font, c);
+    code = font->driver->encode_char (font, c, context);
 
   if (code == FONT_INVALID_CODE)
     return false;
@@ -27620,7 +27623,8 @@ fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
 				       -1, Qnil);
 
 	  face = get_char_face_and_encoding (s->f, c, face_id,
-					     s->char2b + i, true);
+					     s->char2b + i, true,
+					     NULL);
 	  if (face)
 	    {
 	      if (! s->face)
@@ -27777,12 +27781,13 @@ fill_glyph_string (struct glyph_string *s, int face_id,
 	 && glyph->glyph_not_available_p == glyph_not_available_p)
     {
       s->face = get_glyph_face_and_encoding (s->f, glyph,
-					     s->char2b + s->nchars);
+					     s->char2b + s->nchars,
+					     glyph->context);
       ++s->nchars;
       eassert (s->nchars <= end - start);
       s->width += glyph->pixel_width;
-      if (glyph++->padding_p != s->padding_p)
-	break;
+      glyph++;
+      break;
     }
 
   s->font = s->face->font;
@@ -27877,7 +27882,8 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
 }
 
 static struct font_metrics *
-get_per_char_metric (struct font *font, const unsigned *char2b)
+get_per_char_metric (struct font *font, const unsigned *char2b,
+		     struct glyph_context *context)
 {
   static struct font_metrics metrics;
 
@@ -27886,7 +27892,7 @@ get_per_char_metric (struct font *font, const unsigned *char2b)
   if (*char2b == FONT_INVALID_CODE)
     return NULL;
 
-  font->driver->text_extents (font, char2b, 1, &metrics);
+  font->driver->text_extents (font, char2b, 1, &metrics, context);
   return &metrics;
 }
 
@@ -27908,9 +27914,10 @@ normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
 
       /* Get metrics of C, defaulting to a reasonably sized ASCII
 	 character.  */
-      if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
+      if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b, NULL))
 	{
-	  struct font_metrics *pcm = get_per_char_metric (font, &char2b);
+	  struct font_metrics *pcm = get_per_char_metric (font, &char2b,
+							  NULL);
 
 	  if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
 	    {
@@ -27952,10 +27959,12 @@ gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *r
   if (glyph->type == CHAR_GLYPH)
     {
       unsigned char2b;
-      struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
+      struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b,
+						       NULL);
       if (face->font)
 	{
-	  struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
+	  struct font_metrics *pcm = get_per_char_metric (face->font, &char2b,
+							  NULL);
 	  if (pcm)
 	    {
 	      if (pcm->rbearing > pcm->width)
@@ -29841,12 +29850,12 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
 	  str = buf;
 	}
       for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
-	code[len] = font->driver->encode_char (font, str[len]);
+	code[len] = font->driver->encode_char (font, str[len], NULL);
       upper_len = (len + 1) / 2;
       font->driver->text_extents (font, code, upper_len,
-				  &metrics_upper);
+				  &metrics_upper, NULL);
       font->driver->text_extents (font, code + upper_len, len - upper_len,
-				  &metrics_lower);
+				  &metrics_lower, NULL);
 
 
 
@@ -29936,6 +29945,40 @@ #define IT_APPLY_FACE_BOX(it, face)				\
       }								\
     } while (false)
 
+static struct glyph_context *
+make_context (struct it *it)
+{
+  struct glyph_context *context = xmalloc (sizeof *context); // XXX GC
+  char *string = xmalloc (128);
+  char *p = string;
+  ptrdiff_t bytepos = it->current.pos.bytepos;
+  ptrdiff_t charpos = it->current.pos.charpos;
+  ptrdiff_t bp5 = bytepos;
+  ptrdiff_t bp0 = bp5;
+  ptrdiff_t bp1 = bp5;
+  while (bytepos > BEG_BYTE && bp5 - bytepos < 32)
+    dec_both (&charpos, &bytepos);
+  bp0 = bytepos;
+  int i = 0;
+  Lisp_Object pos = make_fixnum (0);
+  while (bytepos >= BEG_BYTE && bytepos < Z_BYTE && bytepos - bp0 < 32)
+    {
+      inc_both (&charpos, &bytepos);
+      memcpy (p, BUF_BYTE_ADDRESS (current_buffer, bytepos - prev_char_len (bytepos)), prev_char_len (bytepos));
+      p += prev_char_len (bytepos);
+      ++i;
+      if (bytepos == bp5)
+	pos = make_fixnum (i);
+    }
+  bp1 = bytepos;
+  eassert (strlen (p) == bp1 - bp0);
+  *p++ = it->c;
+  *p++ = 0;
+  context->string = build_string (string);
+  context->position = pos;
+  return context;
+}
+
 /* RIF:
    Produce glyphs/get display metrics for the display element IT is
    loaded with.  See the description of struct it in dispextern.h
@@ -29973,6 +30016,7 @@ gui_produce_glyphs (struct it *it)
       if (font->vertical_centering)
 	boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
 
+      struct glyph_context *context = NULL;
       if (it->char_to_display != '\n' && it->char_to_display != '\t')
 	{
 	  it->nglyphs = 1;
@@ -29989,9 +30033,11 @@ gui_produce_glyphs (struct it *it)
  	      it->descent = FONT_DESCENT (font) - boff;
  	    }
 
-	  if (get_char_glyph_code (it->char_to_display, font, &char2b))
+	  context = make_context (it);
+	  if (get_char_glyph_code (it->char_to_display, font, &char2b,
+				   context))
 	    {
-	      pcm = get_per_char_metric (font, &char2b);
+	      pcm = get_per_char_metric (font, &char2b, context);
 	      if (pcm->width == 0
 		  && pcm->rbearing == 0 && pcm->lbearing == 0)
 		pcm = NULL;
@@ -30079,9 +30125,13 @@ gui_produce_glyphs (struct it *it)
 				/ FONT_HEIGHT (font));
 		  append_stretch_glyph (it, it->object, it->pixel_width,
 					it->ascent + it->descent, ascent);
+		  it->glyph_row->glyphs[it->area][it->glyph_row->used[it->area] - 1].context = NULL;
 		}
 	      else
-		append_glyph (it);
+		{
+		  append_glyph (it);
+		  it->glyph_row->glyphs[it->area][it->glyph_row->used[it->area] - 1].context = context;
+		}
 
 	      /* If characters with lbearing or rbearing are displayed
 		 in this line, record that fact in a flag of the
@@ -30233,9 +30283,9 @@ gui_produce_glyphs (struct it *it)
 	      it->nglyphs = 1;
 	      if (FONT_TOO_HIGH (font))
 		{
-		  if (get_char_glyph_code (' ', font, &char2b))
+		  if (get_char_glyph_code (' ', font, &char2b, NULL))
 		    {
-		      pcm = get_per_char_metric (font, &char2b);
+		      pcm = get_per_char_metric (font, &char2b, NULL);
 		      if (pcm->width == 0
 			  && pcm->rbearing == 0 && pcm->lbearing == 0)
 			pcm = NULL;
@@ -30372,8 +30422,8 @@ gui_produce_glyphs (struct it *it)
 	  if (! font_not_found_p)
 	    {
 	      get_char_face_and_encoding (it->f, c, it->face_id,
-					  &char2b, false);
-	      pcm = get_per_char_metric (font, &char2b);
+					  &char2b, false, NULL);
+	      pcm = get_per_char_metric (font, &char2b, NULL);
 	    }
 
 	  /* Initialize the bounding box.  */
@@ -30433,8 +30483,9 @@ gui_produce_glyphs (struct it *it)
 	      else
 		{
 		  get_char_face_and_encoding (it->f, ch, face_id,
-					      &char2b, false);
-		  pcm = get_per_char_metric (font, &char2b);
+					      &char2b, false,
+					      make_context (it));
+		  pcm = get_per_char_metric (font, &char2b, make_context (it));
 		}
 	      if (! pcm)
 		cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
diff --git a/src/xterm.c b/src/xterm.c
index 7989cecec7..3b5f0d3524 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1703,7 +1703,8 @@ x_compute_glyph_string_overhangs (struct glyph_string *s)
       if (s->first_glyph->type == CHAR_GLYPH)
 	{
 	  struct font *font = s->font;
-	  font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
+	  font->driver->text_extents (font, s->char2b, s->nchars, &metrics,
+				      NULL);
 	}
       else
 	{
@@ -2047,7 +2048,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
 
 	  /* 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;
+            char2b[j] = s->font->driver->encode_char (s->font, str[j], NULL) & 0xFFFF;
 	  s->font->driver->draw (s, 0, upper_len,
 				 x + glyph->slice.glyphless.upper_xoff,
 				 s->ybase + glyph->slice.glyphless.upper_yoff,

  reply	other threads:[~2020-05-19 21:43 UTC|newest]

Thread overview: 145+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-17 10:41 Unify the Platforms: Cairo+FreeType+Harfbuzz Everywhere (except TTY) Julius Pfrommer
2020-05-17 14:09 ` Arthur Miller
2020-05-17 14:30   ` Eli Zaretskii
2020-05-17 15:06     ` Arthur Miller
2020-05-17 15:56       ` Eli Zaretskii
2020-05-17 16:50         ` Arthur Miller
2020-05-17 17:06           ` Eli Zaretskii
2020-05-17 14:35 ` Eli Zaretskii
2020-05-17 14:59   ` Julius Pfrommer
2020-05-17 15:55     ` Eli Zaretskii
2020-05-17 16:28       ` Pip Cet
2020-05-17 17:00         ` Eli Zaretskii
2020-05-17 18:50           ` Pip Cet
2020-05-17 19:17             ` Eli Zaretskii
2020-05-18 16:08               ` Ligatures (was: Unify the Platforms: Cairo+FreeType+Harfbuzz Everywhere (except TTY)) Eli Zaretskii
2020-05-18 16:45                 ` tomas
2020-05-18 16:49                   ` Eli Zaretskii
2020-05-18 17:05                 ` Ligatures Stefan Monnier
2020-05-18 17:18                   ` Ligatures Eli Zaretskii
2020-05-18 19:19                     ` Ligatures Pip Cet
2020-05-18 19:25                       ` Ligatures tomas
2020-05-18 19:41                         ` Ligatures Pip Cet
2020-05-18 20:20                           ` Ligatures tomas
2020-05-18 19:33                       ` Ligatures Eli Zaretskii
2020-05-18 19:44                         ` Ligatures Clément Pit-Claudel
2020-05-19  2:25                           ` Ligatures Eli Zaretskii
2020-05-19  2:44                             ` Ligatures Clément Pit-Claudel
2020-05-19 13:59                               ` Ligatures Eli Zaretskii
2020-05-19 14:35                                 ` Ligatures Clément Pit-Claudel
2020-05-19 15:21                                   ` Ligatures Eli Zaretskii
2020-05-19 15:44                                     ` Ligatures Clément Pit-Claudel
2020-05-19 16:15                                       ` Ligatures Eli Zaretskii
2020-05-19 15:36                                 ` Ligatures Tassilo Horn
2020-05-19 16:08                                   ` Ligatures Eli Zaretskii
2020-05-19 16:14                                   ` Ligatures Stefan Monnier
2020-05-19  3:47                             ` Ligatures Stefan Monnier
2020-05-19  4:51                               ` Ligatures Clément Pit-Claudel
2020-05-18 19:38                       ` Ligatures Clément Pit-Claudel
2020-05-19 14:55                         ` Ligatures Pip Cet
2020-05-19 15:30                           ` Ligatures Clément Pit-Claudel
2020-05-19 15:52                             ` Ligatures Pip Cet
2020-05-18 17:24                   ` Ligatures tomas
2020-05-18 17:41                     ` Ligatures Eli Zaretskii
2020-05-18 19:07                       ` Ligatures tomas
2020-05-18 19:17                         ` Ligatures Eli Zaretskii
2020-05-18 20:33                     ` Ligatures Stefan Monnier
2020-05-18 17:31                 ` Ligatures (was: Unify the Platforms: Cairo+FreeType+Harfbuzz Everywhere (except TTY)) Clément Pit-Claudel
2020-05-18 17:39                   ` Eli Zaretskii
2020-05-18 19:01                     ` Clément Pit-Claudel
2020-05-18 19:15                       ` Eli Zaretskii
2020-05-18 19:18                       ` tomas
2020-05-18 20:37                       ` Ligatures Stefan Monnier
2020-05-18 21:59                       ` Ligatures (was: Unify the Platforms: Cairo+FreeType+Harfbuzz Everywhere (except TTY)) Alan Third
2020-05-19 13:56                         ` Eli Zaretskii
2020-05-19 14:39                           ` Clément Pit-Claudel
2020-05-19 21:43                             ` Pip Cet [this message]
2020-05-20  1:41                               ` Clément Pit-Claudel
2020-05-20  2:07                               ` Ligatures Stefan Monnier
2020-05-20  7:14                               ` Ligatures (was: Unify the Platforms: Cairo+FreeType+Harfbuzz Everywhere (except TTY)) tomas
2020-05-20 15:18                               ` Eli Zaretskii
2020-05-20 17:31                                 ` Clément Pit-Claudel
2020-05-20 18:01                                   ` Eli Zaretskii
2020-05-20 18:33                                     ` Clément Pit-Claudel
2020-05-20 18:49                                       ` Eli Zaretskii
2020-05-20 18:53                                         ` Clément Pit-Claudel
2020-05-20 19:02                                           ` Eli Zaretskii
2020-05-20 23:19                                   ` Ligatures Stefan Monnier
2020-05-21 10:01                                 ` Ligatures (was: Unify the Platforms: Cairo+FreeType+Harfbuzz Everywhere (except TTY)) Pip Cet
2020-05-21 14:11                                   ` Eli Zaretskii
2020-05-21 16:26                                     ` Pip Cet
2020-05-21 19:08                                       ` Eli Zaretskii
2020-05-21 20:51                                         ` Clément Pit-Claudel
2020-05-21 21:16                                           ` Pip Cet
2020-05-22  6:12                                             ` Eli Zaretskii
2020-05-22  9:25                                               ` Pip Cet
2020-05-22 11:23                                                 ` Eli Zaretskii
2020-05-22 12:52                                                   ` Pip Cet
2020-05-22 13:15                                                     ` Eli Zaretskii
2020-05-22 13:29                                                       ` Clément Pit-Claudel
2020-05-22 14:30                                                         ` Eli Zaretskii
2020-05-22 14:34                                                           ` Clément Pit-Claudel
2020-05-22 19:01                                                             ` Eli Zaretskii
2020-05-22 19:33                                                               ` Clément Pit-Claudel
2020-05-22 19:44                                                                 ` Eli Zaretskii
2020-05-22 20:02                                                                   ` Clément Pit-Claudel
     [not found]                                                                     ` <83mu5z171j.fsf@gnu.org>
2020-05-23 14:34                                                                       ` Clément Pit-Claudel
2020-05-23 16:18                                                                         ` Eli Zaretskii
2020-05-23 16:37                                                                           ` Clément Pit-Claudel
2020-05-22 13:56                                                       ` Pip Cet
     [not found]                                                         ` <83lflj16jn.fsf@gnu.org>
     [not found]                                                           ` <AF222EA0-FE05-4224-8459-2BF82CE27266@vasilij.de>
     [not found]                                                             ` <834ks7110w.fsf@gnu.org>
2020-05-23 11:24                                                               ` Vasilij Schneidermann
2020-05-23 13:04                                                                 ` Eli Zaretskii
     [not found]                                                           ` <83eerb145r.fsf@gnu.org>
     [not found]                                                             ` <CAOqdjBeef8Fa596raEyBUwv0Zr+41LSiYvHW39EdoaXpyxCXVw@mail.gmail.com>
     [not found]                                                               ` <831rnb0zld.fsf@gnu.org>
2020-05-23 12:36                                                                 ` Pip Cet
2020-05-23 14:08                                                                   ` Eli Zaretskii
2020-05-23 15:13                                                                     ` Pip Cet
2020-05-23 16:34                                                                       ` Eli Zaretskii
2020-05-23 22:38                                                                         ` Pip Cet
2020-05-24 15:33                                                                           ` Eli Zaretskii
2020-05-26 18:13                                                                             ` Pip Cet
2020-05-26 19:46                                                                               ` Eli Zaretskii
2020-05-27  9:36                                                                                 ` Pip Cet
2020-05-27 17:13                                                                                   ` Eli Zaretskii
2020-05-27 18:42                                                                                     ` Pip Cet
2020-05-27 19:19                                                                                       ` Eli Zaretskii
2020-05-23 17:32                                                                       ` Eli Zaretskii
2020-05-23 21:29                                                                         ` Pip Cet
2020-05-24 15:19                                                                           ` Eli Zaretskii
2020-05-23 12:47                                                                 ` Ligatures Stefan Monnier
2020-05-23 13:10                                                                   ` Ligatures Eli Zaretskii
2020-05-23 13:45                                                                     ` Ligatures Stefan Monnier
2020-05-23 14:12                                                                       ` Ligatures Eli Zaretskii
2020-05-23 13:36                                                                   ` Ligatures 조성빈
2020-05-23 14:15                                                                     ` Ligatures Stefan Monnier
2020-05-23 14:37                                                                   ` Ligatures Pip Cet
2020-05-22 11:44                                           ` Ligatures (was: Unify the Platforms: Cairo+FreeType+Harfbuzz Everywhere (except TTY)) Eli Zaretskii
2020-05-22 13:26                                             ` Clément Pit-Claudel
2020-05-22 14:29                                               ` Eli Zaretskii
2020-05-22 14:32                                                 ` Clément Pit-Claudel
2020-05-22 19:00                                                   ` Eli Zaretskii
2020-05-21 21:06                                         ` Pip Cet
2020-05-22  6:06                                           ` Eli Zaretskii
2020-05-22  9:34                                             ` Pip Cet
2020-05-22 11:33                                               ` Eli Zaretskii
2020-05-19 20:26                           ` Alan Third
2020-05-19 10:09                   ` Trevor Spiteri
2020-05-19 14:22                     ` Eli Zaretskii
2020-05-19  5:43                 ` Ligatures ASSI
2020-05-19  7:22                   ` Ligatures tomas
2020-05-19  7:55                     ` Ligatures Joost Kremers
2020-05-19  8:07                       ` Ligatures tomas
2020-05-19 10:17                         ` Ligatures Yuri Khan
2020-05-19 14:26                           ` Ligatures Eli Zaretskii
2020-05-19 19:00                             ` Ligatures Yuri Khan
2020-05-19 10:43                         ` Ligatures Werner LEMBERG
2020-05-19 10:48                           ` Ligatures tomas
2020-05-19 14:18                   ` Ligatures Eli Zaretskii
2020-05-19 14:52                     ` Ligatures Eli Zaretskii
2020-05-19 15:11                       ` Ligatures Pip Cet
2020-05-19 15:36                         ` Ligatures Eli Zaretskii
2020-05-19 16:16                           ` Ligatures Pip Cet
2020-05-19 16:41                             ` Ligatures Eli Zaretskii
2020-05-19 17:00                             ` Ligatures Eli Zaretskii
2020-05-17 18:28       ` Unify the Platforms: Cairo+FreeType+Harfbuzz Everywhere (except TTY) Julius Pfrommer
2020-05-17 18:45         ` Eli Zaretskii
2020-05-17 22:28         ` chad
2020-05-18 22:08         ` Alan Third

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAOqdjBfevUKGMcoeuG8JPtV5Qs09VMKW-BufHhQFpXq+qbKxTw@mail.gmail.com \
    --to=pipcet@gmail.com \
    --cc=alan@idiocy.org \
    --cc=cpitclaudel@gmail.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).