aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2019-06-07 17:52:16 +0300
committerEli Zaretskii2019-06-07 17:52:16 +0300
commit4ebfec02f05d838e4c88d10a764c13789816d6d4 (patch)
treef479671bb5f295b5eb324163e56751cb000f20b4 /src
parente5bc9a32b65e16ff48a50d56e3d8b4990e95acac (diff)
parentf3fddfb5ef9b72cecc379e8b7ae4b728ed3895d7 (diff)
downloademacs-4ebfec02f05d838e4c88d10a764c13789816d6d4.tar.gz
emacs-4ebfec02f05d838e4c88d10a764c13789816d6d4.zip
Merge remote-tracking branch 'origin/harfbuzz'
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in9
-rw-r--r--src/chartab.c15
-rw-r--r--src/composite.c44
-rw-r--r--src/composite.h3
-rw-r--r--src/font.c22
-rw-r--r--src/font.h53
-rw-r--r--src/ftcrfont.c97
-rw-r--r--src/ftfont.c146
-rw-r--r--src/ftfont.h8
-rw-r--r--src/ftxfont.c14
-rw-r--r--src/hbfont.c482
-rw-r--r--src/indent.c4
-rw-r--r--src/lisp.h1
-rw-r--r--src/macfont.m33
-rw-r--r--src/w32common.h4
-rw-r--r--src/w32fns.c81
-rw-r--r--src/w32font.c1
-rw-r--r--src/w32uniscribe.c376
-rw-r--r--src/xdisp.c1
-rw-r--r--src/xfns.c14
-rw-r--r--src/xftfont.c88
21 files changed, 1357 insertions, 139 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 3aab5270a4a..be769458d37 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -132,6 +132,8 @@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
132FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ 132FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
133FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ 133FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
134FREETYPE_LIBS = @FREETYPE_LIBS@ 134FREETYPE_LIBS = @FREETYPE_LIBS@
135HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@
136HARFBUZZ_LIBS = @HARFBUZZ_LIBS@
135LIBOTF_CFLAGS = @LIBOTF_CFLAGS@ 137LIBOTF_CFLAGS = @LIBOTF_CFLAGS@
136LIBOTF_LIBS = @LIBOTF_LIBS@ 138LIBOTF_LIBS = @LIBOTF_LIBS@
137M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@ 139M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@
@@ -297,6 +299,7 @@ W32_RES_LINK=@W32_RES_LINK@
297## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE 299## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE
298## ftfont.o ftcrfont.o if USE_CAIRO 300## ftfont.o ftcrfont.o if USE_CAIRO
299## else xfont.o 301## else xfont.o
302## if HAVE_HARFBUZZ, hbfont.o is added regardless of the rest
300FONT_OBJ=@FONT_OBJ@ 303FONT_OBJ=@FONT_OBJ@
301 304
302## Empty for MinGW, cm.o for the rest. 305## Empty for MinGW, cm.o for the rest.
@@ -380,7 +383,7 @@ EMACS_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
380 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) $(XDBE_CFLAGS) \ 383 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) $(XDBE_CFLAGS) \
381 $(WEBKIT_CFLAGS) $(LCMS2_CFLAGS) \ 384 $(WEBKIT_CFLAGS) $(LCMS2_CFLAGS) \
382 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ 385 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
383 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ 386 $(HARFBUZZ_CFLAGS) $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
384 $(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) \ 387 $(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) \
385 $(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \ 388 $(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
386 $(WERROR_CFLAGS) 389 $(WERROR_CFLAGS)
@@ -429,7 +432,7 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
429 w32.o w32console.o w32cygwinx.o w32fns.o w32heap.o w32inevt.o w32notify.o \ 432 w32.o w32console.o w32cygwinx.o w32fns.o w32heap.o w32inevt.o w32notify.o \
430 w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \ 433 w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \
431 w16select.o widget.o xfont.o ftfont.o xftfont.o ftxfont.o gtkutil.o \ 434 w16select.o widget.o xfont.o ftfont.o xftfont.o ftxfont.o gtkutil.o \
432 xsettings.o xgselect.o termcap.o 435 xsettings.o xgselect.o termcap.o hbfont.o
433 436
434## gmalloc.o if !SYSTEM_MALLOC && !DOUG_LEA_MALLOC, else empty. 437## gmalloc.o if !SYSTEM_MALLOC && !DOUG_LEA_MALLOC, else empty.
435GMALLOC_OBJ=@GMALLOC_OBJ@ 438GMALLOC_OBJ=@GMALLOC_OBJ@
@@ -520,7 +523,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
520 $(XDBE_LIBS) \ 523 $(XDBE_LIBS) \
521 $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ 524 $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
522 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 525 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
523 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ 526 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(HARFBUZZ_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
524 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) $(LCMS2_LIBS) \ 527 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) $(LCMS2_LIBS) \
525 $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) \ 528 $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) \
526 $(JSON_LIBS) $(GMP_LIB) 529 $(JSON_LIBS) $(GMP_LIB)
diff --git a/src/chartab.c b/src/chartab.c
index 16017f4a49a..bf8e34b2529 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -1321,22 +1321,25 @@ and put an element value. */)
1321 return Fcdr (Fassq (prop, Vchar_code_property_alist)); 1321 return Fcdr (Fassq (prop, Vchar_code_property_alist));
1322} 1322}
1323 1323
1324Lisp_Object
1325get_unicode_property (Lisp_Object char_table, int ch)
1326{
1327 Lisp_Object val = CHAR_TABLE_REF (char_table, ch);
1328 uniprop_decoder_t decoder = uniprop_get_decoder (char_table);
1329 return (decoder ? decoder (char_table, val) : val);
1330}
1331
1324DEFUN ("get-unicode-property-internal", Fget_unicode_property_internal, 1332DEFUN ("get-unicode-property-internal", Fget_unicode_property_internal,
1325 Sget_unicode_property_internal, 2, 2, 0, 1333 Sget_unicode_property_internal, 2, 2, 0,
1326 doc: /* Return an element of CHAR-TABLE for character CH. 1334 doc: /* Return an element of CHAR-TABLE for character CH.
1327CHAR-TABLE must be what returned by `unicode-property-table-internal'. */) 1335CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
1328 (Lisp_Object char_table, Lisp_Object ch) 1336 (Lisp_Object char_table, Lisp_Object ch)
1329{ 1337{
1330 Lisp_Object val;
1331 uniprop_decoder_t decoder;
1332
1333 CHECK_CHAR_TABLE (char_table); 1338 CHECK_CHAR_TABLE (char_table);
1334 CHECK_CHARACTER (ch); 1339 CHECK_CHARACTER (ch);
1335 if (! UNIPROP_TABLE_P (char_table)) 1340 if (! UNIPROP_TABLE_P (char_table))
1336 error ("Invalid Unicode property table"); 1341 error ("Invalid Unicode property table");
1337 val = CHAR_TABLE_REF (char_table, XFIXNUM (ch)); 1342 return get_unicode_property (char_table, XFIXNUM (ch));
1338 decoder = uniprop_get_decoder (char_table);
1339 return (decoder ? decoder (char_table, val) : val);
1340} 1343}
1341 1344
1342DEFUN ("put-unicode-property-internal", Fput_unicode_property_internal, 1345DEFUN ("put-unicode-property-internal", Fput_unicode_property_internal,
diff --git a/src/composite.c b/src/composite.c
index 7d7ed3f4a69..183062de460 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -865,7 +865,7 @@ fill_gstring_body (Lisp_Object gstring)
865static Lisp_Object 865static Lisp_Object
866autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, 866autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
867 ptrdiff_t limit, struct window *win, struct face *face, 867 ptrdiff_t limit, struct window *win, struct face *face,
868 Lisp_Object string) 868 Lisp_Object string, Lisp_Object direction)
869{ 869{
870 ptrdiff_t count = SPECPDL_INDEX (); 870 ptrdiff_t count = SPECPDL_INDEX ();
871 Lisp_Object pos = make_fixnum (charpos); 871 Lisp_Object pos = make_fixnum (charpos);
@@ -912,8 +912,9 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
912 if (NILP (string)) 912 if (NILP (string))
913 record_unwind_protect (restore_point_unwind, 913 record_unwind_protect (restore_point_unwind,
914 build_marker (current_buffer, pt, pt_byte)); 914 build_marker (current_buffer, pt, pt_byte));
915 lgstring = safe_call (6, Vauto_composition_function, AREF (rule, 2), 915 lgstring = safe_call (7, Vauto_composition_function, AREF (rule, 2),
916 pos, make_fixnum (to), font_object, string); 916 pos, make_fixnum (to), font_object, string,
917 direction);
917 } 918 }
918 return unbind_to (count, lgstring); 919 return unbind_to (count, lgstring);
919} 920}
@@ -1158,7 +1159,9 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
1158 characters to be composed. FACE, if non-NULL, is a base face of 1159 characters to be composed. FACE, if non-NULL, is a base face of
1159 the character. If STRING is not nil, it is a string containing the 1160 the character. If STRING is not nil, it is a string containing the
1160 character to check, and CHARPOS and BYTEPOS are indices in the 1161 character to check, and CHARPOS and BYTEPOS are indices in the
1161 string. In that case, FACE must not be NULL. 1162 string. In that case, FACE must not be NULL. BIDI_LEVEL is the bidi
1163 embedding level of the current paragraph, and is used to calculate the
1164 direction argument to pass to the font shaper.
1162 1165
1163 If the character is composed, setup members of CMP_IT (id, nglyphs, 1166 If the character is composed, setup members of CMP_IT (id, nglyphs,
1164 from, to, reversed_p), and return true. Otherwise, update 1167 from, to, reversed_p), and return true. Otherwise, update
@@ -1167,7 +1170,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
1167bool 1170bool
1168composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos, 1171composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
1169 ptrdiff_t bytepos, ptrdiff_t endpos, struct window *w, 1172 ptrdiff_t bytepos, ptrdiff_t endpos, struct window *w,
1170 struct face *face, Lisp_Object string) 1173 signed char bidi_level, struct face *face, Lisp_Object string)
1171{ 1174{
1172 if (cmp_it->ch == -2) 1175 if (cmp_it->ch == -2)
1173 { 1176 {
@@ -1197,13 +1200,17 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
1197 else if (w) 1200 else if (w)
1198 { 1201 {
1199 Lisp_Object lgstring = Qnil; 1202 Lisp_Object lgstring = Qnil;
1200 Lisp_Object val, elt; 1203 Lisp_Object val, elt, direction = Qnil;
1201 1204
1202 val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch); 1205 val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch);
1203 for (EMACS_INT i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val)) 1206 for (EMACS_INT i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val))
1204 continue; 1207 continue;
1205 if (charpos < endpos) 1208 if (charpos < endpos)
1206 { 1209 {
1210 if ((bidi_level & 1) == 0)
1211 direction = QL2R;
1212 else
1213 direction = QR2L;
1207 for (; CONSP (val); val = XCDR (val)) 1214 for (; CONSP (val); val = XCDR (val))
1208 { 1215 {
1209 elt = XCAR (val); 1216 elt = XCAR (val);
@@ -1213,7 +1220,7 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
1213 if (XFIXNAT (AREF (elt, 1)) != cmp_it->lookback) 1220 if (XFIXNAT (AREF (elt, 1)) != cmp_it->lookback)
1214 goto no_composition; 1221 goto no_composition;
1215 lgstring = autocmp_chars (elt, charpos, bytepos, endpos, 1222 lgstring = autocmp_chars (elt, charpos, bytepos, endpos,
1216 w, face, string); 1223 w, face, string, direction);
1217 if (composition_gstring_p (lgstring)) 1224 if (composition_gstring_p (lgstring))
1218 break; 1225 break;
1219 lgstring = Qnil; 1226 lgstring = Qnil;
@@ -1237,8 +1244,12 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
1237 else 1244 else
1238 bpos = CHAR_TO_BYTE (cpos); 1245 bpos = CHAR_TO_BYTE (cpos);
1239 } 1246 }
1247 if ((bidi_level & 1) == 0)
1248 direction = QL2R;
1249 else
1250 direction = QR2L;
1240 lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face, 1251 lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face,
1241 string); 1252 string, direction);
1242 if (! composition_gstring_p (lgstring) 1253 if (! composition_gstring_p (lgstring)
1243 || cpos + LGSTRING_CHAR_LEN (lgstring) - 1 != charpos) 1254 || cpos + LGSTRING_CHAR_LEN (lgstring) - 1 != charpos)
1244 /* Composition failed or didn't cover the current 1255 /* Composition failed or didn't cover the current
@@ -1558,7 +1569,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit,
1558 for (check = cur; check_pos < check.pos; ) 1569 for (check = cur; check_pos < check.pos; )
1559 BACKWARD_CHAR (check, stop); 1570 BACKWARD_CHAR (check, stop);
1560 *gstring = autocmp_chars (elt, check.pos, check.pos_byte, 1571 *gstring = autocmp_chars (elt, check.pos, check.pos_byte,
1561 tail, w, NULL, string); 1572 tail, w, NULL, string, Qnil);
1562 need_adjustment = 1; 1573 need_adjustment = 1;
1563 if (NILP (*gstring)) 1574 if (NILP (*gstring))
1564 { 1575 {
@@ -1935,15 +1946,24 @@ Use the command `auto-composition-mode' to change this variable. */);
1935 1946
1936 DEFVAR_LISP ("auto-composition-function", Vauto_composition_function, 1947 DEFVAR_LISP ("auto-composition-function", Vauto_composition_function,
1937 doc: /* Function to call to compose characters automatically. 1948 doc: /* Function to call to compose characters automatically.
1938This function is called from the display routine with four arguments: 1949This function is called from the display engine with 6 arguments:
1939FROM, TO, WINDOW, and STRING. 1950FUNC, FROM, TO, FONT-OBJECT, STRING, and DIRECTION.
1951
1952FUNC is the function to compose characters. On text-mode display,
1953FUNC is ignored and `compose-gstring-for-terminal' is used instead.
1940 1954
1941If STRING is nil, the function must compose characters in the region 1955If STRING is nil, the function must compose characters in the region
1942between FROM and TO in the current buffer. 1956between FROM and TO in the current buffer.
1943 1957
1944Otherwise, STRING is a string, and FROM and TO are indices into the 1958Otherwise, STRING is a string, and FROM and TO are indices into the
1945string. In this case, the function must compose characters in the 1959string. In this case, the function must compose characters in the
1946string. */); 1960string.
1961
1962FONT-OBJECT is the font to use, or nil if characters are to be
1963composed on a text-mode display.
1964
1965DIRECTION is the bidi directionality of the text to shape. It could
1966be L2R or R2L, or nil if unknown. */);
1947 Vauto_composition_function = Qnil; 1967 Vauto_composition_function = Qnil;
1948 1968
1949 DEFVAR_LISP ("composition-function-table", Vcomposition_function_table, 1969 DEFVAR_LISP ("composition-function-table", Vcomposition_function_table,
diff --git a/src/composite.h b/src/composite.h
index 86751633c27..45d72fb345d 100644
--- a/src/composite.h
+++ b/src/composite.h
@@ -26,6 +26,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
26#define EMACS_COMPOSITE_H 26#define EMACS_COMPOSITE_H
27 27
28#include "font.h" 28#include "font.h"
29#include "dispextern.h"
29 30
30INLINE_HEADER_BEGIN 31INLINE_HEADER_BEGIN
31 32
@@ -321,7 +322,7 @@ extern void composition_compute_stop_pos (struct composition_it *,
321 Lisp_Object); 322 Lisp_Object);
322extern bool composition_reseat_it (struct composition_it *, ptrdiff_t, 323extern bool composition_reseat_it (struct composition_it *, ptrdiff_t,
323 ptrdiff_t, ptrdiff_t, struct window *, 324 ptrdiff_t, ptrdiff_t, struct window *,
324 struct face *, Lisp_Object); 325 signed char, struct face *, Lisp_Object);
325extern int composition_update_it (struct composition_it *, 326extern int composition_update_it (struct composition_it *,
326 ptrdiff_t, ptrdiff_t, Lisp_Object); 327 ptrdiff_t, ptrdiff_t, Lisp_Object);
327 328
diff --git a/src/font.c b/src/font.c
index 5ca89c97dcf..6ab4923c3d2 100644
--- a/src/font.c
+++ b/src/font.c
@@ -4397,18 +4397,22 @@ font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object)
4397} 4397}
4398 4398
4399 4399
4400DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0, 4400DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 2, 2, 0,
4401 doc: /* Shape the glyph-string GSTRING. 4401 doc: /* Shape the glyph-string GSTRING subject to bidi DIRECTION.
4402Shaping means substituting glyphs and/or adjusting positions of glyphs 4402Shaping means substituting glyphs and/or adjusting positions of glyphs
4403to get the correct visual image of character sequences set in the 4403to get the correct visual image of character sequences set in the
4404header of the glyph-string. 4404header of the glyph-string.
4405 4405
4406DIRECTION should be produced by the UBA, the Unicode Bidirectional
4407Algorithm, and should be a symbol, either L2R or R2L. It can also
4408be nil if the bidi context is unknown.
4409
4406If the shaping was successful, the value is GSTRING itself or a newly 4410If the shaping was successful, the value is GSTRING itself or a newly
4407created glyph-string. Otherwise, the value is nil. 4411created glyph-string. Otherwise, the value is nil.
4408 4412
4409See the documentation of `composition-get-gstring' for the format of 4413See the documentation of `composition-get-gstring' for the format of
4410GSTRING. */) 4414GSTRING. */)
4411 (Lisp_Object gstring) 4415 (Lisp_Object gstring, Lisp_Object direction)
4412{ 4416{
4413 struct font *font; 4417 struct font *font;
4414 Lisp_Object font_object, n, glyph; 4418 Lisp_Object font_object, n, glyph;
@@ -4427,7 +4431,7 @@ GSTRING. */)
4427 /* Try at most three times with larger gstring each time. */ 4431 /* Try at most three times with larger gstring each time. */
4428 for (i = 0; i < 3; i++) 4432 for (i = 0; i < 3; i++)
4429 { 4433 {
4430 n = font->driver->shape (gstring); 4434 n = font->driver->shape (gstring, direction);
4431 if (FIXNUMP (n)) 4435 if (FIXNUMP (n))
4432 break; 4436 break;
4433 gstring = larger_vector (gstring, 4437 gstring = larger_vector (gstring,
@@ -4478,11 +4482,11 @@ GSTRING. */)
4478 4482
4479DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs, 4483DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
4480 2, 2, 0, 4484 2, 2, 0,
4481 doc: /* Return a list of variation glyphs for CHAR in FONT-OBJECT. 4485 doc: /* Return a list of variation glyphs for CHARACTER in FONT-OBJECT.
4482Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID), 4486Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4483where 4487where
4484 VARIATION-SELECTOR is a character code of variation selection 4488 VARIATION-SELECTOR is a character code of variation selector
4485 (#xFE00..#xFE0F or #xE0100..#xE01EF) 4489 (#xFE00..#xFE0F or #xE0100..#xE01EF).
4486 GLYPH-ID is a glyph code of the corresponding variation glyph, 4490 GLYPH-ID is a glyph code of the corresponding variation glyph,
4487a fixnum, if it's small enough, otherwise a bignum. */) 4491a fixnum, if it's small enough, otherwise a bignum. */)
4488 (Lisp_Object font_object, Lisp_Object character) 4492 (Lisp_Object font_object, Lisp_Object character)
@@ -5351,6 +5355,10 @@ syms_of_font (void)
5351 5355
5352 DEFSYM (QCuser_spec, ":user-spec"); 5356 DEFSYM (QCuser_spec, ":user-spec");
5353 5357
5358 /* For shapers that need to know text directionality. */
5359 DEFSYM (QL2R, "L2R");
5360 DEFSYM (QR2L, "R2L");
5361
5354 scratch_font_spec = Ffont_spec (0, NULL); 5362 scratch_font_spec = Ffont_spec (0, NULL);
5355 staticpro (&scratch_font_spec); 5363 staticpro (&scratch_font_spec);
5356 scratch_font_prefer = Ffont_spec (0, NULL); 5364 scratch_font_prefer = Ffont_spec (0, NULL);
diff --git a/src/font.h b/src/font.h
index 9ca0c97dc52..1f35744642b 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;
@@ -703,7 +707,11 @@ struct font_driver
703 707
704 Return the number of output codes. If none of the features are 708 Return the number of output codes. If none of the features are
705 applicable to the input data, return 0. If GSTRING-OUT is too 709 applicable to the input data, return 0. If GSTRING-OUT is too
706 short, return -1. */ 710 short, return -1.
711
712 Note: This method is currently not implemented by any font
713 back-end, and is only called by 'font-drive-otf' and
714 'font-otf-alternates', which are themselves ifdef'ed away. */
707 int (*otf_drive) (struct font *font, Lisp_Object features, 715 int (*otf_drive) (struct font *font, Lisp_Object features,
708 Lisp_Object gstring_in, int from, int to, 716 Lisp_Object gstring_in, int from, int to,
709 Lisp_Object gstring_out, int idx, bool alternate_subst); 717 Lisp_Object gstring_out, int idx, bool alternate_subst);
@@ -725,6 +733,9 @@ struct font_driver
725 (N+1)th element of GSTRING is nil, input of shaping is from the 733 (N+1)th element of GSTRING is nil, input of shaping is from the
726 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and 734 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and
727 CODE are already set. 735 CODE are already set.
736 DIRECTION is either L2R or R2L, or nil if unknown. During
737 redisplay, this comes from applying the UBA, is passed from
738 composition_reseat_it, and is used by the HarfBuzz shaper.
728 739
729 This function updates all fields of the input glyphs. If the 740 This function updates all fields of the input glyphs. If the
730 output glyphs (M) are more than the input glyphs (N), (N+1)th 741 output glyphs (M) are more than the input glyphs (N), (N+1)th
@@ -732,7 +743,7 @@ struct font_driver
732 a new glyph object and storing it in GSTRING. If (M) is greater 743 a new glyph object and storing it in GSTRING. If (M) is greater
733 than the length of GSTRING, this method should return nil. In 744 than the length of GSTRING, this method should return nil. In
734 that case, the method is called again with a larger GSTRING. */ 745 that case, the method is called again with a larger GSTRING. */
735 Lisp_Object (*shape) (Lisp_Object lgstring); 746 Lisp_Object (*shape) (Lisp_Object lgstring, Lisp_Object direction);
736 747
737 /* Optional. 748 /* Optional.
738 If FONT is usable on frame F, return 0. Otherwise return -1. 749 If FONT is usable on frame F, return 0. Otherwise return -1.
@@ -773,6 +784,21 @@ struct font_driver
773 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
774 work after the size change) and get a new one. */ 785 work after the size change) and get a new one. */
775 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 */
776}; 802};
777 803
778 804
@@ -864,6 +890,11 @@ extern void font_fill_lglyph_metrics (Lisp_Object, Lisp_Object);
864extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop, 890extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop,
865 Lisp_Object val); 891 Lisp_Object val);
866 892
893#ifdef HAVE_HARFBUZZ
894extern Lisp_Object hbfont_shape (Lisp_Object, Lisp_Object);
895extern Lisp_Object hbfont_combining_capability (struct font *);
896#endif
897
867#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) 898#if defined (HAVE_XFT) || defined (HAVE_FREETYPE)
868extern void font_put_frame_data (struct frame *, Lisp_Object, void *); 899extern void font_put_frame_data (struct frame *, Lisp_Object, void *);
869extern void *font_get_frame_data (struct frame *f, Lisp_Object); 900extern void *font_get_frame_data (struct frame *f, Lisp_Object);
@@ -885,17 +916,20 @@ extern int ftfont_has_char (Lisp_Object, int);
885extern int ftfont_variation_glyphs (struct font *, int, unsigned[256]); 916extern int ftfont_variation_glyphs (struct font *, int, unsigned[256]);
886extern Lisp_Object ftfont_combining_capability (struct font *); 917extern Lisp_Object ftfont_combining_capability (struct font *);
887extern Lisp_Object ftfont_get_cache (struct frame *); 918extern Lisp_Object ftfont_get_cache (struct frame *);
888extern Lisp_Object ftfont_list (struct frame *, Lisp_Object); 919extern Lisp_Object ftfont_list2 (struct frame *, Lisp_Object, Lisp_Object);
889extern Lisp_Object ftfont_list_family (struct frame *); 920extern Lisp_Object ftfont_list_family (struct frame *);
890extern Lisp_Object ftfont_match (struct frame *, Lisp_Object); 921extern Lisp_Object ftfont_match2 (struct frame *, Lisp_Object, Lisp_Object);
891extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int); 922extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int);
892extern Lisp_Object ftfont_otf_capability (struct font *); 923extern Lisp_Object ftfont_otf_capability (struct font *);
893extern Lisp_Object ftfont_shape (Lisp_Object); 924extern Lisp_Object ftfont_shape (Lisp_Object, Lisp_Object);
894extern unsigned ftfont_encode_char (struct font *, int); 925extern unsigned ftfont_encode_char (struct font *, int);
895extern void ftfont_close (struct font *); 926extern void ftfont_close (struct font *);
896extern void ftfont_filter_properties (Lisp_Object, Lisp_Object); 927extern void ftfont_filter_properties (Lisp_Object, Lisp_Object);
897extern void ftfont_text_extents (struct font *, const unsigned *, int, 928extern void ftfont_text_extents (struct font *, const unsigned *, int,
898 struct font_metrics *); 929 struct font_metrics *);
930#ifdef HAVE_HARFBUZZ
931extern hb_font_t *fthbfont_begin_hb_font (struct font *, double *);
932#endif /* HAVE_HARFBUZZ */
899extern void syms_of_ftfont (void); 933extern void syms_of_ftfont (void);
900#endif /* HAVE_FREETYPE */ 934#endif /* HAVE_FREETYPE */
901#ifdef HAVE_X_WINDOWS 935#ifdef HAVE_X_WINDOWS
@@ -905,6 +939,9 @@ extern void syms_of_xfont (void);
905extern void syms_of_ftxfont (void); 939extern void syms_of_ftxfont (void);
906#ifdef HAVE_XFT 940#ifdef HAVE_XFT
907extern struct font_driver const xftfont_driver; 941extern struct font_driver const xftfont_driver;
942#ifdef HAVE_HARFBUZZ
943extern struct font_driver xfthbfont_driver;
944#endif /* HAVE_HARFBUZZ */
908#endif 945#endif
909#if defined HAVE_FREETYPE || defined HAVE_XFT 946#if defined HAVE_FREETYPE || defined HAVE_XFT
910extern struct font_driver const ftxfont_driver; 947extern struct font_driver const ftxfont_driver;
@@ -917,6 +954,9 @@ extern void syms_of_bdffont (void);
917#ifdef HAVE_NTGUI 954#ifdef HAVE_NTGUI
918extern struct font_driver w32font_driver; 955extern struct font_driver w32font_driver;
919extern struct font_driver uniscribe_font_driver; 956extern struct font_driver uniscribe_font_driver;
957#ifdef HAVE_HARFBUZZ
958extern struct font_driver harfbuzz_font_driver;
959#endif
920extern void syms_of_w32font (void); 960extern void syms_of_w32font (void);
921#endif /* HAVE_NTGUI */ 961#endif /* HAVE_NTGUI */
922#ifdef HAVE_NS 962#ifdef HAVE_NS
@@ -926,6 +966,9 @@ extern void syms_of_macfont (void);
926#endif /* HAVE_NS */ 966#endif /* HAVE_NS */
927#ifdef USE_CAIRO 967#ifdef USE_CAIRO
928extern struct font_driver const ftcrfont_driver; 968extern struct font_driver const ftcrfont_driver;
969#ifdef HAVE_HARFBUZZ
970extern struct font_driver ftcrhbfont_driver;
971#endif /* HAVE_HARFBUZZ */
929extern void syms_of_ftcrfont (void); 972extern void syms_of_ftcrfont (void);
930#endif 973#endif
931 974
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 9686cec0e8c..1c28a7ceb67 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -97,21 +97,13 @@ ftcrfont_glyph_extents (struct font *font,
97static Lisp_Object 97static Lisp_Object
98ftcrfont_list (struct frame *f, Lisp_Object spec) 98ftcrfont_list (struct frame *f, Lisp_Object spec)
99{ 99{
100 Lisp_Object list = ftfont_list (f, spec), tail; 100 return ftfont_list2 (f, spec, Qftcr);
101
102 for (tail = list; CONSP (tail); tail = XCDR (tail))
103 ASET (XCAR (tail), FONT_TYPE_INDEX, Qftcr);
104 return list;
105} 101}
106 102
107static Lisp_Object 103static Lisp_Object
108ftcrfont_match (struct frame *f, Lisp_Object spec) 104ftcrfont_match (struct frame *f, Lisp_Object spec)
109{ 105{
110 Lisp_Object entity = ftfont_match (f, spec); 106 return ftfont_match2 (f, spec, Qftcr);
111
112 if (VECTORP (entity))
113 ASET (entity, FONT_TYPE_INDEX, Qftcr);
114 return entity;
115} 107}
116 108
117static Lisp_Object 109static Lisp_Object
@@ -164,10 +156,16 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
164 unblock_input (); 156 unblock_input ();
165 157
166 font_object = font_build_object (VECSIZE (struct font_info), 158 font_object = font_build_object (VECSIZE (struct font_info),
167 Qftcr, entity, size); 159 AREF (entity, FONT_TYPE_INDEX),
160 entity, size);
168 ASET (font_object, FONT_FILE_INDEX, filename); 161 ASET (font_object, FONT_FILE_INDEX, filename);
169 font = XFONT_OBJECT (font_object); 162 font = XFONT_OBJECT (font_object);
170 font->pixel_size = size; 163 font->pixel_size = size;
164#ifdef HAVE_HARFBUZZ
165 if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qftcrhb))
166 font->driver = &ftcrhbfont_driver;
167 else
168#endif /* HAVE_HARFBUZZ */
171 font->driver = &ftcrfont_driver; 169 font->driver = &ftcrfont_driver;
172 font->encoding_charset = font->repertory_charset = -1; 170 font->encoding_charset = font->repertory_charset = -1;
173 171
@@ -256,6 +254,9 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
256 ftcrfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; 254 ftcrfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
257 ftcrfont_info->otf = NULL; 255 ftcrfont_info->otf = NULL;
258#endif /* HAVE_LIBOTF */ 256#endif /* HAVE_LIBOTF */
257#ifdef HAVE_HARFBUZZ
258 ftcrfont_info->hb_font = NULL;
259#endif /* HAVE_HARFBUZZ */
259 if (ft_face->units_per_EM) 260 if (ft_face->units_per_EM)
260 ftcrfont_info->bitmap_position_unit = 0; 261 ftcrfont_info->bitmap_position_unit = 0;
261 else 262 else
@@ -289,6 +290,13 @@ ftcrfont_close (struct font *font)
289 ftcrfont_info->otf = NULL; 290 ftcrfont_info->otf = NULL;
290 } 291 }
291#endif 292#endif
293#ifdef HAVE_HARFBUZZ
294 if (ftcrfont_info->hb_font)
295 {
296 hb_font_destroy (ftcrfont_info->hb_font);
297 ftcrfont_info->hb_font = NULL;
298 }
299#endif
292 for (int i = 0; i < ftcrfont_info->metrics_nrows; i++) 300 for (int i = 0; i < ftcrfont_info->metrics_nrows; i++)
293 if (ftcrfont_info->metrics[i]) 301 if (ftcrfont_info->metrics[i])
294 xfree (ftcrfont_info->metrics[i]); 302 xfree (ftcrfont_info->metrics[i]);
@@ -427,7 +435,7 @@ ftcrfont_otf_capability (struct font *font)
427 435
428#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF 436#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
429static Lisp_Object 437static Lisp_Object
430ftcrfont_shape (Lisp_Object lgstring) 438ftcrfont_shape (Lisp_Object lgstring, Lisp_Object direction)
431{ 439{
432 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 440 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
433 struct font_info *ftcrfont_info = (struct font_info *) font; 441 struct font_info *ftcrfont_info = (struct font_info *) font;
@@ -439,7 +447,7 @@ ftcrfont_shape (Lisp_Object lgstring)
439 FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); 447 FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
440 448
441 ftcrfont_info->ft_size = ft_face->size; 449 ftcrfont_info->ft_size = ft_face->size;
442 Lisp_Object result = ftfont_shape (lgstring); 450 Lisp_Object result = ftfont_shape (lgstring, direction);
443 cairo_ft_scaled_font_unlock_face (scaled_font); 451 cairo_ft_scaled_font_unlock_face (scaled_font);
444 ftcrfont_info->ft_size = NULL; 452 ftcrfont_info->ft_size = NULL;
445 453
@@ -447,7 +455,7 @@ ftcrfont_shape (Lisp_Object lgstring)
447} 455}
448#endif 456#endif
449 457
450#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 458#if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
451static int 459static int
452ftcrfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) 460ftcrfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
453{ 461{
@@ -462,7 +470,7 @@ ftcrfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
462 470
463 return result; 471 return result;
464} 472}
465#endif /* HAVE_OTF_GET_VARIATION_GLYPHS */ 473#endif /* HAVE_OTF_GET_VARIATION_GLYPHS || HAVE_FT_FACE_GETCHARVARIANTINDEX */
466 474
467static int 475static int
468ftcrfont_draw (struct glyph_string *s, 476ftcrfont_draw (struct glyph_string *s,
@@ -510,6 +518,46 @@ ftcrfont_draw (struct glyph_string *s,
510 return len; 518 return len;
511} 519}
512 520
521#ifdef HAVE_HARFBUZZ
522
523static Lisp_Object
524ftcrhbfont_list (struct frame *f, Lisp_Object spec)
525{
526 return ftfont_list2 (f, spec, Qftcrhb);
527}
528
529static Lisp_Object
530ftcrhbfont_match (struct frame *f, Lisp_Object spec)
531{
532 return ftfont_match2 (f, spec, Qftcrhb);
533}
534
535static hb_font_t *
536ftcrhbfont_begin_hb_font (struct font *font, double *position_unit)
537{
538 struct font_info *ftcrfont_info = (struct font_info *) font;
539 cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font;
540 FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
541
542 ftcrfont_info->ft_size = ft_face->size;
543 hb_font_t *hb_font = fthbfont_begin_hb_font (font, position_unit);
544 if (ftcrfont_info->bitmap_position_unit)
545 *position_unit = ftcrfont_info->bitmap_position_unit;
546
547 return hb_font;
548}
549
550static void
551ftcrhbfont_end_hb_font (struct font *font, hb_font_t *hb_font)
552{
553 struct font_info *ftcrfont_info = (struct font_info *) font;
554 cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font;
555
556 cairo_ft_scaled_font_unlock_face (scaled_font);
557 ftcrfont_info->ft_size = NULL;
558}
559
560#endif /* HAVE_HARFBUZZ */
513 561
514 562
515static void syms_of_ftcrfont_for_pdumper (void); 563static void syms_of_ftcrfont_for_pdumper (void);
@@ -535,17 +583,23 @@ struct font_driver const ftcrfont_driver =
535#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF 583#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
536 .shape = ftcrfont_shape, 584 .shape = ftcrfont_shape,
537#endif 585#endif
538#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 586#if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
539 .get_variation_glyphs = ftcrfont_variation_glyphs, 587 .get_variation_glyphs = ftcrfont_variation_glyphs,
540#endif 588#endif
541 .filter_properties = ftfont_filter_properties, 589 .filter_properties = ftfont_filter_properties,
542 .combining_capability = ftfont_combining_capability, 590 .combining_capability = ftfont_combining_capability,
543 }; 591 };
592#ifdef HAVE_HARFBUZZ
593struct font_driver ftcrhbfont_driver;
594#endif /* HAVE_HARFBUZZ */
544 595
545void 596void
546syms_of_ftcrfont (void) 597syms_of_ftcrfont (void)
547{ 598{
548 DEFSYM (Qftcr, "ftcr"); 599 DEFSYM (Qftcr, "ftcr");
600#ifdef HAVE_HARFBUZZ
601 DEFSYM (Qftcrhb, "ftcrhb");
602#endif /* HAVE_HARFBUZZ */
549 pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper); 603 pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper);
550} 604}
551 605
@@ -553,4 +607,15 @@ static void
553syms_of_ftcrfont_for_pdumper (void) 607syms_of_ftcrfont_for_pdumper (void)
554{ 608{
555 register_font_driver (&ftcrfont_driver, NULL); 609 register_font_driver (&ftcrfont_driver, NULL);
610#ifdef HAVE_HARFBUZZ
611 ftcrhbfont_driver = ftcrfont_driver;
612 ftcrhbfont_driver.type = Qftcrhb;
613 ftcrhbfont_driver.list = ftcrhbfont_list;
614 ftcrhbfont_driver.match = ftcrhbfont_match;
615 ftcrhbfont_driver.shape = hbfont_shape;
616 ftcrhbfont_driver.combining_capability = hbfont_combining_capability;
617 ftcrhbfont_driver.begin_hb_font = ftcrhbfont_begin_hb_font;
618 ftcrhbfont_driver.end_hb_font = ftcrhbfont_end_hb_font;
619 register_font_driver (&ftcrhbfont_driver, NULL);
620#endif /* HAVE_HARFBUZZ */
556} 621}
diff --git a/src/ftfont.c b/src/ftfont.c
index d8b510d7032..efd0fcbd8c0 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -48,6 +48,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
48#include "pdumper.h" 48#include "pdumper.h"
49 49
50static struct font_driver const ftfont_driver; 50static struct font_driver const ftfont_driver;
51#ifdef HAVE_HARFBUZZ
52static struct font_driver fthbfont_driver;
53#endif /* HAVE_HARFBUZZ */
51 54
52/* Flag to tell if FcInit is already called or not. */ 55/* Flag to tell if FcInit is already called or not. */
53static bool fc_initialized; 56static bool fc_initialized;
@@ -788,7 +791,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots
788 return pattern; 791 return pattern;
789} 792}
790 793
791Lisp_Object 794static Lisp_Object
792ftfont_list (struct frame *f, Lisp_Object spec) 795ftfont_list (struct frame *f, Lisp_Object spec)
793{ 796{
794 Lisp_Object val = Qnil, family, adstyle; 797 Lisp_Object val = Qnil, family, adstyle;
@@ -988,6 +991,16 @@ ftfont_list (struct frame *f, Lisp_Object spec)
988} 991}
989 992
990Lisp_Object 993Lisp_Object
994ftfont_list2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
995{
996 Lisp_Object list = ftfont_list (f, spec);
997
998 for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
999 ASET (XCAR (tail), FONT_TYPE_INDEX, type);
1000 return list;
1001}
1002
1003static Lisp_Object
991ftfont_match (struct frame *f, Lisp_Object spec) 1004ftfont_match (struct frame *f, Lisp_Object spec)
992{ 1005{
993 Lisp_Object entity = Qnil; 1006 Lisp_Object entity = Qnil;
@@ -1038,6 +1051,16 @@ ftfont_match (struct frame *f, Lisp_Object spec)
1038} 1051}
1039 1052
1040Lisp_Object 1053Lisp_Object
1054ftfont_match2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
1055{
1056 Lisp_Object entity = ftfont_match (f, spec);
1057
1058 if (! NILP (entity))
1059 ASET (entity, FONT_TYPE_INDEX, type);
1060 return entity;
1061}
1062
1063Lisp_Object
1041ftfont_list_family (struct frame *f) 1064ftfont_list_family (struct frame *f)
1042{ 1065{
1043 Lisp_Object list = Qnil; 1066 Lisp_Object list = Qnil;
@@ -1292,9 +1315,17 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1292 ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; 1315 ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
1293 ftfont_info->otf = NULL; 1316 ftfont_info->otf = NULL;
1294#endif /* HAVE_LIBOTF */ 1317#endif /* HAVE_LIBOTF */
1318#ifdef HAVE_HARFBUZZ
1319 ftfont_info->hb_font = NULL;
1320#endif /* HAVE_HARFBUZZ */
1295 /* This means that there's no need of transformation. */ 1321 /* This means that there's no need of transformation. */
1296 ftfont_info->matrix.xx = 0; 1322 ftfont_info->matrix.xx = 0;
1297 font->pixel_size = size; 1323 font->pixel_size = size;
1324#ifdef HAVE_HARFBUZZ
1325 if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qfreetypehb))
1326 font->driver = &fthbfont_driver;
1327 else
1328#endif /* HAVE_HARFBUZZ */
1298 font->driver = &ftfont_driver; 1329 font->driver = &ftfont_driver;
1299 font->encoding_charset = font->repertory_charset = -1; 1330 font->encoding_charset = font->repertory_charset = -1;
1300 1331
@@ -1407,6 +1438,10 @@ ftfont_close (struct font *font)
1407 if (ftfont_info->otf) 1438 if (ftfont_info->otf)
1408 OTF_close (ftfont_info->otf); 1439 OTF_close (ftfont_info->otf);
1409#endif 1440#endif
1441#ifdef HAVE_HARFBUZZ
1442 if (ftfont_info->hb_font)
1443 hb_font_destroy (ftfont_info->hb_font);
1444#endif
1410 cache_data->ft_face = NULL; 1445 cache_data->ft_face = NULL;
1411 } 1446 }
1412 else 1447 else
@@ -1454,6 +1489,24 @@ ftfont_encode_char (struct font *font, int c)
1454 return (code > 0 ? code : FONT_INVALID_CODE); 1489 return (code > 0 ? code : FONT_INVALID_CODE);
1455} 1490}
1456 1491
1492static bool
1493ftfont_glyph_metrics (FT_Face ft_face, int c, int *advance, int *lbearing,
1494 int *rbearing, int *ascent, int *descent)
1495{
1496 if (FT_Load_Glyph (ft_face, c, FT_LOAD_DEFAULT) == 0)
1497 {
1498 FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
1499 *advance = m->horiAdvance >> 6;
1500 *lbearing = m->horiBearingX >> 6;
1501 *rbearing = (m->horiBearingX + m->width) >> 6;
1502 *ascent = m->horiBearingY >> 6;
1503 *descent = (m->height - m->horiBearingY) >> 6;
1504 return true;
1505 }
1506
1507 return false;
1508}
1509
1457void 1510void
1458ftfont_text_extents (struct font *font, const unsigned int *code, 1511ftfont_text_extents (struct font *font, const unsigned int *code,
1459 int nglyphs, struct font_metrics *metrics) 1512 int nglyphs, struct font_metrics *metrics)
@@ -1468,29 +1521,27 @@ ftfont_text_extents (struct font *font, const unsigned int *code,
1468 1521
1469 for (i = 0, first = 1; i < nglyphs; i++) 1522 for (i = 0, first = 1; i < nglyphs; i++)
1470 { 1523 {
1471 if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0) 1524 int advance, lbearing, rbearing, ascent, descent;
1525 if (ftfont_glyph_metrics (ft_face, code[i], &advance, &lbearing,
1526 &rbearing, &ascent, &descent))
1472 { 1527 {
1473 FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
1474
1475 if (first) 1528 if (first)
1476 { 1529 {
1477 metrics->lbearing = m->horiBearingX >> 6; 1530 metrics->lbearing = lbearing;
1478 metrics->rbearing = (m->horiBearingX + m->width) >> 6; 1531 metrics->rbearing = rbearing;
1479 metrics->ascent = m->horiBearingY >> 6; 1532 metrics->ascent = ascent;
1480 metrics->descent = (m->height - m->horiBearingY) >> 6; 1533 metrics->descent = descent;
1481 first = 0; 1534 first = 0;
1482 } 1535 }
1483 if (metrics->lbearing > width + (m->horiBearingX >> 6)) 1536 if (metrics->lbearing > width + lbearing)
1484 metrics->lbearing = width + (m->horiBearingX >> 6); 1537 metrics->lbearing = width + lbearing;
1485 if (metrics->rbearing 1538 if (metrics->rbearing < width + rbearing)
1486 < width + ((m->horiBearingX + m->width) >> 6)) 1539 metrics->rbearing = width + rbearing;
1487 metrics->rbearing 1540 if (metrics->ascent < ascent)
1488 = width + ((m->horiBearingX + m->width) >> 6); 1541 metrics->ascent = ascent;
1489 if (metrics->ascent < (m->horiBearingY >> 6)) 1542 if (metrics->descent > descent)
1490 metrics->ascent = m->horiBearingY >> 6; 1543 metrics->descent = descent;
1491 if (metrics->descent > ((m->height - m->horiBearingY) >> 6)) 1544 width += advance;
1492 metrics->descent = (m->height - m->horiBearingY) >> 6;
1493 width += m->horiAdvance >> 6;
1494 } 1545 }
1495 else 1546 else
1496 width += font->space_width; 1547 width += font->space_width;
@@ -2757,7 +2808,7 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
2757} 2808}
2758 2809
2759Lisp_Object 2810Lisp_Object
2760ftfont_shape (Lisp_Object lgstring) 2811ftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
2761{ 2812{
2762 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 2813 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2763 struct font_info *ftfont_info = (struct font_info *) font; 2814 struct font_info *ftfont_info = (struct font_info *) font;
@@ -2769,21 +2820,57 @@ ftfont_shape (Lisp_Object lgstring)
2769 2820
2770#endif /* HAVE_M17N_FLT */ 2821#endif /* HAVE_M17N_FLT */
2771 2822
2772#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 2823#endif /* HAVE_LIBOTF */
2773 2824
2825#if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
2774int 2826int
2775ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) 2827ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
2776{ 2828{
2777 struct font_info *ftfont_info = (struct font_info *) font; 2829 struct font_info *ftfont_info = (struct font_info *) font;
2830#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2778 OTF *otf = ftfont_get_otf (ftfont_info); 2831 OTF *otf = ftfont_get_otf (ftfont_info);
2779 2832
2780 if (! otf) 2833 if (! otf)
2781 return 0; 2834 return 0;
2782 return OTF_get_variation_glyphs (otf, c, variations); 2835 return OTF_get_variation_glyphs (otf, c, variations);
2836#else /* !HAVE_OTF_GET_VARIATION_GLYPHS */
2837 FT_Face ft_face = ftfont_info->ft_size->face;
2838 int i, n = 0;
2839
2840 for (i = 0; i < 16; i++)
2841 {
2842 variations[i] = FT_Face_GetCharVariantIndex (ft_face, c, 0xFE00 + i);
2843 if (variations[i])
2844 n++;
2845 }
2846 for (; i < 256; i++)
2847 {
2848 variations[i] = FT_Face_GetCharVariantIndex (ft_face, c,
2849 0xE0100 + (i - 16));
2850 if (variations[i])
2851 n++;
2852 }
2853
2854 return n;
2855#endif /* !HAVE_OTF_GET_VARIATION_GLYPHS */
2783} 2856}
2857#endif /* HAVE_OTF_GET_VARIATION_GLYPHS || HAVE_FT_FACE_GETCHARVARIANTINDEX */
2784 2858
2785#endif /* HAVE_OTF_GET_VARIATION_GLYPHS */ 2859#ifdef HAVE_HARFBUZZ
2786#endif /* HAVE_LIBOTF */ 2860
2861hb_font_t *
2862fthbfont_begin_hb_font (struct font *font, double *position_unit)
2863{
2864 struct font_info *ftfont_info = (struct font_info *) font;
2865
2866 *position_unit = 1.0 / (1 << 6);
2867 if (! ftfont_info->hb_font)
2868 ftfont_info->hb_font
2869 = hb_ft_font_create_referenced (ftfont_info->ft_size->face);
2870 return ftfont_info->hb_font;
2871}
2872
2873#endif /* HAVE_HARFBUZZ */
2787 2874
2788static const char *const ftfont_booleans [] = { 2875static const char *const ftfont_booleans [] = {
2789 ":antialias", 2876 ":antialias",
@@ -2869,7 +2956,7 @@ static struct font_driver const ftfont_driver =
2869#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF 2956#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
2870 .shape = ftfont_shape, 2957 .shape = ftfont_shape,
2871#endif 2958#endif
2872#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 2959#if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
2873 .get_variation_glyphs = ftfont_variation_glyphs, 2960 .get_variation_glyphs = ftfont_variation_glyphs,
2874#endif 2961#endif
2875 .filter_properties = ftfont_filter_properties, 2962 .filter_properties = ftfont_filter_properties,
@@ -2881,6 +2968,9 @@ syms_of_ftfont (void)
2881{ 2968{
2882 /* Symbolic type of this font-driver. */ 2969 /* Symbolic type of this font-driver. */
2883 DEFSYM (Qfreetype, "freetype"); 2970 DEFSYM (Qfreetype, "freetype");
2971#ifdef HAVE_HARFBUZZ
2972 DEFSYM (Qfreetypehb, "freetypehb");
2973#endif /* HAVE_HARFBUZZ */
2884 2974
2885 /* Fontconfig's generic families and their aliases. */ 2975 /* Fontconfig's generic families and their aliases. */
2886 DEFSYM (Qmonospace, "monospace"); 2976 DEFSYM (Qmonospace, "monospace");
@@ -2918,4 +3008,12 @@ syms_of_ftfont_for_pdumper (void)
2918{ 3008{
2919 PDUMPER_RESET_LV (ft_face_cache, Qnil); 3009 PDUMPER_RESET_LV (ft_face_cache, Qnil);
2920 register_font_driver (&ftfont_driver, NULL); 3010 register_font_driver (&ftfont_driver, NULL);
3011#ifdef HAVE_HARFBUZZ
3012 fthbfont_driver = ftfont_driver;
3013 fthbfont_driver.type = Qfreetypehb;
3014 fthbfont_driver.shape = hbfont_shape;
3015 fthbfont_driver.combining_capability = hbfont_combining_capability;
3016 fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font;
3017 register_font_driver (&fthbfont_driver, NULL);
3018#endif /* HAVE_HARFBUZZ */
2921} 3019}
diff --git a/src/ftfont.h b/src/ftfont.h
index 7860469491f..b2280e9aab9 100644
--- a/src/ftfont.h
+++ b/src/ftfont.h
@@ -29,6 +29,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
29# include FT_BDF_H 29# include FT_BDF_H
30#endif 30#endif
31 31
32#ifdef HAVE_HARFBUZZ
33#include <hb.h>
34#include <hb-ft.h>
35#endif /* HAVE_HARFBUZZ */
36
32#ifdef HAVE_LIBOTF 37#ifdef HAVE_LIBOTF
33# include <otf.h> 38# include <otf.h>
34#ifdef HAVE_M17N_FLT 39#ifdef HAVE_M17N_FLT
@@ -54,6 +59,9 @@ struct font_info
54 FT_Size ft_size; 59 FT_Size ft_size;
55 int index; 60 int index;
56 FT_Matrix matrix; 61 FT_Matrix matrix;
62#ifdef HAVE_HARFBUZZ
63 hb_font_t *hb_font;
64#endif /* HAVE_HARFBUZZ */
57 65
58#ifdef USE_CAIRO 66#ifdef USE_CAIRO
59 cairo_scaled_font_t *cr_scaled_font; 67 cairo_scaled_font_t *cr_scaled_font;
diff --git a/src/ftxfont.c b/src/ftxfont.c
index 8bce7f10f1e..b1467360ad6 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
@@ -359,7 +351,7 @@ struct font_driver const ftxfont_driver =
359#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF 351#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
360 .shape = ftfont_shape, 352 .shape = ftfont_shape,
361#endif 353#endif
362#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 354#if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
363 .get_variation_glyphs = ftfont_variation_glyphs, 355 .get_variation_glyphs = ftfont_variation_glyphs,
364#endif 356#endif
365 .filter_properties = ftfont_filter_properties, 357 .filter_properties = ftfont_filter_properties,
diff --git a/src/hbfont.c b/src/hbfont.c
new file mode 100644
index 00000000000..5923efd488d
--- /dev/null
+++ b/src/hbfont.c
@@ -0,0 +1,482 @@
1/* hbfont.c -- Platform-independent support for HarfBuzz font driver.
2 Copyright (C) 2019 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or (at
9your option) any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
18
19#include <config.h>
20#include <math.h>
21#include <hb.h>
22
23#include "lisp.h"
24#include "frame.h"
25#include "composite.h"
26#include "font.h"
27#include "dispextern.h"
28
29#ifdef HAVE_NTGUI
30
31#include "w32common.h"
32
33/* The w32 implementation calls HarfBuzz functions via function
34 pointers. We use the below to declare the function pointers and
35 redirect function names to those pointers. */
36DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_create,
37 (hb_unicode_funcs_t *));
38DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_get_default, (void));
39DEF_DLL_FN (void, hb_unicode_funcs_set_combining_class_func,
40 (hb_unicode_funcs_t *, hb_unicode_combining_class_func_t,
41 void *, hb_destroy_func_t));
42DEF_DLL_FN (void, hb_unicode_funcs_set_general_category_func,
43 (hb_unicode_funcs_t *, hb_unicode_general_category_func_t,
44 void *, hb_destroy_func_t));
45DEF_DLL_FN (void, hb_unicode_funcs_set_mirroring_func,
46 (hb_unicode_funcs_t *, hb_unicode_mirroring_func_t,
47 void *, hb_destroy_func_t));
48DEF_DLL_FN (hb_buffer_t *, hb_buffer_create, (void));
49DEF_DLL_FN (void, hb_buffer_set_unicode_funcs,
50 (hb_buffer_t *, hb_unicode_funcs_t *));
51DEF_DLL_FN (void, hb_buffer_clear_contents, (hb_buffer_t *));
52DEF_DLL_FN (hb_bool_t, hb_buffer_pre_allocate, (hb_buffer_t *, unsigned int));
53DEF_DLL_FN (void, hb_buffer_add, (hb_buffer_t *, hb_codepoint_t, unsigned int));
54DEF_DLL_FN (void, hb_buffer_set_content_type,
55 (hb_buffer_t *, hb_buffer_content_type_t));
56DEF_DLL_FN (void, hb_buffer_set_cluster_level,
57 (hb_buffer_t *, hb_buffer_cluster_level_t));
58DEF_DLL_FN (void, hb_buffer_set_direction, (hb_buffer_t *, hb_direction_t));
59DEF_DLL_FN (void, hb_buffer_set_language, (hb_buffer_t *, hb_language_t));
60DEF_DLL_FN (hb_language_t, hb_language_from_string, (const char *, int));
61DEF_DLL_FN (void, hb_buffer_guess_segment_properties, (hb_buffer_t *));
62DEF_DLL_FN (hb_bool_t, hb_shape_full,
63 (hb_font_t *, hb_buffer_t *, const hb_feature_t *,
64 unsigned int, const char * const *));
65DEF_DLL_FN (unsigned int, hb_buffer_get_length, (hb_buffer_t *));
66DEF_DLL_FN (hb_direction_t, hb_buffer_get_direction, (hb_buffer_t *));
67DEF_DLL_FN (void, hb_buffer_reverse_clusters, (hb_buffer_t *));
68DEF_DLL_FN (hb_glyph_info_t *, hb_buffer_get_glyph_infos,
69 (hb_buffer_t *, unsigned int *));
70DEF_DLL_FN (hb_glyph_position_t *, hb_buffer_get_glyph_positions,
71 (hb_buffer_t *, unsigned int *));
72
73#define hb_unicode_funcs_create fn_hb_unicode_funcs_create
74#define hb_unicode_funcs_get_default fn_hb_unicode_funcs_get_default
75#define hb_unicode_funcs_set_combining_class_func fn_hb_unicode_funcs_set_combining_class_func
76#define hb_unicode_funcs_set_general_category_func fn_hb_unicode_funcs_set_general_category_func
77#define hb_unicode_funcs_set_mirroring_func fn_hb_unicode_funcs_set_mirroring_func
78#define hb_buffer_create fn_hb_buffer_create
79#define hb_buffer_set_unicode_funcs fn_hb_buffer_set_unicode_funcs
80#define hb_buffer_clear_contents fn_hb_buffer_clear_contents
81#define hb_buffer_pre_allocate fn_hb_buffer_pre_allocate
82#define hb_buffer_add fn_hb_buffer_add
83#define hb_buffer_set_content_type fn_hb_buffer_set_content_type
84#define hb_buffer_set_cluster_level fn_hb_buffer_set_cluster_level
85#define hb_buffer_set_direction fn_hb_buffer_set_direction
86#define hb_buffer_set_language fn_hb_buffer_set_language
87#define hb_language_from_string fn_hb_language_from_string
88#define hb_buffer_guess_segment_properties fn_hb_buffer_guess_segment_properties
89#define hb_shape_full fn_hb_shape_full
90#define hb_buffer_get_length fn_hb_buffer_get_length
91#define hb_buffer_get_direction fn_hb_buffer_get_direction
92#define hb_buffer_reverse_clusters fn_hb_buffer_reverse_clusters
93#define hb_buffer_get_glyph_infos fn_hb_buffer_get_glyph_infos
94#define hb_buffer_get_glyph_positions fn_hb_buffer_get_glyph_positions
95
96/* This function is called from syms_of_w32uniscribe_for_pdumper to
97 initialize the above function pointers. */
98bool
99hbfont_init_w32_funcs (HMODULE library)
100{
101 LOAD_DLL_FN (library, hb_unicode_funcs_create);
102 LOAD_DLL_FN (library, hb_unicode_funcs_get_default);
103 LOAD_DLL_FN (library, hb_unicode_funcs_set_combining_class_func);
104 LOAD_DLL_FN (library, hb_unicode_funcs_set_general_category_func);
105 LOAD_DLL_FN (library, hb_unicode_funcs_set_mirroring_func);
106 LOAD_DLL_FN (library, hb_buffer_create);
107 LOAD_DLL_FN (library, hb_buffer_set_unicode_funcs);
108 LOAD_DLL_FN (library, hb_buffer_clear_contents);
109 LOAD_DLL_FN (library, hb_buffer_pre_allocate);
110 LOAD_DLL_FN (library, hb_buffer_add);
111 LOAD_DLL_FN (library, hb_buffer_set_content_type);
112 LOAD_DLL_FN (library, hb_buffer_set_cluster_level);
113 LOAD_DLL_FN (library, hb_buffer_set_direction);
114 LOAD_DLL_FN (library, hb_buffer_set_language);
115 LOAD_DLL_FN (library, hb_language_from_string);
116 LOAD_DLL_FN (library, hb_buffer_guess_segment_properties);
117 LOAD_DLL_FN (library, hb_shape_full);
118 LOAD_DLL_FN (library, hb_buffer_get_length);
119 LOAD_DLL_FN (library, hb_buffer_get_direction);
120 LOAD_DLL_FN (library, hb_buffer_reverse_clusters);
121 LOAD_DLL_FN (library, hb_buffer_get_glyph_infos);
122 LOAD_DLL_FN (library, hb_buffer_get_glyph_positions);
123 return true;
124}
125#endif /* HAVE_NTGUI */
126
127/* Support functions for HarfBuzz shaper. */
128
129static bool combining_class_loaded = false;
130static Lisp_Object canonical_combining_class_table;
131
132static hb_unicode_combining_class_t
133uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
134{
135 /* Load the Unicode table first time it is needed. */
136 if (!combining_class_loaded)
137 {
138 canonical_combining_class_table =
139 uniprop_table (intern ("canonical-combining-class"));
140 if (NILP (canonical_combining_class_table))
141 emacs_abort ();
142 staticpro (&canonical_combining_class_table);
143 combining_class_loaded = true;
144 }
145
146 Lisp_Object combining =
147 get_unicode_property (canonical_combining_class_table, ch);
148 if (FIXNUMP (combining))
149 return (hb_unicode_combining_class_t) XFIXNUM (combining);
150
151 return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
152}
153
154static hb_unicode_general_category_t
155uni_general (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
156{
157 Lisp_Object category = CHAR_TABLE_REF (Vunicode_category_table, ch);
158
159 if (INTEGERP (category))
160 {
161 switch (XFIXNUM (category))
162 {
163 case UNICODE_CATEGORY_Cc:
164 return HB_UNICODE_GENERAL_CATEGORY_CONTROL;
165 case UNICODE_CATEGORY_Cf:
166 return HB_UNICODE_GENERAL_CATEGORY_FORMAT;
167 case UNICODE_CATEGORY_Cn:
168 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
169 case UNICODE_CATEGORY_Co:
170 return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE;
171 case UNICODE_CATEGORY_Cs:
172 return HB_UNICODE_GENERAL_CATEGORY_SURROGATE;
173 case UNICODE_CATEGORY_Ll:
174 return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER;
175 case UNICODE_CATEGORY_Lm:
176 return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER;
177 case UNICODE_CATEGORY_Lo:
178 return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
179 case UNICODE_CATEGORY_Lt:
180 return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER;
181 case UNICODE_CATEGORY_Lu:
182 return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER;
183 case UNICODE_CATEGORY_Mc:
184 return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK;
185 case UNICODE_CATEGORY_Me:
186 return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
187 case UNICODE_CATEGORY_Mn:
188 return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK;
189 case UNICODE_CATEGORY_Nd:
190 return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER;
191 case UNICODE_CATEGORY_Nl:
192 return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER;
193 case UNICODE_CATEGORY_No:
194 return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER;
195 case UNICODE_CATEGORY_Pc:
196 return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION;
197 case UNICODE_CATEGORY_Pd:
198 return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION;
199 case UNICODE_CATEGORY_Pe:
200 return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION;
201 case UNICODE_CATEGORY_Pf:
202 return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION;
203 case UNICODE_CATEGORY_Pi:
204 return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION;
205 case UNICODE_CATEGORY_Po:
206 return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION;
207 case UNICODE_CATEGORY_Ps:
208 return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION;
209 case UNICODE_CATEGORY_Sc:
210 return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL;
211 case UNICODE_CATEGORY_Sk:
212 return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL;
213 case UNICODE_CATEGORY_Sm:
214 return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL;
215 case UNICODE_CATEGORY_So:
216 return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL;
217 case UNICODE_CATEGORY_Zl:
218 return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR;
219 case UNICODE_CATEGORY_Zp:
220 return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR;
221 case UNICODE_CATEGORY_Zs:
222 return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
223 case UNICODE_CATEGORY_UNKNOWN:
224 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
225 }
226 }
227
228 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
229}
230
231static hb_codepoint_t
232uni_mirroring (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
233{
234 return bidi_mirror_char (ch);
235}
236
237static hb_unicode_funcs_t *
238get_hb_unicode_funcs (void)
239{
240 /* Subclass HarfBuzz's default Unicode functions and override functions that
241 * use data Emacs can provide. This way changing Emacs data is reflected in
242 * the shaped output. */
243 hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (hb_unicode_funcs_get_default ());
244
245 hb_unicode_funcs_set_combining_class_func (funcs, uni_combining, NULL, NULL);
246 hb_unicode_funcs_set_general_category_func (funcs, uni_general, NULL, NULL);
247 hb_unicode_funcs_set_mirroring_func (funcs, uni_mirroring, NULL, NULL);
248
249 /* Use default implmentation for Unicode composition/decomposition, we might
250 * want to revisit this later.
251 hb_unicode_funcs_set_compose_func (funcs, uni_compose, NULL, NULL);
252 hb_unicode_funcs_set_decompose_func (funcs, uni_decompose, NULL, NULL);
253 */
254
255 /* Emacs own script mapping for characters differs from Unicode, so we want
256 * to keep the default HarfBuzz's implementation here.
257 hb_unicode_funcs_set_script_func (funcs, uni_script, NULL, NULL);
258 */
259
260 return funcs;
261}
262
263/* HarfBuzz implementation of shape for font backend.
264
265 Shape text in LGSTRING. See the docstring of
266 'composition-get-gstring' for the format of LGSTRING. If the
267 (N+1)th element of LGSTRING is nil, input of shaping is from the
268 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and
269 CODE are already set, but FROM and TO need adjustments according
270 to the glyphs produced by the shaping fuinction.
271 DIRECTION is either L2R or R2L, or nil if unknown. During
272 redisplay, this comes from applying the UBA, is passed from
273 composition_reseat_it, and is used by the HarfBuzz shaper.
274
275 This function updates all fields of the input glyphs. If the
276 output glyphs (M) are more than the input glyphs (N), (N+1)th
277 through (M)th elements of LGSTRING are updated possibly by making
278 a new glyph object and storing it in LGSTRING. If (M) is greater
279 than the length of LGSTRING, nil should be returned. In that case,
280 this function is called again with a larger LGSTRING. */
281Lisp_Object
282hbfont_shape (Lisp_Object lgstring, Lisp_Object direction)
283{
284 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
285 ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring);
286 ptrdiff_t i;
287
288 hb_glyph_info_t *info;
289 hb_glyph_position_t *pos;
290
291 /* Cache the HarfBuzz buffer for better performance and less allocations.
292 * We intentionally never destroy the buffer. */
293 static hb_buffer_t *hb_buffer = NULL;
294 if (! hb_buffer)
295 {
296 hb_buffer = hb_buffer_create ();
297 hb_unicode_funcs_t* ufuncs = get_hb_unicode_funcs();
298 hb_buffer_set_unicode_funcs(hb_buffer, ufuncs);
299 }
300
301 hb_buffer_clear_contents (hb_buffer);
302 hb_buffer_pre_allocate (hb_buffer, text_len);
303
304 /* Copy the characters in their original logical order, so we can
305 assign them to glyphs correctly after shaping. */
306 int *chars = alloca (text_len * sizeof (int));
307 for (i = 0; i < text_len; i++)
308 {
309 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
310 int c;
311
312 if (NILP (g))
313 break;
314 c = LGLYPH_CHAR (g);
315 hb_buffer_add (hb_buffer, c, i);
316 chars[i] = c;
317 }
318
319 text_len = i;
320 if (!text_len)
321 return Qnil;
322
323 hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
324 hb_buffer_set_cluster_level (hb_buffer,
325 HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES);
326
327 /* If the caller didn't provide a meaningful DIRECTION, let HarfBuzz
328 guess it. */
329 if (!NILP (direction))
330 {
331 hb_direction_t dir = HB_DIRECTION_LTR;
332 if (EQ (direction, QL2R))
333 dir = HB_DIRECTION_LTR;
334 else if (EQ (direction, QR2L))
335 dir = HB_DIRECTION_RTL;
336 hb_buffer_set_direction (hb_buffer, dir);
337 }
338
339 /* Leave the script determination to HarfBuzz, until Emacs has a
340 better idea of the script of LGSTRING. FIXME. */
341#if 0
342 hb_buffer_set_script (hb_buffer, XXX);
343#endif
344
345 /* FIXME: This can only handle the single global language, which
346 normally comes from the locale. In addition, if
347 current-iso639-language is a list, we arbitrarily use the first
348 one. We should instead have a notion of the language of the text
349 being shaped. */
350 Lisp_Object lang = Vcurrent_iso639_language;
351 if (CONSP (Vcurrent_iso639_language))
352 lang = XCAR (Vcurrent_iso639_language);
353 if (SYMBOLP (lang))
354 {
355 Lisp_Object lang_str = SYMBOL_NAME (lang);
356 hb_buffer_set_language (hb_buffer,
357 hb_language_from_string (SSDATA (lang_str),
358 SBYTES (lang_str)));
359 }
360
361 /* Guess the default properties for when they cannot be determined above.
362
363 FIXME: maybe drop this guessing once script and language handling
364 is fixed above; but then will need to guess the direction by
365 ourselves, perhaps by looking at the characters using
366 bidi_get_type or somesuch. */
367 hb_buffer_guess_segment_properties (hb_buffer);
368
369 double position_unit;
370 hb_font_t *hb_font
371 = font->driver->begin_hb_font
372 ? font->driver->begin_hb_font (font, &position_unit)
373 : NULL;
374 if (!hb_font)
375 return make_fixnum (0);
376
377 hb_bool_t success = hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL);
378 if (font->driver->end_hb_font)
379 font->driver->end_hb_font (font, hb_font);
380 if (!success)
381 return Qnil;
382
383 glyph_len = hb_buffer_get_length (hb_buffer);
384 if (glyph_len > LGSTRING_GLYPH_LEN (lgstring))
385 return Qnil;
386
387 /* We need the clusters in logical order. */
388 bool buf_reversed = false;
389 if (HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (hb_buffer)))
390 {
391 buf_reversed = true;
392 hb_buffer_reverse_clusters (hb_buffer);
393 }
394 info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
395 pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
396 ptrdiff_t from = -1, to UNINIT, cluster_offset UNINIT;
397 int incr = buf_reversed ? -1 : 1;
398 for (i = 0; i < glyph_len; i++)
399 {
400 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
401 struct font_metrics metrics = {.width = 0};
402 int xoff, yoff, wadjust;
403
404 if (NILP (lglyph))
405 {
406 lglyph = LGLYPH_NEW ();
407 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
408 }
409
410 if (info[i].cluster != from)
411 {
412 int j;
413 /* Found a new cluster. Determine its FROM and TO, and the
414 offset to the first character of the cluster. */
415 /* FROM is the index of the first character that contributed
416 to this cluster. */
417 from = info[i].cluster;
418 /* TO is the index of the last character that contributed to
419 this cluster. */
420 for (j = i; j < glyph_len && info[j].cluster == from; j++)
421 ;
422 to = (j == glyph_len) ? text_len - 1 : info[j].cluster - 1;
423 cluster_offset = 0;
424 /* For RTL buffers, HarfBuzz produces glyphs in a cluster in
425 reverse order, so we need to account for that to record
426 the correct character in each glyph.
427
428 Implementation note: the character codepoint recorded in
429 each glyph is not really used, except when we display the
430 glyphs in descr-text.el. So this is just an aeasthetic
431 issue. */
432 if (buf_reversed)
433 cluster_offset = to - from;
434 }
435
436 /* All the glyphs in a cluster have the same values of FROM and TO. */
437 LGLYPH_SET_FROM (lglyph, from);
438 LGLYPH_SET_TO (lglyph, to);
439
440 /* Not every glyph in a cluster maps directly to a single
441 character; in general, N characters can yield M glyphs, where
442 M could be smaller or greater than N. However, in many cases
443 there is a one-to-one correspondence, and it would be a pity
444 to lose that information, even if it's sometimes inaccurate. */
445 ptrdiff_t char_idx = from + cluster_offset;
446 cluster_offset += incr;
447 if (char_idx > to)
448 char_idx = to;
449 if (char_idx < from)
450 char_idx = from;
451 LGLYPH_SET_CHAR (lglyph, chars[char_idx]);
452 LGLYPH_SET_CODE (lglyph, info[i].codepoint);
453
454 unsigned code = info[i].codepoint;
455 font->driver->text_extents (font, &code, 1, &metrics);
456 LGLYPH_SET_WIDTH (lglyph, metrics.width);
457 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
458 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
459 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
460 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
461
462 xoff = lround (pos[i].x_offset * position_unit);
463 yoff = - lround (pos[i].y_offset * position_unit);
464 wadjust = lround (pos[i].x_advance * position_unit);
465 if (xoff || yoff || wadjust != metrics.width)
466 {
467 Lisp_Object vec = make_uninit_vector (3);
468 ASET (vec, 0, make_fixnum (xoff));
469 ASET (vec, 1, make_fixnum (yoff));
470 ASET (vec, 2, make_fixnum (wadjust));
471 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
472 }
473 }
474
475 return make_fixnum (glyph_len);
476}
477
478Lisp_Object
479hbfont_combining_capability (struct font *font)
480{
481 return Qt;
482}
diff --git a/src/indent.c b/src/indent.c
index 90d8b1ce8e9..f0d709e38b3 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -599,7 +599,7 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, ptrdiff_t *prevcol)
599 if (cmp_it.id >= 0 599 if (cmp_it.id >= 0
600 || (scan == cmp_it.stop_pos 600 || (scan == cmp_it.stop_pos
601 && composition_reseat_it (&cmp_it, scan, scan_byte, end, 601 && composition_reseat_it (&cmp_it, scan, scan_byte, end,
602 w, NULL, Qnil))) 602 w, NEUTRAL_DIR, NULL, Qnil)))
603 composition_update_it (&cmp_it, scan, scan_byte, Qnil); 603 composition_update_it (&cmp_it, scan, scan_byte, Qnil);
604 if (cmp_it.id >= 0) 604 if (cmp_it.id >= 0)
605 { 605 {
@@ -1507,7 +1507,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
1507 if (cmp_it.id >= 0 1507 if (cmp_it.id >= 0
1508 || (pos == cmp_it.stop_pos 1508 || (pos == cmp_it.stop_pos
1509 && composition_reseat_it (&cmp_it, pos, pos_byte, to, win, 1509 && composition_reseat_it (&cmp_it, pos, pos_byte, to, win,
1510 NULL, Qnil))) 1510 NEUTRAL_DIR, NULL, Qnil)))
1511 composition_update_it (&cmp_it, pos, pos_byte, Qnil); 1511 composition_update_it (&cmp_it, pos, pos_byte, Qnil);
1512 if (cmp_it.id >= 0) 1512 if (cmp_it.id >= 0)
1513 { 1513 {
diff --git a/src/lisp.h b/src/lisp.h
index 6db90596899..5bd88f32e6e 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3994,6 +3994,7 @@ extern void map_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Ob
3994 Lisp_Object, struct charset *, 3994 Lisp_Object, struct charset *,
3995 unsigned, unsigned); 3995 unsigned, unsigned);
3996extern Lisp_Object uniprop_table (Lisp_Object); 3996extern Lisp_Object uniprop_table (Lisp_Object);
3997extern Lisp_Object get_unicode_property (Lisp_Object, int);
3997extern void syms_of_chartab (void); 3998extern void syms_of_chartab (void);
3998 3999
3999/* Defined in print.c. */ 4000/* Defined in print.c. */
diff --git a/src/macfont.m b/src/macfont.m
index f825e6291d3..abdf0ecfe59 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -39,6 +39,12 @@ Original author: YAMAMOTO Mitsuharu
39 39
40#include <libkern/OSByteOrder.h> 40#include <libkern/OSByteOrder.h>
41 41
42/* Values for `dir' argument to shaper functions. */
43enum lgstring_direction
44 {
45 DIR_R2L = -1, DIR_UNKNOWN = 0, DIR_L2R = 1,
46 };
47
42static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph); 48static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
43static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph); 49static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
44static CFArrayRef mac_font_create_available_families (void); 50static CFArrayRef mac_font_create_available_families (void);
@@ -49,7 +55,8 @@ static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
49 CFArrayRef); 55 CFArrayRef);
50static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef); 56static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
51static CFIndex mac_font_shape (CTFontRef, CFStringRef, 57static CFIndex mac_font_shape (CTFontRef, CFStringRef,
52 struct mac_glyph_layout *, CFIndex); 58 struct mac_glyph_layout *, CFIndex,
59 enum lgstring_direction);
53static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef); 60static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
54static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef); 61static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
55#if USE_CT_GLYPH_INFO 62#if USE_CT_GLYPH_INFO
@@ -318,7 +325,8 @@ mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
318 325
319static CFIndex 326static CFIndex
320mac_font_shape_1 (NSFont *font, NSString *string, 327mac_font_shape_1 (NSFont *font, NSString *string,
321 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len) 328 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
329 enum lgstring_direction dir)
322{ 330{
323 NSUInteger i; 331 NSUInteger i;
324 CFIndex result = 0; 332 CFIndex result = 0;
@@ -582,11 +590,11 @@ mac_font_shape_1 (NSFont *font, NSString *string,
582static CFIndex 590static CFIndex
583mac_screen_font_shape (ScreenFontRef font, CFStringRef string, 591mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
584 struct mac_glyph_layout *glyph_layouts, 592 struct mac_glyph_layout *glyph_layouts,
585 CFIndex glyph_len) 593 CFIndex glyph_len, enum lgstring_direction dir)
586{ 594{
587 return mac_font_shape_1 ([(NSFont *)font printerFont], 595 return mac_font_shape_1 ([(NSFont *)font printerFont],
588 (NSString *) string, 596 (NSString *) string,
589 glyph_layouts, glyph_len); 597 glyph_layouts, glyph_len, dir);
590} 598}
591 599
592static CGColorRef 600static CGColorRef
@@ -1642,7 +1650,7 @@ static unsigned macfont_encode_char (struct font *, int);
1642static void macfont_text_extents (struct font *, const unsigned int *, int, 1650static void macfont_text_extents (struct font *, const unsigned int *, int,
1643 struct font_metrics *); 1651 struct font_metrics *);
1644static int macfont_draw (struct glyph_string *, int, int, int, int, bool); 1652static int macfont_draw (struct glyph_string *, int, int, int, int, bool);
1645static Lisp_Object macfont_shape (Lisp_Object); 1653static Lisp_Object macfont_shape (Lisp_Object, Lisp_Object);
1646static int macfont_variation_glyphs (struct font *, int c, 1654static int macfont_variation_glyphs (struct font *, int c,
1647 unsigned variations[256]); 1655 unsigned variations[256]);
1648static void macfont_filter_properties (Lisp_Object, Lisp_Object); 1656static void macfont_filter_properties (Lisp_Object, Lisp_Object);
@@ -2926,7 +2934,7 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2926} 2934}
2927 2935
2928static Lisp_Object 2936static Lisp_Object
2929macfont_shape (Lisp_Object lgstring) 2937macfont_shape (Lisp_Object lgstring, Lisp_Object direction)
2930{ 2938{
2931 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 2939 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2932 struct macfont_info *macfont_info = (struct macfont_info *) font; 2940 struct macfont_info *macfont_info = (struct macfont_info *) font;
@@ -2976,12 +2984,18 @@ macfont_shape (Lisp_Object lgstring)
2976 kCFAllocatorNull); 2984 kCFAllocatorNull);
2977 if (string) 2985 if (string)
2978 { 2986 {
2987 enum lgstring_direction dir = DIR_UNKNOWN;
2988
2989 if (EQ (direction, QL2R))
2990 dir = DIR_L2R;
2991 else if (EQ (direction, QR2L))
2992 dir = DIR_R2L;
2979 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len); 2993 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2980 if (macfont_info->screen_font) 2994 if (macfont_info->screen_font)
2981 used = mac_screen_font_shape (macfont_info->screen_font, string, 2995 used = mac_screen_font_shape (macfont_info->screen_font, string,
2982 glyph_layouts, glyph_len); 2996 glyph_layouts, glyph_len, dir);
2983 else 2997 else
2984 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len); 2998 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len, dir);
2985 CFRelease (string); 2999 CFRelease (string);
2986 } 3000 }
2987 3001
@@ -3662,7 +3676,8 @@ mac_font_create_line_with_string_and_font (CFStringRef string,
3662 3676
3663static CFIndex 3677static CFIndex
3664mac_font_shape (CTFontRef font, CFStringRef string, 3678mac_font_shape (CTFontRef font, CFStringRef string,
3665 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len) 3679 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
3680 enum lgstring_direction dir)
3666{ 3681{
3667 CFIndex used, result = 0; 3682 CFIndex used, result = 0;
3668 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font); 3683 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
diff --git a/src/w32common.h b/src/w32common.h
index bca5244caaa..adde784634a 100644
--- a/src/w32common.h
+++ b/src/w32common.h
@@ -81,4 +81,8 @@ get_proc_addr (HINSTANCE handle, LPCSTR fname)
81 } \ 81 } \
82 while (false) 82 while (false)
83 83
84#ifdef HAVE_HARFBUZZ
85extern bool hbfont_init_w32_funcs (HMODULE);
86#endif
87
84#endif /* W32COMMON_H */ 88#endif /* W32COMMON_H */
diff --git a/src/w32fns.c b/src/w32fns.c
index bb74fcc1640..8ebfc119521 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -221,6 +221,7 @@ int menubar_in_use = 0;
221/* From w32uniscribe.c */ 221/* From w32uniscribe.c */
222extern void syms_of_w32uniscribe (void); 222extern void syms_of_w32uniscribe (void);
223extern int uniscribe_available; 223extern int uniscribe_available;
224extern int harfbuzz_available;
224 225
225#ifdef WINDOWSNT 226#ifdef WINDOWSNT
226/* From w32inevt.c */ 227/* From w32inevt.c */
@@ -5843,7 +5844,45 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
5843 specbind (Qx_resource_name, name); 5844 specbind (Qx_resource_name, name);
5844 } 5845 }
5845 5846
5846 if (uniscribe_available) 5847 bool register_uniscribe = uniscribe_available;
5848#ifdef HAVE_HARFBUZZ
5849 /* Register Uniscribe only if HarfBuzz is not available or if
5850 explicitly requested. If Uniscribe is registered, register
5851 HarfBuzz only if explicitly requested. */
5852 bool register_harfbuzz = harfbuzz_available;
5853 if (register_harfbuzz)
5854 register_uniscribe = false;
5855 Lisp_Object dflt_backends
5856 = gui_display_get_arg (dpyinfo, parameters, Qfont_backend,
5857 "fontBackend", "FontBackend", RES_TYPE_STRING);
5858 if (!EQ (dflt_backends, Qunbound))
5859 {
5860 bool harfbuzz_requested = false, uniscribe_requested = false;
5861 if (CONSP (dflt_backends))
5862 {
5863 if (!NILP (Fmemq (Quniscribe, dflt_backends)))
5864 uniscribe_requested = true;
5865 if (!NILP (Fmemq (Qharfbuzz, dflt_backends)))
5866 harfbuzz_requested = true;
5867 }
5868 else if (STRINGP (dflt_backends))
5869 {
5870 if (strcmp (SSDATA (dflt_backends), "uniscribe") == 0)
5871 uniscribe_requested = true;
5872 else if (strcmp (SSDATA (dflt_backends), "harfbuzz") == 0)
5873 harfbuzz_requested = true;
5874 }
5875 if (uniscribe_requested)
5876 {
5877 register_uniscribe = uniscribe_available;
5878 if (!harfbuzz_requested)
5879 register_harfbuzz = false;
5880 }
5881 }
5882 if (register_harfbuzz)
5883 register_font_driver (&harfbuzz_font_driver, f);
5884#endif
5885 if (register_uniscribe)
5847 register_font_driver (&uniscribe_font_driver, f); 5886 register_font_driver (&uniscribe_font_driver, f);
5848 register_font_driver (&w32font_driver, f); 5887 register_font_driver (&w32font_driver, f);
5849 5888
@@ -6896,7 +6935,45 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
6896 specbind (Qx_resource_name, name); 6935 specbind (Qx_resource_name, name);
6897 } 6936 }
6898 6937
6899 if (uniscribe_available) 6938 bool register_uniscribe = uniscribe_available;
6939#ifdef HAVE_HARFBUZZ
6940 /* Register Uniscribe only if HarfBuzz is not available or if
6941 explicitly requested. If Uniscribe is registered, register
6942 HarfBuzz only if explicitly requested. */
6943 bool register_harfbuzz = harfbuzz_available;
6944 if (register_harfbuzz)
6945 register_uniscribe = false;
6946 Lisp_Object dflt_backends
6947 = gui_display_get_arg (dpyinfo, parms, Qfont_backend,
6948 "fontBackend", "FontBackend", RES_TYPE_STRING);
6949 if (!EQ (dflt_backends, Qunbound))
6950 {
6951 bool harfbuzz_requested = false, uniscribe_requested = false;
6952 if (CONSP (dflt_backends))
6953 {
6954 if (!NILP (Fmemq (Quniscribe, dflt_backends)))
6955 uniscribe_requested = true;
6956 if (!NILP (Fmemq (Qharfbuzz, dflt_backends)))
6957 harfbuzz_requested = true;
6958 }
6959 else if (STRINGP (dflt_backends))
6960 {
6961 if (strcmp (SSDATA (dflt_backends), "uniscribe") == 0)
6962 uniscribe_requested = true;
6963 else if (strcmp (SSDATA (dflt_backends), "harfbuzz") == 0)
6964 harfbuzz_requested = true;
6965 }
6966 if (uniscribe_requested)
6967 {
6968 register_uniscribe = uniscribe_available;
6969 if (!harfbuzz_requested)
6970 register_harfbuzz = false;
6971 }
6972 }
6973 if (register_harfbuzz)
6974 register_font_driver (&harfbuzz_font_driver, f);
6975#endif
6976 if (register_uniscribe)
6900 register_font_driver (&uniscribe_font_driver, f); 6977 register_font_driver (&uniscribe_font_driver, f);
6901 register_font_driver (&w32font_driver, f); 6978 register_font_driver (&w32font_driver, f);
6902 6979
diff --git a/src/w32font.c b/src/w32font.c
index 47a33aec35f..14d49b24d9b 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -2646,6 +2646,7 @@ syms_of_w32font (void)
2646{ 2646{
2647 DEFSYM (Qgdi, "gdi"); 2647 DEFSYM (Qgdi, "gdi");
2648 DEFSYM (Quniscribe, "uniscribe"); 2648 DEFSYM (Quniscribe, "uniscribe");
2649 DEFSYM (Qharfbuzz, "harfbuzz");
2649 DEFSYM (QCformat, ":format"); 2650 DEFSYM (QCformat, ":format");
2650 2651
2651 /* Generic font families. */ 2652 /* Generic font families. */
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index 72b524f2eab..caf346a5ec2 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -1,4 +1,5 @@
1/* Font backend for the Microsoft W32 Uniscribe API. 1/* Font backend for the Microsoft W32 Uniscribe API.
2 Windows-specific parts of the HarfBuzz font backend.
2 Copyright (C) 2008-2019 Free Software Foundation, Inc. 3 Copyright (C) 2008-2019 Free Software Foundation, Inc.
3 4
4This file is part of GNU Emacs. 5This file is part of GNU Emacs.
@@ -29,6 +30,14 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
29#define _WIN32_WINNT 0x0600 30#define _WIN32_WINNT 0x0600
30#include <windows.h> 31#include <windows.h>
31#include <usp10.h> 32#include <usp10.h>
33#ifdef HAVE_HARFBUZZ
34# include <hb.h>
35# if GNUC_PREREQ (4, 3, 0)
36# define bswap_32(v) __builtin_bswap32(v)
37# else
38# include <byteswap.h>
39# endif
40#endif
32 41
33#include "lisp.h" 42#include "lisp.h"
34#include "w32term.h" 43#include "w32term.h"
@@ -39,10 +48,16 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
39#include "pdumper.h" 48#include "pdumper.h"
40#include "w32common.h" 49#include "w32common.h"
41 50
51/* Extension of w32font_info used by Uniscribe and HarfBuzz backends. */
42struct uniscribe_font_info 52struct uniscribe_font_info
43{ 53{
44 struct w32font_info w32_font; 54 struct w32font_info w32_font;
45 SCRIPT_CACHE cache; 55 /* This is used by the Uniscribe backend as a pointer to the script
56 cache, and by the HarfBuzz backend as a pointer to a hb_font_t
57 object. */
58 void *cache;
59 /* This is used by the HarfBuzz backend to store the font scale. */
60 double scale;
46}; 61};
47 62
48int uniscribe_available = 0; 63int uniscribe_available = 0;
@@ -51,6 +66,39 @@ int uniscribe_available = 0;
51static int CALLBACK ALIGN_STACK add_opentype_font_name_to_list (ENUMLOGFONTEX *, 66static int CALLBACK ALIGN_STACK add_opentype_font_name_to_list (ENUMLOGFONTEX *,
52 NEWTEXTMETRICEX *, 67 NEWTEXTMETRICEX *,
53 DWORD, LPARAM); 68 DWORD, LPARAM);
69#ifdef HAVE_HARFBUZZ
70
71struct font_driver harfbuzz_font_driver;
72int harfbuzz_available = 0;
73
74/* Typedefs for HarfBuzz functions which we call through function
75 pointers initialized after we load the HarfBuzz DLL. */
76DEF_DLL_FN (hb_blob_t *, hb_blob_create,
77 (const char *, unsigned int, hb_memory_mode_t, void *,
78 hb_destroy_func_t));
79DEF_DLL_FN (hb_face_t *, hb_face_create_for_tables,
80 (hb_reference_table_func_t, void *, hb_destroy_func_t));
81DEF_DLL_FN (unsigned, hb_face_get_glyph_count, (const hb_face_t *));
82DEF_DLL_FN (hb_font_t *, hb_font_create, (hb_face_t *));
83DEF_DLL_FN (void, hb_font_destroy, (hb_font_t *));
84DEF_DLL_FN (void, hb_face_destroy, (hb_face_t *));
85DEF_DLL_FN (unsigned int, hb_face_get_upem, (hb_face_t *));
86DEF_DLL_FN (hb_bool_t, hb_font_get_nominal_glyph,
87 (hb_font_t *, hb_codepoint_t, hb_codepoint_t *));
88DEF_DLL_FN (hb_bool_t, hb_font_get_variation_glyph,
89 (hb_font_t *, hb_codepoint_t, hb_codepoint_t, hb_codepoint_t *));
90
91#define hb_blob_create fn_hb_blob_create
92#define hb_face_create_for_tables fn_hb_face_create_for_tables
93#define hb_face_get_glyph_count fn_hb_face_get_glyph_count
94#define hb_font_create fn_hb_font_create
95#define hb_font_destroy fn_hb_font_destroy
96#define hb_face_destroy fn_hb_face_destroy
97#define hb_face_get_upem fn_hb_face_get_upem
98#define hb_font_get_nominal_glyph fn_hb_font_get_nominal_glyph
99#define hb_font_get_variation_glyph fn_hb_font_get_variation_glyph
100#endif
101
54/* Used by uniscribe_otf_capability. */ 102/* Used by uniscribe_otf_capability. */
55static Lisp_Object otf_features (HDC context, const char *table); 103static Lisp_Object otf_features (HDC context, const char *table);
56 104
@@ -117,7 +165,10 @@ uniscribe_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
117 struct uniscribe_font_info *uniscribe_font 165 struct uniscribe_font_info *uniscribe_font
118 = (struct uniscribe_font_info *) XFONT_OBJECT (font_object); 166 = (struct uniscribe_font_info *) XFONT_OBJECT (font_object);
119 167
120 ASET (font_object, FONT_TYPE_INDEX, Quniscribe); 168 if (!NILP (AREF (font_entity, FONT_TYPE_INDEX)))
169 ASET (font_object, FONT_TYPE_INDEX, AREF (font_entity, FONT_TYPE_INDEX));
170 else /* paranoia: this should never happen */
171 ASET (font_object, FONT_TYPE_INDEX, Quniscribe);
121 172
122 if (!w32font_open_internal (f, font_entity, pixel_size, font_object)) 173 if (!w32font_open_internal (f, font_entity, pixel_size, font_object))
123 { 174 {
@@ -127,10 +178,15 @@ uniscribe_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
127 /* Initialize the cache for this font. */ 178 /* Initialize the cache for this font. */
128 uniscribe_font->cache = NULL; 179 uniscribe_font->cache = NULL;
129 180
130 /* Uniscribe backend uses glyph indices. */ 181 /* Uniscribe and HarfBuzz backends use glyph indices. */
131 uniscribe_font->w32_font.glyph_idx = ETO_GLYPH_INDEX; 182 uniscribe_font->w32_font.glyph_idx = ETO_GLYPH_INDEX;
132 183
133 uniscribe_font->w32_font.font.driver = &uniscribe_font_driver; 184#ifdef HAVE_HARFBUZZ
185 if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qharfbuzz))
186 uniscribe_font->w32_font.font.driver = &harfbuzz_font_driver;
187 else
188#endif /* HAVE_HARFBUZZ */
189 uniscribe_font->w32_font.font.driver = &uniscribe_font_driver;
134 190
135 return font_object; 191 return font_object;
136} 192}
@@ -141,8 +197,16 @@ uniscribe_close (struct font *font)
141 struct uniscribe_font_info *uniscribe_font 197 struct uniscribe_font_info *uniscribe_font
142 = (struct uniscribe_font_info *) font; 198 = (struct uniscribe_font_info *) font;
143 199
200#ifdef HAVE_HARFBUZZ
201 if (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver
202 && uniscribe_font->cache)
203 hb_font_destroy ((hb_font_t *) uniscribe_font->cache);
204 else
205#endif
144 if (uniscribe_font->cache) 206 if (uniscribe_font->cache)
145 ScriptFreeCache (&(uniscribe_font->cache)); 207 ScriptFreeCache ((SCRIPT_CACHE) &(uniscribe_font->cache));
208
209 uniscribe_font->cache = NULL;
146 210
147 w32font_close (font); 211 w32font_close (font);
148} 212}
@@ -205,6 +269,9 @@ uniscribe_otf_capability (struct font *font)
205 (N+1)th element of LGSTRING is nil, input of shaping is from the 269 (N+1)th element of LGSTRING is nil, input of shaping is from the
206 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and 270 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and
207 CODE are already set. 271 CODE are already set.
272 DIRECTION is either L2R or R2L, or nil if unknown. During
273 redisplay, this comes from applying the UBA, is passed from
274 composition_reseat_it, and is used by the HarfBuzz shaper.
208 275
209 This function updates all fields of the input glyphs. If the 276 This function updates all fields of the input glyphs. If the
210 output glyphs (M) are more than the input glyphs (N), (N+1)th 277 output glyphs (M) are more than the input glyphs (N), (N+1)th
@@ -213,7 +280,7 @@ uniscribe_otf_capability (struct font *font)
213 than the length of LGSTRING, nil should be returned. In that case, 280 than the length of LGSTRING, nil should be returned. In that case,
214 this function is called again with a larger LGSTRING. */ 281 this function is called again with a larger LGSTRING. */
215static Lisp_Object 282static Lisp_Object
216uniscribe_shape (Lisp_Object lgstring) 283uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
217{ 284{
218 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 285 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
219 struct uniscribe_font_info *uniscribe_font 286 struct uniscribe_font_info *uniscribe_font
@@ -287,7 +354,7 @@ uniscribe_shape (Lisp_Object lgstring)
287 354
288 /* Context may be NULL here, in which case the cache should be 355 /* Context may be NULL here, in which case the cache should be
289 used without needing to select the font. */ 356 used without needing to select the font. */
290 result = ScriptShape (context, &(uniscribe_font->cache), 357 result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
291 chars + items[i].iCharPos, nchars_in_run, 358 chars + items[i].iCharPos, nchars_in_run,
292 max_glyphs - done_glyphs, &(items[i].a), 359 max_glyphs - done_glyphs, &(items[i].a),
293 glyphs, clusters, attributes, &nglyphs); 360 glyphs, clusters, attributes, &nglyphs);
@@ -301,7 +368,7 @@ uniscribe_shape (Lisp_Object lgstring)
301 context = get_frame_dc (f); 368 context = get_frame_dc (f);
302 old_font = SelectObject (context, FONT_HANDLE (font)); 369 old_font = SelectObject (context, FONT_HANDLE (font));
303 370
304 result = ScriptShape (context, &(uniscribe_font->cache), 371 result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
305 chars + items[i].iCharPos, nchars_in_run, 372 chars + items[i].iCharPos, nchars_in_run,
306 max_glyphs - done_glyphs, &(items[i].a), 373 max_glyphs - done_glyphs, &(items[i].a),
307 glyphs, clusters, attributes, &nglyphs); 374 glyphs, clusters, attributes, &nglyphs);
@@ -326,7 +393,7 @@ uniscribe_shape (Lisp_Object lgstring)
326 } 393 }
327 else 394 else
328 { 395 {
329 result = ScriptPlace (context, &(uniscribe_font->cache), 396 result = ScriptPlace (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
330 glyphs, nglyphs, attributes, &(items[i].a), 397 glyphs, nglyphs, attributes, &(items[i].a),
331 advances, offsets, &overall_metrics); 398 advances, offsets, &overall_metrics);
332 if (result == E_PENDING && !context) 399 if (result == E_PENDING && !context)
@@ -336,13 +403,15 @@ uniscribe_shape (Lisp_Object lgstring)
336 context = get_frame_dc (f); 403 context = get_frame_dc (f);
337 old_font = SelectObject (context, FONT_HANDLE (font)); 404 old_font = SelectObject (context, FONT_HANDLE (font));
338 405
339 result = ScriptPlace (context, &(uniscribe_font->cache), 406 result = ScriptPlace (context,
407 (SCRIPT_CACHE) &(uniscribe_font->cache),
340 glyphs, nglyphs, attributes, &(items[i].a), 408 glyphs, nglyphs, attributes, &(items[i].a),
341 advances, offsets, &overall_metrics); 409 advances, offsets, &overall_metrics);
342 } 410 }
343 if (SUCCEEDED (result)) 411 if (SUCCEEDED (result))
344 { 412 {
345 int j, from, to, adj_offset = 0; 413 int j, from, to, adj_offset = 0;
414 int cluster_offset = 0;
346 415
347 from = 0; 416 from = 0;
348 to = from; 417 to = from;
@@ -386,6 +455,7 @@ uniscribe_shape (Lisp_Object lgstring)
386 } 455 }
387 } 456 }
388 } 457 }
458 cluster_offset = 0;
389 459
390 /* For RTL text, the Uniscribe shaper prepares 460 /* For RTL text, the Uniscribe shaper prepares
391 the values in ADVANCES array for layout in 461 the values in ADVANCES array for layout in
@@ -401,6 +471,8 @@ uniscribe_shape (Lisp_Object lgstring)
401 adjustment for the base character, which is 471 adjustment for the base character, which is
402 then updated for each successive glyph in the 472 then updated for each successive glyph in the
403 grapheme cluster. */ 473 grapheme cluster. */
474 /* FIXME: Should we use DIRECTION here instead
475 of what ScriptItemize guessed? */
404 if (items[i].a.fRTL) 476 if (items[i].a.fRTL)
405 { 477 {
406 int j1 = j; 478 int j1 = j;
@@ -414,8 +486,11 @@ uniscribe_shape (Lisp_Object lgstring)
414 } 486 }
415 } 487 }
416 488
417 LGLYPH_SET_CHAR (lglyph, chars[items[i].iCharPos 489 int char_idx = items[i].iCharPos + from + cluster_offset;
418 + from]); 490 if (from + cluster_offset > to)
491 char_idx = items[i].iCharPos + to;
492 cluster_offset++;
493 LGLYPH_SET_CHAR (lglyph, chars[char_idx]);
419 LGLYPH_SET_FROM (lglyph, items[i].iCharPos + from); 494 LGLYPH_SET_FROM (lglyph, items[i].iCharPos + from);
420 LGLYPH_SET_TO (lglyph, items[i].iCharPos + to); 495 LGLYPH_SET_TO (lglyph, items[i].iCharPos + to);
421 496
@@ -424,18 +499,18 @@ uniscribe_shape (Lisp_Object lgstring)
424 LGLYPH_SET_ASCENT (lglyph, font->ascent); 499 LGLYPH_SET_ASCENT (lglyph, font->ascent);
425 LGLYPH_SET_DESCENT (lglyph, font->descent); 500 LGLYPH_SET_DESCENT (lglyph, font->descent);
426 501
427 result = ScriptGetGlyphABCWidth (context, 502 result = ScriptGetGlyphABCWidth
428 &(uniscribe_font->cache), 503 (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
429 glyphs[j], &char_metric); 504 glyphs[j], &char_metric);
430 if (result == E_PENDING && !context) 505 if (result == E_PENDING && !context)
431 { 506 {
432 /* Cache incomplete... */ 507 /* Cache incomplete... */
433 f = XFRAME (selected_frame); 508 f = XFRAME (selected_frame);
434 context = get_frame_dc (f); 509 context = get_frame_dc (f);
435 old_font = SelectObject (context, FONT_HANDLE (font)); 510 old_font = SelectObject (context, FONT_HANDLE (font));
436 result = ScriptGetGlyphABCWidth (context, 511 result = ScriptGetGlyphABCWidth
437 &(uniscribe_font->cache), 512 (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
438 glyphs[j], &char_metric); 513 glyphs[j], &char_metric);
439 } 514 }
440 515
441 if (SUCCEEDED (result)) 516 if (SUCCEEDED (result))
@@ -567,7 +642,8 @@ uniscribe_encode_char (struct font *font, int c)
567 order. */ 642 order. */
568 items[0].a.fLogicalOrder = 1; 643 items[0].a.fLogicalOrder = 1;
569 644
570 result = ScriptShape (context, &(uniscribe_font->cache), 645 result = ScriptShape (context,
646 (SCRIPT_CACHE) &(uniscribe_font->cache),
571 ch, len, 2, &(items[0].a), 647 ch, len, 2, &(items[0].a),
572 glyphs, clusters, attrs, &nglyphs); 648 glyphs, clusters, attrs, &nglyphs);
573 649
@@ -578,7 +654,8 @@ uniscribe_encode_char (struct font *font, int c)
578 f = XFRAME (selected_frame); 654 f = XFRAME (selected_frame);
579 context = get_frame_dc (f); 655 context = get_frame_dc (f);
580 old_font = SelectObject (context, FONT_HANDLE (font)); 656 old_font = SelectObject (context, FONT_HANDLE (font));
581 result = ScriptShape (context, &(uniscribe_font->cache), 657 result = ScriptShape (context,
658 (SCRIPT_CACHE) &(uniscribe_font->cache),
582 ch, len, 2, &(items[0].a), 659 ch, len, 2, &(items[0].a),
583 glyphs, clusters, attrs, &nglyphs); 660 glyphs, clusters, attrs, &nglyphs);
584 } 661 }
@@ -596,7 +673,8 @@ uniscribe_encode_char (struct font *font, int c)
596 when shaped. But we still need the return from here 673 when shaped. But we still need the return from here
597 to be valid for the shaping engine to be invoked 674 to be valid for the shaping engine to be invoked
598 later. */ 675 later. */
599 result = ScriptGetCMap (context, &(uniscribe_font->cache), 676 result = ScriptGetCMap (context,
677 (SCRIPT_CACHE) &(uniscribe_font->cache),
600 ch, len, 0, glyphs); 678 ch, len, 0, glyphs);
601 if (SUCCEEDED (result) && glyphs[0]) 679 if (SUCCEEDED (result) && glyphs[0])
602 code = glyphs[0]; 680 code = glyphs[0];
@@ -1143,6 +1221,210 @@ font_table_error:
1143 return Qnil; 1221 return Qnil;
1144} 1222}
1145 1223
1224#ifdef HAVE_HARFBUZZ
1225
1226/* W32 implementation of the 'list' method for HarfBuzz backend. */
1227static Lisp_Object
1228w32hb_list (struct frame *f, Lisp_Object font_spec)
1229{
1230 Lisp_Object fonts = w32font_list_internal (f, font_spec, true);
1231 FONT_ADD_LOG ("harfbuzz-list", font_spec, fonts);
1232
1233 for (Lisp_Object tail = fonts; CONSP (tail); tail = XCDR (tail))
1234 ASET (XCAR (tail), FONT_TYPE_INDEX, Qharfbuzz);
1235
1236 return fonts;
1237}
1238
1239/* W32 implementation of the 'match' method for HarfBuzz backend. */
1240static Lisp_Object
1241w32hb_match (struct frame *f, Lisp_Object font_spec)
1242{
1243 Lisp_Object entity = w32font_match_internal (f, font_spec, true);
1244 FONT_ADD_LOG ("harfbuzz-match", font_spec, entity);
1245
1246 if (! NILP (entity))
1247 ASET (entity, FONT_TYPE_INDEX, Qharfbuzz);
1248 return entity;
1249}
1250
1251/* Callback function to free memory. We need this so we could pass it
1252 to HarfBuzz as the function to call to destroy objects for which we
1253 allocated data by calling our 'malloc' (as opposed to 'malloc' from
1254 the MS CRT, against which HarfBuzz was linked). */
1255static void
1256free_cb (void *ptr)
1257{
1258 free (ptr);
1259}
1260
1261/* A function used as reference_table_func for HarfBuzz. It returns
1262 the data of a specified table of a font as a blob. */
1263static hb_blob_t *
1264w32hb_get_font_table (hb_face_t *face, hb_tag_t tag, void *data)
1265{
1266 struct frame *f = XFRAME (selected_frame);
1267 HDC context = get_frame_dc (f);
1268 HFONT old_font = SelectObject (context, (HFONT) data);
1269 char *font_data = NULL;
1270 DWORD font_data_size = 0, val;
1271 DWORD table = bswap_32 (tag);
1272 hb_blob_t *blob = NULL;
1273
1274 val = GetFontData (context, table, 0, font_data, font_data_size);
1275 if (val != GDI_ERROR)
1276 {
1277 font_data_size = val;
1278 /* Don't call xmalloc, because it can signal an error, while
1279 we are inside a critical section established by get_frame_dc. */
1280 font_data = malloc (font_data_size);
1281 if (font_data)
1282 {
1283 val = GetFontData (context, table, 0, font_data, font_data_size);
1284 if (val != GDI_ERROR)
1285 blob = hb_blob_create (font_data, font_data_size,
1286 HB_MEMORY_MODE_READONLY, font_data, free_cb);
1287 }
1288 }
1289
1290 /* Restore graphics context. */
1291 SelectObject (context, old_font);
1292 release_frame_dc (f, context);
1293
1294 return blob;
1295}
1296
1297/* Helper function used by the HarfBuzz implementations of the
1298 encode_char, has_char, and begin_hb_font methods. It creates an
1299 hb_font_t object for a given Emacs font. */
1300static hb_font_t *
1301w32hb_get_font (struct font *font, double *scale)
1302{
1303 hb_font_t *hb_font = NULL;
1304 HFONT font_handle = FONT_HANDLE (font);
1305 hb_face_t *hb_face =
1306 hb_face_create_for_tables (w32hb_get_font_table, font_handle, NULL);
1307 if (hb_face_get_glyph_count (hb_face) > 0)
1308 hb_font = hb_font_create (hb_face);
1309
1310 struct uniscribe_font_info *uniscribe_font =
1311 (struct uniscribe_font_info *) font;
1312 unsigned upem = hb_face_get_upem (hb_face);
1313 eassert (upem > 0);
1314 /* https://support.microsoft.com/en-sg/help/74299/info-calculating-the-logical-height-and-point-size-of-a-font. */
1315 LONG font_point_size =
1316 uniscribe_font->w32_font.metrics.tmHeight
1317 - uniscribe_font->w32_font.metrics.tmInternalLeading;
1318 /* https://docs.microsoft.com/en-us/typography/opentype/spec/ttch01,
1319 under "Converting FUnits to pixels". */
1320 *scale = font_point_size * 1.0 / upem;
1321
1322 hb_face_destroy (hb_face);
1323
1324 /* FIXME: Can hb_font be non-NULL and yet invalid? Compare to get_empty? */
1325 return hb_font;
1326}
1327
1328/* W32 implementation of encode_char method for HarfBuzz backend. */
1329static unsigned
1330w32hb_encode_char (struct font *font, int c)
1331{
1332 struct uniscribe_font_info *uniscribe_font
1333 = (struct uniscribe_font_info *) font;
1334 eassert (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver);
1335 hb_font_t *hb_font = uniscribe_font->cache;
1336
1337 /* First time we use this font with HarfBuzz, create the hb_font_t
1338 object and cache it. */
1339 if (!hb_font)
1340 {
1341 double scale;
1342 hb_font = w32hb_get_font (font, &scale);
1343 if (!hb_font)
1344 return FONT_INVALID_CODE;
1345
1346 uniscribe_font->cache = hb_font;
1347 eassert (scale > 0.0);
1348 uniscribe_font->scale = scale;
1349 }
1350 hb_codepoint_t glyph;
1351 if (hb_font_get_nominal_glyph (hb_font, c, &glyph))
1352 return glyph;
1353 return FONT_INVALID_CODE;
1354}
1355
1356/* W32 implementation of HarfBuzz begin_hb_font and end_hb_font
1357 methods. */
1358
1359/* Return a HarfBuzz font object for FONT and store in POSITION_UNIT
1360 the scale factor to convert a hb_position_t value to the number of
1361 pixels. Return NULL if HarfBuzz font object is not available for
1362 FONT. */
1363static hb_font_t *
1364w32hb_begin_font (struct font *font, double *position_unit)
1365{
1366 struct uniscribe_font_info *uniscribe_font
1367 = (struct uniscribe_font_info *) font;
1368 eassert (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver);
1369
1370 /* First time we use this font with HarfBuzz, create the hb_font_t
1371 object and cache it. */
1372 if (!uniscribe_font->cache)
1373 {
1374 double scale;
1375 uniscribe_font->cache = w32hb_get_font (font, &scale);
1376 eassert (scale > 0.0);
1377 uniscribe_font->scale = scale;
1378 }
1379 *position_unit = uniscribe_font->scale;
1380 return (hb_font_t *) uniscribe_font->cache;
1381}
1382
1383/* W32 implementation of get_variation_glyphs method for HarfBuzz.
1384
1385 Return the number of variation glyphs of character C supported by
1386 FONT. VARIATIONS is an array of 256 elements. If the variation
1387 selector N (1..256) defines a glyph, that glyph code is stored in
1388 the (N-1)th element of VARIATIONS. */
1389static int
1390w32hb_get_variation_glyphs (struct font *font, int c, unsigned variations[256])
1391{
1392 struct uniscribe_font_info *uniscribe_font
1393 = (struct uniscribe_font_info *) font;
1394 eassert (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver);
1395
1396 /* First time we use this font with HarfBuzz, create the hb_font_t
1397 object and cache it. */
1398 if (!uniscribe_font->cache)
1399 {
1400 double scale;
1401 uniscribe_font->cache = w32hb_get_font (font, &scale);
1402 eassert (scale > 0.0);
1403 uniscribe_font->scale = scale;
1404 }
1405
1406 int i, n = 0;
1407 hb_font_t *hb_font = uniscribe_font->cache;
1408 for (i = 0; i < 16; i++)
1409 {
1410 if (hb_font_get_variation_glyph (hb_font, c, 0xFE00 + i, &variations[i]))
1411 n++;
1412 else
1413 variations[i] = 0;
1414 }
1415 for ( ; i < 256; i++)
1416 {
1417 if (hb_font_get_variation_glyph (hb_font, c, 0xE0100 + (i - 16),
1418 &variations[i]))
1419 n++;
1420 else
1421 variations[i] = 0;
1422 }
1423
1424 return n;
1425}
1426#endif /* HAVE_HARFBUZZ */
1427
1146#undef OTF_INT16_VAL 1428#undef OTF_INT16_VAL
1147#undef OTF_TAG_VAL 1429#undef OTF_TAG_VAL
1148#undef OTF_TAG 1430#undef OTF_TAG
@@ -1191,17 +1473,32 @@ syms_of_w32uniscribe (void)
1191 pdumper_do_now_and_after_load (syms_of_w32uniscribe_for_pdumper); 1473 pdumper_do_now_and_after_load (syms_of_w32uniscribe_for_pdumper);
1192} 1474}
1193 1475
1476#ifdef HAVE_HARFBUZZ
1477static bool
1478load_harfbuzz_funcs (HMODULE library)
1479{
1480 LOAD_DLL_FN (library, hb_blob_create);
1481 LOAD_DLL_FN (library, hb_face_create_for_tables);
1482 LOAD_DLL_FN (library, hb_face_get_glyph_count);
1483 LOAD_DLL_FN (library, hb_font_create);
1484 LOAD_DLL_FN (library, hb_font_destroy);
1485 LOAD_DLL_FN (library, hb_face_get_upem);
1486 LOAD_DLL_FN (library, hb_face_destroy);
1487 LOAD_DLL_FN (library, hb_font_get_nominal_glyph);
1488 LOAD_DLL_FN (library, hb_font_get_variation_glyph);
1489 return hbfont_init_w32_funcs (library);
1490}
1491#endif /* HAVE_HARFBUZZ */
1492
1194static void 1493static void
1195syms_of_w32uniscribe_for_pdumper (void) 1494syms_of_w32uniscribe_for_pdumper (void)
1196{ 1495{
1197 HMODULE uniscribe; 1496 /* Don't init Uniscribe and HarfBuzz when dumping */
1198
1199 /* Don't init uniscribe when dumping */
1200 if (!initialized) 1497 if (!initialized)
1201 return; 1498 return;
1202 1499
1203 /* Don't register if uniscribe is not available. */ 1500 /* Don't register if Uniscribe is not available. */
1204 uniscribe = GetModuleHandle ("usp10"); 1501 HMODULE uniscribe = GetModuleHandle ("usp10");
1205 if (!uniscribe) 1502 if (!uniscribe)
1206 return; 1503 return;
1207 1504
@@ -1221,4 +1518,31 @@ syms_of_w32uniscribe_for_pdumper (void)
1221 uniscribe_new_apis = true; 1518 uniscribe_new_apis = true;
1222 else 1519 else
1223 uniscribe_new_apis = false; 1520 uniscribe_new_apis = false;
1521
1522#ifdef HAVE_HARFBUZZ
1523 /* Currently, HarfBuzz DLLs are always named libharfbuzz-0.dll, as
1524 the project keeps the ABI backward-compatible. So we can
1525 hard-code the name of the library here, for now. If they ever
1526 break ABI compatibility, we may need to load the DLL that
1527 corresponds to the HarfBuzz version for which Emacs was built. */
1528 HMODULE harfbuzz = LoadLibrary ("libharfbuzz-0.dll");
1529 /* Don't register if HarfBuzz is not available. */
1530 if (!harfbuzz)
1531 return;
1532
1533 if (!load_harfbuzz_funcs (harfbuzz))
1534 return;
1535
1536 harfbuzz_available = 1;
1537 harfbuzz_font_driver = uniscribe_font_driver;
1538 harfbuzz_font_driver.type = Qharfbuzz;
1539 harfbuzz_font_driver.list = w32hb_list;
1540 harfbuzz_font_driver.match = w32hb_match;
1541 harfbuzz_font_driver.encode_char = w32hb_encode_char;
1542 harfbuzz_font_driver.shape = hbfont_shape;
1543 harfbuzz_font_driver.get_variation_glyphs = w32hb_get_variation_glyphs;
1544 harfbuzz_font_driver.combining_capability = hbfont_combining_capability;
1545 harfbuzz_font_driver.begin_hb_font = w32hb_begin_font;
1546 register_font_driver (&harfbuzz_font_driver, NULL);
1547#endif /* HAVE_HARFBUZZ */
1224} 1548}
diff --git a/src/xdisp.c b/src/xdisp.c
index aa10abeb191..4031571dd99 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -6955,6 +6955,7 @@ static next_element_function const get_next_element[NUM_IT_METHODS] =
6955 || ((IT)->cmp_it.stop_pos == (CHARPOS) \ 6955 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
6956 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \ 6956 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
6957 END_CHARPOS, (IT)->w, \ 6957 END_CHARPOS, (IT)->w, \
6958 (IT)->bidi_it.resolved_level, \
6958 FACE_FROM_ID_OR_NULL ((IT)->f, \ 6959 FACE_FROM_ID_OR_NULL ((IT)->f, \
6959 (IT)->face_id), \ 6960 (IT)->face_id), \
6960 (IT)->string))) 6961 (IT)->string)))
diff --git a/src/xfns.c b/src/xfns.c
index 4195980d33e..460dd1316e6 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3780,10 +3780,16 @@ This function is an internal primitive--use `make-frame' instead. */)
3780 3780
3781#ifdef USE_CAIRO 3781#ifdef USE_CAIRO
3782 register_font_driver (&ftcrfont_driver, f); 3782 register_font_driver (&ftcrfont_driver, f);
3783#ifdef HAVE_HARFBUZZ
3784 register_font_driver (&ftcrhbfont_driver, f);
3785#endif /* HAVE_HARFBUZZ */
3783#else 3786#else
3784#ifdef HAVE_FREETYPE 3787#ifdef HAVE_FREETYPE
3785#ifdef HAVE_XFT 3788#ifdef HAVE_XFT
3786 register_font_driver (&xftfont_driver, f); 3789 register_font_driver (&xftfont_driver, f);
3790#ifdef HAVE_HARFBUZZ
3791 register_font_driver (&xfthbfont_driver, f);
3792#endif
3787#else /* not HAVE_XFT */ 3793#else /* not HAVE_XFT */
3788 register_font_driver (&ftxfont_driver, f); 3794 register_font_driver (&ftxfont_driver, f);
3789#endif /* not HAVE_XFT */ 3795#endif /* not HAVE_XFT */
@@ -6205,15 +6211,21 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
6205 6211
6206#ifdef USE_CAIRO 6212#ifdef USE_CAIRO
6207 register_font_driver (&ftcrfont_driver, f); 6213 register_font_driver (&ftcrfont_driver, f);
6214#ifdef HAVE_HARFBUZZ
6215 register_font_driver (&ftcrhbfont_driver, f);
6216#endif /* HAVE_HARFBUZZ */
6208#else 6217#else
6209 register_font_driver (&xfont_driver, f);
6210#ifdef HAVE_FREETYPE 6218#ifdef HAVE_FREETYPE
6211#ifdef HAVE_XFT 6219#ifdef HAVE_XFT
6212 register_font_driver (&xftfont_driver, f); 6220 register_font_driver (&xftfont_driver, f);
6221#ifdef HAVE_HARFBUZZ
6222 register_font_driver (&xfthbfont_driver, f);
6223#endif
6213#else /* not HAVE_XFT */ 6224#else /* not HAVE_XFT */
6214 register_font_driver (&ftxfont_driver, f); 6225 register_font_driver (&ftxfont_driver, f);
6215#endif /* not HAVE_XFT */ 6226#endif /* not HAVE_XFT */
6216#endif /* HAVE_FREETYPE */ 6227#endif /* HAVE_FREETYPE */
6228 register_font_driver (&xfont_driver, f);
6217#endif /* not USE_CAIRO */ 6229#endif /* not USE_CAIRO */
6218 6230
6219 image_cache_refcount = 6231 image_cache_refcount =
diff --git a/src/xftfont.c b/src/xftfont.c
index 4f0a0d81d85..04cda12fb52 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];
@@ -174,10 +166,16 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
174 /* We should not destroy PAT here because it is kept in XFTFONT and 166 /* We should not destroy PAT here because it is kept in XFTFONT and
175 destroyed automatically when XFTFONT is closed. */ 167 destroyed automatically when XFTFONT is closed. */
176 font_object = font_build_object (VECSIZE (struct font_info), 168 font_object = font_build_object (VECSIZE (struct font_info),
177 Qxft, entity, size); 169 AREF (entity, FONT_TYPE_INDEX),
170 entity, size);
178 ASET (font_object, FONT_FILE_INDEX, filename); 171 ASET (font_object, FONT_FILE_INDEX, filename);
179 font = XFONT_OBJECT (font_object); 172 font = XFONT_OBJECT (font_object);
180 font->pixel_size = size; 173 font->pixel_size = size;
174#ifdef HAVE_HARFBUZZ
175 if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qxfthb))
176 font->driver = &xfthbfont_driver;
177 else
178#endif /* HAVE_HARFBUZZ */
181 font->driver = &xftfont_driver; 179 font->driver = &xftfont_driver;
182 font->encoding_charset = font->repertory_charset = -1; 180 font->encoding_charset = font->repertory_charset = -1;
183 181
@@ -273,6 +271,9 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
273 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; 271 xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
274 xftfont_info->otf = NULL; 272 xftfont_info->otf = NULL;
275#endif /* HAVE_LIBOTF */ 273#endif /* HAVE_LIBOTF */
274#ifdef HAVE_HARFBUZZ
275 xftfont_info->hb_font = NULL;
276#endif /* HAVE_HARFBUZZ */
276 xftfont_info->ft_size = ft_face->size; 277 xftfont_info->ft_size = ft_face->size;
277 278
278 font->baseline_offset = 0; 279 font->baseline_offset = 0;
@@ -312,6 +313,13 @@ xftfont_close (struct font *font)
312 xftfont_info->otf = NULL; 313 xftfont_info->otf = NULL;
313 } 314 }
314#endif 315#endif
316#ifdef HAVE_HARFBUZZ
317 if (xftfont_info->hb_font)
318 {
319 hb_font_destroy (xftfont_info->hb_font);
320 xftfont_info->hb_font = NULL;
321 }
322#endif
315 323
316 /* See comment in xfont_close. */ 324 /* See comment in xfont_close. */
317 if (xftfont_info->xftfont 325 if (xftfont_info->xftfont
@@ -503,13 +511,13 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
503 511
504#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF 512#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
505static Lisp_Object 513static Lisp_Object
506xftfont_shape (Lisp_Object lgstring) 514xftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
507{ 515{
508 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 516 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
509 struct font_info *xftfont_info = (struct font_info *) font; 517 struct font_info *xftfont_info = (struct font_info *) font;
510 FT_Face ft_face = XftLockFace (xftfont_info->xftfont); 518 FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
511 xftfont_info->ft_size = ft_face->size; 519 xftfont_info->ft_size = ft_face->size;
512 Lisp_Object val = ftfont_shape (lgstring); 520 Lisp_Object val = ftfont_shape (lgstring, direction);
513 XftUnlockFace (xftfont_info->xftfont); 521 XftUnlockFace (xftfont_info->xftfont);
514 return val; 522 return val;
515} 523}
@@ -591,6 +599,41 @@ xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
591 return ok; 599 return ok;
592} 600}
593 601
602#ifdef HAVE_HARFBUZZ
603
604static Lisp_Object
605xfthbfont_list (struct frame *f, Lisp_Object spec)
606{
607 return ftfont_list2 (f, spec, Qxfthb);
608}
609
610static Lisp_Object
611xfthbfont_match (struct frame *f, Lisp_Object spec)
612{
613 return ftfont_match2 (f, spec, Qxfthb);
614}
615
616static hb_font_t *
617xfthbfont_begin_hb_font (struct font *font, double *position_unit)
618{
619 struct font_info *xftfont_info = (struct font_info *) font;
620 FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
621
622 xftfont_info->ft_size = ft_face->size;
623
624 return fthbfont_begin_hb_font (font, position_unit);
625}
626
627static void
628xfthbfont_end_hb_font (struct font *font, hb_font_t *hb_font)
629{
630 struct font_info *xftfont_info = (struct font_info *) font;
631
632 XftUnlockFace (xftfont_info->xftfont);
633}
634
635#endif /* HAVE_HARFBUZZ */
636
594static void syms_of_xftfont_for_pdumper (void); 637static void syms_of_xftfont_for_pdumper (void);
595 638
596struct font_driver const xftfont_driver = 639struct font_driver const xftfont_driver =
@@ -618,7 +661,7 @@ struct font_driver const xftfont_driver =
618#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF 661#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
619 .shape = xftfont_shape, 662 .shape = xftfont_shape,
620#endif 663#endif
621#ifdef HAVE_OTF_GET_VARIATION_GLYPHS 664#if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
622 .get_variation_glyphs = ftfont_variation_glyphs, 665 .get_variation_glyphs = ftfont_variation_glyphs,
623#endif 666#endif
624 .filter_properties = ftfont_filter_properties, 667 .filter_properties = ftfont_filter_properties,
@@ -626,11 +669,17 @@ struct font_driver const xftfont_driver =
626 .combining_capability = ftfont_combining_capability, 669 .combining_capability = ftfont_combining_capability,
627 .drop_xrender_surfaces = xftfont_drop_xrender_surfaces, 670 .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
628 }; 671 };
672#ifdef HAVE_HARFBUZZ
673struct font_driver xfthbfont_driver;
674#endif /* HAVE_HARFBUZZ */
629 675
630void 676void
631syms_of_xftfont (void) 677syms_of_xftfont (void)
632{ 678{
633 DEFSYM (Qxft, "xft"); 679 DEFSYM (Qxft, "xft");
680#ifdef HAVE_HARFBUZZ
681 DEFSYM (Qxfthb, "xfthb");
682#endif /* HAVE_HARFBUZZ */
634 683
635 DEFVAR_BOOL ("xft-font-ascent-descent-override", 684 DEFVAR_BOOL ("xft-font-ascent-descent-override",
636 xft_font_ascent_descent_override, 685 xft_font_ascent_descent_override,
@@ -645,4 +694,15 @@ static void
645syms_of_xftfont_for_pdumper (void) 694syms_of_xftfont_for_pdumper (void)
646{ 695{
647 register_font_driver (&xftfont_driver, NULL); 696 register_font_driver (&xftfont_driver, NULL);
697#ifdef HAVE_HARFBUZZ
698 xfthbfont_driver = xftfont_driver;
699 xfthbfont_driver.type = Qxfthb;
700 xfthbfont_driver.list = xfthbfont_list;
701 xfthbfont_driver.match = xfthbfont_match;
702 xfthbfont_driver.shape = hbfont_shape;
703 xfthbfont_driver.combining_capability = hbfont_combining_capability;
704 xfthbfont_driver.begin_hb_font = xfthbfont_begin_hb_font;
705 xfthbfont_driver.end_hb_font = xfthbfont_end_hb_font;
706 register_font_driver (&xfthbfont_driver, NULL);
707#endif /* HAVE_HARFBUZZ */
648} 708}