]> code.delx.au - gnu-emacs/blob - src/w32uniscribe.c
A better fix for bug#21303
[gnu-emacs] / src / w32uniscribe.c
1 /* Font backend for the Microsoft W32 Uniscribe API.
2 Copyright (C) 2008-2015 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
9 (at 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 <http://www.gnu.org/licenses/>. */
18
19
20 #include <config.h>
21 /* Override API version - Uniscribe is only available as standard
22 since Windows 2000, though most users of older systems will have it
23 since it installs with Internet Explorer 5.0 and other software.
24 Also, MinGW64 w32api headers by default define OPENTYPE_TAG typedef
25 only if _WIN32_WINNT >= 0x0600. We only use the affected APIs if
26 they are available, so there is no chance of calling non-existent
27 functions. */
28 #undef _WIN32_WINNT
29 #define _WIN32_WINNT 0x0600
30 #include <windows.h>
31 #include <usp10.h>
32
33 #include "lisp.h"
34 #include "w32term.h"
35 #include "frame.h"
36 #include "dispextern.h"
37 #include "character.h"
38 #include "charset.h"
39 #include "composite.h"
40 #include "fontset.h"
41 #include "font.h"
42 #include "w32font.h"
43
44 struct uniscribe_font_info
45 {
46 struct w32font_info w32_font;
47 SCRIPT_CACHE cache;
48 };
49
50 int uniscribe_available = 0;
51
52 /* EnumFontFamiliesEx callback. */
53 static int CALLBACK ALIGN_STACK add_opentype_font_name_to_list (ENUMLOGFONTEX *,
54 NEWTEXTMETRICEX *,
55 DWORD, LPARAM);
56 /* Used by uniscribe_otf_capability. */
57 static Lisp_Object otf_features (HDC context, char *table);
58
59 static int
60 memq_no_quit (Lisp_Object elt, Lisp_Object list)
61 {
62 while (CONSP (list) && ! EQ (XCAR (list), elt))
63 list = XCDR (list);
64 return (CONSP (list));
65 }
66
67 \f
68 /* Font backend interface implementation. */
69 static Lisp_Object
70 uniscribe_list (struct frame *f, Lisp_Object font_spec)
71 {
72 Lisp_Object fonts = w32font_list_internal (f, font_spec, true);
73 FONT_ADD_LOG ("uniscribe-list", font_spec, fonts);
74 return fonts;
75 }
76
77 static Lisp_Object
78 uniscribe_match (struct frame *f, Lisp_Object font_spec)
79 {
80 Lisp_Object entity = w32font_match_internal (f, font_spec, true);
81 FONT_ADD_LOG ("uniscribe-match", font_spec, entity);
82 return entity;
83 }
84
85 static Lisp_Object
86 uniscribe_list_family (struct frame *f)
87 {
88 Lisp_Object list = Qnil;
89 LOGFONT font_match_pattern;
90 HDC dc;
91
92 memset (&font_match_pattern, 0, sizeof (font_match_pattern));
93 /* Limit enumerated fonts to outline fonts to save time. */
94 font_match_pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
95
96 dc = get_frame_dc (f);
97
98 EnumFontFamiliesEx (dc, &font_match_pattern,
99 (FONTENUMPROC) add_opentype_font_name_to_list,
100 (LPARAM) &list, 0);
101 release_frame_dc (f, dc);
102
103 return list;
104 }
105
106 static Lisp_Object
107 uniscribe_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
108 {
109 Lisp_Object font_object
110 = font_make_object (VECSIZE (struct uniscribe_font_info),
111 font_entity, pixel_size);
112 struct uniscribe_font_info *uniscribe_font
113 = (struct uniscribe_font_info *) XFONT_OBJECT (font_object);
114
115 ASET (font_object, FONT_TYPE_INDEX, Quniscribe);
116
117 if (!w32font_open_internal (f, font_entity, pixel_size, font_object))
118 {
119 return Qnil;
120 }
121
122 /* Initialize the cache for this font. */
123 uniscribe_font->cache = NULL;
124
125 /* Uniscribe backend uses glyph indices. */
126 uniscribe_font->w32_font.glyph_idx = ETO_GLYPH_INDEX;
127
128 uniscribe_font->w32_font.font.driver = &uniscribe_font_driver;
129
130 return font_object;
131 }
132
133 static void
134 uniscribe_close (struct font *font)
135 {
136 struct uniscribe_font_info *uniscribe_font
137 = (struct uniscribe_font_info *) font;
138
139 if (uniscribe_font->cache)
140 ScriptFreeCache (&(uniscribe_font->cache));
141
142 w32font_close (font);
143 }
144
145 /* Return a list describing which scripts/languages FONT supports by
146 which GSUB/GPOS features of OpenType tables.
147
148 Implementation note: otf_features called by this function uses
149 GetFontData to access the font tables directly, instead of using
150 ScriptGetFontScriptTags etc. APIs even if those are available. The
151 reason is that font-get, which uses the result of this function,
152 expects a cons cell (GSUB . GPOS) where the features are reported
153 separately for these 2 OTF tables, while the Uniscribe APIs report
154 the features as a single list. There doesn't seem to be a reason
155 for returning the features in 2 separate parts, except for
156 compatibility with libotf; the features are disjoint (each can
157 appear only in one of the 2 slots), and no client of this data
158 discerns between the two slots: the few that request this data all
159 look in both slots. If use of the Uniscribe APIs ever becomes
160 necessary here, and the 2 separate slots are still required, it
161 should be possible to split the feature list the APIs return into 2
162 because each sub-list is alphabetically sorted, so the place where
163 the sorting order breaks is where the GSUB features end and GPOS
164 features begin. But for now, this is not necessary, so we leave
165 the original code in place. */
166 static Lisp_Object
167 uniscribe_otf_capability (struct font *font)
168 {
169 HDC context;
170 HFONT old_font;
171 struct frame *f;
172 Lisp_Object capability = Fcons (Qnil, Qnil);
173 Lisp_Object features;
174
175 f = XFRAME (selected_frame);
176 context = get_frame_dc (f);
177 old_font = SelectObject (context, FONT_HANDLE (font));
178
179 features = otf_features (context, "GSUB");
180 XSETCAR (capability, features);
181 features = otf_features (context, "GPOS");
182 XSETCDR (capability, features);
183
184 SelectObject (context, old_font);
185 release_frame_dc (f, context);
186
187 return capability;
188 }
189
190 /* Uniscribe implementation of shape for font backend.
191
192 Shape text in LGSTRING. See the docstring of
193 `composition-get-gstring' for the format of LGSTRING. If the
194 (N+1)th element of LGSTRING is nil, input of shaping is from the
195 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and
196 CODE are already set.
197
198 This function updates all fields of the input glyphs. If the
199 output glyphs (M) are more than the input glyphs (N), (N+1)th
200 through (M)th elements of LGSTRING are updated possibly by making
201 a new glyph object and storing it in LGSTRING. If (M) is greater
202 than the length of LGSTRING, nil should be returned. In that case,
203 this function is called again with a larger LGSTRING. */
204 static Lisp_Object
205 uniscribe_shape (Lisp_Object lgstring)
206 {
207 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
208 struct uniscribe_font_info *uniscribe_font
209 = (struct uniscribe_font_info *) font;
210 EMACS_UINT nchars;
211 int nitems, max_items, i, max_glyphs, done_glyphs;
212 wchar_t *chars;
213 WORD *glyphs, *clusters;
214 SCRIPT_ITEM *items;
215 SCRIPT_VISATTR *attributes;
216 int *advances;
217 GOFFSET *offsets;
218 ABC overall_metrics;
219 HRESULT result;
220 struct frame * f = NULL;
221 HDC context = NULL;
222 HFONT old_font = NULL;
223
224 /* Get the chars from lgstring in a form we can use with uniscribe. */
225 max_glyphs = nchars = LGSTRING_GLYPH_LEN (lgstring);
226 done_glyphs = 0;
227 chars = (wchar_t *) alloca (nchars * sizeof (wchar_t));
228 /* FIXME: This loop assumes that characters in the input LGSTRING
229 are all inside the BMP. Need to encode characters beyond the BMP
230 as UTF-16. */
231 for (i = 0; i < nchars; i++)
232 {
233 /* lgstring can be bigger than the number of characters in it, in
234 the case where more glyphs are required to display those characters.
235 If that is the case, note the real number of characters. */
236 if (NILP (LGSTRING_GLYPH (lgstring, i)))
237 nchars = i;
238 else
239 chars[i] = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
240 }
241
242 /* First we need to break up the glyph string into runs of glyphs that
243 can be treated together. First try a single run. */
244 max_items = 2;
245 items = xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1);
246
247 while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL,
248 items, &nitems)) == E_OUTOFMEMORY)
249 {
250 /* If that wasn't enough, keep trying with one more run. */
251 max_items++;
252 items = (SCRIPT_ITEM *) xrealloc (items,
253 sizeof (SCRIPT_ITEM) * max_items + 1);
254 }
255
256 if (FAILED (result))
257 {
258 xfree (items);
259 return Qnil;
260 }
261
262 glyphs = alloca (max_glyphs * sizeof (WORD));
263 clusters = alloca (nchars * sizeof (WORD));
264 attributes = alloca (max_glyphs * sizeof (SCRIPT_VISATTR));
265 advances = alloca (max_glyphs * sizeof (int));
266 offsets = alloca (max_glyphs * sizeof (GOFFSET));
267
268 for (i = 0; i < nitems; i++)
269 {
270 int nglyphs, nchars_in_run;
271 nchars_in_run = items[i+1].iCharPos - items[i].iCharPos;
272 /* Force ScriptShape to generate glyphs in the same order as
273 they are in the input LGSTRING, which is in the logical
274 order. */
275 items[i].a.fLogicalOrder = 1;
276
277 /* Context may be NULL here, in which case the cache should be
278 used without needing to select the font. */
279 result = ScriptShape (context, &(uniscribe_font->cache),
280 chars + items[i].iCharPos, nchars_in_run,
281 max_glyphs - done_glyphs, &(items[i].a),
282 glyphs, clusters, attributes, &nglyphs);
283
284 if (result == E_PENDING && !context)
285 {
286 /* This assumes the selected frame is on the same display as the
287 one we are drawing. It would be better for the frame to be
288 passed in. */
289 f = XFRAME (selected_frame);
290 context = get_frame_dc (f);
291 old_font = SelectObject (context, FONT_HANDLE (font));
292
293 result = ScriptShape (context, &(uniscribe_font->cache),
294 chars + items[i].iCharPos, nchars_in_run,
295 max_glyphs - done_glyphs, &(items[i].a),
296 glyphs, clusters, attributes, &nglyphs);
297 }
298
299 if (result == E_OUTOFMEMORY)
300 {
301 /* Need a bigger lgstring. */
302 lgstring = Qnil;
303 break;
304 }
305 else if (FAILED (result))
306 {
307 /* Can't shape this run - return results so far if any. */
308 break;
309 }
310 else if (items[i].a.fNoGlyphIndex)
311 {
312 /* Glyph indices not supported by this font (or OS), means we
313 can't really do any meaningful shaping. */
314 break;
315 }
316 else
317 {
318 result = ScriptPlace (context, &(uniscribe_font->cache),
319 glyphs, nglyphs, attributes, &(items[i].a),
320 advances, offsets, &overall_metrics);
321 if (result == E_PENDING && !context)
322 {
323 /* Cache not complete... */
324 f = XFRAME (selected_frame);
325 context = get_frame_dc (f);
326 old_font = SelectObject (context, FONT_HANDLE (font));
327
328 result = ScriptPlace (context, &(uniscribe_font->cache),
329 glyphs, nglyphs, attributes, &(items[i].a),
330 advances, offsets, &overall_metrics);
331 }
332 if (SUCCEEDED (result))
333 {
334 int j, from, to, adj_offset = 0;
335
336 from = 0;
337 to = from;
338
339 for (j = 0; j < nglyphs; j++)
340 {
341 int lglyph_index = j + done_glyphs;
342 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, lglyph_index);
343 ABC char_metric;
344 unsigned gl;
345
346 if (NILP (lglyph))
347 {
348 lglyph = LGLYPH_NEW ();
349 LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph);
350 }
351 /* Copy to a 32-bit data type to shut up the
352 compiler warning in LGLYPH_SET_CODE about
353 comparison being always false. */
354 gl = glyphs[j];
355 LGLYPH_SET_CODE (lglyph, gl);
356
357 /* Detect clusters, for linking codes back to
358 characters. */
359 if (attributes[j].fClusterStart)
360 {
361 while (from < nchars_in_run && clusters[from] < j)
362 from++;
363 if (from >= nchars_in_run)
364 from = to = nchars_in_run - 1;
365 else
366 {
367 int k;
368 to = nchars_in_run - 1;
369 for (k = from + 1; k < nchars_in_run; k++)
370 {
371 if (clusters[k] > j)
372 {
373 to = k - 1;
374 break;
375 }
376 }
377 }
378
379 /* For RTL text, the Uniscribe shaper prepares
380 the values in ADVANCES array for layout in
381 reverse order, whereby "advance width" is
382 applied to move the pen in reverse direction
383 and _before_ drawing the glyph. Since we
384 draw glyphs in their normal left-to-right
385 order, we need to adjust the coordinates of
386 each non-base glyph in a grapheme cluster via
387 X-OFF component of the gstring's ADJUSTMENT
388 sub-vector. This loop computes, for each
389 grapheme cluster, the initial value of the
390 adjustment for the base character, which is
391 then updated for each successive glyph in the
392 grapheme cluster. */
393 if (items[i].a.fRTL)
394 {
395 int j1 = j;
396
397 adj_offset = 0;
398 while (j1 < nglyphs && !attributes[j1].fClusterStart)
399 {
400 adj_offset += advances[j1];
401 j1++;
402 }
403 }
404 }
405
406 LGLYPH_SET_CHAR (lglyph, chars[items[i].iCharPos
407 + from]);
408 LGLYPH_SET_FROM (lglyph, items[i].iCharPos + from);
409 LGLYPH_SET_TO (lglyph, items[i].iCharPos + to);
410
411 /* Metrics. */
412 LGLYPH_SET_WIDTH (lglyph, advances[j]);
413 LGLYPH_SET_ASCENT (lglyph, font->ascent);
414 LGLYPH_SET_DESCENT (lglyph, font->descent);
415
416 result = ScriptGetGlyphABCWidth (context,
417 &(uniscribe_font->cache),
418 glyphs[j], &char_metric);
419 if (result == E_PENDING && !context)
420 {
421 /* Cache incomplete... */
422 f = XFRAME (selected_frame);
423 context = get_frame_dc (f);
424 old_font = SelectObject (context, FONT_HANDLE (font));
425 result = ScriptGetGlyphABCWidth (context,
426 &(uniscribe_font->cache),
427 glyphs[j], &char_metric);
428 }
429
430 if (SUCCEEDED (result))
431 {
432 int lbearing = char_metric.abcA;
433 int rbearing = char_metric.abcA + char_metric.abcB;
434
435 LGLYPH_SET_LBEARING (lglyph, lbearing);
436 LGLYPH_SET_RBEARING (lglyph, rbearing);
437 }
438 else
439 {
440 LGLYPH_SET_LBEARING (lglyph, 0);
441 LGLYPH_SET_RBEARING (lglyph, advances[j]);
442 }
443
444 if (offsets[j].du || offsets[j].dv
445 /* For non-base glyphs of RTL grapheme clusters,
446 adjust the X offset even if both DU and DV
447 are zero. */
448 || (!attributes[j].fClusterStart && items[i].a.fRTL))
449 {
450 Lisp_Object vec = make_uninit_vector (3);
451
452 if (items[i].a.fRTL)
453 {
454 /* Empirically, it looks like Uniscribe
455 interprets DU in reverse direction for
456 RTL clusters. E.g., if we don't reverse
457 the direction, the Hebrew point HOLAM is
458 drawn above the right edge of the base
459 consonant, instead of above the left edge. */
460 ASET (vec, 0, make_number (-offsets[j].du
461 + adj_offset));
462 /* Update the adjustment value for the width
463 advance of the glyph we just emitted. */
464 adj_offset -= 2 * advances[j];
465 }
466 else
467 ASET (vec, 0, make_number (offsets[j].du + adj_offset));
468 /* In the font definition coordinate system, the
469 Y coordinate points up, while in our screen
470 coordinates Y grows downwards. So we need to
471 reverse the sign of Y-OFFSET here. */
472 ASET (vec, 1, make_number (-offsets[j].dv));
473 /* Based on what ftfont.c does... */
474 ASET (vec, 2, make_number (advances[j]));
475 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
476 }
477 else
478 {
479 LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
480 /* Update the adjustment value to compensate for
481 the width of the base character. */
482 if (items[i].a.fRTL)
483 adj_offset -= advances[j];
484 }
485 }
486 }
487 }
488 done_glyphs += nglyphs;
489 }
490
491 xfree (items);
492
493 if (context)
494 {
495 SelectObject (context, old_font);
496 release_frame_dc (f, context);
497 }
498
499 if (NILP (lgstring))
500 return Qnil;
501 else
502 return make_number (done_glyphs);
503 }
504
505 /* Uniscribe implementation of encode_char for font backend.
506 Return a glyph code of FONT for character C (Unicode code point).
507 If FONT doesn't have such a glyph, return FONT_INVALID_CODE. */
508 static unsigned
509 uniscribe_encode_char (struct font *font, int c)
510 {
511 HDC context = NULL;
512 struct frame *f = NULL;
513 HFONT old_font = NULL;
514 unsigned code = FONT_INVALID_CODE;
515 wchar_t ch[2];
516 int len;
517 SCRIPT_ITEM* items;
518 int nitems;
519 struct uniscribe_font_info *uniscribe_font
520 = (struct uniscribe_font_info *)font;
521
522 if (c < 0x10000)
523 {
524 ch[0] = (wchar_t) c;
525 len = 1;
526 }
527 else
528 {
529 DWORD surrogate = c - 0x10000;
530
531 /* High surrogate: U+D800 - U+DBFF. */
532 ch[0] = 0xD800 + ((surrogate >> 10) & 0x03FF);
533 /* Low surrogate: U+DC00 - U+DFFF. */
534 ch[1] = 0xDC00 + (surrogate & 0x03FF);
535 len = 2;
536 }
537
538 /* Non BMP characters must be handled by the uniscribe shaping
539 engine as GDI functions (except blindly displaying lines of
540 Unicode text) and the promising looking ScriptGetCMap do not
541 convert surrogate pairs to glyph indexes correctly. */
542 {
543 items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1);
544 if (SUCCEEDED (ScriptItemize (ch, len, 2, NULL, NULL, items, &nitems)))
545 {
546 HRESULT result;
547 /* Surrogates seem to need 2 here, even though only one glyph is
548 returned. Indic characters can also produce 2 or more glyphs for
549 a single code point, but they need to use uniscribe_shape
550 above for correct display. */
551 WORD glyphs[2], clusters[2];
552 SCRIPT_VISATTR attrs[2];
553 int nglyphs;
554
555 /* Force ScriptShape to generate glyphs in the logical
556 order. */
557 items[0].a.fLogicalOrder = 1;
558
559 result = ScriptShape (context, &(uniscribe_font->cache),
560 ch, len, 2, &(items[0].a),
561 glyphs, clusters, attrs, &nglyphs);
562
563 if (result == E_PENDING)
564 {
565 /* Use selected frame until API is updated to pass
566 the frame. */
567 f = XFRAME (selected_frame);
568 context = get_frame_dc (f);
569 old_font = SelectObject (context, FONT_HANDLE (font));
570 result = ScriptShape (context, &(uniscribe_font->cache),
571 ch, len, 2, &(items[0].a),
572 glyphs, clusters, attrs, &nglyphs);
573 }
574
575 if (SUCCEEDED (result) && nglyphs == 1)
576 {
577 /* Some fonts return .notdef glyphs instead of failing.
578 (TrueType spec reserves glyph code 0 for .notdef) */
579 if (glyphs[0])
580 code = glyphs[0];
581 }
582 else if (SUCCEEDED (result) || result == E_OUTOFMEMORY)
583 {
584 /* This character produces zero or more than one glyph
585 when shaped. But we still need the return from here
586 to be valid for the shaping engine to be invoked
587 later. */
588 result = ScriptGetCMap (context, &(uniscribe_font->cache),
589 ch, len, 0, glyphs);
590 if (SUCCEEDED (result) && glyphs[0])
591 code = glyphs[0];
592 }
593 }
594 }
595 if (context)
596 {
597 SelectObject (context, old_font);
598 release_frame_dc (f, context);
599 }
600
601 return code;
602 }
603
604 /*
605 Shared with w32font:
606 Lisp_Object uniscribe_get_cache (Lisp_Object frame);
607 void uniscribe_free_entity (Lisp_Object font_entity);
608 int uniscribe_has_char (Lisp_Object entity, int c);
609 void uniscribe_text_extents (struct font *font, unsigned *code,
610 int nglyphs, struct font_metrics *metrics);
611 int uniscribe_draw (struct glyph_string *s, int from, int to,
612 int x, int y, int with_background);
613
614 Unused:
615 int uniscribe_prepare_face (struct frame *f, struct face *face);
616 void uniscribe_done_face (struct frame *f, struct face *face);
617 int uniscribe_get_bitmap (struct font *font, unsigned code,
618 struct font_bitmap *bitmap, int bits_per_pixel);
619 void uniscribe_free_bitmap (struct font *font, struct font_bitmap *bitmap);
620 int uniscribe_anchor_point (struct font *font, unsigned code,
621 int index, int *x, int *y);
622 int uniscribe_start_for_frame (struct frame *f);
623 int uniscribe_end_for_frame (struct frame *f);
624
625 */
626
627 \f
628 /* Callback function for EnumFontFamiliesEx.
629 Adds the name of opentype fonts to a Lisp list (passed in as the
630 lParam arg). */
631 static int CALLBACK ALIGN_STACK
632 add_opentype_font_name_to_list (ENUMLOGFONTEX *logical_font,
633 NEWTEXTMETRICEX *physical_font,
634 DWORD font_type, LPARAM list_object)
635 {
636 Lisp_Object* list = (Lisp_Object *) list_object;
637 Lisp_Object family;
638
639 /* Skip vertical fonts (intended only for printing) */
640 if (logical_font->elfLogFont.lfFaceName[0] == '@')
641 return 1;
642
643 /* Skip non opentype fonts. Count old truetype fonts as opentype,
644 as some of them do contain GPOS and GSUB data that Uniscribe
645 can make use of. */
646 if (!(physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE)
647 && font_type != TRUETYPE_FONTTYPE)
648 return 1;
649
650 /* Skip fonts that have no Unicode coverage. */
651 if (!physical_font->ntmFontSig.fsUsb[3]
652 && !physical_font->ntmFontSig.fsUsb[2]
653 && !physical_font->ntmFontSig.fsUsb[1]
654 && !(physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff))
655 return 1;
656
657 family = intern_font_name (logical_font->elfLogFont.lfFaceName);
658 if (! memq_no_quit (family, *list))
659 *list = Fcons (family, *list);
660
661 return 1;
662 }
663
664 \f
665 /* :otf property handling.
666 Since the necessary Uniscribe APIs for getting font tag information
667 are only available in Vista, we may need to parse the font data directly
668 according to the OpenType Specification. */
669
670 /* Push into DWORD backwards to cope with endianness. */
671 #define OTF_TAG(STR) \
672 ((STR[3] << 24) | (STR[2] << 16) | (STR[1] << 8) | STR[0])
673
674 #define OTF_INT16_VAL(TABLE, OFFSET, PTR) \
675 do { \
676 BYTE temp, data[2]; \
677 if (GetFontData (context, TABLE, OFFSET, data, 2) != 2) \
678 goto font_table_error; \
679 temp = data[0], data[0] = data[1], data[1] = temp; \
680 memcpy (PTR, data, 2); \
681 } while (0)
682
683 /* Do not reverse the bytes, because we will compare with a OTF_TAG value
684 that has them reversed already. */
685 #define OTF_DWORDTAG_VAL(TABLE, OFFSET, PTR) \
686 do { \
687 if (GetFontData (context, TABLE, OFFSET, PTR, 4) != 4) \
688 goto font_table_error; \
689 } while (0)
690
691 #define OTF_TAG_VAL(TABLE, OFFSET, STR) \
692 do { \
693 if (GetFontData (context, TABLE, OFFSET, STR, 4) != 4) \
694 goto font_table_error; \
695 STR[4] = '\0'; \
696 } while (0)
697
698 #define SNAME(VAL) SSDATA (SYMBOL_NAME (VAL))
699
700 /* Uniscribe APIs available only since Windows Vista. */
701 typedef HRESULT (WINAPI *ScriptGetFontScriptTags_Proc)
702 (HDC, SCRIPT_CACHE *, SCRIPT_ANALYSIS *, int, OPENTYPE_TAG *, int *);
703
704 typedef HRESULT (WINAPI *ScriptGetFontLanguageTags_Proc)
705 (HDC, SCRIPT_CACHE *, SCRIPT_ANALYSIS *, OPENTYPE_TAG, int, OPENTYPE_TAG *, int *);
706
707 typedef HRESULT (WINAPI *ScriptGetFontFeatureTags_Proc)
708 (HDC, SCRIPT_CACHE *, SCRIPT_ANALYSIS *, OPENTYPE_TAG, OPENTYPE_TAG, int, OPENTYPE_TAG *, int *);
709
710 ScriptGetFontScriptTags_Proc script_get_font_scripts_fn;
711 ScriptGetFontLanguageTags_Proc script_get_font_languages_fn;
712 ScriptGetFontFeatureTags_Proc script_get_font_features_fn;
713
714 static bool uniscribe_new_apis;
715
716 /* Verify that all the required features in FEATURES, each of whose
717 elements is a list or nil, can be found among the N feature tags in
718 FTAGS. Return 'true' if the required features are supported,
719 'false' if not. Each list in FEATURES can include an element of
720 nil, which means all the elements after it must not be in FTAGS. */
721 static bool
722 uniscribe_check_features (Lisp_Object features[2], OPENTYPE_TAG *ftags, int n)
723 {
724 int j;
725
726 for (j = 0; j < 2; j++)
727 {
728 bool negative = false;
729 Lisp_Object rest;
730
731 for (rest = features[j]; CONSP (rest); rest = XCDR (rest))
732 {
733 Lisp_Object feature = XCAR (rest);
734
735 /* The font must NOT have any of the features after nil.
736 See the doc string of 'font-spec', under ':otf'. */
737 if (NILP (feature))
738 negative = true;
739 else
740 {
741 OPENTYPE_TAG feature_tag = OTF_TAG (SNAME (feature));
742 int i;
743
744 for (i = 0; i < n; i++)
745 {
746 if (ftags[i] == feature_tag)
747 {
748 /* Test fails if we find a feature that the font
749 must NOT have. */
750 if (negative)
751 return false;
752 break;
753 }
754 }
755
756 /* Test fails if we do NOT find a feature that the font
757 should have. */
758 if (i >= n && !negative)
759 return false;
760 }
761 }
762 }
763
764 return true;
765 }
766
767 /* Check if font supports the required OTF script/language/features
768 using the Unsicribe APIs available since Windows Vista. We prefer
769 these APIs as a kind of future-proofing Emacs: they seem to
770 retrieve script tags that the old code (and also libotf) doesn't
771 seem to be able to get, e.g., some fonts that claim support for
772 "dev2" script don't show "deva", but the new APIs do report it. */
773 static int
774 uniscribe_check_otf_1 (HDC context, Lisp_Object script, Lisp_Object lang,
775 Lisp_Object features[2], int *retval)
776 {
777 SCRIPT_CACHE cache = NULL;
778 OPENTYPE_TAG tags[32], script_tag, lang_tag;
779 int max_tags = ARRAYELTS (tags);
780 int ntags, i, ret = 0;
781 HRESULT rslt;
782 Lisp_Object rest;
783
784 *retval = 0;
785
786 rslt = script_get_font_scripts_fn (context, &cache, NULL, max_tags,
787 tags, &ntags);
788 if (FAILED (rslt))
789 {
790 DebPrint (("ScriptGetFontScriptTags failed with 0x%x\n", rslt));
791 ret = -1;
792 goto no_support;
793 }
794 if (NILP (script))
795 script_tag = OTF_TAG ("DFLT");
796 else
797 script_tag = OTF_TAG (SNAME (script));
798 for (i = 0; i < ntags; i++)
799 if (tags[i] == script_tag)
800 break;
801
802 if (i >= ntags)
803 goto no_support;
804
805 if (NILP (lang))
806 lang_tag = OTF_TAG ("dflt");
807 else
808 {
809 rslt = script_get_font_languages_fn (context, &cache, NULL, script_tag,
810 max_tags, tags, &ntags);
811 if (FAILED (rslt))
812 {
813 DebPrint (("ScriptGetFontLanguageTags failed with 0x%x\n", rslt));
814 ret = -1;
815 goto no_support;
816 }
817 if (ntags == 0)
818 lang_tag = OTF_TAG ("dflt");
819 else
820 {
821 lang_tag = OTF_TAG (SNAME (lang));
822 for (i = 0; i < ntags; i++)
823 if (tags[i] == lang_tag)
824 break;
825
826 if (i >= ntags)
827 goto no_support;
828 }
829 }
830
831 if (!NILP (features[0]))
832 {
833 /* Are the 2 feature lists valid? */
834 if (!CONSP (features[0])
835 || (!NILP (features[1]) && !CONSP (features[1])))
836 goto no_support;
837 rslt = script_get_font_features_fn (context, &cache, NULL,
838 script_tag, lang_tag,
839 max_tags, tags, &ntags);
840 if (FAILED (rslt))
841 {
842 DebPrint (("ScriptGetFontFeatureTags failed with 0x%x\n", rslt));
843 ret = -1;
844 goto no_support;
845 }
846
847 /* ScriptGetFontFeatureTags doesn't let us query features
848 separately for GSUB and GPOS, so we check them all together.
849 It doesn't really matter, since the features in GSUB and GPOS
850 are disjoint, i.e. no feature can appear in both tables. */
851 if (!uniscribe_check_features (features, tags, ntags))
852 goto no_support;
853 }
854
855 ret = 1;
856 *retval = 1;
857
858 no_support:
859 if (cache)
860 ScriptFreeCache (&cache);
861 return ret;
862 }
863
864 /* Check if font supports the otf script/language/features specified.
865 OTF_SPEC is in the format
866 (script lang [(gsub_feature ...)|nil] [(gpos_feature ...)]?) */
867 int
868 uniscribe_check_otf (LOGFONT *font, Lisp_Object otf_spec)
869 {
870 Lisp_Object script, lang, rest;
871 Lisp_Object features[2];
872 DWORD feature_tables[2];
873 DWORD script_tag, default_script, lang_tag = 0;
874 struct frame * f;
875 HDC context;
876 HFONT check_font, old_font;
877 int i, retval = 0;
878 struct gcpro gcpro1;
879
880 /* Check the spec is in the right format. */
881 if (!CONSP (otf_spec) || XINT (Flength (otf_spec)) < 3)
882 return 0;
883
884 /* Break otf_spec into its components. */
885 script = XCAR (otf_spec);
886 rest = XCDR (otf_spec);
887
888 lang = XCAR (rest);
889 rest = XCDR (rest);
890
891 features[0] = XCAR (rest);
892 rest = XCDR (rest);
893 if (NILP (rest))
894 features[1] = Qnil;
895 else
896 features[1] = XCAR (rest);
897
898 /* Set up graphics context so we can use the font. */
899 f = XFRAME (selected_frame);
900 context = get_frame_dc (f);
901 check_font = CreateFontIndirect (font);
902 old_font = SelectObject (context, check_font);
903
904 /* If we are on Vista or later, use the new APIs. */
905 if (uniscribe_new_apis
906 && !w32_disable_new_uniscribe_apis
907 && uniscribe_check_otf_1 (context, script, lang, features, &retval) != -1)
908 goto done;
909
910 /* Set up tags we will use in the search. */
911 feature_tables[0] = OTF_TAG ("GSUB");
912 feature_tables[1] = OTF_TAG ("GPOS");
913 default_script = OTF_TAG ("DFLT");
914 if (NILP (script))
915 script_tag = default_script;
916 else
917 script_tag = OTF_TAG (SNAME (script));
918 if (!NILP (lang))
919 lang_tag = OTF_TAG (SNAME (lang));
920
921 /* Everything else is contained within otf_spec so should get
922 marked along with it. */
923 GCPRO1 (otf_spec);
924
925 /* Scan GSUB and GPOS tables. */
926 for (i = 0; i < 2; i++)
927 {
928 int j, n_match_features;
929 unsigned short scriptlist_table, feature_table, n_scripts;
930 unsigned short script_table, langsys_table, n_langs;
931 unsigned short feature_index, n_features;
932 DWORD tbl = feature_tables[i];
933 DWORD feature_id, *ftags;
934 Lisp_Object farray[2];
935
936 /* Skip if no features requested from this table. */
937 if (NILP (features[i]))
938 continue;
939
940 /* If features is not a cons, this font spec is messed up. */
941 if (!CONSP (features[i]))
942 goto no_support;
943
944 /* Read GPOS/GSUB header. */
945 OTF_INT16_VAL (tbl, 4, &scriptlist_table);
946 OTF_INT16_VAL (tbl, 6, &feature_table);
947 OTF_INT16_VAL (tbl, scriptlist_table, &n_scripts);
948
949 /* Find the appropriate script table. */
950 script_table = 0;
951 for (j = 0; j < n_scripts; j++)
952 {
953 DWORD script_id;
954 OTF_DWORDTAG_VAL (tbl, scriptlist_table + 2 + j * 6, &script_id);
955 if (script_id == script_tag)
956 {
957 OTF_INT16_VAL (tbl, scriptlist_table + 6 + j * 6, &script_table);
958 break;
959 }
960 #if 0 /* Causes false positives. */
961 /* If there is a DFLT script defined in the font, use it
962 if the specified script is not found. */
963 else if (script_id == default_script)
964 OTF_INT16_VAL (tbl, scriptlist_table + 6 + j * 6, &script_table);
965 #endif
966 }
967 /* If no specific or default script table was found, then this font
968 does not support the script. */
969 if (!script_table)
970 goto no_support;
971
972 /* Offset is from beginning of scriptlist_table. */
973 script_table += scriptlist_table;
974
975 /* Get default langsys table. */
976 OTF_INT16_VAL (tbl, script_table, &langsys_table);
977
978 /* If lang was specified, see if font contains a specific entry. */
979 if (!NILP (lang))
980 {
981 OTF_INT16_VAL (tbl, script_table + 2, &n_langs);
982
983 for (j = 0; j < n_langs; j++)
984 {
985 DWORD lang_id;
986 OTF_DWORDTAG_VAL (tbl, script_table + 4 + j * 6, &lang_id);
987 if (lang_id == lang_tag)
988 {
989 OTF_INT16_VAL (tbl, script_table + 8 + j * 6, &langsys_table);
990 break;
991 }
992 }
993 }
994
995 if (!langsys_table)
996 goto no_support;
997
998 /* Offset is from beginning of script table. */
999 langsys_table += script_table;
1000
1001 /* If there are no features to check, skip checking. */
1002 if (NILP (features[i]))
1003 continue;
1004 if (!CONSP (features[i]))
1005 goto no_support;
1006
1007 n_match_features = 0;
1008
1009 /* First get required feature (if any). */
1010 OTF_INT16_VAL (tbl, langsys_table + 2, &feature_index);
1011 if (feature_index != 0xFFFF)
1012 n_match_features = 1;
1013 OTF_INT16_VAL (tbl, langsys_table + 4, &n_features);
1014 n_match_features += n_features;
1015 USE_SAFE_ALLOCA;
1016 SAFE_NALLOCA (ftags, 1, n_match_features);
1017 int k = 0;
1018 if (feature_index != 0xFFFF)
1019 {
1020 OTF_DWORDTAG_VAL (tbl, feature_table + 2 + feature_index * 6,
1021 &feature_id);
1022 ftags[k++] = feature_id;
1023 }
1024 /* Now get all the other features. */
1025 for (j = 0; j < n_features; j++)
1026 {
1027 OTF_INT16_VAL (tbl, langsys_table + 6 + j * 2, &feature_index);
1028 OTF_DWORDTAG_VAL (tbl, feature_table + 2 + feature_index * 6,
1029 &feature_id);
1030 ftags[k++] = feature_id;
1031 }
1032
1033 /* Check the features for this table. */
1034 farray[0] = features[i];
1035 farray[1] = Qnil;
1036 if (!uniscribe_check_features (farray, ftags, n_match_features))
1037 goto no_support;
1038 SAFE_FREE ();
1039 }
1040
1041 retval = 1;
1042
1043 done:
1044 no_support:
1045 font_table_error:
1046 /* restore graphics context. */
1047 SelectObject (context, old_font);
1048 DeleteObject (check_font);
1049 release_frame_dc (f, context);
1050
1051 return retval;
1052 }
1053
1054 static Lisp_Object
1055 otf_features (HDC context, char *table)
1056 {
1057 Lisp_Object script_list = Qnil;
1058 unsigned short scriptlist_table, n_scripts, feature_table;
1059 DWORD tbl = OTF_TAG (table);
1060 int i, j, k;
1061
1062 /* Look for scripts in the table. */
1063 OTF_INT16_VAL (tbl, 4, &scriptlist_table);
1064 OTF_INT16_VAL (tbl, 6, &feature_table);
1065 OTF_INT16_VAL (tbl, scriptlist_table, &n_scripts);
1066
1067 for (i = n_scripts - 1; i >= 0; i--)
1068 {
1069 char script[5], lang[5];
1070 unsigned short script_table, lang_count, langsys_table, feature_count;
1071 Lisp_Object script_tag, langsys_list, langsys_tag, feature_list;
1072 unsigned short record_offset = scriptlist_table + 2 + i * 6;
1073 OTF_TAG_VAL (tbl, record_offset, script);
1074 OTF_INT16_VAL (tbl, record_offset + 4, &script_table);
1075
1076 /* Offset is from beginning of script table. */
1077 script_table += scriptlist_table;
1078
1079 script_tag = intern (script);
1080 langsys_list = Qnil;
1081
1082 /* Optional default lang. */
1083 OTF_INT16_VAL (tbl, script_table, &langsys_table);
1084 if (langsys_table)
1085 {
1086 /* Offset is from beginning of script table. */
1087 langsys_table += script_table;
1088
1089 langsys_tag = Qnil;
1090 feature_list = Qnil;
1091 OTF_INT16_VAL (tbl, langsys_table + 4, &feature_count);
1092 for (k = feature_count - 1; k >= 0; k--)
1093 {
1094 char feature[5];
1095 unsigned short index;
1096 OTF_INT16_VAL (tbl, langsys_table + 6 + k * 2, &index);
1097 OTF_TAG_VAL (tbl, feature_table + 2 + index * 6, feature);
1098 feature_list = Fcons (intern (feature), feature_list);
1099 }
1100 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1101 langsys_list);
1102 }
1103
1104 /* List of supported languages. */
1105 OTF_INT16_VAL (tbl, script_table + 2, &lang_count);
1106
1107 for (j = lang_count - 1; j >= 0; j--)
1108 {
1109 record_offset = script_table + 4 + j * 6;
1110 OTF_TAG_VAL (tbl, record_offset, lang);
1111 OTF_INT16_VAL (tbl, record_offset + 4, &langsys_table);
1112
1113 /* Offset is from beginning of script table. */
1114 langsys_table += script_table;
1115
1116 langsys_tag = intern (lang);
1117 feature_list = Qnil;
1118 OTF_INT16_VAL (tbl, langsys_table + 4, &feature_count);
1119 for (k = feature_count - 1; k >= 0; k--)
1120 {
1121 char feature[5];
1122 unsigned short index;
1123 OTF_INT16_VAL (tbl, langsys_table + 6 + k * 2, &index);
1124 OTF_TAG_VAL (tbl, feature_table + 2 + index * 6, feature);
1125 feature_list = Fcons (intern (feature), feature_list);
1126 }
1127 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1128 langsys_list);
1129
1130 }
1131
1132 script_list = Fcons (Fcons (script_tag, langsys_list), script_list);
1133 }
1134
1135 return script_list;
1136
1137 font_table_error:
1138 return Qnil;
1139 }
1140
1141 #undef OTF_INT16_VAL
1142 #undef OTF_TAG_VAL
1143 #undef OTF_TAG
1144
1145 \f
1146 struct font_driver uniscribe_font_driver =
1147 {
1148 LISP_INITIALLY_ZERO, /* Quniscribe */
1149 0, /* case insensitive */
1150 w32font_get_cache,
1151 uniscribe_list,
1152 uniscribe_match,
1153 uniscribe_list_family,
1154 NULL, /* free_entity */
1155 uniscribe_open,
1156 uniscribe_close,
1157 NULL, /* prepare_face */
1158 NULL, /* done_face */
1159 w32font_has_char,
1160 uniscribe_encode_char,
1161 w32font_text_extents,
1162 w32font_draw,
1163 NULL, /* get_bitmap */
1164 NULL, /* free_bitmap */
1165 NULL, /* anchor_point */
1166 uniscribe_otf_capability, /* Defined so (font-get FONTOBJ :otf) works. */
1167 NULL, /* otf_drive - use shape instead. */
1168 NULL, /* start_for_frame */
1169 NULL, /* end_for_frame */
1170 uniscribe_shape,
1171 NULL, /* check */
1172 NULL, /* get_variation_glyphs */
1173 NULL, /* filter_properties */
1174 NULL, /* cached_font_ok */
1175 };
1176
1177 /* Note that this should be called at every startup, not just when dumping,
1178 as it needs to test for the existence of the Uniscribe library. */
1179 void
1180 syms_of_w32uniscribe (void)
1181 {
1182 HMODULE uniscribe;
1183
1184 /* Don't init uniscribe when dumping */
1185 if (!initialized)
1186 return;
1187
1188 /* Don't register if uniscribe is not available. */
1189 uniscribe = GetModuleHandle ("usp10");
1190 if (!uniscribe)
1191 return;
1192
1193 uniscribe_font_driver.type = Quniscribe;
1194 uniscribe_available = 1;
1195
1196 register_font_driver (&uniscribe_font_driver, NULL);
1197
1198 script_get_font_scripts_fn = (ScriptGetFontScriptTags_Proc)
1199 GetProcAddress (uniscribe, "ScriptGetFontScriptTags");
1200 script_get_font_languages_fn = (ScriptGetFontLanguageTags_Proc)
1201 GetProcAddress (uniscribe, "ScriptGetFontLanguageTags");
1202 script_get_font_features_fn = (ScriptGetFontFeatureTags_Proc)
1203 GetProcAddress (uniscribe, "ScriptGetFontFeatureTags");
1204 if (script_get_font_scripts_fn
1205 && script_get_font_languages_fn
1206 && script_get_font_features_fn)
1207 uniscribe_new_apis = true;
1208 else
1209 uniscribe_new_apis = false;
1210 }