]> git.eshelyaron.com Git - emacs.git/commitdiff
Implement the otf_capability method for HarfBuzz
authorYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
Mon, 1 Jul 2019 07:58:53 +0000 (16:58 +0900)
committerYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
Mon, 1 Jul 2019 07:58:53 +0000 (16:58 +0900)
* src/hbfont.c: Include hb-ot.h.
[HAVE_NTGUI]: Add DEF_DLL_FN and #define for hb_tag_to_string,
hb_font_get_face, hb_ot_layout_table_get_script_tags,
hb_ot_layout_table_get_feature_tags, hb_ot_layout_script_get_language_tags,
and hb_ot_layout_language_get_feature_tags.
(hbfont_init_w32_funcs) [HAVE_NTGUI]: Add LOAD_DLL_FN for them.
(hbfont_otf_features, hbfont_otf_capability): New functions.

* src/font.h (hbfont_otf_capability) [HAVE_HARFBUZZ]: Add extern.

* src/ftcrfont.c (syms_of_ftcrfont_for_pdumper) [HAVE_HARFBUZZ]:
* src/ftfont.c (syms_of_ftfont_for_pdumper) [HAVE_HARFBUZZ]:
* src/w32uniscribe.c (syms_of_w32uniscribe_for_pdumper) [HAVE_HARFBUZZ]:
* src/xftfont.c (syms_of_xftfont_for_pdumper) [HAVE_HARFBUZZ]: Populate
otf_capability method with hbfont_otf_capability.

src/font.h
src/ftcrfont.c
src/ftfont.c
src/hbfont.c
src/w32uniscribe.c
src/xftfont.c

index 1f35744642b25bd1ecd700dac9e4ede8d02c7834..3387878ad30662467af122290ab1aa62084e8ae4 100644 (file)
@@ -891,6 +891,7 @@ extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop,
                                    Lisp_Object val);
 
 #ifdef HAVE_HARFBUZZ
+extern Lisp_Object hbfont_otf_capability (struct font *);
 extern Lisp_Object hbfont_shape (Lisp_Object, Lisp_Object);
 extern Lisp_Object hbfont_combining_capability (struct font *);
 #endif
index f15e79334ac0850776e6b233d08cc69ce3caae4e..ff61ecfe313838111ad80088e538899a5954abe6 100644 (file)
@@ -621,6 +621,7 @@ syms_of_ftcrfont_for_pdumper (void)
   ftcrhbfont_driver.type = Qftcrhb;
   ftcrhbfont_driver.list = ftcrhbfont_list;
   ftcrhbfont_driver.match = ftcrhbfont_match;
+  ftcrhbfont_driver.otf_capability = hbfont_otf_capability,
   ftcrhbfont_driver.shape = hbfont_shape;
   ftcrhbfont_driver.combining_capability = hbfont_combining_capability;
   ftcrhbfont_driver.begin_hb_font = ftcrhbfont_begin_hb_font;
index 384279f616b21a4bbc55f1529344559f6b15d443..6f03d96660692436045183d385b9081748853b62 100644 (file)
@@ -3012,6 +3012,7 @@ syms_of_ftfont_for_pdumper (void)
 #ifdef HAVE_HARFBUZZ
   fthbfont_driver = ftfont_driver;
   fthbfont_driver.type = Qfreetypehb;
+  fthbfont_driver.otf_capability = hbfont_otf_capability,
   fthbfont_driver.shape = hbfont_shape;
   fthbfont_driver.combining_capability = hbfont_combining_capability;
   fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font;
index 623bee61cc857de38fb243da430ab6612de41c9b..455c1a7a554b06eefb4c9d7472bafc3c2b094d1c 100644 (file)
@@ -19,6 +19,7 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <math.h>
 #include <hb.h>
+#include <hb-ot.h>
 
 #include "lisp.h"
 #include "frame.h"
@@ -69,6 +70,18 @@ DEF_DLL_FN (hb_glyph_info_t *, hb_buffer_get_glyph_infos,
            (hb_buffer_t *, unsigned int *));
 DEF_DLL_FN (hb_glyph_position_t *, hb_buffer_get_glyph_positions,
            (hb_buffer_t *, unsigned int *));
