diff options
| author | Eli Zaretskii | 2019-06-07 17:52:16 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2019-06-07 17:52:16 +0300 |
| commit | 4ebfec02f05d838e4c88d10a764c13789816d6d4 (patch) | |
| tree | f479671bb5f295b5eb324163e56751cb000f20b4 /src | |
| parent | e5bc9a32b65e16ff48a50d56e3d8b4990e95acac (diff) | |
| parent | f3fddfb5ef9b72cecc379e8b7ae4b728ed3895d7 (diff) | |
| download | emacs-4ebfec02f05d838e4c88d10a764c13789816d6d4.tar.gz emacs-4ebfec02f05d838e4c88d10a764c13789816d6d4.zip | |
Merge remote-tracking branch 'origin/harfbuzz'
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.in | 9 | ||||
| -rw-r--r-- | src/chartab.c | 15 | ||||
| -rw-r--r-- | src/composite.c | 44 | ||||
| -rw-r--r-- | src/composite.h | 3 | ||||
| -rw-r--r-- | src/font.c | 22 | ||||
| -rw-r--r-- | src/font.h | 53 | ||||
| -rw-r--r-- | src/ftcrfont.c | 97 | ||||
| -rw-r--r-- | src/ftfont.c | 146 | ||||
| -rw-r--r-- | src/ftfont.h | 8 | ||||
| -rw-r--r-- | src/ftxfont.c | 14 | ||||
| -rw-r--r-- | src/hbfont.c | 482 | ||||
| -rw-r--r-- | src/indent.c | 4 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/macfont.m | 33 | ||||
| -rw-r--r-- | src/w32common.h | 4 | ||||
| -rw-r--r-- | src/w32fns.c | 81 | ||||
| -rw-r--r-- | src/w32font.c | 1 | ||||
| -rw-r--r-- | src/w32uniscribe.c | 376 | ||||
| -rw-r--r-- | src/xdisp.c | 1 | ||||
| -rw-r--r-- | src/xfns.c | 14 | ||||
| -rw-r--r-- | src/xftfont.c | 88 |
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@ | |||
| 132 | FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ | 132 | FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ |
| 133 | FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ | 133 | FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ |
| 134 | FREETYPE_LIBS = @FREETYPE_LIBS@ | 134 | FREETYPE_LIBS = @FREETYPE_LIBS@ |
| 135 | HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ | ||
| 136 | HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ | ||
| 135 | LIBOTF_CFLAGS = @LIBOTF_CFLAGS@ | 137 | LIBOTF_CFLAGS = @LIBOTF_CFLAGS@ |
| 136 | LIBOTF_LIBS = @LIBOTF_LIBS@ | 138 | LIBOTF_LIBS = @LIBOTF_LIBS@ |
| 137 | M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@ | 139 | M17N_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 | ||
| 300 | FONT_OBJ=@FONT_OBJ@ | 303 | FONT_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. |
| 435 | GMALLOC_OBJ=@GMALLOC_OBJ@ | 438 | GMALLOC_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 | ||
| 1324 | Lisp_Object | ||
| 1325 | get_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 | |||
| 1324 | DEFUN ("get-unicode-property-internal", Fget_unicode_property_internal, | 1332 | DEFUN ("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. |
| 1327 | CHAR-TABLE must be what returned by `unicode-property-table-internal'. */) | 1335 | CHAR-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 | ||
| 1342 | DEFUN ("put-unicode-property-internal", Fput_unicode_property_internal, | 1345 | DEFUN ("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) | |||
| 865 | static Lisp_Object | 865 | static Lisp_Object |
| 866 | autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, | 866 | autocmp_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, | |||
| 1167 | bool | 1170 | bool |
| 1168 | composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos, | 1171 | composition_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. |
| 1938 | This function is called from the display routine with four arguments: | 1949 | This function is called from the display engine with 6 arguments: |
| 1939 | FROM, TO, WINDOW, and STRING. | 1950 | FUNC, FROM, TO, FONT-OBJECT, STRING, and DIRECTION. |
| 1951 | |||
| 1952 | FUNC is the function to compose characters. On text-mode display, | ||
| 1953 | FUNC is ignored and `compose-gstring-for-terminal' is used instead. | ||
| 1940 | 1954 | ||
| 1941 | If STRING is nil, the function must compose characters in the region | 1955 | If STRING is nil, the function must compose characters in the region |
| 1942 | between FROM and TO in the current buffer. | 1956 | between FROM and TO in the current buffer. |
| 1943 | 1957 | ||
| 1944 | Otherwise, STRING is a string, and FROM and TO are indices into the | 1958 | Otherwise, STRING is a string, and FROM and TO are indices into the |
| 1945 | string. In this case, the function must compose characters in the | 1959 | string. In this case, the function must compose characters in the |
| 1946 | string. */); | 1960 | string. |
| 1961 | |||
| 1962 | FONT-OBJECT is the font to use, or nil if characters are to be | ||
| 1963 | composed on a text-mode display. | ||
| 1964 | |||
| 1965 | DIRECTION is the bidi directionality of the text to shape. It could | ||
| 1966 | be 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 | ||
| 30 | INLINE_HEADER_BEGIN | 31 | INLINE_HEADER_BEGIN |
| 31 | 32 | ||
| @@ -321,7 +322,7 @@ extern void composition_compute_stop_pos (struct composition_it *, | |||
| 321 | Lisp_Object); | 322 | Lisp_Object); |
| 322 | extern bool composition_reseat_it (struct composition_it *, ptrdiff_t, | 323 | extern 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); |
| 325 | extern int composition_update_it (struct composition_it *, | 326 | extern 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 | ||
| 4400 | DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0, | 4400 | DEFUN ("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. |
| 4402 | Shaping means substituting glyphs and/or adjusting positions of glyphs | 4402 | Shaping means substituting glyphs and/or adjusting positions of glyphs |
| 4403 | to get the correct visual image of character sequences set in the | 4403 | to get the correct visual image of character sequences set in the |
| 4404 | header of the glyph-string. | 4404 | header of the glyph-string. |
| 4405 | 4405 | ||
| 4406 | DIRECTION should be produced by the UBA, the Unicode Bidirectional | ||
| 4407 | Algorithm, and should be a symbol, either L2R or R2L. It can also | ||
| 4408 | be nil if the bidi context is unknown. | ||
| 4409 | |||
| 4406 | If the shaping was successful, the value is GSTRING itself or a newly | 4410 | If the shaping was successful, the value is GSTRING itself or a newly |
| 4407 | created glyph-string. Otherwise, the value is nil. | 4411 | created glyph-string. Otherwise, the value is nil. |
| 4408 | 4412 | ||
| 4409 | See the documentation of `composition-get-gstring' for the format of | 4413 | See the documentation of `composition-get-gstring' for the format of |
| 4410 | GSTRING. */) | 4414 | GSTRING. */) |
| 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 | ||
| 4479 | DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs, | 4483 | DEFUN ("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. |
| 4482 | Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID), | 4486 | Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID), |
| 4483 | where | 4487 | where |
| 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, |
| 4487 | a fixnum, if it's small enough, otherwise a bignum. */) | 4491 | a 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 | |||
| 25 | struct composition_it; | 29 | struct composition_it; |
| 26 | struct face; | 30 | struct face; |
| 27 | struct glyph_string; | 31 | struct 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); | |||
| 864 | extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop, | 890 | extern 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 | ||
| 894 | extern Lisp_Object hbfont_shape (Lisp_Object, Lisp_Object); | ||
| 895 | extern 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) |
| 868 | extern void font_put_frame_data (struct frame *, Lisp_Object, void *); | 899 | extern void font_put_frame_data (struct frame *, Lisp_Object, void *); |
| 869 | extern void *font_get_frame_data (struct frame *f, Lisp_Object); | 900 | extern void *font_get_frame_data (struct frame *f, Lisp_Object); |
| @@ -885,17 +916,20 @@ extern int ftfont_has_char (Lisp_Object, int); | |||
| 885 | extern int ftfont_variation_glyphs (struct font *, int, unsigned[256]); | 916 | extern int ftfont_variation_glyphs (struct font *, int, unsigned[256]); |
| 886 | extern Lisp_Object ftfont_combining_capability (struct font *); | 917 | extern Lisp_Object ftfont_combining_capability (struct font *); |
| 887 | extern Lisp_Object ftfont_get_cache (struct frame *); | 918 | extern Lisp_Object ftfont_get_cache (struct frame *); |
| 888 | extern Lisp_Object ftfont_list (struct frame *, Lisp_Object); | 919 | extern Lisp_Object ftfont_list2 (struct frame *, Lisp_Object, Lisp_Object); |
| 889 | extern Lisp_Object ftfont_list_family (struct frame *); | 920 | extern Lisp_Object ftfont_list_family (struct frame *); |
| 890 | extern Lisp_Object ftfont_match (struct frame *, Lisp_Object); | 921 | extern Lisp_Object ftfont_match2 (struct frame *, Lisp_Object, Lisp_Object); |
| 891 | extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int); | 922 | extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int); |
| 892 | extern Lisp_Object ftfont_otf_capability (struct font *); | 923 | extern Lisp_Object ftfont_otf_capability (struct font *); |
| 893 | extern Lisp_Object ftfont_shape (Lisp_Object); | 924 | extern Lisp_Object ftfont_shape (Lisp_Object, Lisp_Object); |
| 894 | extern unsigned ftfont_encode_char (struct font *, int); | 925 | extern unsigned ftfont_encode_char (struct font *, int); |
| 895 | extern void ftfont_close (struct font *); | 926 | extern void ftfont_close (struct font *); |
| 896 | extern void ftfont_filter_properties (Lisp_Object, Lisp_Object); | 927 | extern void ftfont_filter_properties (Lisp_Object, Lisp_Object); |
| 897 | extern void ftfont_text_extents (struct font *, const unsigned *, int, | 928 | extern void ftfont_text_extents (struct font *, const unsigned *, int, |
| 898 | struct font_metrics *); | 929 | struct font_metrics *); |
| 930 | #ifdef HAVE_HARFBUZZ | ||
| 931 | extern hb_font_t *fthbfont_begin_hb_font (struct font *, double *); | ||
| 932 | #endif /* HAVE_HARFBUZZ */ | ||
| 899 | extern void syms_of_ftfont (void); | 933 | extern 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); | |||
| 905 | extern void syms_of_ftxfont (void); | 939 | extern void syms_of_ftxfont (void); |
| 906 | #ifdef HAVE_XFT | 940 | #ifdef HAVE_XFT |
| 907 | extern struct font_driver const xftfont_driver; | 941 | extern struct font_driver const xftfont_driver; |
| 942 | #ifdef HAVE_HARFBUZZ | ||
| 943 | extern 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 |
| 910 | extern struct font_driver const ftxfont_driver; | 947 | extern struct font_driver const ftxfont_driver; |
| @@ -917,6 +954,9 @@ extern void syms_of_bdffont (void); | |||
| 917 | #ifdef HAVE_NTGUI | 954 | #ifdef HAVE_NTGUI |
| 918 | extern struct font_driver w32font_driver; | 955 | extern struct font_driver w32font_driver; |
| 919 | extern struct font_driver uniscribe_font_driver; | 956 | extern struct font_driver uniscribe_font_driver; |
| 957 | #ifdef HAVE_HARFBUZZ | ||
| 958 | extern struct font_driver harfbuzz_font_driver; | ||
| 959 | #endif | ||
| 920 | extern void syms_of_w32font (void); | 960 | extern 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 |
| 928 | extern struct font_driver const ftcrfont_driver; | 968 | extern struct font_driver const ftcrfont_driver; |
| 969 | #ifdef HAVE_HARFBUZZ | ||
| 970 | extern struct font_driver ftcrhbfont_driver; | ||
| 971 | #endif /* HAVE_HARFBUZZ */ | ||
| 929 | extern void syms_of_ftcrfont (void); | 972 | extern 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, | |||
| 97 | static Lisp_Object | 97 | static Lisp_Object |
| 98 | ftcrfont_list (struct frame *f, Lisp_Object spec) | 98 | ftcrfont_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 | ||
| 107 | static Lisp_Object | 103 | static Lisp_Object |
| 108 | ftcrfont_match (struct frame *f, Lisp_Object spec) | 104 | ftcrfont_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 | ||
| 117 | static Lisp_Object | 109 | static 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 |
| 429 | static Lisp_Object | 437 | static Lisp_Object |
| 430 | ftcrfont_shape (Lisp_Object lgstring) | 438 | ftcrfont_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 |
| 451 | static int | 459 | static int |
| 452 | ftcrfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) | 460 | ftcrfont_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 | ||
| 467 | static int | 475 | static int |
| 468 | ftcrfont_draw (struct glyph_string *s, | 476 | ftcrfont_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 | |||
| 523 | static Lisp_Object | ||
| 524 | ftcrhbfont_list (struct frame *f, Lisp_Object spec) | ||
| 525 | { | ||
| 526 | return ftfont_list2 (f, spec, Qftcrhb); | ||
| 527 | } | ||
| 528 | |||
| 529 | static Lisp_Object | ||
| 530 | ftcrhbfont_match (struct frame *f, Lisp_Object spec) | ||
| 531 | { | ||
| 532 | return ftfont_match2 (f, spec, Qftcrhb); | ||
| 533 | } | ||
| 534 | |||
| 535 | static hb_font_t * | ||
| 536 | ftcrhbfont_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 | |||
| 550 | static void | ||
| 551 | ftcrhbfont_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 | ||
| 515 | static void syms_of_ftcrfont_for_pdumper (void); | 563 | static 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 | ||
| 593 | struct font_driver ftcrhbfont_driver; | ||
| 594 | #endif /* HAVE_HARFBUZZ */ | ||
| 544 | 595 | ||
| 545 | void | 596 | void |
| 546 | syms_of_ftcrfont (void) | 597 | syms_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 | |||
| 553 | syms_of_ftcrfont_for_pdumper (void) | 607 | syms_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 | ||
| 50 | static struct font_driver const ftfont_driver; | 50 | static struct font_driver const ftfont_driver; |
| 51 | #ifdef HAVE_HARFBUZZ | ||
| 52 | static 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. */ |
| 53 | static bool fc_initialized; | 56 | static 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 | ||
| 791 | Lisp_Object | 794 | static Lisp_Object |
| 792 | ftfont_list (struct frame *f, Lisp_Object spec) | 795 | ftfont_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 | ||
| 990 | Lisp_Object | 993 | Lisp_Object |
| 994 | ftfont_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 | |||
| 1003 | static Lisp_Object | ||
| 991 | ftfont_match (struct frame *f, Lisp_Object spec) | 1004 | ftfont_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 | ||
| 1040 | Lisp_Object | 1053 | Lisp_Object |
| 1054 | ftfont_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 | |||
| 1063 | Lisp_Object | ||
| 1041 | ftfont_list_family (struct frame *f) | 1064 | ftfont_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 | ||
| 1492 | static bool | ||
| 1493 | ftfont_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 | |||
| 1457 | void | 1510 | void |
| 1458 | ftfont_text_extents (struct font *font, const unsigned int *code, | 1511 | ftfont_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 | ||
| 2759 | Lisp_Object | 2810 | Lisp_Object |
| 2760 | ftfont_shape (Lisp_Object lgstring) | 2811 | ftfont_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 | ||
| 2774 | int | 2826 | int |
| 2775 | ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) | 2827 | ftfont_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 | |
| 2861 | hb_font_t * | ||
| 2862 | fthbfont_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 | ||
| 2788 | static const char *const ftfont_booleans [] = { | 2875 | static 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 | |||
| 209 | static Lisp_Object | 209 | static Lisp_Object |
| 210 | ftxfont_list (struct frame *f, Lisp_Object spec) | 210 | ftxfont_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 | ||
| 219 | static Lisp_Object | 215 | static Lisp_Object |
| 220 | ftxfont_match (struct frame *f, Lisp_Object spec) | 216 | ftxfont_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 | ||
| 229 | static Lisp_Object | 221 | static 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 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 9 | your option) any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along 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. */ | ||
| 36 | DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_create, | ||
| 37 | (hb_unicode_funcs_t *)); | ||
| 38 | DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_get_default, (void)); | ||
| 39 | DEF_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)); | ||
| 42 | DEF_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)); | ||
| 45 | DEF_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)); | ||
| 48 | DEF_DLL_FN (hb_buffer_t *, hb_buffer_create, (void)); | ||
| 49 | DEF_DLL_FN (void, hb_buffer_set_unicode_funcs, | ||
| 50 | (hb_buffer_t *, hb_unicode_funcs_t *)); | ||
| 51 | DEF_DLL_FN (void, hb_buffer_clear_contents, (hb_buffer_t *)); | ||
| 52 | DEF_DLL_FN (hb_bool_t, hb_buffer_pre_allocate, (hb_buffer_t *, unsigned int)); | ||
| 53 | DEF_DLL_FN (void, hb_buffer_add, (hb_buffer_t *, hb_codepoint_t, unsigned int)); | ||
| 54 | DEF_DLL_FN (void, hb_buffer_set_content_type, | ||
| 55 | (hb_buffer_t *, hb_buffer_content_type_t)); | ||
| 56 | DEF_DLL_FN (void, hb_buffer_set_cluster_level, | ||
| 57 | (hb_buffer_t *, hb_buffer_cluster_level_t)); | ||
| 58 | DEF_DLL_FN (void, hb_buffer_set_direction, (hb_buffer_t *, hb_direction_t)); | ||
| 59 | DEF_DLL_FN (void, hb_buffer_set_language, (hb_buffer_t *, hb_language_t)); | ||
| 60 | DEF_DLL_FN (hb_language_t, hb_language_from_string, (const char *, int)); | ||
| 61 | DEF_DLL_FN (void, hb_buffer_guess_segment_properties, (hb_buffer_t *)); | ||
| 62 | DEF_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 *)); | ||
| 65 | DEF_DLL_FN (unsigned int, hb_buffer_get_length, (hb_buffer_t *)); | ||
| 66 | DEF_DLL_FN (hb_direction_t, hb_buffer_get_direction, (hb_buffer_t *)); | ||
| 67 | DEF_DLL_FN (void, hb_buffer_reverse_clusters, (hb_buffer_t *)); | ||
| 68 | DEF_DLL_FN (hb_glyph_info_t *, hb_buffer_get_glyph_infos, | ||
| 69 | (hb_buffer_t *, unsigned int *)); | ||
| 70 | DEF_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. */ | ||
| 98 | bool | ||
| 99 | hbfont_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 | |||
| 129 | static bool combining_class_loaded = false; | ||
| 130 | static Lisp_Object canonical_combining_class_table; | ||
| 131 | |||
| 132 | static hb_unicode_combining_class_t | ||
| 133 | uni_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 | |||
| 154 | static hb_unicode_general_category_t | ||
| 155 | uni_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 | |||
| 231 | static hb_codepoint_t | ||
| 232 | uni_mirroring (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data) | ||
| 233 | { | ||
| 234 | return bidi_mirror_char (ch); | ||
| 235 | } | ||
| 236 | |||
| 237 | static hb_unicode_funcs_t * | ||
| 238 | get_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. */ | ||
| 281 | Lisp_Object | ||
| 282 | hbfont_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 | |||
| 478 | Lisp_Object | ||
| 479 | hbfont_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); |
| 3996 | extern Lisp_Object uniprop_table (Lisp_Object); | 3996 | extern Lisp_Object uniprop_table (Lisp_Object); |
| 3997 | extern Lisp_Object get_unicode_property (Lisp_Object, int); | ||
| 3997 | extern void syms_of_chartab (void); | 3998 | extern 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. */ | ||
| 43 | enum lgstring_direction | ||
| 44 | { | ||
| 45 | DIR_R2L = -1, DIR_UNKNOWN = 0, DIR_L2R = 1, | ||
| 46 | }; | ||
| 47 | |||
| 42 | static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph); | 48 | static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph); |
| 43 | static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph); | 49 | static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph); |
| 44 | static CFArrayRef mac_font_create_available_families (void); | 50 | static CFArrayRef mac_font_create_available_families (void); |
| @@ -49,7 +55,8 @@ static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef, | |||
| 49 | CFArrayRef); | 55 | CFArrayRef); |
| 50 | static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef); | 56 | static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef); |
| 51 | static CFIndex mac_font_shape (CTFontRef, CFStringRef, | 57 | static CFIndex mac_font_shape (CTFontRef, CFStringRef, |
| 52 | struct mac_glyph_layout *, CFIndex); | 58 | struct mac_glyph_layout *, CFIndex, |
| 59 | enum lgstring_direction); | ||
| 53 | static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef); | 60 | static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef); |
| 54 | static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef); | 61 | static 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 | ||
| 319 | static CFIndex | 326 | static CFIndex |
| 320 | mac_font_shape_1 (NSFont *font, NSString *string, | 327 | mac_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, | |||
| 582 | static CFIndex | 590 | static CFIndex |
| 583 | mac_screen_font_shape (ScreenFontRef font, CFStringRef string, | 591 | mac_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 | ||
| 592 | static CGColorRef | 600 | static CGColorRef |
| @@ -1642,7 +1650,7 @@ static unsigned macfont_encode_char (struct font *, int); | |||
| 1642 | static void macfont_text_extents (struct font *, const unsigned int *, int, | 1650 | static void macfont_text_extents (struct font *, const unsigned int *, int, |
| 1643 | struct font_metrics *); | 1651 | struct font_metrics *); |
| 1644 | static int macfont_draw (struct glyph_string *, int, int, int, int, bool); | 1652 | static int macfont_draw (struct glyph_string *, int, int, int, int, bool); |
| 1645 | static Lisp_Object macfont_shape (Lisp_Object); | 1653 | static Lisp_Object macfont_shape (Lisp_Object, Lisp_Object); |
| 1646 | static int macfont_variation_glyphs (struct font *, int c, | 1654 | static int macfont_variation_glyphs (struct font *, int c, |
| 1647 | unsigned variations[256]); | 1655 | unsigned variations[256]); |
| 1648 | static void macfont_filter_properties (Lisp_Object, Lisp_Object); | 1656 | static 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 | ||
| 2928 | static Lisp_Object | 2936 | static Lisp_Object |
| 2929 | macfont_shape (Lisp_Object lgstring) | 2937 | macfont_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 | ||
| 3663 | static CFIndex | 3677 | static CFIndex |
| 3664 | mac_font_shape (CTFontRef font, CFStringRef string, | 3678 | mac_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 | ||
| 85 | extern 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 */ |
| 222 | extern void syms_of_w32uniscribe (void); | 222 | extern void syms_of_w32uniscribe (void); |
| 223 | extern int uniscribe_available; | 223 | extern int uniscribe_available; |
| 224 | extern 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 | ||
| 4 | This file is part of GNU Emacs. | 5 | This 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. */ | ||
| 42 | struct uniscribe_font_info | 52 | struct 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 | ||
| 48 | int uniscribe_available = 0; | 63 | int uniscribe_available = 0; |
| @@ -51,6 +66,39 @@ int uniscribe_available = 0; | |||
| 51 | static int CALLBACK ALIGN_STACK add_opentype_font_name_to_list (ENUMLOGFONTEX *, | 66 | static 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 | |||
| 71 | struct font_driver harfbuzz_font_driver; | ||
| 72 | int harfbuzz_available = 0; | ||
| 73 | |||
| 74 | /* Typedefs for HarfBuzz functions which we call through function | ||
| 75 | pointers initialized after we load the HarfBuzz DLL. */ | ||
| 76 | DEF_DLL_FN (hb_blob_t *, hb_blob_create, | ||
| 77 | (const char *, unsigned int, hb_memory_mode_t, void *, | ||
| 78 | hb_destroy_func_t)); | ||
| 79 | DEF_DLL_FN (hb_face_t *, hb_face_create_for_tables, | ||
| 80 | (hb_reference_table_func_t, void *, hb_destroy_func_t)); | ||
| 81 | DEF_DLL_FN (unsigned, hb_face_get_glyph_count, (const hb_face_t *)); | ||
| 82 | DEF_DLL_FN (hb_font_t *, hb_font_create, (hb_face_t *)); | ||
| 83 | DEF_DLL_FN (void, hb_font_destroy, (hb_font_t *)); | ||
| 84 | DEF_DLL_FN (void, hb_face_destroy, (hb_face_t *)); | ||
| 85 | DEF_DLL_FN (unsigned int, hb_face_get_upem, (hb_face_t *)); | ||
| 86 | DEF_DLL_FN (hb_bool_t, hb_font_get_nominal_glyph, | ||
| 87 | (hb_font_t *, hb_codepoint_t, hb_codepoint_t *)); | ||
| 88 | DEF_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. */ |
| 55 | static Lisp_Object otf_features (HDC context, const char *table); | 103 | static 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. */ |
| 215 | static Lisp_Object | 282 | static Lisp_Object |
| 216 | uniscribe_shape (Lisp_Object lgstring) | 283 | uniscribe_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. */ | ||
| 1227 | static Lisp_Object | ||
| 1228 | w32hb_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. */ | ||
| 1240 | static Lisp_Object | ||
| 1241 | w32hb_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). */ | ||
| 1255 | static void | ||
| 1256 | free_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. */ | ||
| 1263 | static hb_blob_t * | ||
| 1264 | w32hb_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. */ | ||
| 1300 | static hb_font_t * | ||
| 1301 | w32hb_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. */ | ||
| 1329 | static unsigned | ||
| 1330 | w32hb_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. */ | ||
| 1363 | static hb_font_t * | ||
| 1364 | w32hb_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. */ | ||
| 1389 | static int | ||
| 1390 | w32hb_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 | ||
| 1477 | static bool | ||
| 1478 | load_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 | |||
| 1194 | static void | 1493 | static void |
| 1195 | syms_of_w32uniscribe_for_pdumper (void) | 1494 | syms_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, | |||
| 108 | static Lisp_Object | 108 | static Lisp_Object |
| 109 | xftfont_list (struct frame *f, Lisp_Object spec) | 109 | xftfont_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 | ||
| 118 | static Lisp_Object | 114 | static Lisp_Object |
| 119 | xftfont_match (struct frame *f, Lisp_Object spec) | 115 | xftfont_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 | ||
| 128 | static FcChar8 ascii_printable[95]; | 120 | static 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 |
| 505 | static Lisp_Object | 513 | static Lisp_Object |
| 506 | xftfont_shape (Lisp_Object lgstring) | 514 | xftfont_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 | |||
| 604 | static Lisp_Object | ||
| 605 | xfthbfont_list (struct frame *f, Lisp_Object spec) | ||
| 606 | { | ||
| 607 | return ftfont_list2 (f, spec, Qxfthb); | ||
| 608 | } | ||
| 609 | |||
| 610 | static Lisp_Object | ||
| 611 | xfthbfont_match (struct frame *f, Lisp_Object spec) | ||
| 612 | { | ||
| 613 | return ftfont_match2 (f, spec, Qxfthb); | ||
| 614 | } | ||
| 615 | |||
| 616 | static hb_font_t * | ||
| 617 | xfthbfont_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 | |||
| 627 | static void | ||
| 628 | xfthbfont_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 | |||
| 594 | static void syms_of_xftfont_for_pdumper (void); | 637 | static void syms_of_xftfont_for_pdumper (void); |
| 595 | 638 | ||
| 596 | struct font_driver const xftfont_driver = | 639 | struct 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 | ||
| 673 | struct font_driver xfthbfont_driver; | ||
| 674 | #endif /* HAVE_HARFBUZZ */ | ||
| 629 | 675 | ||
| 630 | void | 676 | void |
| 631 | syms_of_xftfont (void) | 677 | syms_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 | |||
| 645 | syms_of_xftfont_for_pdumper (void) | 694 | syms_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 | } |