]> git.eshelyaron.com Git - emacs.git/commitdiff
Merge from origin/emacs-28
authorStefan Kangas <stefankangas@gmail.com>
Wed, 28 Sep 2022 13:35:06 +0000 (15:35 +0200)
committerStefan Kangas <stefankangas@gmail.com>
Wed, 28 Sep 2022 13:35:06 +0000 (15:35 +0200)
72aac80184 ; Fix typo
c54a64491f Add .mailmap for proper git log output
f9a072c592 ; Fix typo
3d056f6947 * doc/emacs/ack.texi (Acknowledgments): Update maintainers.
00159c086c ; Add commentary to disabled OTF support code in font.c

# Conflicts:
# src/font.c

1  2 
src/font.c

diff --cc src/font.c
index defbb5084b502885472153701218297b72563d62,8f448d9bdc3200360cf5c3938bbe12f196195704..6e720bc2856e95fbf56707fd392ae4fbbb58f64e
@@@ -4692,134 -4363,428 +4402,427 @@@ Each element of the value is a cons (VA
  where
    VARIATION-SELECTOR is a character code of variation selector
      (#xFE00..#xFE0F or #xE0100..#xE01EF).
 -  GLYPH-ID is a glyph code of the corresponding variation glyph,
 -a fixnum, if it's small enough, otherwise a bignum.  */)
 +  GLYPH-ID is a glyph code of the corresponding variation glyph, an integer.  */)
    (Lisp_Object font_object, Lisp_Object character)
  {
-   unsigned variations[256];
-   struct font *font;
-   int i, n;
-   Lisp_Object val;
+   unsigned variations[256];
+   struct font *font;
+   int i, n;
+   Lisp_Object val;
+   CHECK_FONT_OBJECT (font_object);
+   CHECK_CHARACTER (character);
+   font = XFONT_OBJECT (font_object);
+   if (! font->driver->get_variation_glyphs)
+     return Qnil;
+   n = font->driver->get_variation_glyphs (font, XFIXNUM (character), variations);
+   if (! n)
+     return Qnil;
+   val = Qnil;
+   for (i = 0; i < 255; i++)
+     if (variations[i])
+       {
+       int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
+       Lisp_Object code = INT_TO_INTEGER (variations[i]);
+       val = Fcons (Fcons (make_fixnum (vs), code), val);
+       }
+   return val;
+ }
+ /* Return a description of the font at POSITION in the current buffer.
+    If the 2nd optional arg CH is non-nil, it is a character to check
+    the font instead of the character at POSITION.
+    For a graphical display, return a cons (FONT-OBJECT . GLYPH-CODE).
+    FONT-OBJECT is the font for the character at POSITION in the current
+    buffer.  This is computed from all the text properties and overlays
+    that apply to POSITION.  POSITION may be nil, in which case,
+    FONT-SPEC is the font for displaying the character CH with the
+    default face.  GLYPH-CODE is the glyph code in the font to use for
+    the character, it is a fixnum, if it is small enough, otherwise a
+    bignum.
+    For a text terminal, return a nonnegative integer glyph code for
+    the character, or a negative integer if the character is not
+    displayable.  Terminal glyph codes are system-dependent integers
+    that represent displayable characters: for example, on a Linux x86
+    console they represent VGA code points.
+    It returns nil in the following cases:
+    (1) The window system doesn't have a font for the character (thus
+    it is displayed by an empty box).
+    (2) The character code is invalid.
+    (3) If POSITION is not nil, and the current buffer is not displayed
+    in any window.
+    (4) For a text terminal, the terminal does not report glyph codes.
+    In addition, the returned font name may not take into account of
+    such redisplay engine hooks as what used in jit-lock-mode if
+    POSITION is currently not visible.  */
+ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
+        doc: /* For internal use only.  */)
+   (Lisp_Object position, Lisp_Object ch)
+ {
+   ptrdiff_t pos, pos_byte, dummy;
+   int face_id;
+   int c;
+   struct frame *f;
+   if (NILP (position))
+     {
+       CHECK_CHARACTER (ch);
+       c = XFIXNUM (ch);
+       f = XFRAME (selected_frame);
+       face_id = lookup_basic_face (NULL, f, DEFAULT_FACE_ID);
+       pos = -1;
+     }
+   else
+     {
+       Lisp_Object window;
+       struct window *w;
+       EMACS_INT fixed_pos = fix_position (position);
+       if (! (BEGV <= fixed_pos && fixed_pos < ZV))
+       args_out_of_range_3 (position, make_fixnum (BEGV), make_fixnum (ZV));
+       pos = fixed_pos;
+       pos_byte = CHAR_TO_BYTE (pos);
+       if (NILP (ch))
+       c = FETCH_CHAR (pos_byte);
+       else
+       {
+         CHECK_FIXNAT (ch);
+         c = XFIXNUM (ch);
+       }
+       window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
+       if (NILP (window))
+       return Qnil;
+       w = XWINDOW (window);
+       f = XFRAME (w->frame);
+       face_id = face_at_buffer_position (w, pos, &dummy,
+                                          pos + 100, false, -1, 0);
+     }
+   if (! CHAR_VALID_P (c))
+     return Qnil;
+   if (! FRAME_WINDOW_P (f))
+     return terminal_glyph_code (FRAME_TERMINAL (f), c);
+   /* We need the basic faces to be valid below, so recompute them if
+      some code just happened to clear the face cache.  */
+   if (FRAME_FACE_CACHE (f)->used == 0)
+     recompute_basic_faces (f);
+   face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
+   struct face *face = FACE_FROM_ID (f, face_id);
+   if (! face->font)
+     return Qnil;
+   unsigned code = face->font->driver->encode_char (face->font, c);
+   if (code == FONT_INVALID_CODE)
+     return Qnil;
+   Lisp_Object font_object;
+   XSETFONT (font_object, face->font);
+   return Fcons (font_object, INT_TO_INTEGER (code));
+ }
\f
+ /* This part (through the next ^L) is still experimental and not
+    tested much.  We may drastically change codes.  */
+ /* This code implements support for extracting OTF features of a font
+    and exposing them to Lisp, including application of those features
+    to arbitrary stretches of text.  FIXME: it would be good to finish
+    this work and have this in Emacs.  */
+ /* OTF handler.  */
+ #if 0
+ #define LGSTRING_HEADER_SIZE 6
+ #define LGSTRING_GLYPH_SIZE 8
+ static int
+ check_gstring (Lisp_Object gstring)
+ {
+   Lisp_Object val;
+   ptrdiff_t i;
+   int j;
+   CHECK_VECTOR (gstring);
+   val = AREF (gstring, 0);
+   CHECK_VECTOR (val);
+   if (ASIZE (val) < LGSTRING_HEADER_SIZE)
+     goto err;
+   CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
+   if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
+     CHECK_FIXNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
+   if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
+     CHECK_FIXNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
+   if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
+     CHECK_FIXNAT (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
+   if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
+     CHECK_FIXNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
+   if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
+     CHECK_FIXNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
+   for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
+     {
+       val = LGSTRING_GLYPH (gstring, i);
+       CHECK_VECTOR (val);
+       if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
+       goto err;
+       if (NILP (AREF (val, LGLYPH_IX_CHAR)))
+       break;
+       CHECK_FIXNAT (AREF (val, LGLYPH_IX_FROM));
+       CHECK_FIXNAT (AREF (val, LGLYPH_IX_TO));
+       CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
+       if (!NILP (AREF (val, LGLYPH_IX_CODE)))
+       CHECK_FIXNAT (AREF (val, LGLYPH_IX_CODE));
+       if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
+       CHECK_FIXNAT (AREF (val, LGLYPH_IX_WIDTH));
+       if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
+       {
+         val = AREF (val, LGLYPH_IX_ADJUSTMENT);
+         CHECK_VECTOR (val);
+         if (ASIZE (val) < 3)
+           goto err;
+         for (j = 0; j < 3; j++)
+           CHECK_FIXNUM (AREF (val, j));
+       }
+     }
+   return i;
+  err:
+   error ("Invalid glyph-string format");
+   return -1;
+ }
+ static void
+ check_otf_features (Lisp_Object otf_features)
+ {
+   Lisp_Object val;
+   CHECK_CONS (otf_features);
+   CHECK_SYMBOL (XCAR (otf_features));
+   otf_features = XCDR (otf_features);
+   CHECK_CONS (otf_features);
+   CHECK_SYMBOL (XCAR (otf_features));
+   otf_features = XCDR (otf_features);
+   for (val = Fcar (otf_features); CONSP (val); val = XCDR (val))
+     {
+       CHECK_SYMBOL (XCAR (val));
+       if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
+       error ("Invalid OTF GSUB feature: %s",
+              SDATA (SYMBOL_NAME (XCAR (val))));
+     }
+   otf_features = XCDR (otf_features);
+   for (val = Fcar (otf_features); CONSP (val); val = XCDR (val))
+     {
+       CHECK_SYMBOL (XCAR (val));
+       if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
+       error ("Invalid OTF GPOS feature: %s",
+              SDATA (SYMBOL_NAME (XCAR (val))));
+     }
+ }
+ #ifdef HAVE_LIBOTF
+ #include <otf.h>
+ Lisp_Object otf_list;
+ static Lisp_Object
+ otf_tag_symbol (OTF_Tag tag)
+ {
+   char name[5];
+   OTF_tag_name (tag, name);
+   return Fintern (make_unibyte_string (name, 4), Qnil);
+ }
+ static OTF *
+ otf_open (Lisp_Object file)
+ {
+   Lisp_Object val = Fassoc (file, otf_list, Qnil);
+   OTF *otf;
  
-   CHECK_FONT_OBJECT (font_object);
-   CHECK_CHARACTER (character);
-   font = XFONT_OBJECT (font_object);
-   if (! font->driver->get_variation_glyphs)
-     return Qnil;
-   n = font->driver->get_variation_glyphs (font, XFIXNUM (character), variations);
-   if (! n)
-     return Qnil;
-   val = Qnil;
-   for (i = 0; i < 255; i++)
-     if (variations[i])
-       {
-       int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
-       Lisp_Object code = INT_TO_INTEGER (variations[i]);
-       val = Fcons (Fcons (make_fixnum (vs), code), val);
-       }
-   return val;
+   if (! NILP (val))
+     otf = xmint_pointer (XCDR (val));
+   else
+     {
+       otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL;
+       val = make_mint_ptr (otf);
+       otf_list = Fcons (Fcons (file, val), otf_list);
+     }
+   return otf;
  }
  
- /* Return a description of the font at POSITION in the current buffer.
-    If the 2nd optional arg CH is non-nil, it is a character to check
-    the font instead of the character at POSITION.
  
-    For a graphical display, return a cons (FONT-OBJECT . GLYPH-CODE).
-    FONT-OBJECT is the font for the character at POSITION in the current
-    buffer.  This is computed from all the text properties and overlays
-    that apply to POSITION.  POSITION may be nil, in which case,
-    FONT-SPEC is the font for displaying the character CH with the
-    default face.  GLYPH-CODE is the glyph code in the font to use for
-    the character, as an integer.
+ /* Return a list describing which scripts/languages FONT supports by
+    which GSUB/GPOS features of OpenType tables.  See the comment of
+    (struct font_driver).otf_capability.  */
  
-    For a text terminal, return a nonnegative integer glyph code for
-    the character, or a negative integer if the character is not
-    displayable.  Terminal glyph codes are system-dependent integers
-    that represent displayable characters: for example, on a Linux x86
-    console they represent VGA code points.
+ Lisp_Object
+ font_otf_capability (struct font *font)
+ {
+   OTF *otf;
+   Lisp_Object capability = Fcons (Qnil, Qnil);
+   int i;
  
-    It returns nil in the following cases:
+   otf = otf_open (font->props[FONT_FILE_INDEX]);
+   if (! otf)
+     return Qnil;
+   for (i = 0; i < 2; i++)
+     {
+       OTF_GSUB_GPOS *gsub_gpos;
+       Lisp_Object script_list = Qnil;
+       int j;
  
-    (1) The window system doesn't have a font for the character (thus
-    it is displayed by an empty box).
+       if (OTF_get_features (otf, i == 0) < 0)
+       continue;
+       gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
+       for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
+       {
+         OTF_Script *script = gsub_gpos->ScriptList.Script + j;
+         Lisp_Object langsys_list = Qnil;
+         Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
+         int k;
  
-    (2) The character code is invalid.
+         for (k = script->LangSysCount; k >= 0; k--)
+           {
+             OTF_LangSys *langsys;
+             Lisp_Object feature_list = Qnil;
+             Lisp_Object langsys_tag;
+             int l;
  
-    (3) If POSITION is not nil, and the current buffer is not displayed
-    in any window.
+             if (k == script->LangSysCount)
+               {
+                 langsys = &script->DefaultLangSys;
+                 langsys_tag = Qnil;
+               }
+             else
+               {
+                 langsys = script->LangSys + k;
+                 langsys_tag
+                   = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
+               }
+             for (l = langsys->FeatureCount - 1; l >= 0; l--)
+               {
+                 OTF_Feature *feature
+                   = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
+                 Lisp_Object feature_tag
+                   = otf_tag_symbol (feature->FeatureTag);
  
-    (4) For a text terminal, the terminal does not report glyph codes.
+                 feature_list = Fcons (feature_tag, feature_list);
+               }
+             langsys_list = Fcons (Fcons (langsys_tag, feature_list),
+                                   langsys_list);
+           }
+         script_list = Fcons (Fcons (script_tag, langsys_list),
+                              script_list);
+       }
  
-    In addition, the returned font name may not take into account of
-    such redisplay engine hooks as what used in jit-lock-mode if
-    POSITION is currently not visible.  */
+       if (i == 0)
+       XSETCAR (capability, script_list);
+       else
+       XSETCDR (capability, script_list);
+     }
  
+   return capability;
+ }
  
- DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
-        doc: /* For internal use only.  */)
-   (Lisp_Object position, Lisp_Object ch)
+ /* Parse OTF features in SPEC and write a proper features spec string
+    in FEATURES for the call of OTF_drive_gsub/gpos (of libotf).  It is
+    assured that the sufficient memory has already allocated for
+    FEATURES.  */
+ static void
+ generate_otf_features (Lisp_Object spec, char *features)
  {
-   ptrdiff_t pos, pos_byte, dummy;
-   int face_id;
-   int c;
-   struct frame *f;
+   Lisp_Object val;
+   char *p;
+   bool asterisk;
  
-   if (NILP (position))
-     {
-       CHECK_CHARACTER (ch);
-       c = XFIXNUM (ch);
-       f = XFRAME (selected_frame);
-       face_id = lookup_basic_face (NULL, f, DEFAULT_FACE_ID);
-       pos = -1;
-     }
-   else
+   p = features;
+   *p = '\0';
+   for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
      {
-       Lisp_Object window;
-       struct window *w;
-       EMACS_INT fixed_pos = fix_position (position);
-       if (! (BEGV <= fixed_pos && fixed_pos < ZV))
-       args_out_of_range_3 (position, make_fixnum (BEGV), make_fixnum (ZV));
-       pos = fixed_pos;
-       pos_byte = CHAR_TO_BYTE (pos);
-       if (NILP (ch))
-       c = FETCH_CHAR (pos_byte);
+       val = XCAR (spec);
+       CHECK_SYMBOL (val);
+       if (p > features)
+       *p++ = ',';
+       if (SREF (SYMBOL_NAME (val), 0) == '*')
+       {
+         asterisk = 1;
+         *p++ = '*';
+       }
+       else if (! asterisk)
+       {
+         val = SYMBOL_NAME (val);
+         p += esprintf (p, "%s", SDATA (val));
+       }
        else
        {
-         CHECK_FIXNAT (ch);
-         c = XFIXNUM (ch);
+         val = SYMBOL_NAME (val);
+         p += esprintf (p, "~%s", SDATA (val));
        }
-       window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
-       if (NILP (window))
-       return Qnil;
-       w = XWINDOW (window);
-       f = XFRAME (w->frame);
-       face_id = face_at_buffer_position (w, pos, &dummy,
-                                          pos + 100, false, -1, 0);
      }
-   if (! CHAR_VALID_P (c))
-     return Qnil;
+   if (CONSP (spec))
+     error ("OTF spec too long");
+ }
  