+DEF_DLL_FN (void, hb_tag_to_string, (hb_tag_t, char *));
+DEF_DLL_FN (hb_face_t *, hb_font_get_face, (hb_font_t *font));
+DEF_DLL_FN (unsigned int, hb_ot_layout_table_get_script_tags,
+           (hb_face_t *, hb_tag_t, unsigned int, unsigned int *, hb_tag_t *));
+DEF_DLL_FN (unsigned int, hb_ot_layout_table_get_feature_tags,
+           (hb_face_t *, hb_tag_t, unsigned int, unsigned int *, hb_tag_t *));
+DEF_DLL_FN (unsigned int, hb_ot_layout_script_get_language_tags,
+           (hb_face_t *, hb_tag_t, unsigned int, unsigned int, unsigned int *,
+            hb_tag_t *));
+DEF_DLL_FN (unsigned int, hb_ot_layout_language_get_feature_tags,
+           (hb_face_t *, hb_tag_t, unsigned int, unsigned int, unsigned int,
+            unsigned int *, hb_tag_t *));
 
 #define hb_unicode_funcs_create fn_hb_unicode_funcs_create
 #define hb_unicode_funcs_get_default fn_hb_unicode_funcs_get_default
@@ -92,6 +105,12 @@ DEF_DLL_FN (hb_glyph_position_t *, hb_buffer_get_glyph_positions,
 #define hb_buffer_reverse_clusters fn_hb_buffer_reverse_clusters
 #define hb_buffer_get_glyph_infos fn_hb_buffer_get_glyph_infos
 #define hb_buffer_get_glyph_positions fn_hb_buffer_get_glyph_positions
+#define hb_tag_to_string fn_hb_tag_to_string
+#define hb_font_get_face fn_hb_font_get_face
+#define hb_ot_layout_table_get_script_tags fn_hb_ot_layout_table_get_script_tags
+#define hb_ot_layout_table_get_feature_tags fn_hb_ot_layout_table_get_feature_tags
+#define hb_ot_layout_script_get_language_tags fn_hb_ot_layout_script_get_language_tags
+#define hb_ot_layout_language_get_feature_tags fn_hb_ot_layout_language_get_feature_tags
 
 /* This function is called from syms_of_w32uniscribe_for_pdumper to
    initialize the above function pointers.  */
@@ -120,10 +139,103 @@ hbfont_init_w32_funcs (HMODULE library)
   LOAD_DLL_FN (library, hb_buffer_reverse_clusters);
   LOAD_DLL_FN (library, hb_buffer_get_glyph_infos);
   LOAD_DLL_FN (library, hb_buffer_get_glyph_positions);
+  LOAD_DLL_FN (library, hb_tag_to_string);
+  LOAD_DLL_FN (library, hb_font_get_face);
+  LOAD_DLL_FN (library, hb_ot_layout_table_get_script_tags);
+  LOAD_DLL_FN (library, hb_ot_layout_table_get_feature_tags);
+  LOAD_DLL_FN (library, hb_ot_layout_script_get_language_tags);
+  LOAD_DLL_FN (library, hb_ot_layout_language_get_feature_tags);
   return true;
 }
 #endif /* HAVE_NTGUI */
 
