aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2018-12-29 16:35:09 +0200
committerEli Zaretskii2018-12-29 16:35:09 +0200
commit48776b70115edf3775df19d80f734048dadff198 (patch)
tree10a7e72a45bbbdf8dbfed4afce59fc9a5b975110
parent1a80b5d9b8cfa0e523b596db5d1e7e6074dbee46 (diff)
downloademacs-48776b70115edf3775df19d80f734048dadff198.tar.gz
emacs-48776b70115edf3775df19d80f734048dadff198.zip
Provide text directionality and language to HarfBuzz shaper
* lisp/language/tv-util.el (tai-viet-composition-function): * lisp/language/ethio-util.el (ethio-composition-function): * lisp/language/japanese.el (compose-gstring-for-variation-glyph): * lisp/language/thai-util.el (thai-composition-function): * lisp/language/misc-lang.el (arabic-shape-gstring): * lisp/language/lao-util.el (lao-composition-function): * lisp/language/hebrew.el (hebrew-shape-gstring): * lisp/composite.el (compose-gstring-for-graphic) (compose-gstring-for-dotted-circle, auto-compose-chars) (compose-gstring-for-terminal): Accept 2nd argument DIRECTION; all callers changed. * src/composite.c (composition_reseat_it): Call auto-composition-function with one more argument DIRECTION. (syms_of_composite) <auto-composition-function>: Update the doc string. * src/ftfont.c (ftfont_shape_by_hb): Compute language and direction, and set buffer properties accordingly. * src/composite.c (autocmp_chars): * src/w32uniscribe.c (uniscribe_shape): * src/xftfont.c (xftfont_shape): * src/ftfont.c (ftfont_shape, ftfont_shape_by_hb): * src/font.c (Ffont_shape_gstring): Accept an additional argument DIRECTION. * src/macfont.m (lgstring_direction): New enum. (mac_font_shape_1, mac_screen_font_shape, mac_font_shape): Accept an additional argument specifying text direction. All callers changed. * src/font.c (syms_of_font): New symbols QL2R and QR2L. * src/font.h (shape): Accept new argument DIRECTION. All implementations changed. (Bug#33729) (ftfont_shape): Update prototype.
-rw-r--r--lisp/composite.el26
-rw-r--r--lisp/language/ethio-util.el2
-rw-r--r--lisp/language/hebrew.el6
-rw-r--r--lisp/language/ind-util.el3
-rw-r--r--lisp/language/japanese.el2
-rw-r--r--lisp/language/lao-util.el6
-rw-r--r--lisp/language/misc-lang.el4
-rw-r--r--lisp/language/thai-util.el6
-rw-r--r--lisp/language/tv-util.el2
-rw-r--r--src/composite.c28
-rw-r--r--src/font.c16
-rw-r--r--src/font.h13
-rw-r--r--src/ftfont.c41
-rw-r--r--src/macfont.m31
-rw-r--r--src/w32uniscribe.c7
-rw-r--r--src/xftfont.c4
16 files changed, 135 insertions, 62 deletions
diff --git a/lisp/composite.el b/lisp/composite.el
index 3d4805e8fa0..6d280c84d78 100644
--- a/lisp/composite.el
+++ b/lisp/composite.el
@@ -382,8 +382,8 @@ This function is the default value of `compose-chars-after-function'."
382 (looking-at pattern)) 382 (looking-at pattern))
383 (<= (match-end 0) limit)) 383 (<= (match-end 0) limit))
384 (setq result 384 (setq result
385 (funcall func pos (match-end 0) font-obj object))) 385 (funcall func pos (match-end 0) font-obj object nil)))
386 (setq result (funcall func pos limit font-obj object))) 386 (setq result (funcall func pos limit font-obj object nil)))
387 (if result (setq tail nil)))))) 387 (if result (setq tail nil))))))
388 result)) 388 result))
389 389
@@ -524,8 +524,9 @@ after a sequence of character events."
524 (setq from (1+ from))) 524 (setq from (1+ from)))
525 gstring)) 525 gstring))
526 526
527(defun compose-gstring-for-graphic (gstring) 527(defun compose-gstring-for-graphic (gstring direction)
528 "Compose glyph-string GSTRING for graphic display. 528 "Compose glyph-string GSTRING under bidi DIRECTION for graphic display.
529DIRECTION is either L2R or R2L, or nil if unknown.
529Combining characters are composed with the preceding base 530Combining characters are composed with the preceding base
530character. If the preceding character is not a base character, 531character. If the preceding character is not a base character,
531each combining character is composed as a spacing character by 532each combining character is composed as a spacing character by
@@ -559,7 +560,7 @@ All non-spacing characters have this function in
559 560
560 ;; A base character and the following non-spacing characters. 561 ;; A base character and the following non-spacing characters.
561 (t 562 (t
562 (let ((gstr (font-shape-gstring gstring))) 563 (let ((gstr (font-shape-gstring gstring direction)))
563 (if (and gstr 564 (if (and gstr
564 (> (lglyph-to (lgstring-glyph gstr 0)) 0)) 565 (> (lglyph-to (lgstring-glyph gstr 0)) 0))
565 gstr 566 gstr
@@ -686,12 +687,12 @@ All non-spacing characters have this function in
686 (setq i (1+ i)))) 687 (setq i (1+ i))))
687 gstring)))))) 688 gstring))))))
688 689
689(defun compose-gstring-for-dotted-circle (gstring) 690(defun compose-gstring-for-dotted-circle (gstring direction)
690 (let* ((dc (lgstring-glyph gstring 0)) ; glyph of dotted-circle 691 (let* ((dc (lgstring-glyph gstring 0)) ; glyph of dotted-circle
691 (dc-id (lglyph-code dc)) 692 (dc-id (lglyph-code dc))
692 (fc (lgstring-glyph gstring 1)) ; glyph of the following char 693 (fc (lgstring-glyph gstring 1)) ; glyph of the following char
693 (fc-id (lglyph-code fc)) 694 (fc-id (lglyph-code fc))
694 (gstr (and nil (font-shape-gstring gstring)))) 695 (gstr (and nil (font-shape-gstring gstring direction))))
695 (if (and gstr 696 (if (and gstr
696 (or (= (lgstring-glyph-len gstr) 1) 697 (or (= (lgstring-glyph-len gstr) 1)
697 (and (= (lgstring-glyph-len gstr) 2) 698 (and (= (lgstring-glyph-len gstr) 2)
@@ -742,7 +743,7 @@ All non-spacing characters have this function in
742 (aset composition-function-table #x25CC 743 (aset composition-function-table #x25CC
743 `([,(purecopy ".\\c^") 0 compose-gstring-for-dotted-circle]))) 744 `([,(purecopy ".\\c^") 0 compose-gstring-for-dotted-circle])))
744 745
745(defun compose-gstring-for-terminal (gstring) 746(defun compose-gstring-for-terminal (gstring _direction)
746 "Compose glyph-string GSTRING for terminal display. 747 "Compose glyph-string GSTRING for terminal display.
747Non-spacing characters are composed with the preceding base 748Non-spacing characters are composed with the preceding base
748character. If the preceding character is not a base character, 749character. If the preceding character is not a base character,
@@ -799,10 +800,11 @@ prepending a space before it."
799 gstring)) 800 gstring))
800 801
801 802
802(defun auto-compose-chars (func from to font-object string) 803(defun auto-compose-chars (func from to font-object string direction)
803 "Compose the characters at FROM by FUNC. 804 "Compose the characters at FROM by FUNC.
804FUNC is called with one argument GSTRING which is built for characters 805FUNC is called with two arguments: GSTRING, which is built for
805in the region FROM (inclusive) and TO (exclusive). 806characters in the region FROM (inclusive) and TO (exclusive);
807and DIRECTION, which is the bidi directionality of the characters.
806 808
807If the character are composed on a graphic display, FONT-OBJECT 809If the character are composed on a graphic display, FONT-OBJECT
808is a font to use. Otherwise, FONT-OBJECT is nil, and the function 810is a font to use. Otherwise, FONT-OBJECT is nil, and the function
@@ -819,7 +821,7 @@ This function is the default value of `auto-composition-function' (which see)."
819 gstring 821 gstring
820 (or (fontp font-object 'font-object) 822 (or (fontp font-object 'font-object)
821 (setq func 'compose-gstring-for-terminal)) 823 (setq func 'compose-gstring-for-terminal))
822 (funcall func gstring)))) 824 (funcall func gstring direction))))
823 825
824(put 'auto-composition-mode 'permanent-local t) 826(put 'auto-composition-mode 'permanent-local t)
825 827
diff --git a/lisp/language/ethio-util.el b/lisp/language/ethio-util.el
index 1ea01684eaa..0729a6d3a63 100644
--- a/lisp/language/ethio-util.el
+++ b/lisp/language/ethio-util.el
@@ -1014,7 +1014,7 @@ With ARG, insert that many delimiters."
1014;; 1014;;
1015 1015
1016;;;###autoload 1016;;;###autoload
1017(defun ethio-composition-function (pos to font-object string) 1017(defun ethio-composition-function (pos to font-object string _direction)
1018 (setq pos (1- pos)) 1018 (setq pos (1- pos))
1019 (let ((pattern "\\ce\\(áŸ\\|ö ‡Š\\)")) 1019 (let ((pattern "\\ce\\(áŸ\\|ö ‡Š\\)"))
1020 (if string 1020 (if string
diff --git a/lisp/language/hebrew.el b/lisp/language/hebrew.el
index c004337c2f8..52188f44725 100644
--- a/lisp/language/hebrew.el
+++ b/lisp/language/hebrew.el
@@ -152,7 +152,7 @@ Bidirectional editing is supported.")))
152;; (3) If the font has precomposed glyphs, use them as far as 152;; (3) If the font has precomposed glyphs, use them as far as
153;; possible. Adjust the remaining glyphs artificially. 153;; possible. Adjust the remaining glyphs artificially.
154 154
155(defun hebrew-shape-gstring (gstring) 155(defun hebrew-shape-gstring (gstring direction)
156 (let* ((font (lgstring-font gstring)) 156 (let* ((font (lgstring-font gstring))
157 (otf (font-get font :otf)) 157 (otf (font-get font :otf))
158 (nchars (lgstring-char-len gstring)) 158 (nchars (lgstring-char-len gstring))
@@ -172,7 +172,7 @@ Bidirectional editing is supported.")))
172 172
173 ((or (assq 'hebr (car otf)) (assq 'hebr (cdr otf))) 173 ((or (assq 'hebr (car otf)) (assq 'hebr (cdr otf)))
174 ;; FONT has OpenType features for Hebrew. 174 ;; FONT has OpenType features for Hebrew.
175 (font-shape-gstring gstring)) 175 (font-shape-gstring gstring direction))
176 176
177 (t 177 (t
178 ;; FONT doesn't have OpenType features for Hebrew. 178 ;; FONT doesn't have OpenType features for Hebrew.
@@ -217,7 +217,7 @@ Bidirectional editing is supported.")))
217 ;; Now IDX is an index to the first non-precomposed glyph. 217 ;; Now IDX is an index to the first non-precomposed glyph.
218 ;; Adjust positions of the remaining glyphs artificially. 218 ;; Adjust positions of the remaining glyphs artificially.
219 (if (font-get font :combining-capability) 219 (if (font-get font :combining-capability)
220 (font-shape-gstring gstring) 220 (font-shape-gstring gstring direction)
221 (setq base-width (lglyph-width (lgstring-glyph gstring 0))) 221 (setq base-width (lglyph-width (lgstring-glyph gstring 0)))
222 (while (< idx nglyphs) 222 (while (< idx nglyphs)
223 (setq glyph (lgstring-glyph gstring idx)) 223 (setq glyph (lgstring-glyph gstring idx))
diff --git a/lisp/language/ind-util.el b/lisp/language/ind-util.el
index 85e99181b5c..e5eaf1cb4a4 100644
--- a/lisp/language/ind-util.el
+++ b/lisp/language/ind-util.el
@@ -829,6 +829,9 @@ Returns new end position."
829 (let ((pos from) newpos func (max to)) 829 (let ((pos from) newpos func (max to))
830 (narrow-to-region from to) 830 (narrow-to-region from to)
831 (while (< pos max) 831 (while (< pos max)
832 ;; FIXME: The below seems to assume
833 ;; composition-function-table holds functions? That is no
834 ;; longer true, since long ago.
832 (setq func (aref composition-function-table (char-after pos))) 835 (setq func (aref composition-function-table (char-after pos)))
833 (if (fboundp func) 836 (if (fboundp func)
834 (setq newpos (funcall func pos nil) 837 (setq newpos (funcall func pos nil)
diff --git a/lisp/language/japanese.el b/lisp/language/japanese.el
index f6d9e1bf450..b1fb56980a4 100644
--- a/lisp/language/japanese.el
+++ b/lisp/language/japanese.el
@@ -248,7 +248,7 @@ eucJP-ms is defined in <http://www.opengroup.or.jp/jvc/cde/appendix.html>."
248 (define-translation-table 'unicode-to-jisx0213 248 (define-translation-table 'unicode-to-jisx0213
249 (char-table-extra-slot table 0))) 249 (char-table-extra-slot table 0)))
250 250
251(defun compose-gstring-for-variation-glyph (gstring) 251(defun compose-gstring-for-variation-glyph (gstring _direction)
252 "Compose glyph-string GSTRING for graphic display. 252 "Compose glyph-string GSTRING for graphic display.
253GSTRING must have two glyphs; the first is a glyph for a han character, 253GSTRING must have two glyphs; the first is a glyph for a han character,
254and the second is a glyph for a variation selector." 254and the second is a glyph for a variation selector."
diff --git a/lisp/language/lao-util.el b/lisp/language/lao-util.el
index 554f7cfd83a..4d58be2fc57 100644
--- a/lisp/language/lao-util.el
+++ b/lisp/language/lao-util.el
@@ -489,10 +489,10 @@ syllable. In that case, FROM and TO are indexes to STR."
489 lao-str))) 489 lao-str)))
490 490
491;;;###autoload 491;;;###autoload
492(defun lao-composition-function (gstring) 492(defun lao-composition-function (gstring direction)
493 (if (= (lgstring-char-len gstring) 1) 493 (if (= (lgstring-char-len gstring) 1)
494 (compose-gstring-for-graphic gstring) 494 (compose-gstring-for-graphic gstring direction)
495 (or (font-shape-gstring gstring) 495 (or (font-shape-gstring gstring direction)
496 (let ((glyph-len (lgstring-glyph-len gstring)) 496 (let ((glyph-len (lgstring-glyph-len gstring))
497 (i 0) 497 (i 0)
498 glyph) 498 glyph)
diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el
index c1aa79cae45..e25e63b4c5c 100644
--- a/lisp/language/misc-lang.el
+++ b/lisp/language/misc-lang.el
@@ -101,8 +101,8 @@ thin (i.e. 1-dot width) space."
101;; Record error in arabic-change-gstring. 101;; Record error in arabic-change-gstring.
102(defvar arabic-shape-log nil) 102(defvar arabic-shape-log nil)
103 103
104(defun arabic-shape-gstring (gstring) 104(defun arabic-shape-gstring (gstring direction)
105 (setq gstring (font-shape-gstring gstring)) 105 (setq gstring (font-shape-gstring gstring direction))
106 (condition-case err 106 (condition-case err
107 (when arabic-shaper-ZWNJ-handling 107 (when arabic-shaper-ZWNJ-handling
108 (let ((font (lgstring-font gstring)) 108 (let ((font (lgstring-font gstring))
diff --git a/lisp/language/thai-util.el b/lisp/language/thai-util.el
index d6c9732a9e8..638d4832d93 100644
--- a/lisp/language/thai-util.el
+++ b/lisp/language/thai-util.el
@@ -225,10 +225,10 @@ positions (integers or markers) specifying the region."
225 (thai-compose-region (point-min) (point-max))) 225 (thai-compose-region (point-min) (point-max)))
226 226
227;;;###autoload 227;;;###autoload
228(defun thai-composition-function (gstring) 228(defun thai-composition-function (gstring direction)
229 (if (= (lgstring-char-len gstring) 1) 229 (if (= (lgstring-char-len gstring) 1)
230 (compose-gstring-for-graphic gstring) 230 (compose-gstring-for-graphic gstring direction)
231 (or (font-shape-gstring gstring) 231 (or (font-shape-gstring gstring direction)
232 (let ((glyph-len (lgstring-glyph-len gstring)) 232 (let ((glyph-len (lgstring-glyph-len gstring))
233 (last-char (lgstring-char gstring 233 (last-char (lgstring-char gstring
234 (1- (lgstring-char-len gstring)))) 234 (1- (lgstring-char-len gstring))))
diff --git a/lisp/language/tv-util.el b/lisp/language/tv-util.el
index a667956a060..7ce8ee1e500 100644
--- a/lisp/language/tv-util.el
+++ b/lisp/language/tv-util.el
@@ -128,7 +128,7 @@
128 128
129 129
130;;;###autoload 130;;;###autoload
131(defun tai-viet-composition-function (from to font-object string) 131(defun tai-viet-composition-function (from to font-object string _direction)
132 (if string 132 (if string
133 (if (string-match tai-viet-re string from) 133 (if (string-match tai-viet-re string from)
134 (tai-viet-compose-string from (match-end 0) string)) 134 (tai-viet-compose-string from (match-end 0) string))
diff --git a/src/composite.c b/src/composite.c
index 9819805c399..48824946e64 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -873,7 +873,7 @@ fill_gstring_body (Lisp_Object gstring)
873static Lisp_Object 873static Lisp_Object
874autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, 874autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
875 ptrdiff_t limit, struct window *win, struct face *face, 875 ptrdiff_t limit, struct window *win, struct face *face,
876 Lisp_Object string) 876 Lisp_Object string, Lisp_Object direction)
877{ 877{
878 ptrdiff_t count = SPECPDL_INDEX (); 878 ptrdiff_t count = SPECPDL_INDEX ();
879 Lisp_Object pos = make_fixnum (charpos); 879 Lisp_Object pos = make_fixnum (charpos);
@@ -920,8 +920,9 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
920 if (NILP (string)) 920 if (NILP (string))
921 record_unwind_protect (restore_point_unwind, 921 record_unwind_protect (restore_point_unwind,
922 build_marker (current_buffer, pt, pt_byte)); 922 build_marker (current_buffer, pt, pt_byte));
923 lgstring = safe_call (6, Vauto_composition_function, AREF (rule, 2), 923 lgstring = safe_call (7, Vauto_composition_function, AREF (rule, 2),
924 pos, make_fixnum (to), font_object, string); 924 pos, make_fixnum (to), font_object, string,
925 direction);
925 } 926 }
926 return unbind_to (count, lgstring); 927 return unbind_to (count, lgstring);
927} 928}
@@ -1221,7 +1222,7 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
1221 if (XFIXNAT (AREF (elt, 1)) != cmp_it->lookback) 1222 if (XFIXNAT (AREF (elt, 1)) != cmp_it->lookback)
1222 goto no_composition; 1223 goto no_composition;
1223 lgstring = autocmp_chars (elt, charpos, bytepos, endpos, 1224 lgstring = autocmp_chars (elt, charpos, bytepos, endpos,
1224 w, face, string); 1225 w, face, string, QL2R);
1225 if (composition_gstring_p (lgstring)) 1226 if (composition_gstring_p (lgstring))
1226 break; 1227 break;
1227 lgstring = Qnil; 1228 lgstring = Qnil;
@@ -1246,7 +1247,7 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
1246 bpos = CHAR_TO_BYTE (cpos); 1247 bpos = CHAR_TO_BYTE (cpos);
1247 } 1248 }
1248 lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face, 1249 lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face,
1249 string); 1250 string, QR2L);
1250 if (! composition_gstring_p (lgstring) 1251 if (! composition_gstring_p (lgstring)
1251 || cpos + LGSTRING_CHAR_LEN (lgstring) - 1 != charpos) 1252 || cpos + LGSTRING_CHAR_LEN (lgstring) - 1 != charpos)
1252 /* Composition failed or didn't cover the current 1253 /* Composition failed or didn't cover the current
@@ -1566,7 +1567,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit,
1566 for (check = cur; check_pos < check.pos; ) 1567 for (check = cur; check_pos < check.pos; )
1567 BACKWARD_CHAR (check, stop); 1568 BACKWARD_CHAR (check, stop);
1568 *gstring = autocmp_chars (elt, check.pos, check.pos_byte, 1569 *gstring = autocmp_chars (elt, check.pos, check.pos_byte,
1569 tail, w, NULL, string); 1570 tail, w, NULL, string, Qnil);
1570 need_adjustment = 1; 1571 need_adjustment = 1;
1571 if (NILP (*gstring)) 1572 if (NILP (*gstring))
1572 { 1573 {
@@ -1943,15 +1944,24 @@ Use the command `auto-composition-mode' to change this variable. */);
1943 1944
1944 DEFVAR_LISP ("auto-composition-function", Vauto_composition_function, 1945 DEFVAR_LISP ("auto-composition-function", Vauto_composition_function,
1945 doc: /* Function to call to compose characters automatically. 1946 doc: /* Function to call to compose characters automatically.
1946This function is called from the display routine with four arguments: 1947This function is called from the display engine with 6 arguments:
1947FROM, TO, WINDOW, and STRING. 1948FUNC, FROM, TO, FONT-OBJECT, STRING, and DIRECTION.
1949
1950FUNC is the function to compose characters. On text-mode display,
1951FUNC is ignored and `compose-gstring-for-terminal' is used instead.
1948 1952
1949If STRING is nil, the function must compose characters in the region 1953If STRING is nil, the function must compose characters in the region
1950between FROM and TO in the current buffer. 1954between FROM and TO in the current buffer.
1951 1955
1952Otherwise, STRING is a string, and FROM and TO are indices into the 1956Otherwise, STRING is a string, and FROM and TO are indices into the
1953string. In this case, the function must compose characters in the 1957string. In this case, the function must compose characters in the
1954string. */); 1958string.
1959
1960FONT-OBJECT is the font to use, or nil if characters are to be
1961composed on a text-mode display.
1962
1963DIRECTION is the bidi directionality of the text to shape. It could
1964be L2R or R2L, or nil if unknown. */);
1955 Vauto_composition_function = Qnil; 1965 Vauto_composition_function = Qnil;
1956 1966
1957 DEFVAR_LISP ("composition-function-table", Vcomposition_function_table, 1967 DEFVAR_LISP ("composition-function-table", Vcomposition_function_table,
diff --git a/src/font.c b/src/font.c
index e81c267de41..fc8efa7f235 100644
--- a/src/font.c
+++ b/src/font.c
@@ -4397,18 +4397,22 @@ font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object)
4397} 4397}
4398 4398
4399 4399
4400DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0, 4400DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 2, 2, 0,
4401 doc: /* Shape the glyph-string GSTRING. 4401 doc: /* Shape the glyph-string GSTRING subject to bidi DIRECTION.
4402Shaping means substituting glyphs and/or adjusting positions of glyphs 4402Shaping means substituting glyphs and/or adjusting positions of glyphs
4403to get the correct visual image of character sequences set in the 4403to get the correct visual image of character sequences set in the
4404header of the glyph-string. 4404header of the glyph-string.
4405 4405
4406DIRECTION should be produced by the UBA, the Unicode Bidirectional
4407Algorithm, and should be a symbol, either L2R or R2L. It can also
4408be nil if the bidi context is unknown.
4409
4406If the shaping was successful, the value is GSTRING itself or a newly 4410If the shaping was successful, the value is GSTRING itself or a newly
4407created glyph-string. Otherwise, the value is nil. 4411created glyph-string. Otherwise, the value is nil.
4408 4412
4409See the documentation of `composition-get-gstring' for the format of 4413See the documentation of `composition-get-gstring' for the format of
4410GSTRING. */) 4414GSTRING. */)
4411 (Lisp_Object gstring) 4415 (Lisp_Object gstring, Lisp_Object direction)
4412{ 4416{
4413 struct font *font; 4417 struct font *font;
4414 Lisp_Object font_object, n, glyph; 4418 Lisp_Object font_object, n, glyph;
@@ -4427,7 +4431,7 @@ GSTRING. */)
4427 /* Try at most three times with larger gstring each time. */ 4431 /* Try at most three times with larger gstring each time. */
4428 for (i = 0; i < 3; i++) 4432 for (i = 0; i < 3; i++)
4429 { 4433 {
4430 n = font->driver->shape (gstring); 4434 n = font->driver->shape (gstring, direction);
4431 if (FIXNUMP (n)) 4435 if (FIXNUMP (n))
4432 break; 4436 break;
4433 gstring = larger_vector (gstring, 4437 gstring = larger_vector (gstring,
@@ -5350,6 +5354,10 @@ syms_of_font (void)
5350 5354
5351 DEFSYM (QCuser_spec, ":user-spec"); 5355 DEFSYM (QCuser_spec, ":user-spec");
5352 5356
5357 /* For shapers that need to know text directionality. */
5358 DEFSYM (QL2R, "L2R");
5359 DEFSYM (QR2L, "R2L");
5360
5353 staticpro (&scratch_font_spec); 5361 staticpro (&scratch_font_spec);
5354 scratch_font_spec = Ffont_spec (0, NULL); 5362 scratch_font_spec = Ffont_spec (0, NULL);
5355 staticpro (&scratch_font_prefer); 5363 staticpro (&scratch_font_prefer);
diff --git a/src/font.h b/src/font.h
index 1741b3f3964..52bdaa38899 100644
--- a/src/font.h
+++ b/src/font.h
@@ -700,7 +700,11 @@ struct font_driver
700 700
701 Return the number of output codes. If none of the features are 701 Return the number of output codes. If none of the features are
702 applicable to the input data, return 0. If GSTRING-OUT is too 702 applicable to the input data, return 0. If GSTRING-OUT is too
703 short, return -1. */ 703 short, return -1.
704
705 Note: This method is currently not implemented by any font
706 back-end, and is only called by 'font-drive-otf' and
707 'font-otf-alternates', which are themselves ifdef'ed away. */
704 int (*otf_drive) (struct font *font, Lisp_Object features, 708 int (*otf_drive) (struct font *font, Lisp_Object features,
705 Lisp_Object gstring_in, int from, int to, 709 Lisp_Object gstring_in, int from, int to,
706 Lisp_Object gstring_out, int idx, bool alternate_subst); 710 Lisp_Object gstring_out, int idx, bool alternate_subst);
@@ -723,6 +727,9 @@ struct font_driver
723 (N+1)th element of GSTRING is nil, input of shaping is from the 727 (N+1)th element of GSTRING is nil, input of shaping is from the
724 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and 728 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and
725 CODE are already set. 729 CODE are already set.
730 DIRECTION is either L2R or R2L, or nil if unknown. During
731 redisplay, this comes from applying the UBA, is passed from
732 composition_reseat_it, and is used by the HarfBuzz shaper.
726 733
727 This function updates all fields of the input glyphs. If the 734 This function updates all fields of the input glyphs. If the
728 output glyphs (M) are more than the input glyphs (N), (N+1)th 735 output glyphs (M) are more than the input glyphs (N), (N+1)th
@@ -730,7 +737,7 @@ struct font_driver
730 a new glyph object and storing it in GSTRING. If (M) is greater 737 a new glyph object and storing it in GSTRING. If (M) is greater
731 than the length of GSTRING, nil should be return. In that case, 738 than the length of GSTRING, nil should be return. In that case,
732 this function is called again with the larger GSTRING. */ 739 this function is called again with the larger GSTRING. */
733 Lisp_Object (*shape) (Lisp_Object lgstring); 740 Lisp_Object (*shape) (Lisp_Object lgstring, Lisp_Object direction);
734 741
735 /* Optional. 742 /* Optional.
736 743
@@ -887,7 +894,7 @@ extern Lisp_Object ftfont_list_family (struct frame *);
887extern Lisp_Object ftfont_match (struct frame *, Lisp_Object); 894extern Lisp_Object ftfont_match (struct frame *, Lisp_Object);
888extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int); 895extern Lisp_Object ftfont_open (struct frame *, Lisp_Object, int);
889extern Lisp_Object ftfont_otf_capability (struct font *); 896extern Lisp_Object ftfont_otf_capability (struct font *);
890extern Lisp_Object ftfont_shape (Lisp_Object); 897extern Lisp_Object ftfont_shape (Lisp_Object, Lisp_Object);
891extern unsigned ftfont_encode_char (struct font *, int); 898extern unsigned ftfont_encode_char (struct font *, int);
892extern void ftfont_close (struct font *); 899extern void ftfont_close (struct font *);
893extern void ftfont_filter_properties (Lisp_Object, Lisp_Object); 900extern void ftfont_filter_properties (Lisp_Object, Lisp_Object);
diff --git a/src/ftfont.c b/src/ftfont.c
index 74d72f94abd..5a8adfdb24c 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -2797,7 +2797,7 @@ get_hb_unicode_funcs (void)
2797 2797
2798static Lisp_Object 2798static Lisp_Object
2799ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font, 2799ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
2800 FT_Matrix *matrix) 2800 FT_Matrix *matrix, Lisp_Object direction)
2801{ 2801{
2802 ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring); 2802 ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring);
2803 ptrdiff_t i; 2803 ptrdiff_t i;
@@ -2836,15 +2836,38 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
2836 hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE); 2836 hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
2837 hb_buffer_set_cluster_level (hb_buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); 2837 hb_buffer_set_cluster_level (hb_buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
2838 2838
2839 /* FIXME: guess_segment_properties is BAD BAD BAD. 2839 /* Set the default properties for when they cannot be determined
2840 * we need to get these properties with the LGSTRING. */ 2840 below. */
2841#if 1
2842 hb_buffer_guess_segment_properties (hb_buffer); 2841 hb_buffer_guess_segment_properties (hb_buffer);
2843#else 2842 hb_direction_t dir = HB_DIRECTION_INVALID;
2844 hb_buffer_set_direction (hb_buffer, XXX); 2843 if (EQ (direction, QL2R))
2844 dir = HB_DIRECTION_LTR;
2845 else if (EQ (direction, QR2L))
2846 dir = HB_DIRECTION_RTL;
2847 /* If the caller didn't provide a meaningful DIRECTION, let HarfBuzz
2848 guess it. */
2849 if (dir != HB_DIRECTION_INVALID)
2850 hb_buffer_set_direction (hb_buffer, dir);
2851 /* Leave the script determination to HarfBuzz, until Emacs has a
2852 better idea of the script of LGSTRING. FIXME. */
2853#if 0
2845 hb_buffer_set_script (hb_buffer, XXX); 2854 hb_buffer_set_script (hb_buffer, XXX);
2846 hb_buffer_set_language (hb_buffer, XXX);
2847#endif 2855#endif
2856 /* FIXME: This can only handle the single global language, which
2857 normally comes from the locale. In addition, if
2858 current-iso639-language is a list, we arbitrarily use the first
2859 one. We should instead have a notion of the language of the text
2860 being shaped. */
2861 Lisp_Object lang = Vcurrent_iso639_language;
2862 if (CONSP (Vcurrent_iso639_language))
2863 lang = XCAR (Vcurrent_iso639_language);
2864 if (SYMBOLP (lang))
2865 {
2866 Lisp_Object lang_str = SYMBOL_NAME (lang);
2867 hb_buffer_set_language (hb_buffer,
2868 hb_language_from_string (SSDATA (lang_str),
2869 SBYTES (lang_str)));
2870 }
2848 2871
2849 if (!hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL)) 2872 if (!hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL))
2850 return Qnil; 2873 return Qnil;
@@ -2919,7 +2942,7 @@ ftfont_shape_by_hb (Lisp_Object lgstring, FT_Face ft_face, hb_font_t *hb_font,
2919#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ 2942#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ
2920 2943
2921Lisp_Object 2944Lisp_Object
2922ftfont_shape (Lisp_Object lgstring) 2945ftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
2923{ 2946{
2924 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 2947 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2925 struct ftfont_info *ftfont_info = (struct ftfont_info *) font; 2948 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
@@ -2929,7 +2952,7 @@ ftfont_shape (Lisp_Object lgstring)
2929 hb_font_t *hb_font = ftfont_get_hb_font (ftfont_info); 2952 hb_font_t *hb_font = ftfont_get_hb_font (ftfont_info);
2930 2953
2931 return ftfont_shape_by_hb (lgstring, ftfont_info->ft_size->face, 2954 return ftfont_shape_by_hb (lgstring, ftfont_info->ft_size->face,
2932 hb_font, &ftfont_info->matrix); 2955 hb_font, &ftfont_info->matrix, direction);
2933 } 2956 }
2934 else 2957 else
2935#endif /* HAVE_HARFBUZZ */ 2958#endif /* HAVE_HARFBUZZ */
diff --git a/src/macfont.m b/src/macfont.m
index d137648937c..ee6c1737269 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -38,6 +38,12 @@ Original author: YAMAMOTO Mitsuharu
38 38
39#include <libkern/OSByteOrder.h> 39#include <libkern/OSByteOrder.h>
40 40
41/* Values for `dir' argument to shaper functions. */
42enum lgstring_direction
43 {
44 DIR_R2L = -1, DIR_UNKNOWN = 0, DIR_L2R = 1,
45 };
46
41static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph); 47static double mac_font_get_advance_width_for_glyph (CTFontRef, CGGlyph);
42static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph); 48static CGRect mac_font_get_bounding_rect_for_glyph (CTFontRef, CGGlyph);
43static CFArrayRef mac_font_create_available_families (void); 49static CFArrayRef mac_font_create_available_families (void);
@@ -48,7 +54,8 @@ static Boolean mac_font_descriptor_supports_languages (CTFontDescriptorRef,
48 CFArrayRef); 54 CFArrayRef);
49static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef); 55static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionaryRef);
50static CFIndex mac_font_shape (CTFontRef, CFStringRef, 56static CFIndex mac_font_shape (CTFontRef, CFStringRef,
51 struct mac_glyph_layout *, CFIndex); 57 struct mac_glyph_layout *, CFIndex,
58 enum lgstring_direction);
52static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef); 59static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
53static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef); 60static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
54#if USE_CT_GLYPH_INFO 61#if USE_CT_GLYPH_INFO
@@ -317,7 +324,8 @@ mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
317 324
318static CFIndex 325static CFIndex
319mac_font_shape_1 (NSFont *font, NSString *string, 326mac_font_shape_1 (NSFont *font, NSString *string,
320 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len) 327 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
328 enum lgstring_direction dir)
321{ 329{
322 NSUInteger i; 330 NSUInteger i;
323 CFIndex result = 0; 331 CFIndex result = 0;
@@ -581,11 +589,11 @@ mac_font_shape_1 (NSFont *font, NSString *string,
581static CFIndex 589static CFIndex
582mac_screen_font_shape (ScreenFontRef font, CFStringRef string, 590mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
583 struct mac_glyph_layout *glyph_layouts, 591 struct mac_glyph_layout *glyph_layouts,
584 CFIndex glyph_len) 592 CFIndex glyph_len, enum lgstring_direction dir)
585{ 593{
586 return mac_font_shape_1 ([(NSFont *)font printerFont], 594 return mac_font_shape_1 ([(NSFont *)font printerFont],
587 (NSString *) string, 595 (NSString *) string,
588 glyph_layouts, glyph_len); 596 glyph_layouts, glyph_len, dir);
589} 597}
590 598
591static CGColorRef 599static CGColorRef
@@ -2916,7 +2924,7 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2916} 2924}
2917 2925
2918static Lisp_Object 2926static Lisp_Object
2919macfont_shape (Lisp_Object lgstring) 2927macfont_shape (Lisp_Object lgstring, Lisp_Object direction)
2920{ 2928{
2921 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 2929 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2922 struct macfont_info *macfont_info = (struct macfont_info *) font; 2930 struct macfont_info *macfont_info = (struct macfont_info *) font;
@@ -2966,12 +2974,18 @@ macfont_shape (Lisp_Object lgstring)
2966 kCFAllocatorNull); 2974 kCFAllocatorNull);
2967 if (string) 2975 if (string)
2968 { 2976 {
2977 enum lgstring_direction dir = DIR_UNKNOWN;
2978
2979 if (EQ (direction, QL2R))
2980 dir = DIR_L2R;
2981 else if (EQ (direction, QR2L))
2982 dir = DIR_R2L;
2969 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len); 2983 glyph_layouts = alloca (sizeof (struct mac_glyph_layout) * glyph_len);
2970 if (macfont_info->screen_font) 2984 if (macfont_info->screen_font)
2971 used = mac_screen_font_shape (macfont_info->screen_font, string, 2985 used = mac_screen_font_shape (macfont_info->screen_font, string,
2972 glyph_layouts, glyph_len); 2986 glyph_layouts, glyph_len, dir);
2973 else 2987 else
2974 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len); 2988 used = mac_font_shape (macfont, string, glyph_layouts, glyph_len, dir);
2975 CFRelease (string); 2989 CFRelease (string);
2976 } 2990 }
2977 2991
@@ -3652,7 +3666,8 @@ mac_font_create_line_with_string_and_font (CFStringRef string,
3652 3666
3653static CFIndex 3667static CFIndex
3654mac_font_shape (CTFontRef font, CFStringRef string, 3668mac_font_shape (CTFontRef font, CFStringRef string,
3655 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len) 3669 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len,
3670 lgstring_direction dir)
3656{ 3671{
3657 CFIndex used, result = 0; 3672 CFIndex used, result = 0;
3658 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font); 3673 CTLineRef ctline = mac_font_create_line_with_string_and_font (string, font);
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index 29c9c7a0bd1..3c400f38b13 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -198,6 +198,9 @@ uniscribe_otf_capability (struct font *font)
198 (N+1)th element of LGSTRING is nil, input of shaping is from the 198 (N+1)th element of LGSTRING is nil, input of shaping is from the
199 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and 199 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and
200 CODE are already set. 200 CODE are already set.
201 DIRECTION is either L2R or R2L, or nil if unknown. During
202 redisplay, this comes from applying the UBA, is passed from
203 composition_reseat_it, and is used by the HarfBuzz shaper.
201 204
202 This function updates all fields of the input glyphs. If the 205 This function updates all fields of the input glyphs. If the
203 output glyphs (M) are more than the input glyphs (N), (N+1)th 206 output glyphs (M) are more than the input glyphs (N), (N+1)th
@@ -206,7 +209,7 @@ uniscribe_otf_capability (struct font *font)
206 than the length of LGSTRING, nil should be returned. In that case, 209 than the length of LGSTRING, nil should be returned. In that case,
207 this function is called again with a larger LGSTRING. */ 210 this function is called again with a larger LGSTRING. */
208static Lisp_Object 211static Lisp_Object
209uniscribe_shape (Lisp_Object lgstring) 212uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
210{ 213{
211 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 214 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
212 struct uniscribe_font_info *uniscribe_font 215 struct uniscribe_font_info *uniscribe_font
@@ -394,6 +397,8 @@ uniscribe_shape (Lisp_Object lgstring)
394 adjustment for the base character, which is 397 adjustment for the base character, which is
395 then updated for each successive glyph in the 398 then updated for each successive glyph in the
396 grapheme cluster. */ 399 grapheme cluster. */
400 /* FIXME: Should we use DIRECTION here instead
401 of what ScriptItemize guessed? */
397 if (items[i].a.fRTL) 402 if (items[i].a.fRTL)
398 { 403 {
399 int j1 = j; 404 int j1 = j;
diff --git a/src/xftfont.c b/src/xftfont.c
index 56d0e30e24c..6f56c053bb7 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -674,13 +674,13 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
674 674
675#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ 675#if (defined HAVE_M17N_FLT && defined HAVE_LIBOTF) || defined HAVE_HARFBUZZ
676static Lisp_Object 676static Lisp_Object
677xftfont_shape (Lisp_Object lgstring) 677xftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
678{ 678{
679 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring)); 679 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
680 struct xftfont_info *xftfont_info = (struct xftfont_info *) font; 680 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
681 FT_Face ft_face = XftLockFace (xftfont_info->xftfont); 681 FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
682 xftfont_info->ft_size = ft_face->size; 682 xftfont_info->ft_size = ft_face->size;
683 Lisp_Object val = ftfont_shape (lgstring); 683 Lisp_Object val = ftfont_shape (lgstring, direction);
684 XftUnlockFace (xftfont_info->xftfont); 684 XftUnlockFace (xftfont_info->xftfont);
685 return val; 685 return val;
686} 686}