-   if (! FRAME_WINDOW_P (f))
-     return terminal_glyph_code (FRAME_TERMINAL (f), c);
+ Lisp_Object
+ font_otf_DeviceTable (OTF_DeviceTable *device_table)
+ {
+   int len = device_table->StartSize - device_table->EndSize + 1;
  
-   /* We need the basic faces to be valid below, so recompute them if
-      some code just happened to clear the face cache.  */
-   if (FRAME_FACE_CACHE (f)->used == 0)
-     recompute_basic_faces (f);
+   return Fcons (make_fixnum (len),
+               make_unibyte_string (device_table->DeltaValue, len));
+ }
  
-   face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
-   struct face *face = FACE_FROM_ID (f, face_id);
-   if (! face->font)
-     return Qnil;
-   unsigned code = face->font->driver->encode_char (face->font, c);
-   if (code == FONT_INVALID_CODE)
-     return Qnil;
-   Lisp_Object font_object;
-   XSETFONT (font_object, face->font);
-   return Fcons (font_object, INT_TO_INTEGER (code));
+ Lisp_Object
+ font_otf_ValueRecord (int value_format, OTF_ValueRecord *value_record)
+ {
+   Lisp_Object val = make_nil_vector (8);
+   if (value_format & OTF_XPlacement)
+     ASET (val, 0, make_fixnum (value_record->XPlacement));
+   if (value_format & OTF_YPlacement)
+     ASET (val, 1, make_fixnum (value_record->YPlacement));
+   if (value_format & OTF_XAdvance)
+     ASET (val, 2, make_fixnum (value_record->XAdvance));
+   if (value_format & OTF_YAdvance)
+     ASET (val, 3, make_fixnum (value_record->YAdvance));
+   if (value_format & OTF_XPlaDevice)
+     ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
+   if (value_format & OTF_YPlaDevice)
+     ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
+   if (value_format & OTF_XAdvDevice)
+     ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
+   if (value_format & OTF_YAdvDevice)
+     ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
+   return val;
  }
  
- #if 0
+ Lisp_Object
+ font_otf_Anchor (OTF_Anchor *anchor)
+ {
+   Lisp_Object val = make_nil_vector (anchor->AnchorFormat + 1);
+   ASET (val, 0, make_fixnum (anchor->XCoordinate));
+   ASET (val, 1, make_fixnum (anchor->YCoordinate));
+   if (anchor->AnchorFormat == 2)
+     ASET (val, 2, make_fixnum (anchor->f.f1.AnchorPoint));
+   else
+     {
+       ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
+       ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
+     }
+   return val;
+ }
+ #endif        /* HAVE_LIBOTF */
  
  DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
         doc: /* Apply OpenType features on glyph-string GSTRING-IN.