+static Lisp_Object
+hbfont_otf_features (hb_face_t *face, hb_tag_t table_tag)
+{
+  hb_tag_t *language_tags = NULL, *feature_tags = NULL;
+  char buf[4];
+  unsigned int script_count
+    = hb_ot_layout_table_get_script_tags (face, table_tag, 0, NULL, NULL);
+  hb_tag_t *script_tags = xnmalloc (script_count, sizeof *script_tags);
+  hb_ot_layout_table_get_script_tags (face, table_tag, 0, &script_count,
+                                     script_tags);
+  Lisp_Object scripts = Qnil;
+  for (int i = script_count - 1; i >= 0; i--)
+    {
+      unsigned int language_count
+       = hb_ot_layout_script_get_language_tags (face, table_tag, i, 0,
+                                                NULL, NULL);
+      language_tags = xnrealloc (language_tags, language_count,
+                                sizeof *language_tags);
+      hb_ot_layout_script_get_language_tags (face, table_tag, i, 0,
+                                            &language_count, language_tags);
+      Lisp_Object langsyses = Qnil;
+      for (int j = language_count - 1; j >= -1; j--)
+       {
+         unsigned int language_index
+           = j >= 0 ? j : HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
+         unsigned int feature_count
+           = hb_ot_layout_language_get_feature_tags (face, table_tag,
+                                                     i, language_index, 0,
+                                                     NULL, NULL);
+         if (feature_count == 0)
+           continue;
+         feature_tags = xnrealloc (feature_tags, feature_count,
+                                   sizeof *feature_tags);
+         hb_ot_layout_language_get_feature_tags (face, table_tag,
+                                                 i, language_index, 0,
+                                                 &feature_count, feature_tags);
+         Lisp_Object features = Qnil;
+         for (int k = feature_count - 1; k >= 0; k--)
+           {
+             hb_tag_to_string (feature_tags[k], buf);
+             features = Fcons (font_intern_prop (buf, 4, 1), features);
+           }
+
+         Lisp_Object sym = Qnil;
+         if (j >= 0)
+           {
+             hb_tag_to_string (language_tags[j], buf);
+             sym = font_intern_prop (buf, 4, 1);
+           }
+         langsyses = Fcons (Fcons (sym, features), langsyses);
+       }
+
+      hb_tag_to_string (script_tags[i], buf);
+      scripts = Fcons (Fcons (font_intern_prop (buf, 4, 1), langsyses),
+                      scripts);
+    }
+  xfree (feature_tags);
+  xfree (language_tags);
+  xfree (script_tags);
+
+  return scripts;
+}
+
+Lisp_Object
+hbfont_otf_capability (struct font *font)
+{
+  double position_unit;
+  hb_font_t *hb_font
+    = font->driver->begin_hb_font
+    ? font->driver->begin_hb_font (font, &position_unit)
+    : NULL;
+  if (!hb_font)
+    return Qnil;
+
+  Lisp_Object gsub_gpos = Fcons (Qnil, Qnil);
+  hb_face_t *face = hb_font_get_face (hb_font);
+  if (hb_ot_layout_table_get_feature_tags (face, HB_OT_TAG_GSUB, 0, NULL, NULL))
+    XSETCAR (gsub_gpos, hbfont_otf_features (face, HB_OT_TAG_GSUB));
+  if (hb_ot_layout_table_get_feature_tags (face, HB_OT_TAG_GPOS, 0, NULL, NULL))
+    XSETCDR (gsub_gpos, hbfont_otf_features (face, HB_OT_TAG_GPOS));
+
+  if (font->driver->end_hb_font)
+    font->driver->end_hb_font (font, hb_font);
+
+  return gsub_gpos;
+}
+
 /* Support functions for HarfBuzz shaper.  */
 
 static bool combining_class_loaded = false;
index d59d564abb4aa1724daa8146024f796daedd2f3c..aa6bebdc024fdae12b849feef791f8e67ea63cbb 100644 (file)
@@ -1540,6 +1540,7 @@ syms_of_w32uniscribe_for_pdumper (void)
   harfbuzz_font_driver.list = w32hb_list;
   harfbuzz_font_driver.match = w32hb_match;
   harfbuzz_font_driver.encode_char = w32hb_encode_char;
+  harfbuzz_font_driver.otf_capability = hbfont_otf_capability,
   harfbuzz_font_driver.shape = hbfont_shape;
   harfbuzz_font_driver.get_variation_glyphs = w32hb_get_variation_glyphs;
   harfbuzz_font_driver.combining_capability = hbfont_combining_capability;
index 4d2a5f520e00ed8678e89595bc4acfcbba52da84..2cad6db933b9c508ab4cbb8511414b5a34fd17d7 100644 (file)
@@ -700,6 +700,7 @@ syms_of_xftfont_for_pdumper (void)
   xfthbfont_driver.type = Qxfthb;
   xfthbfont_driver.list = xfthbfont_list;
   xfthbfont_driver.match = xfthbfont_match;
+  xfthbfont_driver.otf_capability = hbfont_otf_capability,
   xfthbfont_driver.shape = hbfont_shape;
   xfthbfont_driver.combining_capability = hbfont_combining_capability;
   xfthbfont_driver.begin_hb_font = xfthbfont_begin_hb_font;