emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master a2a62f7: Enhance font_range to check for emoji composition trigge


From: Robert Pluim
Subject: master a2a62f7: Enhance font_range to check for emoji composition triggers
Date: Mon, 27 Sep 2021 04:32:51 -0400 (EDT)

branch: master
commit a2a62f71051f1295492780f320e9b7bc02b6e6f4
Author: Robert Pluim <rpluim@gmail.com>
Commit: Robert Pluim <rpluim@gmail.com>

    Enhance font_range to check for emoji composition triggers
    
    If the codepoint that triggered composition is from the emoji script,
    use the emoji font to check the string being composed, rather than the
    font of the first character of the string.  This makes e.g.
    
    "emoji codepoint with Emoji_Presentation = No followed by VS-16 (FE0F)"
    
    display the emoji version of the glyph for that codepoint.
    
    * admin/unidata/blocks.awk: Add VS-1 through VS-16 to the emoji
    script.
    * src/composite.c (autocmp_chars): Accept additional argument CH for
    the codepoint that triggered composition, pass it to font_range.
    (composition_reseat_it, find_automatic_composition): Pass codepoint
    that triggered composition to autocmp_chars.
    * src/font.c (font_range): Accept additional argument CH for the
    triggering codepoint.  If the codepoint is from the 'emoji' script,
    use Vscript_representative_chars to find the font to use for the
    composition attempt.
    (syms_of_font): Add Qemoji symbol.
    * src/font.h: Update font_range prototype for argument CH.
    * etc/NEWS: Announce change.
---
 admin/unidata/blocks.awk |  6 ++++++
 etc/NEWS                 | 12 ++++++++++++
 src/composite.c          | 13 +++++++------
 src/font.c               | 27 +++++++++++++++++++++++++--
 src/font.h               |  2 +-
 5 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/admin/unidata/blocks.awk b/admin/unidata/blocks.awk
