aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2019-06-01 12:53:41 +0300
committerEli Zaretskii2019-06-01 12:53:41 +0300
commit4363777d5c60af8bc93b30d4f6c5e12dc2761160 (patch)
tree2ff9ea97c469140df5630f6ee5c250e745a78dcb /src
parentb7730c259bc91f030069e408aaddb43f02da3a3a (diff)
downloademacs-4363777d5c60af8bc93b30d4f6c5e12dc2761160.tar.gz
emacs-4363777d5c60af8bc93b30d4f6c5e12dc2761160.zip
Move common HarfBuzz code to a common file hbfont.c
* src/hbfont.c: New file, with code moved from w32uniscribe.c and renamed/modified as appropriate. * src/w32uniscribe.c: Move to hbfont.c DEF_DLL_FN and macro definitions for HarfBuzz functions used in hbfont.c (load_harfbuzz_funcs): Move loading of HarfBuzz functions used by hbfont.c to hbfont.c:hbfont_init_w32_funcs, and call that function from here. (syms_of_w32uniscribe_for_pdumper): Fill the 'shape' and 'combining_capability' members with hbfont.c function names. * src/w32common.h (hbfont_init_w32_funcs) [HAVE_HARFBUZZ]: Add prototype. * src/font.h (hbfont_shape, hbfont_combining_capability) [HAVE_HARFBUZZ]: Add prototypes. * src/Makefile.in (SOME_MACHINE_OBJECTS): Add hbfont.o. * configure.ac (FONT_OBJ): Add hbfont.o if HAVE_HARFBUZZ.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in3
-rw-r--r--src/font.h5
-rw-r--r--src/hbfont.c484
-rw-r--r--src/w32common.h4
-rw-r--r--src/w32uniscribe.c429
5 files changed, 499 insertions, 426 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 512738840ea..be769458d37 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -299,6 +299,7 @@ W32_RES_LINK=@W32_RES_LINK@
299## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE 299## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE
300## ftfont.o ftcrfont.o if USE_CAIRO 300## ftfont.o ftcrfont.o if USE_CAIRO
301## else xfont.o 301## else xfont.o
302## if HAVE_HARFBUZZ, hbfont.o is added regardless of the rest
302FONT_OBJ=@FONT_OBJ@ 303FONT_OBJ=@FONT_OBJ@
303 304
304## Empty for MinGW, cm.o for the rest. 305## Empty for MinGW, cm.o for the rest.
@@ -431,7 +432,7 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
431 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 \
432 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 \
433 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 \
434 xsettings.o xgselect.o termcap.o 435 xsettings.o xgselect.o termcap.o hbfont.o
435 436
436## gmalloc.o if !SYSTEM_MALLOC && !DOUG_LEA_MALLOC, else empty. 437## gmalloc.o if !SYSTEM_MALLOC && !DOUG_LEA_MALLOC, else empty.
437GMALLOC_OBJ=@GMALLOC_OBJ@ 438GMALLOC_OBJ=@GMALLOC_OBJ@
diff --git a/src/font.h b/src/font.h
index 4d1341a0db8..99b95836d7a 100644
--- a/src/font.h
+++ b/src/font.h
@@ -890,6 +890,11 @@ extern void font_fill_lglyph_metrics (Lisp_Object, Lisp_Object);
890extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop, 890extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop,
891 Lisp_Object val); 891 Lisp_Object val);
892 892
893#ifdef HAVE_HARFBUZZ
894extern Lisp_Object hbfont_shape (Lisp_Object, Lisp_Object);
895extern Lisp_Object hbfont_combining_capability (struct font *);
896#endif
897
893#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) 898#if defined (HAVE_XFT) || defined (HAVE_FREETYPE)
894extern void font_put_frame_data (struct frame *, Lisp_Object, void *); 899extern void font_put_frame_data (struct frame *, Lisp_Object, void *);
895extern void *font_get_frame_data (struct frame *f, Lisp_Object); 900extern void *font_get_frame_data (struct frame *f, Lisp_Object);
diff --git a/src/hbfont.c b/src/hbfont.c
new file mode 100644
index 00000000000..392414e9109
--- /dev/null
+++ b/src/hbfont.c
@@ -0,0 +1,484 @@
1/* hbfont.c -- Platform-independent support for HarfBuzz font driver.
2 Copyright (C) 2019 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or (at
9your option) any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
18
19#include <config.h>
20#include <math.h>
21#include <hb.h>
22
23#include "lisp.h"
24#include "frame.h"
25#include "composite.h"
26#include "font.h"
27#include "dispextern.h"
28
29#ifdef HAVE_NTGUI
30
31#include "w32common.h"
32
33/* The w32 implementation calls HarfBuzz functions via function
34 pointers. We use the below to declare the function pointers and
35 redirect function names to those pointers. */
36DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_create,
37 (hb_unicode_funcs_t *));
38DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_get_default, (void));
39DEF_DLL_FN (void, hb_unicode_funcs_set_combining_class_func,
40 (hb_unicode_funcs_t *, hb_unicode_combining_class_func_t,
41 void *, hb_destroy_func_t));
42DEF_DLL_FN (void, hb_unicode_funcs_set_general_category_func,
43 (hb_unicode_funcs_t *, hb_unicode_general_category_func_t,
44 void *, hb_destroy_func_t));
45DEF_DLL_FN (void, hb_unicode_funcs_set_mirroring_func,
46 (hb_unicode_funcs_t *, hb_unicode_mirroring_func_t,
47 void *, hb_destroy_func_t));
48DEF_DLL_FN (hb_buffer_t *, hb_buffer_create, (void));
49DEF_DLL_FN (void, hb_buffer_set_unicode_funcs,
50 (hb_buffer_t *, hb_unicode_funcs_t *));
51DEF_DLL_FN (void, hb_buffer_clear_contents, (hb_buffer_t *));
52DEF_DLL_FN (hb_bool_t, hb_buffer_pre_allocate, (hb_buffer_t *, unsigned int));
53DEF_DLL_FN (void, hb_buffer_add, (hb_buffer_t *, hb_codepoint_t, unsigned int));
54DEF_DLL_FN (void, hb_buffer_set_content_type,
55 (hb_buffer_t *, hb_buffer_content_type_t));
56DEF_DLL_FN (void, hb_buffer_set_cluster_level,
57 (hb_buffer_t *, hb_buffer_cluster_level_t));
58DEF_DLL_FN (void, hb_buffer_set_direction, (hb_buffer_t *, hb_direction_t));
59DEF_DLL_FN (void, hb_buffer_set_language, (hb_buffer_t *, hb_language_t));
60DEF_DLL_FN (hb_language_t, hb_language_from_string, (const char *, int));
61DEF_DLL_FN (void, hb_buffer_guess_segment_properties, (hb_buffer_t *));
62DEF_DLL_FN (hb_bool_t, hb_shape_full,
63 (hb_font_t *, hb_buffer_t *, const hb_feature_t *,
64 unsigned int, const char * const *));
65DEF_DLL_FN (unsigned int, hb_buffer_get_length, (hb_buffer_t *));
66DEF_DLL_FN (hb_direction_t, hb_buffer_get_direction, (hb_buffer_t *));
67DEF_DLL_FN (void, hb_buffer_reverse_clusters, (hb_buffer_t *));
68DEF_DLL_FN (hb_glyph_info_t *, hb_buffer_get_glyph_infos,
69 (hb_buffer_t *, unsigned int *));
70DEF_DLL_FN (hb_glyph_position_t *, hb_buffer_get_glyph_positions,
71 (hb_buffer_t *, unsigned int *));
72
73#define hb_unicode_funcs_create fn_hb_unicode_funcs_create
74#define hb_unicode_funcs_get_default fn_hb_unicode_funcs_get_default
75#define hb_unicode_funcs_set_combining_class_func fn_hb_unicode_funcs_set_combining_class_func
76#define hb_unicode_funcs_set_general_category_func fn_hb_unicode_funcs_set_general_category_func
77#define hb_unicode_funcs_set_mirroring_func fn_hb_unicode_funcs_set_mirroring_func
78#define hb_buffer_create fn_hb_buffer_create
79#define hb_buffer_set_unicode_funcs fn_hb_buffer_set_unicode_funcs
80#define hb_buffer_clear_contents fn_hb_buffer_clear_contents
81#define hb_buffer_pre_allocate fn_hb_buffer_pre_allocate
82#define hb_buffer_add fn_hb_buffer_add
83#define hb_buffer_set_content_type fn_hb_buffer_set_content_type
84#define hb_buffer_set_cluster_level fn_hb_buffer_set_cluster_level
85#define hb_buffer_set_direction fn_hb_buffer_set_direction
86#define hb_buffer_set_language fn_hb_buffer_set_language
87#define hb_language_from_string fn_hb_language_from_string
88#define hb_buffer_guess_segment_properties fn_hb_buffer_guess_segment_properties
89#define hb_shape_full fn_hb_shape_full
90#define hb_buffer_get_length fn_hb_buffer_get_length
91#define hb_buffer_get_direction fn_hb_buffer_get_direction
92#define hb_buffer_reverse_clusters fn_hb_buffer_reverse_clusters
93#define hb_buffer_get_glyph_infos fn_hb_buffer_get_glyph_infos
94#define hb_buffer_get_glyph_positions fn_hb_buffer_get_glyph_positions
95
96/* This function is called from syms_of_w32uniscribe_for_pdumper to
97 initialize the above function pointers. */
98bool
99hbfont_init_w32_funcs (HMODULE library)
100{
101 LOAD_DLL_FN (library, hb_unicode_funcs_create);
102 LOAD_DLL_FN (library, hb_unicode_funcs_get_default);
103 LOAD_DLL_FN (library, hb_unicode_funcs_set_combining_class_func);
104 LOAD_DLL_FN (library, hb_unicode_funcs_set_general_category_func);
105 LOAD_DLL_FN (library, hb_unicode_funcs_set_mirroring_func);
106 LOAD_DLL_FN (library, hb_buffer_create);
107 LOAD_DLL_FN (library, hb_buffer_set_unicode_funcs);
108 LOAD_DLL_FN (library, hb_buffer_clear_contents);
109 LOAD_DLL_FN (library, hb_buffer_pre_allocate);
110 LOAD_DLL_FN (library, hb_buffer_add);
111 LOAD_DLL_FN (library, hb_buffer_set_content_type);
112 LOAD_DLL_FN (library, hb_buffer_set_cluster_level);
113 LOAD_DLL_FN (library, hb_buffer_set_direction);
114 LOAD_DLL_FN (library, hb_buffer_set_language);
115 LOAD_DLL_FN (library, hb_language_from_string);
116 LOAD_DLL_FN (library, hb_buffer_guess_segment_properties);
117 LOAD_DLL_FN (library, hb_shape_full);
118 LOAD_DLL_FN (library, hb_buffer_get_length);
119 LOAD_DLL_FN (library, hb_buffer_get_direction);
120 LOAD_DLL_FN (library, hb_buffer_reverse_clusters);
121 LOAD_DLL_FN (library, hb_buffer_get_glyph_infos);
122 LOAD_DLL_FN (library, hb_buffer_get_glyph_positions);
123 return true;
124}
125#endif /* HAVE_NTGUI */
126
127/* Support functions for HarfBuzz shaper. */
128
129static bool combining_class_loaded = false;
130static Lisp_Object canonical_combining_class_table;
131
132static hb_unicode_combining_class_t
133uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
134{
135 /* Load the Unicode table first time it is needed. */
136 if (!combining_class_loaded)
137 {
138 canonical_combining_class_table =
139 uniprop_table (intern ("canonical-combining-class"));
140 if (NILP (canonical_combining_class_table))
141 emacs_abort ();
142 staticpro (&canonical_combining_class_table);
143 combining_class_loaded = true;
144 }
145
146 Lisp_Object combining =
147 get_unicode_property (canonical_combining_class_table, ch);
148 if (FIXNUMP (combining))
149 return (hb_unicode_combining_class_t) XFIXNUM (combining);
150
151 return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
152}
153
154static hb_unicode_general_category_t
155uni_general (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
156{
157 Lisp_Object category = CHAR_TABLE_REF (Vunicode_category_table, ch);
158
159 if (INTEGERP (category))
160 {
161 switch (XFIXNUM (category))
162 {
163 case UNICODE_CATEGORY_Cc:
164 return HB_UNICODE_GENERAL_CATEGORY_CONTROL;
165 case UNICODE_CATEGORY_Cf:
166 return HB_UNICODE_GENERAL_CATEGORY_FORMAT;
167 case UNICODE_CATEGORY_Cn:
168 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
169 case UNICODE_CATEGORY_Co:
170 return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE;
171 case UNICODE_CATEGORY_Cs:
172 return HB_UNICODE_GENERAL_CATEGORY_SURROGATE;
173 case UNICODE_CATEGORY_Ll:
174 return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER;
175 case UNICODE_CATEGORY_Lm:
176 return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER;
177 case UNICODE_CATEGORY_Lo:
178 return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
179 case UNICODE_CATEGORY_Lt:
180 return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER;
181 case UNICODE_CATEGORY_Lu:
182 return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER;
183 case UNICODE_CATEGORY_Mc:
184 return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK;
185 case UNICODE_CATEGORY_Me:
186 return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
187 case UNICODE_CATEGORY_Mn:
188 return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK;
189 case UNICODE_CATEGORY_Nd:
190 return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER;
191 case UNICODE_CATEGORY_Nl:
192 return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER;
193 case UNICODE_CATEGORY_No:
194 return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER;
195 case UNICODE_CATEGORY_Pc:
196 return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION;
197 case UNICODE_CATEGORY_Pd:
198 return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION;
199 case UNICODE_CATEGORY_Pe:
200 return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION;
201 case UNICODE_CATEGORY_Pf:
202 return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION;
203 case UNICODE_CATEGORY_Pi:
204 return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION;
205 case UNICODE_CATEGORY_Po:
206 return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION;
207 case UNICODE_CATEGORY_Ps:
208 return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION;
209 case UNICODE_CATEGORY_Sc:
210 return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL;
211 case UNICODE_CATEGORY_Sk:
212 return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL;
213 case UNICODE_CATEGORY_Sm:
214 return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL;
215 case UNICODE_CATEGORY_So:
216 return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL;
217 case UNICODE_CATEGORY_Zl:
218 return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR;
219 case UNICODE_CATEGORY_Zp:
220 return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR;
221 case UNICODE_CATEGORY_Zs:
222 return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
223 case UNICODE_CATEGORY_UNKNOWN:
224 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
225 }
226 }
227
228 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
229}
230
231static hb_codepoint_t
232uni_mirroring (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
233{
234 return bidi_mirror_char (ch);
235}
236
237static hb_unicode_funcs_t *
238get_hb_unicode_funcs (void)
239{
240 /* Subclass HarfBuzz's default Unicode functions and override functions that
241 * use data Emacs can provide. This way changing Emacs data is reflected in
242 * the shaped output. */
243 hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (hb_unicode_funcs_get_default ());
244
245 hb_unicode_funcs_set_combining_class_func (funcs, uni_combining, NULL, NULL);
246 hb_unicode_funcs_set_general_category_func (funcs, uni_general, NULL, NULL);
247 hb_unicode_funcs_set_mirroring_func (funcs, uni_mirroring, NULL, NULL);
248
249 /* Use default implmentation for Unicode composition/decomposition, we might
250 * want to revisit this later.
251 hb_unicode_funcs_set_compose_func (funcs, uni_compose, NULL, NULL);
252 hb_unicode_funcs_set_decompose_func (funcs, uni_decompose, NULL, NULL);
253 */
254
255 /* Emacs own script mapping for characters differs from Unicode, so we want
256 * to keep the default HarfBuzz's implementation here.
257 hb_unicode_funcs_set_script_func (funcs, uni_script, NULL, NULL);
258 */
259
260 return funcs;
261}
262
263/* HarfBuzz implementation of shape for font backend. See the
264 commentary before uniscribe_shape for the meaning of the
265 arguments.
266
267 Shape text in LGSTRING. See the docstring of
268 'composition-get-gstring' for the format of LGSTRING. If the
269 (N+1)th element of LGSTRING is nil, input of shaping is from the
270 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and
271 CODE are already set, but FROM and TO need adjustments according
272 to the glyphs produced by the shaping fuinction.
273 DIRECTION is either L2R or R2L, or nil if unknown. During
274 redisplay, this comes from applying the UBA, is passed from
275 composition_reseat_it, and is used by the HarfBuzz shaper.
276
277 This function updates all fields of the input glyphs. If the
278 output glyphs (M) are more than the input glyphs (N), (N+1)th
279 through (M)th elements of LGSTRING are updated possibly by making
280 a new glyph object and storing it in LGSTRING. If (M) is greater
281 than the length of LGSTRING, nil should be returned. In that case,
282 this function is called again with a larger LGSTRING. */
283Lisp_Object
284hbfont_shape (Lisp_Object lgstring, Lisp_Object direction)
285{
286 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
287 ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring);
288 ptrdiff_t i;
289
290 hb_glyph_info_t *info;
291 hb_glyph_position_t *pos;
292
293 /* Cache the HarfBuzz buffer for better performance and less allocations.
294 * We intentionally never destroy the buffer. */
295 static hb_buffer_t *hb_buffer = NULL;
296 if (! hb_buffer)
297 {
298 hb_buffer = hb_buffer_create ();
299 hb_unicode_funcs_t* ufuncs = get_hb_unicode_funcs();
300 hb_buffer_set_unicode_funcs(hb_buffer, ufuncs);
301 }
302
303 hb_buffer_clear_contents (hb_buffer);
304 hb_buffer_pre_allocate (hb_buffer, text_len);
305
306 /* Copy the characters in their original logical order, so we can
307 assign them to glyphs correctly after shaping. */
308 int *chars = alloca (text_len * sizeof (int));
309 for (i = 0; i < text_len; i++)
310 {
311 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
312 int c;
313
314 if (NILP (g))
315 break;
316 c = LGLYPH_CHAR (g);
317 hb_buffer_add (hb_buffer, c, i);
318 chars[i] = c;
319 }
320
321 text_len = i;
322 if (!text_len)
323 return Qnil;
324
325 hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
326 hb_buffer_set_cluster_level (hb_buffer,
327 HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES);
328
329 /* If the caller didn't provide a meaningful DIRECTION, let HarfBuzz
330 guess it. */
331 if (!NILP (direction))
332 {
333 hb_direction_t dir = HB_DIRECTION_LTR;
334 if (EQ (direction, QL2R))
335 dir = HB_DIRECTION_LTR;
336 else if (EQ (direction, QR2L))
337 dir = HB_DIRECTION_RTL;
338 hb_buffer_set_direction (hb_buffer, dir);
339 }
340
341 /* Leave the script determination to HarfBuzz, until Emacs has a
342 better idea of the script of LGSTRING. FIXME. */
343#if 0
344 hb_buffer_set_script (hb_buffer, XXX);
345#endif
346
347 /* FIXME: This can only handle the single global language, which
348 normally comes from the locale. In addition, if
349 current-iso639-language is a list, we arbitrarily use the first
350 one. We should instead have a notion of the language of the text
351 being shaped. */
352 Lisp_Object lang = Vcurrent_iso639_language;
353 if (CONSP (Vcurrent_iso639_language))
354 lang = XCAR (Vcurrent_iso639_language);
355 if (SYMBOLP (lang))
356 {
357 Lisp_Object lang_str = SYMBOL_NAME (lang);
358 hb_buffer_set_language (hb_buffer,
359 hb_language_from_string (SSDATA (lang_str),
360 SBYTES (lang_str)));
361 }
362
363 /* Guess the default properties for when they cannot be determined above.
364
365 FIXME: maybe drop this guessing once script and language handling
366 is fixed above; but then will need to guess the direction by
367 ourselves, perhaps by looking at the the characters using
368 bidi_get_type or somesuch. */
369 hb_buffer_guess_segment_properties (hb_buffer);
370
371 double position_unit;
372 hb_font_t *hb_font
373 = font->driver->begin_hb_font
374 ? font->driver->begin_hb_font (font, &position_unit)
375 : NULL;
376 if (!hb_font)
377 return make_fixnum (0);
378
379 hb_bool_t success = hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL);
380 if (font->driver->end_hb_font)
381 font->driver->end_hb_font (font, hb_font);
382 if (!success)
383 return Qnil;
384
385 glyph_len = hb_buffer_get_length (hb_buffer);
386 if (glyph_len > LGSTRING_GLYPH_LEN (lgstring))
387 return Qnil;
388
389 /* We need the clusters in logical order. */
390 bool buf_reversed = false;
391 if (HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (hb_buffer)))
392 {
393 buf_reversed = true;
394 hb_buffer_reverse_clusters (hb_buffer);
395 }
396 info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
397 pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
398 int from = -1, to, cluster_offset = 0;
399 int char_idx, incr = buf_reversed ? -1 : 1;
400 for (i = 0; i < glyph_len; i++)
401 {
402 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
403 struct font_metrics metrics = {.width = 0};
404 int xoff, yoff, wadjust;
405
406 if (NILP (lglyph))
407 {
408 lglyph = LGLYPH_NEW ();
409 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
410 }
411
412 if (info[i].cluster != from)
413 {
414 int j;
415 /* Found a new cluster. Determine its FROM and TO, and the
416 offset to the first character of the cluster. */
417 /* FROM is the index of the first character that contributed
418 to this cluster. */
419 from = info[i].cluster;
420 /* TO is the index of the last character that contributed to
421 this cluster. */
422 for (j = i; j < glyph_len && info[j].cluster == from; j++)
423 ;
424 to = (j == glyph_len) ? text_len - 1 : info[j].cluster - 1;
425 cluster_offset = 0;
426 /* For RTL buffers, HarfBuzz produces glyphs in a cluster in
427 reverse order, so we need to account for that to record
428 the correct character in each glyph.
429
430 Implementation note: the character codepoint recorded in
431 each glyph is not really used, except when we display the
432 glyphs in descr-text.el. So this is just an aeasthetic
433 issue. */
434 if (buf_reversed)
435 cluster_offset = to - from;
436 }
437
438 /* All the glyphs in a cluster have the same values of FROM and TO. */
439 LGLYPH_SET_FROM (lglyph, from);
440 LGLYPH_SET_TO (lglyph, to);
441
442 /* Not every glyph in a cluster maps directly to a single
443 character; in general, N characters can yield M glyphs, where
444 M could be smaller or greater than N. However, in many cases
445 there is a one-to-one correspondence, and it would be a pity
446 to lose that information, even if it's sometimes inaccurate. */
447 char_idx = from + cluster_offset;
448 cluster_offset += incr;
449 if (char_idx > to)
450 char_idx = to;
451 if (char_idx < from)
452 char_idx = from;
453 LGLYPH_SET_CHAR (lglyph, chars[char_idx]);
454 LGLYPH_SET_CODE (lglyph, info[i].codepoint);
455
456 unsigned code = info[i].codepoint;
457 font->driver->text_extents (font, &code, 1, &metrics);
458 LGLYPH_SET_WIDTH (lglyph, metrics.width);
459 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
460 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
461 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
462 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
463
464 xoff = lround (pos[i].x_offset * position_unit);
465 yoff = - lround (pos[i].y_offset * position_unit);
466 wadjust = lround (pos[i].x_advance * position_unit);
467 if (xoff || yoff || wadjust != metrics.width)
468 {
469 Lisp_Object vec = make_uninit_vector (3);
470 ASET (vec, 0, make_fixnum (xoff));
471 ASET (vec, 1, make_fixnum (yoff));
472 ASET (vec, 2, make_fixnum (wadjust));
473 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
474 }
475 }
476
477 return make_fixnum (glyph_len);
478}
479
480Lisp_Object
481hbfont_combining_capability (struct font *font)
482{
483 return Qt;
484}
diff --git a/src/w32common.h b/src/w32common.h
index bca5244caaa..adde784634a 100644
--- a/src/w32common.h
+++ b/src/w32common.h
@@ -81,4 +81,8 @@ get_proc_addr (HINSTANCE handle, LPCSTR fname)
81 } \ 81 } \
82 while (false) 82 while (false)
83 83
84#ifdef HAVE_HARFBUZZ
85extern bool hbfont_init_w32_funcs (HMODULE);
86#endif
87
84#endif /* W32COMMON_H */ 88#endif /* W32COMMON_H */
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index f1e69452160..5372eb15252 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -1,4 +1,5 @@
1/* Font backend for the Microsoft W32 Uniscribe API. 1/* Font backend for the Microsoft W32 Uniscribe API.
2 Windows-specific parts of the HarfBuzz font backend.
2 Copyright (C) 2008-2019 Free Software Foundation, Inc. 3 Copyright (C) 2008-2019 Free Software Foundation, Inc.
3 4
4This file is part of GNU Emacs. 5This file is part of GNU Emacs.
@@ -85,42 +86,6 @@ DEF_DLL_FN (void, hb_face_destroy, (hb_face_t *));
85DEF_DLL_FN (unsigned int, hb_face_get_upem, (hb_face_t *)); 86DEF_DLL_FN (unsigned int, hb_face_get_upem, (hb_face_t *));
86DEF_DLL_FN (hb_bool_t, hb_font_get_nominal_glyph, 87DEF_DLL_FN (hb_bool_t, hb_font_get_nominal_glyph,
87 (hb_font_t *, hb_codepoint_t, hb_codepoint_t *)); 88 (hb_font_t *, hb_codepoint_t, hb_codepoint_t *));
88DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_create,
89 (hb_unicode_funcs_t *));
90DEF_DLL_FN (hb_unicode_funcs_t *, hb_unicode_funcs_get_default, (void));
91DEF_DLL_FN (void, hb_unicode_funcs_set_combining_class_func,
92 (hb_unicode_funcs_t *, hb_unicode_combining_class_func_t,
93 void *, hb_destroy_func_t));
94DEF_DLL_FN (void, hb_unicode_funcs_set_general_category_func,
95 (hb_unicode_funcs_t *, hb_unicode_general_category_func_t,
96 void *, hb_destroy_func_t));
97DEF_DLL_FN (void, hb_unicode_funcs_set_mirroring_func,
98 (hb_unicode_funcs_t *, hb_unicode_mirroring_func_t,
99 void *, hb_destroy_func_t));
100DEF_DLL_FN (hb_buffer_t *, hb_buffer_create, (void));
101DEF_DLL_FN (void, hb_buffer_set_unicode_funcs,
102 (hb_buffer_t *, hb_unicode_funcs_t *));
103DEF_DLL_FN (void, hb_buffer_clear_contents, (hb_buffer_t *));
104DEF_DLL_FN (hb_bool_t, hb_buffer_pre_allocate, (hb_buffer_t *, unsigned int));
105DEF_DLL_FN (void, hb_buffer_add, (hb_buffer_t *, hb_codepoint_t, unsigned int));
106DEF_DLL_FN (void, hb_buffer_set_content_type,
107 (hb_buffer_t *, hb_buffer_content_type_t));
108DEF_DLL_FN (void, hb_buffer_set_cluster_level,
109 (hb_buffer_t *, hb_buffer_cluster_level_t));
110DEF_DLL_FN (void, hb_buffer_set_direction, (hb_buffer_t *, hb_direction_t));
111DEF_DLL_FN (void, hb_buffer_set_language, (hb_buffer_t *, hb_language_t));
112DEF_DLL_FN (hb_language_t, hb_language_from_string, (const char *, int));
113DEF_DLL_FN (void, hb_buffer_guess_segment_properties, (hb_buffer_t *));
114DEF_DLL_FN (hb_bool_t, hb_shape_full,
115 (hb_font_t *, hb_buffer_t *, const hb_feature_t *,
116 unsigned int, const char * const *));
117DEF_DLL_FN (unsigned int, hb_buffer_get_length, (hb_buffer_t *));
118DEF_DLL_FN (hb_direction_t, hb_buffer_get_direction, (hb_buffer_t *));
119DEF_DLL_FN (void, hb_buffer_reverse_clusters, (hb_buffer_t *));
120DEF_DLL_FN (hb_glyph_info_t *, hb_buffer_get_glyph_infos,
121 (hb_buffer_t *, unsigned int *));
122DEF_DLL_FN (hb_glyph_position_t *, hb_buffer_get_glyph_positions,
123 (hb_buffer_t *, unsigned int *));
124 89
125#define hb_blob_create fn_hb_blob_create 90#define hb_blob_create fn_hb_blob_create
126#define hb_face_create_for_tables fn_hb_face_create_for_tables 91#define hb_face_create_for_tables fn_hb_face_create_for_tables
@@ -130,28 +95,6 @@ DEF_DLL_FN (hb_glyph_position_t *, hb_buffer_get_glyph_positions,
130#define hb_face_destroy fn_hb_face_destroy 95#define hb_face_destroy fn_hb_face_destroy
131#define hb_face_get_upem fn_hb_face_get_upem 96#define hb_face_get_upem fn_hb_face_get_upem
132#define hb_font_get_nominal_glyph fn_hb_font_get_nominal_glyph 97#define hb_font_get_nominal_glyph fn_hb_font_get_nominal_glyph
133#define hb_unicode_funcs_create fn_hb_unicode_funcs_create
134#define hb_unicode_funcs_get_default fn_hb_unicode_funcs_get_default
135#define hb_unicode_funcs_set_combining_class_func fn_hb_unicode_funcs_set_combining_class_func
136#define hb_unicode_funcs_set_general_category_func fn_hb_unicode_funcs_set_general_category_func
137#define hb_unicode_funcs_set_mirroring_func fn_hb_unicode_funcs_set_mirroring_func
138#define hb_buffer_create fn_hb_buffer_create
139#define hb_buffer_set_unicode_funcs fn_hb_buffer_set_unicode_funcs
140#define hb_buffer_clear_contents fn_hb_buffer_clear_contents
141#define hb_buffer_pre_allocate fn_hb_buffer_pre_allocate
142#define hb_buffer_add fn_hb_buffer_add
143#define hb_buffer_set_content_type fn_hb_buffer_set_content_type
144#define hb_buffer_set_cluster_level fn_hb_buffer_set_cluster_level
145#define hb_buffer_set_direction fn_hb_buffer_set_direction
146#define hb_buffer_set_language fn_hb_buffer_set_language
147#define hb_language_from_string fn_hb_language_from_string
148#define hb_buffer_guess_segment_properties fn_hb_buffer_guess_segment_properties
149#define hb_shape_full fn_hb_shape_full
150#define hb_buffer_get_length fn_hb_buffer_get_length
151#define hb_buffer_get_direction fn_hb_buffer_get_direction
152#define hb_buffer_reverse_clusters fn_hb_buffer_reverse_clusters
153#define hb_buffer_get_glyph_infos fn_hb_buffer_get_glyph_infos
154#define hb_buffer_get_glyph_positions fn_hb_buffer_get_glyph_positions
155#endif 98#endif
156 99
157/* Used by uniscribe_otf_capability. */ 100/* Used by uniscribe_otf_capability. */
@@ -1434,348 +1377,6 @@ w32hb_begin_font (struct font *font, double *position_unit)
1434 *position_unit = uniscribe_font->scale; 1377 *position_unit = uniscribe_font->scale;
1435 return (hb_font_t *) uniscribe_font->cache; 1378 return (hb_font_t *) uniscribe_font->cache;
1436} 1379}
1437
1438static bool combining_class_loaded = false;
1439static Lisp_Object canonical_combining_class_table;
1440
1441static hb_unicode_combining_class_t
1442w32uni_combining (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
1443{
1444 /* Load the Unicode table first time it is needed. */
1445 if (!combining_class_loaded)
1446 {
1447 canonical_combining_class_table =
1448 uniprop_table (intern ("canonical-combining-class"));
1449 if (NILP (canonical_combining_class_table))
1450 emacs_abort ();
1451 staticpro (&canonical_combining_class_table);
1452 combining_class_loaded = true;
1453 }
1454
1455 Lisp_Object combining =
1456 get_unicode_property (canonical_combining_class_table, ch);
1457 if (FIXNUMP (combining))
1458 return (hb_unicode_combining_class_t) XFIXNUM (combining);
1459
1460 return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
1461}
1462
1463static hb_unicode_general_category_t
1464w32uni_general (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
1465{
1466 Lisp_Object category = CHAR_TABLE_REF (Vunicode_category_table, ch);
1467
1468 if (INTEGERP (category))
1469 {
1470 switch (XFIXNUM (category))
1471 {
1472 case UNICODE_CATEGORY_Cc:
1473 return HB_UNICODE_GENERAL_CATEGORY_CONTROL;
1474 case UNICODE_CATEGORY_Cf:
1475 return HB_UNICODE_GENERAL_CATEGORY_FORMAT;
1476 case UNICODE_CATEGORY_Cn:
1477 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
1478 case UNICODE_CATEGORY_Co:
1479 return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE;
1480 case UNICODE_CATEGORY_Cs:
1481 return HB_UNICODE_GENERAL_CATEGORY_SURROGATE;
1482 case UNICODE_CATEGORY_Ll:
1483 return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER;
1484 case UNICODE_CATEGORY_Lm:
1485 return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER;
1486 case UNICODE_CATEGORY_Lo:
1487 return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
1488 case UNICODE_CATEGORY_Lt:
1489 return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER;
1490 case UNICODE_CATEGORY_Lu:
1491 return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER;
1492 case UNICODE_CATEGORY_Mc:
1493 return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK;
1494 case UNICODE_CATEGORY_Me:
1495 return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
1496 case UNICODE_CATEGORY_Mn:
1497 return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK;
1498 case UNICODE_CATEGORY_Nd:
1499 return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER;
1500 case UNICODE_CATEGORY_Nl:
1501 return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER;
1502 case UNICODE_CATEGORY_No:
1503 return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER;
1504 case UNICODE_CATEGORY_Pc:
1505 return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION;
1506 case UNICODE_CATEGORY_Pd:
1507 return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION;
1508 case UNICODE_CATEGORY_Pe:
1509 return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION;
1510 case UNICODE_CATEGORY_Pf:
1511 return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION;
1512 case UNICODE_CATEGORY_Pi:
1513 return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION;
1514 case UNICODE_CATEGORY_Po:
1515 return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION;
1516 case UNICODE_CATEGORY_Ps:
1517 return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION;
1518 case UNICODE_CATEGORY_Sc:
1519 return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL;
1520 case UNICODE_CATEGORY_Sk:
1521 return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL;
1522 case UNICODE_CATEGORY_Sm:
1523 return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL;
1524 case UNICODE_CATEGORY_So:
1525 return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL;
1526 case UNICODE_CATEGORY_Zl:
1527 return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR;
1528 case UNICODE_CATEGORY_Zp:
1529 return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR;
1530 case UNICODE_CATEGORY_Zs:
1531 return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
1532 case UNICODE_CATEGORY_UNKNOWN:
1533 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
1534 }
1535 }
1536
1537 return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
1538}
1539
1540static hb_codepoint_t
1541w32uni_mirroring (hb_unicode_funcs_t *funcs, hb_codepoint_t ch, void *user_data)
1542{
1543 return bidi_mirror_char (ch);
1544}
1545
1546static hb_unicode_funcs_t *
1547get_hb_unicode_funcs (void)
1548{
1549 /* Subclass HarfBuzz's default Unicode functions and override functions that
1550 * use data Emacs can provide. This way changing Emacs data is reflected in
1551 * the shaped output. */
1552 hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (hb_unicode_funcs_get_default ());
1553
1554 hb_unicode_funcs_set_combining_class_func (funcs, w32uni_combining, NULL, NULL);
1555 hb_unicode_funcs_set_general_category_func (funcs, w32uni_general, NULL, NULL);
1556 hb_unicode_funcs_set_mirroring_func (funcs, w32uni_mirroring, NULL, NULL);
1557
1558 /* Use default implmentation for Unicode composition/decomposition, we might
1559 * want to revisit this later.
1560 hb_unicode_funcs_set_compose_func (funcs, uni_compose, NULL, NULL);
1561 hb_unicode_funcs_set_decompose_func (funcs, uni_decompose, NULL, NULL);
1562 */
1563
1564 /* Emacs own script mapping for characters differs from Unicode, so we want
1565 * to keep the default HarfBuzz's implementation here.
1566 hb_unicode_funcs_set_script_func (funcs, uni_script, NULL, NULL);
1567 */
1568
1569 return funcs;
1570}
1571
1572/* HarfBuzz implementation of shape for font backend. See the
1573 commentary before uniscribe_shape for the meaning of the
1574 arguments. */
1575static Lisp_Object
1576w32hb_shape (Lisp_Object lgstring, Lisp_Object direction)
1577{
1578 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
1579 ptrdiff_t glyph_len = 0, text_len = LGSTRING_GLYPH_LEN (lgstring);
1580 ptrdiff_t i;
1581
1582 hb_glyph_info_t *info;
1583 hb_glyph_position_t *pos;
1584
1585 /* Cache the HarfBuzz buffer for better performance and less allocations.
1586 * We intentionally never destroy the buffer. */
1587 static hb_buffer_t *hb_buffer = NULL;
1588 if (! hb_buffer)
1589 {
1590 hb_buffer = hb_buffer_create ();
1591 hb_unicode_funcs_t* ufuncs = get_hb_unicode_funcs();
1592 hb_buffer_set_unicode_funcs(hb_buffer, ufuncs);
1593 }
1594
1595 hb_buffer_clear_contents (hb_buffer);
1596 hb_buffer_pre_allocate (hb_buffer, text_len);
1597
1598 /* Copy the characters in their original logical order, so we can
1599 assign them to glyphs correctly after shaping. */
1600 int *chars = alloca (text_len * sizeof (int));
1601 for (i = 0; i < text_len; i++)
1602 {
1603 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
1604 int c;
1605
1606 if (NILP (g))
1607 break;
1608 c = LGLYPH_CHAR (g);
1609 hb_buffer_add (hb_buffer, c, i);
1610 chars[i] = c;
1611 }
1612
1613 text_len = i;
1614 if (!text_len)
1615 return Qnil;
1616
1617 hb_buffer_set_content_type (hb_buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
1618 hb_buffer_set_cluster_level (hb_buffer,
1619 HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES);
1620
1621 /* If the caller didn't provide a meaningful DIRECTION, let HarfBuzz
1622 guess it. */
1623 if (!NILP (direction))
1624 {
1625 hb_direction_t dir = HB_DIRECTION_LTR;
1626 if (EQ (direction, QL2R))
1627 dir = HB_DIRECTION_LTR;
1628 else if (EQ (direction, QR2L))
1629 dir = HB_DIRECTION_RTL;
1630 hb_buffer_set_direction (hb_buffer, dir);
1631 }
1632
1633 /* Leave the script determination to HarfBuzz, until Emacs has a
1634 better idea of the script of LGSTRING. FIXME. */
1635#if 0
1636 hb_buffer_set_script (hb_buffer, XXX);
1637#endif
1638
1639 /* FIXME: This can only handle the single global language, which
1640 normally comes from the locale. In addition, if
1641 current-iso639-language is a list, we arbitrarily use the first
1642 one. We should instead have a notion of the language of the text
1643 being shaped. */
1644 Lisp_Object lang = Vcurrent_iso639_language;
1645 if (CONSP (Vcurrent_iso639_language))
1646 lang = XCAR (Vcurrent_iso639_language);
1647 if (SYMBOLP (lang))
1648 {
1649 Lisp_Object lang_str = SYMBOL_NAME (lang);
1650 hb_buffer_set_language (hb_buffer,
1651 hb_language_from_string (SSDATA (lang_str),
1652 SBYTES (lang_str)));
1653 }
1654
1655 /* Guess the default properties for when they cannot be determined above.
1656
1657 FIXME: maybe drop this guessing once script and language handling
1658 is fixed above; but then will need to guess the direction by
1659 ourselves, perhaps by looking at the the characters using
1660 bidi_get_type or somesuch. */
1661 hb_buffer_guess_segment_properties (hb_buffer);
1662
1663 double position_unit;
1664 hb_font_t *hb_font
1665 = font->driver->begin_hb_font
1666 ? font->driver->begin_hb_font (font, &position_unit)
1667 : NULL;
1668 if (!hb_font)
1669 return make_fixnum (0);
1670
1671 hb_bool_t success = hb_shape_full (hb_font, hb_buffer, NULL, 0, NULL);
1672 if (font->driver->end_hb_font)
1673 font->driver->end_hb_font (font, hb_font);
1674 if (!success)
1675 return Qnil;
1676
1677 glyph_len = hb_buffer_get_length (hb_buffer);
1678 /* FIXME: can't we just grow the lgstring in this case? Giving up is an
1679 * overly heavy handed solution. */
1680 if (glyph_len > LGSTRING_GLYPH_LEN (lgstring))
1681 return Qnil;
1682
1683 /* We need the clusters in logical order. */
1684 bool buf_reversed = false;
1685 if (HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (hb_buffer)))
1686 {
1687 buf_reversed = true;
1688 hb_buffer_reverse_clusters (hb_buffer);
1689 }
1690 info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
1691 pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
1692 int from = -1, to, cluster_offset = 0;
1693 int char_idx, incr = buf_reversed ? -1 : 1;
1694 for (i = 0; i < glyph_len; i++)
1695 {
1696 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
1697 struct font_metrics metrics = {.width = 0};
1698 int xoff, yoff, wadjust;
1699
1700 if (NILP (lglyph))
1701 {
1702 lglyph = LGLYPH_NEW ();
1703 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
1704 }
1705
1706 if (info[i].cluster != from)
1707 {
1708 int j;
1709 /* Found a new cluster. Determine its FROM and TO, and the
1710 offset to the first character of the cluster. */
1711 /* FROM is the index of the first character that contributed
1712 to this cluster. */
1713 from = info[i].cluster;
1714 /* TO is the index of the last character that contributed to
1715 this cluster. */
1716 for (j = i; j < glyph_len && info[j].cluster == from; j++)
1717 ;
1718 to = (j == glyph_len) ? text_len - 1 : info[j].cluster - 1;
1719 cluster_offset = 0;
1720 /* For RTL buffers, HarfBuzz produces glyphs in a cluster in
1721 reverse order, so we need to account for that to record
1722 the correct character in each glyph.
1723
1724 Implementation note: the character codepoint recorded in
1725 each glyph is not really used, except when we display the
1726 glyphs in descr-text.el. So this is just an aeasthetic
1727 issue. */
1728 if (buf_reversed)
1729 cluster_offset = to - from;
1730 }
1731
1732 /* All the glyphs in a cluster have the same values of FROM and TO. */
1733 LGLYPH_SET_FROM (lglyph, from);
1734 LGLYPH_SET_TO (lglyph, to);
1735
1736 /* Not every glyph in a cluster maps directly to a single
1737 character; in general, N characters can yield M glyphs, where
1738 M could be smaller or greater than N. However, in many cases
1739 there is a one-to-one correspondence, and it would be a pity
1740 to lose that information, even if it's sometimes inaccurate. */
1741 char_idx = from + cluster_offset;
1742 cluster_offset += incr;
1743 if (char_idx > to)
1744 char_idx = to;
1745 if (char_idx < from)
1746 char_idx = from;
1747 LGLYPH_SET_CHAR (lglyph, chars[char_idx]);
1748 LGLYPH_SET_CODE (lglyph, info[i].codepoint);
1749
1750 unsigned code = info[i].codepoint;
1751 font->driver->text_extents (font, &code, 1, &metrics);
1752 LGLYPH_SET_WIDTH (lglyph, metrics.width);
1753 LGLYPH_SET_LBEARING (lglyph, metrics.lbearing);
1754 LGLYPH_SET_RBEARING (lglyph, metrics.rbearing);
1755 LGLYPH_SET_ASCENT (lglyph, metrics.ascent);
1756 LGLYPH_SET_DESCENT (lglyph, metrics.descent);
1757
1758 xoff = lround (pos[i].x_offset * position_unit);
1759 yoff = - lround (pos[i].y_offset * position_unit);
1760 wadjust = lround (pos[i].x_advance * position_unit);
1761 if (xoff || yoff || wadjust != metrics.width)
1762 {
1763 Lisp_Object vec = make_uninit_vector (3);
1764 ASET (vec, 0, make_fixnum (xoff));
1765 ASET (vec, 1, make_fixnum (yoff));
1766 ASET (vec, 2, make_fixnum (wadjust));
1767 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
1768 }
1769 }
1770
1771 return make_fixnum (glyph_len);
1772}
1773
1774static Lisp_Object
1775w32hb_combining_capability (struct font *font)
1776{
1777 return Qt;
1778}
1779#endif /* HAVE_HARFBUZZ */ 1380#endif /* HAVE_HARFBUZZ */
1780 1381
1781#undef OTF_INT16_VAL 1382#undef OTF_INT16_VAL
@@ -1838,29 +1439,7 @@ load_harfbuzz_funcs (HMODULE library)
1838 LOAD_DLL_FN (library, hb_face_get_upem); 1439 LOAD_DLL_FN (library, hb_face_get_upem);
1839 LOAD_DLL_FN (library, hb_face_destroy); 1440 LOAD_DLL_FN (library, hb_face_destroy);
1840 LOAD_DLL_FN (library, hb_font_get_nominal_glyph); 1441 LOAD_DLL_FN (library, hb_font_get_nominal_glyph);
1841 LOAD_DLL_FN (library, hb_unicode_funcs_create); 1442 return hbfont_init_w32_funcs (library);
1842 LOAD_DLL_FN (library, hb_unicode_funcs_get_default);
1843 LOAD_DLL_FN (library, hb_unicode_funcs_set_combining_class_func);
1844 LOAD_DLL_FN (library, hb_unicode_funcs_set_general_category_func);
1845 LOAD_DLL_FN (library, hb_unicode_funcs_set_mirroring_func);
1846 LOAD_DLL_FN (library, hb_buffer_create);
1847 LOAD_DLL_FN (library, hb_buffer_set_unicode_funcs);
1848 LOAD_DLL_FN (library, hb_buffer_clear_contents);
1849 LOAD_DLL_FN (library, hb_buffer_pre_allocate);
1850 LOAD_DLL_FN (library, hb_buffer_add);
1851 LOAD_DLL_FN (library, hb_buffer_set_content_type);
1852 LOAD_DLL_FN (library, hb_buffer_set_cluster_level);
1853 LOAD_DLL_FN (library, hb_buffer_set_direction);
1854 LOAD_DLL_FN (library, hb_buffer_set_language);
1855 LOAD_DLL_FN (library, hb_language_from_string);
1856 LOAD_DLL_FN (library, hb_buffer_guess_segment_properties);
1857 LOAD_DLL_FN (library, hb_shape_full);
1858 LOAD_DLL_FN (library, hb_buffer_get_length);
1859 LOAD_DLL_FN (library, hb_buffer_get_direction);
1860 LOAD_DLL_FN (library, hb_buffer_reverse_clusters);
1861 LOAD_DLL_FN (library, hb_buffer_get_glyph_infos);
1862 LOAD_DLL_FN (library, hb_buffer_get_glyph_positions);
1863 return true;
1864} 1443}
1865#endif /* HAVE_HARFBUZZ */ 1444#endif /* HAVE_HARFBUZZ */
1866 1445
@@ -1913,8 +1492,8 @@ syms_of_w32uniscribe_for_pdumper (void)
1913 harfbuzz_font_driver.list = w32hb_list; 1492 harfbuzz_font_driver.list = w32hb_list;
1914 harfbuzz_font_driver.match = w32hb_match; 1493 harfbuzz_font_driver.match = w32hb_match;
1915 harfbuzz_font_driver.encode_char = w32hb_encode_char; 1494 harfbuzz_font_driver.encode_char = w32hb_encode_char;
1916 harfbuzz_font_driver.shape = w32hb_shape; 1495 harfbuzz_font_driver.shape = hbfont_shape;
1917 harfbuzz_font_driver.combining_capability = w32hb_combining_capability; 1496 harfbuzz_font_driver.combining_capability = hbfont_combining_capability;
1918 harfbuzz_font_driver.begin_hb_font = w32hb_begin_font; 1497 harfbuzz_font_driver.begin_hb_font = w32hb_begin_font;
1919 register_font_driver (&harfbuzz_font_driver, NULL); 1498 register_font_driver (&harfbuzz_font_driver, NULL);
1920#endif /* HAVE_HARFBUZZ */ 1499#endif /* HAVE_HARFBUZZ */