aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2019-05-05 08:21:49 +0900
committerYAMAMOTO Mitsuharu2019-05-05 08:21:49 +0900
commitf208d5ae77cf381c6f1db9b1aef76d5e9805a106 (patch)
treed8047fb6b76a577eb69925e96f85142aabbbb943 /src
parent27511b9821d3a4d3dcb7d8bf50c37d1a46247362 (diff)
downloademacs-f208d5ae77cf381c6f1db9b1aef76d5e9805a106.tar.gz
emacs-f208d5ae77cf381c6f1db9b1aef76d5e9805a106.zip
Add new font backend drivers for text shaping by HarfBuzz
* etc/NEWS: Mention new font backend drivers xfthb and ftcrhb. * src/font.h [HAVE_HARFBUZZ]: Include hb.h. (struct font_driver) [HAVE_HARFBUZZ]: New members begin_hb_font and end_hb_font. (ftfont_match, ftfont_list): Remove externs. (ftfont_match2, ftfont_list2): (fthbfont_combining_capability, fthbfont_begin_hb_font) (fthbfont_shape) [HAVE_HARFBUZZ]: (xfthbfont_driver) [HAVE_XFT && HAVE_HARFBUZZ]: (ftcrhbfont_driver) [USE_CAIRO && HAVE_HARFBUZZ]: Add externs. * src/ftcrfont.c (ftcrfont_list): Use ftfont_list2. (ftcrfont_match): Use ftfont_match2. (ftcrfont_open): Get font type from entity. (ftcrfont_open) [HAVE_HARFBUZZ]: Use HarfBuzz version of driver if specified. (ftcrfont_shape) [HAVE_HARFBUZZ]: Make shaping fail. (ftcrhbfont_list, ftcrhbfont_match) (ftcrhbfont_begin_hb_font) [HAVE_HARFBUZZ]: New functions. (ftcrhbfont_driver) [HAVE_HARFBUZZ]: New variable. (syms_of_ftcrfont_for_pdumper) [HAVE_HARFBUZZ]: Initialize and register it. (syms_of_ftcrfont) [HAVE_HARFBUZZ]: New symbol Qftcrhb. * src/ftfont.c: Include math.h for lround. (fthbfont_driver) [HAVE_HARFBUZZ]: New variable. (ftfont_get_hb_font) [HAVE_HARFBUZZ]: Remove function. (ftfont_list, ftfont_match): Make static. (ftfont_list2, ftfont_match2): New functions. (ftfont_open2) [HAVE_HARFBUZZ]: Use HarfBuzz version of driver if specified. (ftfont_open): Get font type from entity. (ftfont_shape, ftfont_combining_capability, ftfont_driver) [HAVE_HARFBUZZ]: Move HarfBuzz specific part from here ... (fthbfont_shape, fthbfont_combining_capability) (fthbfont_driver) [HAVE_HARFBUZZ]: ... to here. New functions and variable. (fthbfont_begin_hb_font) [HAVE_HARFBUZZ]: New function. (fthbfont_shape_by_hb) [HAVE_HARFBUZZ]: Rename from ftfont_shape_by_hb. Don't take FreeType specific arguments ft_face and matrix. Use begin_hb_font and end_hb_font font driver functions. Use text_extents font driver functions instead of ftfont_glyph_metrics. (syms_of_ftfont) [HAVE_HARFBUZZ]: New symbol Qfreetypehb. (syms_of_ftfont_for_pdumper) [HAVE_HARFBUZZ]: Initialize and register fthbfont_drivert. * src/ftxfont.c (ftxfont_list): Use ftfont_list2. (ftxfont_match): Use ftfont_match2. (ftxfont_driver) [HAVE_HARFBUZZ]: Don't initialize shape member explicitly. * src/xfns.c (Fx_create_frame) [USE_CAIRO && HAVE_HARFBUZZ]: (Fx_create_frame) [HAVE_XFT && HAVE_HARFBUZZ]: Register HarfBuzz versions of font drivers. * src/xftfont.c (xftfont_list): Use ftfont_list2. (xftfont_match): Use ftfont_match2. (xftfont_open): Get font type from entity. (xftfont_open) [HAVE_HARFBUZZ]: Use HarfBuzz version of driver if specified. (xftfont_shape) [HAVE_HARFBUZZ]: Make shaping fail. (xfthbfont_list, xfthbfont_match, xfthbfont_begin_hb_font) (xfthbfont_end_hb_font) [HAVE_HARFBUZZ]: New functions. (xftfont_driver) [HAVE_HARFBUZZ]: Don't initialize shape member explicitly. (xfthbfont_driver) [HAVE_HARFBUZZ]: New variable. (syms_of_xftfont_for_pdumper) [HAVE_HARFBUZZ]: Initialize and register it. (syms_of_xftfont) [HAVE_HARFBUZZ]: New symbol Qxfthb.
Diffstat (limited to 'src')
-rw-r--r--src/font.h34
-rw-r--r--src/ftcrfont.c71
-rw-r--r--src/ftfont.c174
-rw-r--r--src/ftxfont.c14
-rw-r--r--src/xfns.c6
-rw-r--r--src/xftfont.c76
6 files changed, 274 insertions, 101 deletions
diff --git a/src/font.h b/src/font.h
index 3540a8dba22..1f62a61f0be 100644
--- a/src/font.h
+++ b/src/font.h
@@ -22,6 +22,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
22#ifndef EMACS_FONT_H 22#ifndef EMACS_FONT_H
23#define EMACS_FONT_H 23#define EMACS_FONT_H
24 24
25#ifdef HAVE_HARFBUZZ
26#include <hb.h>
27#endif /* HAVE_HARFBUZZ */
28
25struct composition_it; 29struct composition_it;
26struct face; 30struct face;
27struct glyph_string; 31struct glyph_string;
@@ -780,6 +784,21 @@ struct font_driver
780 relies on this hook to throw away its old XftDraw (which won't 784 relies on this hook to throw away its old XftDraw (which won't
781 work after the size change) and get a new one. */ 785 work after the size change) and get a new one. */
782 void (*drop_xrender_surfaces) (struct frame *f); 786 void (*drop_xrender_surfaces) (struct frame *f);
787
788#ifdef HAVE_HARFBUZZ
789 /* Optional.
790 Return a HarfBuzz font object for FONT and store to
791 *POSITION_UNIT the scale factor to convert a hb_position_t value
792 to the number of pixels. Return NULL if HarfBuzz font object is
793 not available for FONT. */
794 hb_font_t *(*begin_hb_font) (struct font *font, double *position_unit);
795
796 /* Optional.
797 Called when the return value (passed as HB_FONT) of begin_hb_font
798 above is no longer used. Not called if the return value of
799 begin_hb_font was NULL. */
800 void (*end_hb_font) (struct font *font, hb_font_t *hb_font);
801#endif /* HAVE_HARFBUZZ */
783}; 802};
784 803
785 804
@@ -892,9 +911,9 @@ extern int ftfont_has_char (Lisp_Object, int);
892extern int ftfont_variation_glyphs (struct font *, int, unsigned[256]); 911extern int ftfont_variation_glyphs (struct font *, int, unsigned[256]);
893extern Lisp_Object ftfont_combining_capability (struct font *); 912extern Lisp_Object ftfont_combining_capability (struct font *);
894extern Lisp_Object ftfont_get_cache (struct frame *); 913extern Lisp_Object ftfont_get_cache (struct frame *);
895extern Lisp_Object ftfont_list (struct frame *, Lisp_Object); 914extern Lisp_Object ftfont_list2 (struct frame *, Lisp_Object, Lisp_Object);
896extern Lisp_Object ftfont_list_family (struct frame *); 915extern Lisp_Object ftfont_list_family (struct frame *);
897extern Lisp_Object ftfont_match (struct frame *, Lisp_Object); 916extern Lisp_Object ftfont_match2 (struct frame *, Lisp_Object, Lisp_Object);
898extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int); 917extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int);
899extern Lisp_Object ftfont_otf_capability (struct font *); 918extern Lisp_Object ftfont_otf_capability (struct font *);
900extern Lisp_Object ftfont_shape (Lisp_Object, Lisp_Object); 919extern Lisp_Object ftfont_shape (Lisp_Object, Lisp_Object);
@@ -903,6 +922,11 @@ extern void ftfont_close (struct font *);
903extern void ftfont_filter_properties (Lisp_Object, Lisp_Object); 922extern void ftfont_filter_properties (Lisp_Object, Lisp_Object);
904extern void ftfont_text_extents (struct font *, unsigned *, int, 923extern void ftfont_text_extents (struct font *, unsigned *, int,
905 struct font_metrics *); 924 struct font_metrics *);
925#ifdef HAVE_HARFBUZZ
926extern Lisp_Object fthbfont_combining_capability (struct font *);
927extern hb_font_t *fthbfont_begin_hb_font (struct font *, double *);
928extern Lisp_Object fthbfont_shape (Lisp_Object, Lisp_Object);
929#endif /* HAVE_HARFBUZZ */
906extern void syms_of_ftfont (void); 930extern void syms_of_ftfont (void);
907#endif /* HAVE_FREETYPE */ 931#endif /* HAVE_FREETYPE */
908#ifdef HAVE_X_WINDOWS 932#ifdef HAVE_X_WINDOWS
@@ -912,6 +936,9 @@ extern void syms_of_xfont (void);
912extern void syms_of_ftxfont (void); 936extern void syms_of_ftxfont (void);
913#ifdef HAVE_XFT 937#ifdef HAVE_XFT
914extern struct font_driver const xftfont_driver; 938extern struct font_driver const xftfont_driver;
939#ifdef HAVE_HARFBUZZ
940extern struct font_driver xfthbfont_driver;
941#endif /* HAVE_HARFBUZZ */
915#endif 942#endif
916#if defined HAVE_FREETYPE || defined HAVE_XFT 943#if defined HAVE_FREETYPE || defined HAVE_XFT
917extern struct font_driver const ftxfont_driver; 944extern struct font_driver const ftxfont_driver;
@@ -933,6 +960,9 @@ extern void syms_of_macfont (void);
933#endif /* HAVE_NS */ 960#endif /* HAVE_NS */
934#ifdef USE_CAIRO 961#ifdef USE_CAIRO
935extern struct font_driver const ftcrfont_driver; 962extern struct font_driver const ftcrfont_driver;
963#ifdef HAVE_HARFBUZZ
964extern struct font_driver ftcrhbfont_driver;
965#endif /* HAVE_HARFBUZZ */
936extern void syms_of_ftcrfont (void); 966extern void syms_of_ftcrfont (void);
937#endif 967#endif
938 968
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index c0f62e0418e..dc59c2bcadc 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -98,21 +98,13 @@ ftcrfont_glyph_extents (struct font *font,
98static Lisp_Object 98static Lisp_Object
99ftcrfont_list (struct frame *f, Lisp_Object spec) 99ftcrfont_list (struct frame *f, Lisp_Object spec)
100{ 100{
101 Lisp_Object list = ftfont_list (f, spec), tail; 101 return ftfont_list2 (f, spec, Qftcr);
102
103 for (tail = list; CONSP (tail); tail = XCDR (tail))
104 ASET (XCAR (tail), FONT_TYPE_INDEX, Qftcr);
105 return list;
106} 102}
107 103
108static Lisp_Object 104static Lisp_Object
109ftcrfont_match (struct frame *f, Lisp_Object spec) 105ftcrfont_match (struct frame *f, Lisp_Object spec)
110{ 106{
111 Lisp_Object entity = ftfont_match (f, spec); 107 return ftfont_match2 (f, spec, Qftcr);
112
113 if (VECTORP (entity))
114 ASET (entity, FONT_TYPE_INDEX, Qftcr);
115 return entity;
116} 108}
117 109
118static Lisp_Object 110static Lisp_Object
@@ -124,7 +116,8 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
124 if (size == 0) 116 if (size == 0)
125 size = pixel_size; 117 size = pixel_size;
126 font_object = font_build_object (VECSIZE (struct font_info), 118 font_object = font_build_object (VECSIZE (struct font_info),
127 Qftcr, entity, size); 119 AREF (entity, FONT_TYPE_INDEX),
120 entity, size);
128 block_input (); 121 block_input ();
129 font_object = ftfont_open2 (f, entity, pixel_size, font_object); 122 font_object = ftfont_open2 (f, entity, pixel_size, font_object);
130 if (FONT_OBJECT_P (font_object)) 123 if (FONT_OBJECT_P (font_object))
@@ -133,6 +126,11 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
133 struct font_info *ftcrfont_info = (struct font_info *) font; 126 struct font_info *ftcrfont_info = (struct font_info *) font;
134 FT_Face ft_face = ftcrfont_info->ft_size->face; 127 FT_Face ft_face = ftcrfont_info->ft_size->face;
135 128
129#ifdef HAVE_HARFBUZZ
130 if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qftcrhb))
131 font->driver = &ftcrhbfont_driver;
132 else
133#endif /* HAVE_HARFBUZZ */
136 font->driver = &ftcrfont_driver; 134 font->driver = &ftcrfont_driver;
137 FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw); 135 FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw);
138 FT_Activate_Size (ftcrfont_info->ft_size_draw); 136 FT_Activate_Size (ftcrfont_info->ft_size_draw);
@@ -291,7 +289,7 @@ ftcrfont_anchor_point (struct font *font, unsigned int code, int idx,
291static Lisp_Object 289static Lisp_Object
292ftcrfont_shape (Lisp_Object lgstring, Lisp_Object direction) 290ftcrfont_shape (Lisp_Object lgstring, Lisp_Object direction)
293{ 291{
294#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ 292#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
295 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 293 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
296 struct font_info *ftcrfont_info = (struct font_info *) font; 294 struct font_info *ftcrfont_info = (struct font_info *) font;
297 295
@@ -361,6 +359,39 @@ ftcrfont_draw (struct glyph_string *s,
361 return len; 359 return len;
362} 360}
363 361
362#ifdef HAVE_HARFBUZZ
363
364static Lisp_Object
365ftcrhbfont_list (struct frame *f, Lisp_Object spec)
366{
367 return ftfont_list2 (f, spec, Qftcrhb);
368}
369
370static Lisp_Object
371ftcrhbfont_match (struct frame *f, Lisp_Object spec)
372{
373 return ftfont_match2 (f, spec, Qftcrhb);
374}
375
376static hb_font_t *
377ftcrhbfont_begin_hb_font (struct font *font, double *position_unit)
378{
379 struct font_info *ftcrfont_info = (struct font_info *) font;
380
381 FT_Activate_Size (ftcrfont_info->ft_size_draw);
382 hb_font_t *hb_font = fthbfont_begin_hb_font (font, position_unit);
383 int i = ftcrfont_info->bitmap_strike_index;
384 if (i >= 0)
385 {
386 FT_Face ft_face = ftcrfont_info->ft_size_draw->face;
387 *position_unit = ((double) font->height
388 / ft_face->available_sizes[i].height) / (1 << 6);
389 }
390
391 return hb_font;
392}
393
394#endif /* HAVE_HARFBUZZ */
364 395
365 396
366static void syms_of_ftcrfont_for_pdumper (void); 397static void syms_of_ftcrfont_for_pdumper (void);
@@ -390,11 +421,17 @@ struct font_driver const ftcrfont_driver =
390 .filter_properties = ftfont_filter_properties, 421 .filter_properties = ftfont_filter_properties,
391 .combining_capability = ftfont_combining_capability, 422 .combining_capability = ftfont_combining_capability,
392 }; 423 };
424#ifdef HAVE_HARFBUZZ
425struct font_driver ftcrhbfont_driver;
426#endif /* HAVE_HARFBUZZ */
393 427
394void 428void
395syms_of_ftcrfont (void) 429syms_of_ftcrfont (void)
396{ 430{
397 DEFSYM (Qftcr, "ftcr"); 431 DEFSYM (Qftcr, "ftcr");
432#ifdef HAVE_HARFBUZZ
433 DEFSYM (Qftcrhb, "ftcrhb");
434#endif /* HAVE_HARFBUZZ */
398 pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper); 435 pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper);
399} 436}
400 437
@@ -402,4 +439,14 @@ static void
402syms_of_ftcrfont_for_pdumper (void) 439syms_of_ftcrfont_for_pdumper (void)
403{ 440{
404 register_font_driver (&ftcrfont_driver, NULL); 441 register_font_driver (&ftcrfont_driver, NULL);
442#ifdef HAVE_HARFBUZZ
443 ftcrhbfont_driver = ftcrfont_driver;
444 ftcrhbfont_driver.type = Qftcrhb;
445 ftcrhbfont_driver.list = ftcrhbfont_list;
446 ftcrhbfont_driver.match = ftcrhbfont_match;
447 ftcrhbfont_driver.shape = fthbfont_shape;
448 ftcrhbfont_driver.combining_capability = fthbfont_combining_capability;
449 ftcrhbfont_driver.begin_hb_font = ftcrhbfont_begin_hb_font;
450 register_font_driver (&ftcrhbfont_driver, NULL);
451#endif /* HAVE_HARFBUZZ */
405} 452}
diff --git a/src/ftfont.c b/src/ftfont.c
index 58c462a90fe..f4e0d7d8408 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
21 21
22#include <config.h> 22#include <config.h>
23#include <stdio.h> 23#include <stdio.h>
24#include <math.h>
24#include <fontconfig/fontconfig.h> 25#include <fontconfig/fontconfig.h>
25#include <fontconfig/fcfreetype.h> 26#include <fontconfig/fcfreetype.h>
26 27
@@ -48,6 +49,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
48#include "pdumper.h" 49#include "pdumper.h"
49 50
50static struct font_driver const ftfont_driver; 51static struct font_driver const ftfont_driver;
52#ifdef HAVE_HARFBUZZ
53static struct font_driver fthbfont_driver;
54#endif /* HAVE_HARFBUZZ */
51 55
52/* Flag to tell if FcInit is already called or not. */ 56/* Flag to tell if FcInit is already called or not. */
53static bool fc_initialized; 57static bool fc_initialized;
@@ -466,19 +470,6 @@ ftfont_get_otf (struct font_info *ftfont_info)
466} 470}
467#endif /* HAVE_LIBOTF */ 471#endif /* HAVE_LIBOTF */
468 472
469#ifdef HAVE_HARFBUZZ
470
471static hb_font_t *
472ftfont_get_hb_font (struct font_info *ftfont_info)
473{
474 if (! ftfont_info->hb_font)
475 ftfont_info->hb_font
476 = hb_ft_font_create_referenced (ftfont_info->ft_size->face);
477 return ftfont_info->hb_font;
478}
479
480#endif /* HAVE_HARFBUZZ */
481
482Lisp_Object 473Lisp_Object
483ftfont_get_cache (struct frame *f) 474ftfont_get_cache (struct frame *f)
484{ 475{
@@ -801,7 +792,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots
801 return pattern; 792 return pattern;
802} 793}
803 794
804Lisp_Object 795static Lisp_Object
805ftfont_list (struct frame *f, Lisp_Object spec) 796ftfont_list (struct frame *f, Lisp_Object spec)
806{ 797{
807 Lisp_Object val = Qnil, family, adstyle; 798 Lisp_Object val = Qnil, family, adstyle;
@@ -1001,6 +992,16 @@ ftfont_list (struct frame *f, Lisp_Object spec)
1001} 992}
1002 993
1003Lisp_Object 994Lisp_Object
995ftfont_list2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
996{
997 Lisp_Object list = ftfont_list (f, spec);
998
999 for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
1000 ASET (XCAR (tail), FONT_TYPE_INDEX, type);
1001 return list;
1002}
1003
1004static Lisp_Object
1004ftfont_match (struct frame *f, Lisp_Object spec) 1005ftfont_match (struct frame *f, Lisp_Object spec)
1005{ 1006{
1006 Lisp_Object entity = Qnil; 1007 Lisp_Object entity = Qnil;
@@ -1051,6 +1052,16 @@ ftfont_match (struct frame *f, Lisp_Object spec)
1051} 1052}
1052 1053
1053Lisp_Object 1054Lisp_Object
1055ftfont_match2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
1056{
1057 Lisp_Object entity = ftfont_match (f, spec);
1058
1059 if (! NILP (entity))
1060 ASET (entity, FONT_TYPE_INDEX, type);
1061 return entity;
1062}
1063
1064Lisp_Object
1054ftfont_list_family (struct frame *f) 1065ftfont_list_family (struct frame *f)
1055{ 1066{
1056 Lisp_Object list = Qnil; 1067 Lisp_Object list = Qnil;
@@ -1185,6 +1196,11 @@ ftfont_open2 (struct frame *f,
1185 /* This means that there's no need of transformation. */ 1196 /* This means that there's no need of transformation. */
1186 ftfont_info->matrix.xx = 0; 1197 ftfont_info->matrix.xx = 0;
1187 font->pixel_size = size; 1198 font->pixel_size = size;
1199#ifdef HAVE_HARFBUZZ
1200 if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qfreetypehb))
1201 font->driver = &fthbfont_driver;
1202 else
1203#endif /* HAVE_HARFBUZZ */
1188 font->driver = &ftfont_driver; 1204 font->driver = &ftfont_driver;
1189 font->encoding_charset = font->repertory_charset = -1; 1205 font->encoding_charset = font->repertory_charset = -1;
1190 1206
@@ -1266,7 +1282,8 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1266 if (size == 0) 1282 if (size == 0)
1267 size = pixel_size; 1283 size = pixel_size;
1268 font_object = font_build_object (VECSIZE (struct font_info), 1284 font_object = font_build_object (VECSIZE (struct font_info),
1269 Qfreetype, entity, size); 1285 AREF (entity, FONT_TYPE_INDEX),
1286 entity, size);
1270 font_object = ftfont_open2 (f, entity, pixel_size, font_object); 1287 font_object = ftfont_open2 (f, entity, pixel_size, font_object);
1271 if (FONT_OBJECT_P (font_object)) 1288 if (FONT_OBJECT_P (font_object))
1272 { 1289 {
@@ -2673,6 +2690,17 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
2673 return make_fixnum (i); 2690 return make_fixnum (i);
2674} 2691}
2675 2692
2693Lisp_Object
2694ftfont_shape (Lisp_Object lgstring)
2695{
2696 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2697 struct font_info *ftfont_info = (struct font_info *) font;
2698 OTF *otf = ftfont_get_otf (ftfont_info);
2699
2700 return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf,
2701 &ftfont_info->matrix);
2702}
2703
2676#endif /* HAVE_M17N_FLT */ 2704#endif /* HAVE_M17N_FLT */
2677 2705
2678#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 2706#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
@@ -2693,6 +2721,18 @@ ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
2693 2721
2694#ifdef HAVE_HARFBUZZ 2722#ifdef HAVE_HARFBUZZ
2695 2723
2724hb_font_t *
2725fthbfont_begin_hb_font (struct font *font, double *position_unit)
2726{
2727 struct font_info *ftfont_info = (struct font_info *) font;
2728
2729 *position_unit = 1.0 / (1 << 6);
2730 if (! ftfont_info->hb_font)
2731 ftfont_info->hb_font
2732 = hb_ft_font_create_referenced (ftfont_info->ft_size->face);
2733 return ftfont_info->hb_font;
2734}
2735
2696static hb_unicode_combining_class_t 2736static hb_unicode_combining_class_t
2697uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data) 2737uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
2698{ 2738{
@@ -2818,8 +2858,8 @@ get_hb_unicode_funcs (void)
2818} 2858}
2819 2859
2820static Lisp_Object 2860static Lisp_Object
2821ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font, 2861fthbfont_shape_by_hb (Lisp_Object lgstring, struct font *font,
2822 FT_Matrix *matrix, Lisp_Object direction) 2862 Lisp_Object direction)
2823{ 2863{
2824 ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring); 2864 ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring);
2825 ptrdiff_t i; 2865 ptrdiff_t i;
@@ -2892,7 +2932,15 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
2892 above. FIXME: drop once script handling is fixed above. */ 2932 above. FIXME: drop once script handling is fixed above. */
2893 hb_buffer_guess_segment_properties (hb_buffer); 2933 hb_buffer_guess_segment_properties (hb_buffer);
2894 2934
2895 if (!hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL)) 2935 double position_unit;
2936 hb_font_t *hb_font = font->driver->begin_hb_font (font, &position_unit);
2937 if (!hb_font)
2938 return make_fixnum (0);
2939
2940 hb_bool_t success = hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL);
2941 if (font->driver->end_hb_font)
2942 font->driver->end_hb_font (font, hb_font);
2943 if (!success)
2896 return Qnil; 2944 return Qnil;
2897 2945
2898 glyph_len = hb_buffer_get_length (hb_buffer); 2946 glyph_len = hb_buffer_get_length (hb_buffer);
@@ -2913,7 +2961,8 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
2913 { 2961 {
2914 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i); 2962 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2915 EMACS_INT from, to; 2963 EMACS_INT from, to;
2916 int advance = 0, lbearing, rbearing, ascent, descent; 2964 struct font_metrics metrics = {.width = 0};
2965 int xoff, yoff, wadjust;
2917 ptrdiff_t j = i; 2966 ptrdiff_t j = i;
2918 2967
2919 if (NILP (lglyph)) 2968 if (NILP (lglyph))
@@ -2936,61 +2985,46 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
2936 LGLYPH_SET_CHAR (lglyph, LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, from))); 2985 LGLYPH_SET_CHAR (lglyph, LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, from)));
2937 LGLYPH_SET_CODE (lglyph, info[i].codepoint); 2986 LGLYPH_SET_CODE (lglyph, info[i].codepoint);
2938 2987
2939 if (ftfont_glyph_metrics (ft_face, info[i].codepoint, &advance, &lbearing, 2988 unsigned code = info[i].codepoint;
2940 &rbearing, &ascent, &descent)) 2989 font->driver->text_extents (font, &code, 1, &metrics);
2941 { 2990 LGLYPH_SET_WIDTH (lglyph, metrics.width);
2942 LGLYPH_SET_WIDTH (lglyph, advance); 2991 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
2943 LGLYPH_SET_LBEARING (lglyph, lbearing); 2992 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
2944 LGLYPH_SET_RBEARING (lglyph, rbearing); 2993 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
2945 LGLYPH_SET_ASCENT (lglyph, ascent); 2994 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
2946 LGLYPH_SET_DESCENT (lglyph, descent); 2995
2947 } 2996 xoff = lround (pos[i].x_offset * position_unit);
2948 2997 yoff = - lround (pos[i].y_offset * position_unit);
2949 if (pos[i].x_offset || pos[i].y_offset || 2998 wadjust = lround (pos[i].x_advance * position_unit);
2950 (pos[i].x_advance >> 6) != advance) 2999 if (xoff || yoff || wadjust != metrics.width)
2951 { 3000 {
2952 Lisp_Object vec = make_uninit_vector (3); 3001 Lisp_Object vec = make_uninit_vector (3);
2953 ASET (vec, 0, make_fixnum (pos[i].x_offset >> 6)); 3002 ASET (vec, 0, make_fixnum (xoff));
2954 ASET (vec, 1, make_fixnum (-(pos[i].y_offset >> 6))); 3003 ASET (vec, 1, make_fixnum (yoff));
2955 ASET (vec, 2, make_fixnum (pos[i].x_advance >> 6)); 3004 ASET (vec, 2, make_fixnum (wadjust));
2956 LGLYPH_SET_ADJUSTMENT (lglyph, vec); 3005 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2957 } 3006 }
2958 } 3007 }
2959 3008
2960 return make_fixnum (glyph_len); 3009 return make_fixnum (glyph_len);
2961} 3010}
2962 3011
2963#endif /* HAVE_HARFBUZZ */ 3012Lisp_Object
2964 3013fthbfont_combining_capability (struct font *font)
2965#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ 3014{
3015 return Qt;
3016}
2966 3017
2967Lisp_Object 3018Lisp_Object
2968ftfont_shape (Lisp_Object lgstring, Lisp_Object direction) 3019fthbfont_shape (Lisp_Object lgstring, Lisp_Object direction)
2969{ 3020{
2970 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 3021 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2971 struct font_info *ftfont_info = (struct font_info *) font; 3022 struct font_info *ftfont_info = (struct font_info *) font;
2972#ifdef HAVE_HARFBUZZ
2973 if (getenv ("EMACS_NO_HARFBUZZ") == NULL)
2974 {
2975 hb_font_t *hb_font = ftfont_get_hb_font (ftfont_info);
2976
2977 return ftfont_shape_by_hb (lgstring, ftfont_info->ft_size->face,
2978 hb_font, &ftfont_info->matrix, direction);
2979 }
2980 else
2981#endif /* HAVE_HARFBUZZ */
2982 {
2983#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
2984 OTF *otf = ftfont_get_otf (ftfont_info);
2985 3023
2986 return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, 3024 return fthbfont_shape_by_hb (lgstring, font, direction);
2987 otf, &ftfont_info->matrix);
2988#endif /* defined HAVE_M17N_FLT && defined HAVE_LIBOTF */
2989 }
2990 return make_fixnum (0);
2991} 3025}
2992 3026
2993#endif /* (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ */ 3027#endif /* HAVE_HARFBUZZ */
2994 3028
2995static const char *const ftfont_booleans [] = { 3029static const char *const ftfont_booleans [] = {
2996 ":antialias", 3030 ":antialias",
@@ -3046,7 +3080,7 @@ ftfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3046Lisp_Object 3080Lisp_Object
3047ftfont_combining_capability (struct font *font) 3081ftfont_combining_capability (struct font *font)
3048{ 3082{
3049#if defined HAVE_M17N_FLT || defined HAVE_HARFBUZZ 3083#ifdef HAVE_M17N_FLT
3050 return Qt; 3084 return Qt;
3051#else 3085#else
3052 return Qnil; 3086 return Qnil;
@@ -3073,7 +3107,7 @@ static struct font_driver const ftfont_driver =
3073#ifdef HAVE_LIBOTF 3107#ifdef HAVE_LIBOTF
3074 .otf_capability = ftfont_otf_capability, 3108 .otf_capability = ftfont_otf_capability,
3075#endif 3109#endif
3076#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ 3110#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
3077 .shape = ftfont_shape, 3111 .shape = ftfont_shape,
3078#endif 3112#endif
3079#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 3113#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
@@ -3082,12 +3116,18 @@ static struct font_driver const ftfont_driver =
3082 .filter_properties = ftfont_filter_properties, 3116 .filter_properties = ftfont_filter_properties,
3083 .combining_capability = ftfont_combining_capability, 3117 .combining_capability = ftfont_combining_capability,
3084 }; 3118 };
3119#ifdef HAVE_HARFBUZZ
3120static struct font_driver fthbfont_driver;
3121#endif /* HAVE_HARFBUZZ */
3085 3122
3086void 3123void
3087syms_of_ftfont (void) 3124syms_of_ftfont (void)
3088{ 3125{
3089 /* Symbolic type of this font-driver. */ 3126 /* Symbolic type of this font-driver. */
3090 DEFSYM (Qfreetype, "freetype"); 3127 DEFSYM (Qfreetype, "freetype");
3128#ifdef HAVE_HARFBUZZ
3129 DEFSYM (Qfreetypehb, "freetypehb");
3130#endif /* HAVE_HARFBUZZ */
3091 3131
3092 /* Fontconfig's generic families and their aliases. */ 3132 /* Fontconfig's generic families and their aliases. */
3093 DEFSYM (Qmonospace, "monospace"); 3133 DEFSYM (Qmonospace, "monospace");
@@ -3114,4 +3154,12 @@ syms_of_ftfont_for_pdumper (void)
3114{ 3154{
3115 PDUMPER_RESET_LV (ft_face_cache, Qnil); 3155 PDUMPER_RESET_LV (ft_face_cache, Qnil);
3116 register_font_driver (&ftfont_driver, NULL); 3156 register_font_driver (&ftfont_driver, NULL);
3157#ifdef HAVE_HARFBUZZ
3158 fthbfont_driver = ftfont_driver;
3159 fthbfont_driver.type = Qfreetypehb;
3160 fthbfont_driver.shape = fthbfont_shape;
3161 fthbfont_driver.combining_capability = fthbfont_combining_capability;
3162 fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font;
3163 register_font_driver (&fthbfont_driver, NULL);
3164#endif /* HAVE_HARFBUZZ */
3117} 3165}
diff --git a/src/ftxfont.c b/src/ftxfont.c
index a549fd723bb..949ef4c503b 100644
--- a/src/ftxfont.c
+++ b/src/ftxfont.c
@@ -209,21 +209,13 @@ ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int y
209static Lisp_Object 209static Lisp_Object
210ftxfont_list (struct frame *f, Lisp_Object spec) 210ftxfont_list (struct frame *f, Lisp_Object spec)
211{ 211{
212 Lisp_Object list = ftfont_list (f, spec), tail; 212 return ftfont_list2 (f, spec, Qftx);
213
214 for (tail = list; CONSP (tail); tail = XCDR (tail))
215 ASET (XCAR (tail), FONT_TYPE_INDEX, Qftx);
216 return list;
217} 213}
218 214
219static Lisp_Object 215static Lisp_Object
220ftxfont_match (struct frame *f, Lisp_Object spec) 216ftxfont_match (struct frame *f, Lisp_Object spec)
221{ 217{
222 Lisp_Object entity = ftfont_match (f, spec); 218 return ftfont_match2 (f, spec, Qftx);
223
224 if (VECTORP (entity))
225 ASET (entity, FONT_TYPE_INDEX, Qftx);
226 return entity;
227} 219}
228 220
229static Lisp_Object 221static Lisp_Object
@@ -362,7 +354,7 @@ struct font_driver const ftxfont_driver =
362 .otf_capability = ftfont_otf_capability, 354 .otf_capability = ftfont_otf_capability,
363#endif 355#endif
364 .end_for_frame = ftxfont_end_for_frame, 356 .end_for_frame = ftxfont_end_for_frame,
365#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ 357#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
366 .shape = ftfont_shape, 358 .shape = ftfont_shape,
367#endif 359#endif
368#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 360#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
diff --git a/src/xfns.c b/src/xfns.c
index 2ceb55a30ad..50a430aa78c 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3774,10 +3774,16 @@ This function is an internal primitive--use `make-frame' instead. */)
3774 3774
3775#ifdef USE_CAIRO 3775#ifdef USE_CAIRO
3776 register_font_driver (&ftcrfont_driver, f); 3776 register_font_driver (&ftcrfont_driver, f);
3777#ifdef HAVE_HARFBUZZ
3778 register_font_driver (&ftcrhbfont_driver, f);
3779#endif /* HAVE_HARFBUZZ */
3777#else 3780#else
3778#ifdef HAVE_FREETYPE 3781#ifdef HAVE_FREETYPE
3779#ifdef HAVE_XFT 3782#ifdef HAVE_XFT
3780 register_font_driver (&xftfont_driver, f); 3783 register_font_driver (&xftfont_driver, f);
3784#ifdef HAVE_HARFBUZZ
3785 register_font_driver (&xfthbfont_driver, f);
3786#endif
3781#else /* not HAVE_XFT */ 3787#else /* not HAVE_XFT */
3782 register_font_driver (&ftxfont_driver, f); 3788 register_font_driver (&ftxfont_driver, f);
3783#endif /* not HAVE_XFT */ 3789#endif /* not HAVE_XFT */
diff --git a/src/xftfont.c b/src/xftfont.c
index b636a759048..f7b87f96569 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -108,21 +108,13 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc,
108static Lisp_Object 108static Lisp_Object
109xftfont_list (struct frame *f, Lisp_Object spec) 109xftfont_list (struct frame *f, Lisp_Object spec)
110{ 110{
111 Lisp_Object list = ftfont_list (f, spec); 111 return ftfont_list2 (f, spec, Qxft);
112
113 for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
114 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
115 return list;
116} 112}
117 113
118static Lisp_Object 114static Lisp_Object
119xftfont_match (struct frame *f, Lisp_Object spec) 115xftfont_match (struct frame *f, Lisp_Object spec)
120{ 116{
121 Lisp_Object entity = ftfont_match (f, spec); 117 return ftfont_match2 (f, spec, Qxft);
122
123 if (! NILP (entity))
124 ASET (entity, FONT_TYPE_INDEX, Qxft);
125 return entity;
126} 118}
127 119
128static FcChar8 ascii_printable[95]; 120static FcChar8 ascii_printable[95];
@@ -311,10 +303,16 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
311 /* We should not destroy PAT here because it is kept in XFTFONT and 303 /* We should not destroy PAT here because it is kept in XFTFONT and
312 destroyed automatically when XFTFONT is closed. */ 304 destroyed automatically when XFTFONT is closed. */
313 font_object = font_build_object (VECSIZE (struct font_info), 305 font_object = font_build_object (VECSIZE (struct font_info),
314 Qxft, entity, size); 306 AREF (entity, FONT_TYPE_INDEX),
307 entity, size);
315 ASET (font_object, FONT_FILE_INDEX, filename); 308 ASET (font_object, FONT_FILE_INDEX, filename);
316 font = XFONT_OBJECT (font_object); 309 font = XFONT_OBJECT (font_object);
317 font->pixel_size = size; 310 font->pixel_size = size;
311#ifdef HAVE_HARFBUZZ
312 if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qxfthb))
313 font->driver = &xfthbfont_driver;
314 else
315#endif /* HAVE_HARFBUZZ */
318 font->driver = &xftfont_driver; 316 font->driver = &xftfont_driver;
319 font->encoding_charset = font->repertory_charset = -1; 317 font->encoding_charset = font->repertory_charset = -1;
320 318
@@ -649,7 +647,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
649 return len; 647 return len;
650} 648}
651 649
652#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ 650#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
653static Lisp_Object 651static Lisp_Object
654xftfont_shape (Lisp_Object lgstring, Lisp_Object direction) 652xftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
655{ 653{
@@ -739,6 +737,41 @@ xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
739 return ok; 737 return ok;
740} 738}
741 739
740#ifdef HAVE_HARFBUZZ
741
742static Lisp_Object
743xfthbfont_list (struct frame *f, Lisp_Object spec)
744{
745 return ftfont_list2 (f, spec, Qxfthb);
746}
747
748static Lisp_Object
749xfthbfont_match (struct frame *f, Lisp_Object spec)
750{
751 return ftfont_match2 (f, spec, Qxfthb);
752}
753
754static hb_font_t *
755xfthbfont_begin_hb_font (struct font *font, double *position_unit)
756{
757 struct font_info *xftfont_info = (struct font_info *) font;
758 FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
759
760 xftfont_info->ft_size = ft_face->size;
761
762 return fthbfont_begin_hb_font (font, position_unit);
763}
764
765static void
766xfthbfont_end_hb_font (struct font *font, hb_font_t *hb_font)
767{
768 struct font_info *xftfont_info = (struct font_info *) font;
769
770 XftUnlockFace (xftfont_info->xftfont);
771}
772
773#endif /* HAVE_HARFBUZZ */
774
742static void syms_of_xftfont_for_pdumper (void); 775static void syms_of_xftfont_for_pdumper (void);
743 776
744struct font_driver const xftfont_driver = 777struct font_driver const xftfont_driver =
@@ -763,7 +796,7 @@ struct font_driver const xftfont_driver =
763 .otf_capability = ftfont_otf_capability, 796 .otf_capability = ftfont_otf_capability,
764#endif 797#endif
765 .end_for_frame = xftfont_end_for_frame, 798 .end_for_frame = xftfont_end_for_frame,
766#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ 799#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
767 .shape = xftfont_shape, 800 .shape = xftfont_shape,
768#endif 801#endif
769#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 802#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
@@ -774,11 +807,17 @@ struct font_driver const xftfont_driver =
774 .combining_capability = ftfont_combining_capability, 807 .combining_capability = ftfont_combining_capability,
775 .drop_xrender_surfaces = xftfont_drop_xrender_surfaces, 808 .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
776 }; 809 };
810#ifdef HAVE_HARFBUZZ
811struct font_driver xfthbfont_driver;
812#endif /* HAVE_HARFBUZZ */
777 813
778void 814void
779syms_of_xftfont (void) 815syms_of_xftfont (void)
780{ 816{
781 DEFSYM (Qxft, "xft"); 817 DEFSYM (Qxft, "xft");
818#ifdef HAVE_HARFBUZZ
819 DEFSYM (Qxfthb, "xfthb");
820#endif /* HAVE_HARFBUZZ */
782 DEFSYM (QChinting, ":hinting"); 821 DEFSYM (QChinting, ":hinting");
783 DEFSYM (QCautohint, ":autohint"); 822 DEFSYM (QCautohint, ":autohint");
784 DEFSYM (QChintstyle, ":hintstyle"); 823 DEFSYM (QChintstyle, ":hintstyle");
@@ -799,4 +838,15 @@ static void
799syms_of_xftfont_for_pdumper (void) 838syms_of_xftfont_for_pdumper (void)
800{ 839{
801 register_font_driver (&xftfont_driver, NULL); 840 register_font_driver (&xftfont_driver, NULL);
841#ifdef HAVE_HARFBUZZ
842 xfthbfont_driver = xftfont_driver;
843 xfthbfont_driver.type = Qxfthb;
844 xfthbfont_driver.list = xfthbfont_list;
845 xfthbfont_driver.match = xfthbfont_match;
846 xfthbfont_driver.shape = fthbfont_shape;
847 xfthbfont_driver.combining_capability = fthbfont_combining_capability;
848 xfthbfont_driver.begin_hb_font = xfthbfont_begin_hb_font;
849 xfthbfont_driver.end_hb_font = xfthbfont_end_hb_font;
850 register_font_driver (&xfthbfont_driver, NULL);
851#endif /* HAVE_HARFBUZZ */
802} 852}