index b0303d7..96b0413 100755
--- a/admin/unidata/blocks.awk
+++ b/admin/unidata/blocks.awk
@@ -243,6 +243,12 @@ END {
     override_start[idx] = "1F590"
     override_end[idx] = "1F590"
 
+    ## These are here so that font_range can choose Emoji presentation
+    ## for the preceding codepoint when it encounters a VS
+    idx++
+    override_start[idx] = "FE00"
+    override_end[idx] = "FE0F"
+
     for (k in override_start)
     {
         i++
diff --git a/etc/NEWS b/etc/NEWS
index 72a4b10..381712f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -157,6 +157,18 @@ as single glyphs instead of multiple ones.  'Noto Color 
Emoji' is one
 such suitable font.
 
 +++
+** Composition of emoji has been improved.
+If autocomposition is triggered by an emoji character, then the emoji
+font is now used to check if composition can be performed, rather than
+the font of the first character of the string being composed.  This
+allows e.g.
+
+'Emoji codepoint' + VS-16
+
+to be displayed using the emoji font even if 'Emoji codepoint' does
+not have emoji presentation by default.
+
++++
 ** New command 'execute-extended-command-for-buffer'.
 This new command, bound to 'M-S-x', works like
 'execute-extended-command', but limits the set of commands to the
diff --git a/src/composite.c b/src/composite.c
index c37b1fd..f456e7a 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -882,14 +882,15 @@ fill_gstring_body (Lisp_Object gstring)
 /* Try to compose the characters at CHARPOS according to composition
    rule RULE ([PATTERN PREV-CHARS FUNC]).  LIMIT limits the characters
    to compose.  STRING, if not nil, is a target string.  WIN is a
-   window where the characters are being displayed.  If characters are
+   window where the characters are being displayed.  CH is the
+   character that triggered the composition check.  If characters are
    successfully composed, return the composition as a glyph-string
    object.  Otherwise return nil.  */
 
 static Lisp_Object
 autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
               ptrdiff_t limit, struct window *win, struct face *face,
-              Lisp_Object string, Lisp_Object direction)
+              Lisp_Object string, Lisp_Object direction, int ch)
 {
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object pos = make_fixnum (charpos);
@@ -920,7 +921,7 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, 
ptrdiff_t bytepos,
   struct frame *f = XFRAME (font_object);
   if (FRAME_WINDOW_P (f))
     {
-      font_object = font_range (charpos, bytepos, &to, win, face, string);
+      font_object = font_range (charpos, bytepos, &to, win, face, string, ch);
       if (! FONT_OBJECT_P (font_object)
          || (! NILP (re)
              && to < limit
@@ -1272,7 +1273,7 @@ composition_reseat_it (struct composition_it *cmp_it, 
ptrdiff_t charpos,
              if (XFIXNAT (AREF (elt, 1)) != cmp_it->lookback)
                goto no_composition;
              lgstring = autocmp_chars (elt, charpos, bytepos, endpos,
-                                       w, face, string, direction);
+                                       w, face, string, direction, cmp_it->ch);
              if (composition_gstring_p (lgstring))
                break;
              lgstring = Qnil;
@@ -1310,7 +1311,7 @@ composition_reseat_it (struct composition_it *cmp_it, 
ptrdiff_t charpos,
          else
            direction = QR2L;
          lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face,
-                                   string, direction);
+                                   string, direction, cmp_it->ch);
          if (! composition_gstring_p (lgstring)
              || cpos + LGSTRING_CHAR_LEN (lgstring) - 1 != charpos)
            /* Composition failed or didn't cover the current
@@ -1679,7 +1680,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t 
limit, ptrdiff_t backlim,
                  for (check = cur; check_pos < check.pos; )
                    BACKWARD_CHAR (check, stop);
                  *gstring = autocmp_chars (elt, check.pos, check.pos_byte,
-                                           tail, w, NULL, string, Qnil);
+                                           tail, w, NULL, string, Qnil, c);
                  need_adjustment = 1;
                  if (NILP (*gstring))
                    {
diff --git a/src/font.c b/src/font.c
index e043ef8..82a1dff 100644
--- a/src/font.c
+++ b/src/font.c
@@ -3866,6 +3866,9 @@ font_at (int c, ptrdiff_t pos, struct face *face, struct 
window *w,
    If STRING is not nil, it is the string to check instead of the current
    buffer.  In that case, FACE must be not NULL.
 
+   CH is the character that actually caused the composition
+   process to start, it may be different from the character at POS.
+
    The return value is the font-object for the character at POS.
    *LIMIT is set to the position where that font can't be used.
 
@@ -3873,15 +3876,16 @@ font_at (int c, ptrdiff_t pos, struct face *face, 
struct window *w,
 
 Lisp_Object
 font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
-           struct window *w, struct face *face, Lisp_Object string)
+           struct window *w, struct face *face, Lisp_Object string,
+           int ch)
 {
   ptrdiff_t ignore;
   int c;
   Lisp_Object font_object = Qnil;
+  struct frame *f = XFRAME (w->frame);
 
   if (!face)
     {
-      struct frame *f = XFRAME (w->frame);
       int face_id;
 
       if (NILP (string))
@@ -3900,6 +3904,24 @@ font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t 
*limit,
       face = FACE_FROM_ID (f, face_id);
     }
 
+  /* If the composition was triggered by an emoji, use a character
+     from 'script-representative-chars', rather than the first
+     character in the string, to determine the font to use.  */
+  if (EQ (CHAR_TABLE_REF (Vchar_script_table, ch),
+         Qemoji))
+    {
+      Lisp_Object val = assq_no_quit (Qemoji, Vscript_representative_chars);
+      if (CONSP (val))
+       {
+         val = XCDR (val);
+         if (CONSP (val))
+           val = XCAR (val);
+         else if (VECTORP (val))
+           val = AREF (val, 0);
+         font_object = font_for_char (face, XFIXNAT (val), pos - 1, string);
+       }
+    }
+
   while (pos < *limit)
     {
       c = (NILP (string)
@@ -5423,6 +5445,7 @@ syms_of_font (void)
   DEFSYM (Qiso8859_1, "iso8859-1");
   DEFSYM (Qiso10646_1, "iso10646-1");
   DEFSYM (Qunicode_bmp, "unicode-bmp");
+  DEFSYM (Qemoji, "emoji");
 
   /* Symbols representing keys of font extra info.  */
   DEFSYM (QCotf, ":otf");
diff --git a/src/font.h b/src/font.h
index d3e1530..1da72cc 100644
--- a/src/font.h
+++ b/src/font.h
@@ -885,7 +885,7 @@ valid_font_driver (struct font_driver const *d)
 extern Lisp_Object font_update_drivers (struct frame *f, Lisp_Object list);
 extern Lisp_Object font_range (ptrdiff_t, ptrdiff_t, ptrdiff_t *,
                               struct window *, struct face *,
-                              Lisp_Object);
+                              Lisp_Object, int);
 extern void font_fill_lglyph_metrics (Lisp_Object, struct font *, unsigned 
int);
 
 extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop,



reply via email to

[Prev in Thread] Current Thread [Next in Thread]