1 /* Font backend for the Microsoft W32 Uniscribe API.
2 Copyright (C) 2008-2015 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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.
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.
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/>. */
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
29 #define _WIN32_WINNT 0x0600
36 #include "dispextern.h"
37 #include "character.h"
39 #include "composite.h"
44 struct uniscribe_font_info
46 struct w32font_info w32_font
;
50 int uniscribe_available
= 0;
52 /* EnumFontFamiliesEx callback. */
53 static int CALLBACK ALIGN_STACK
add_opentype_font_name_to_list (ENUMLOGFONTEX
*,
56 /* Used by uniscribe_otf_capability. */
57 static Lisp_Object
otf_features (HDC context
, char *table
);
60 memq_no_quit (Lisp_Object elt
, Lisp_Object list
)
62 while (CONSP (list
) && ! EQ (XCAR (list
), elt
))
64 return (CONSP (list
));
68 /* Font backend interface implementation. */
70 uniscribe_list (struct frame
*f
, Lisp_Object font_spec
)
72 Lisp_Object fonts
= w32font_list_internal (f
, font_spec
, true);
73 FONT_ADD_LOG ("uniscribe-list", font_spec
, fonts
);
78 uniscribe_match (struct frame
*f
, Lisp_Object font_spec
)
80 Lisp_Object entity
= w32font_match_internal (f
, font_spec
, true);
81 FONT_ADD_LOG ("uniscribe-match", font_spec
, entity
);
86 uniscribe_list_family (struct frame
*f
)
88 Lisp_Object list
= Qnil
;
89 LOGFONT font_match_pattern
;
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
;
96 dc
= get_frame_dc (f
);
98 EnumFontFamiliesEx (dc
, &font_match_pattern
,
99 (FONTENUMPROC
) add_opentype_font_name_to_list
,
101 release_frame_dc (f
, dc
);
107 uniscribe_open (struct frame
*f
, Lisp_Object font_entity
, int pixel_size
)
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
);
115 ASET (font_object
, FONT_TYPE_INDEX
, Quniscribe
);
117 if (!w32font_open_internal (f
, font_entity
, pixel_size
, font_object
))
122 /* Initialize the cache for this font. */
123 uniscribe_font
->cache
= NULL
;
125 /* Uniscribe backend uses glyph indices. */
126 uniscribe_font
->w32_font
.glyph_idx
= ETO_GLYPH_INDEX
;
128 uniscribe_font
->w32_font
.font
.driver
= &uniscribe_font_driver
;
134 uniscribe_close (struct font
*font
)
136 struct uniscribe_font_info
*uniscribe_font
137 = (struct uniscribe_font_info
*) font
;
139 if (uniscribe_font
->cache
)
140 ScriptFreeCache (&(uniscribe_font
->cache
));
142 w32font_close (font
);
145 /* Return a list describing which scripts/languages FONT supports by
146 which GSUB/GPOS features of OpenType tables.
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. */
167 uniscribe_otf_capability (struct font
*font
)
172 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
173 Lisp_Object features
;
175 f
= XFRAME (selected_frame
);
176 context
= get_frame_dc (f
);
177 old_font
= SelectObject (context
, FONT_HANDLE (font
));
179 features
= otf_features (context
, "GSUB");
180 XSETCAR (capability
, features
);
181 features
= otf_features (context
, "GPOS");
182 XSETCDR (capability
, features
);
184 SelectObject (context
, old_font
);
185 release_frame_dc (f
, context
);
190 /* Uniscribe implementation of shape for font backend.
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.
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. */
205 uniscribe_shape (Lisp_Object lgstring
)
207 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
208 struct uniscribe_font_info
*uniscribe_font
209 = (struct uniscribe_font_info
*) font
;
211 int nitems
, max_items
, i
, max_glyphs
, done_glyphs
;
213 WORD
*glyphs
, *clusters
;
215 SCRIPT_VISATTR
*attributes
;
220 struct frame
* f
= NULL
;
222 HFONT old_font
= NULL
;
224 /* Get the chars from lgstring in a form we can use with uniscribe. */
225 max_glyphs
= nchars
= LGSTRING_GLYPH_LEN (lgstring
);
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
231 for (i
= 0; i
< nchars
; i
++)
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
)))
239 chars
[i
] = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring
, i
));
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. */
245 items
= xmalloc (sizeof (SCRIPT_ITEM
) * max_items
+ 1);
247 while ((result
= ScriptItemize (chars
, nchars
, max_items
, NULL
, NULL
,
248 items
, &nitems
)) == E_OUTOFMEMORY
)
250 /* If that wasn't enough, keep trying with one more run. */
252 items
= (SCRIPT_ITEM
*) xrealloc (items
,
253 sizeof (SCRIPT_ITEM
) * max_items
+ 1);
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
));
268 for (i
= 0; i
< nitems
; i
++)
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
275 items
[i
].a
.fLogicalOrder
= 1;
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
);
284 if (result
== E_PENDING
&& !context
)
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
289 f
= XFRAME (selected_frame
);
290 context
= get_frame_dc (f
);
291 old_font
= SelectObject (context
, FONT_HANDLE (font
));
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
);
299 if (result
== E_OUTOFMEMORY
)
301 /* Need a bigger lgstring. */
305 else if (FAILED (result
))
307 /* Can't shape this run - return results so far if any. */
310 else if (items
[i
].a
.fNoGlyphIndex
)
312 /* Glyph indices not supported by this font (or OS), means we
313 can't really do any meaningful shaping. */
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
)
323 /* Cache not complete... */
324 f
= XFRAME (selected_frame
);
325 context
= get_frame_dc (f
);
326 old_font
= SelectObject (context
, FONT_HANDLE (font
));
328 result
= ScriptPlace (context
, &(uniscribe_font
->cache
),
329 glyphs
, nglyphs
, attributes
, &(items
[i
].a
),
330 advances
, offsets
, &overall_metrics
);
332 if (SUCCEEDED (result
))
334 int j
, from
, to
, adj_offset
= 0;
339 for (j
= 0; j
< nglyphs
; j
++)
341 int lglyph_index
= j
+ done_glyphs
;
342 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, lglyph_index
);
348 lglyph
= LGLYPH_NEW ();
349 LGSTRING_SET_GLYPH (lgstring
, lglyph_index
, lglyph
);
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. */
355 LGLYPH_SET_CODE (lglyph
, gl
);
357 /* Detect clusters, for linking codes back to
359 if (attributes
[j
].fClusterStart
)
361 while (from
< nchars_in_run
&& clusters
[from
] < j
)
363 if (from
>= nchars_in_run
)
364 from
= to
= nchars_in_run
- 1;
368 to
= nchars_in_run
- 1;
369 for (k
= from
+ 1; k
< nchars_in_run
; k
++)
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
398 while (j1
< nglyphs
&& !attributes
[j1
].fClusterStart
)
400 adj_offset
+= advances
[j1
];
406 LGLYPH_SET_CHAR (lglyph
, chars
[items
[i
].iCharPos
408 LGLYPH_SET_FROM (lglyph
, items
[i
].iCharPos
+ from
);
409 LGLYPH_SET_TO (lglyph
, items
[i
].iCharPos
+ to
);
412 LGLYPH_SET_WIDTH (lglyph
, advances
[j
]);
413 LGLYPH_SET_ASCENT (lglyph
, font
->ascent
);
414 LGLYPH_SET_DESCENT (lglyph
, font
->descent
);
416 result
= ScriptGetGlyphABCWidth (context
,
417 &(uniscribe_font
->cache
),
418 glyphs
[j
], &char_metric
);
419 if (result
== E_PENDING
&& !context
)
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
);
430 if (SUCCEEDED (result
))
432 int lbearing
= char_metric
.abcA
;
433 int rbearing
= char_metric
.abcA
+ char_metric
.abcB
;
435 LGLYPH_SET_LBEARING (lglyph
, lbearing
);
436 LGLYPH_SET_RBEARING (lglyph
, rbearing
);
440 LGLYPH_SET_LBEARING (lglyph
, 0);
441 LGLYPH_SET_RBEARING (lglyph
, advances
[j
]);
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
448 || (!attributes
[j
].fClusterStart
&& items
[i
].a
.fRTL
))
450 Lisp_Object vec
= make_uninit_vector (3);
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
462 /* Update the adjustment value for the width
463 advance of the glyph we just emitted. */
464 adj_offset
-= 2 * advances
[j
];
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
);
479 LGLYPH_SET_ADJUSTMENT (lglyph
, Qnil
);
480 /* Update the adjustment value to compensate for
481 the width of the base character. */
483 adj_offset
-= advances
[j
];
488 done_glyphs
+= nglyphs
;
495 SelectObject (context
, old_font
);
496 release_frame_dc (f
, context
);
502 return make_number (done_glyphs
);
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. */
509 uniscribe_encode_char (struct font
*font
, int c
)
512 struct frame
*f
= NULL
;
513 HFONT old_font
= NULL
;
514 unsigned code
= FONT_INVALID_CODE
;
519 struct uniscribe_font_info
*uniscribe_font
520 = (struct uniscribe_font_info
*)font
;
529 DWORD surrogate
= c
- 0x10000;
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);
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. */
543 items
= (SCRIPT_ITEM
*) alloca (sizeof (SCRIPT_ITEM
) * 2 + 1);
544 if (SUCCEEDED (ScriptItemize (ch
, len
, 2, NULL
, NULL
, items
, &nitems
)))
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];
555 /* Force ScriptShape to generate glyphs in the logical
557 items
[0].a
.fLogicalOrder
= 1;
559 result
= ScriptShape (context
, &(uniscribe_font
->cache
),
560 ch
, len
, 2, &(items
[0].a
),
561 glyphs
, clusters
, attrs
, &nglyphs
);
563 if (result
== E_PENDING
)
565 /* Use selected frame until API is updated to pass
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
);
575 if (SUCCEEDED (result
) && nglyphs
== 1)
577 /* Some fonts return .notdef glyphs instead of failing.
578 (TrueType spec reserves glyph code 0 for .notdef) */
582 else if (SUCCEEDED (result
) || result
== E_OUTOFMEMORY
)
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
588 result
= ScriptGetCMap (context
, &(uniscribe_font
->cache
),
590 if (SUCCEEDED (result
) && glyphs
[0])
597 SelectObject (context
, old_font
);
598 release_frame_dc (f
, context
);
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);
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);
628 /* Callback function for EnumFontFamiliesEx.
629 Adds the name of opentype fonts to a Lisp list (passed in as the
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
)
636 Lisp_Object
* list
= (Lisp_Object
*) list_object
;
639 /* Skip vertical fonts (intended only for printing) */
640 if (logical_font
->elfLogFont
.lfFaceName
[0] == '@')
643 /* Skip non opentype fonts. Count old truetype fonts as opentype,
644 as some of them do contain GPOS and GSUB data that Uniscribe
646 if (!(physical_font
->ntmTm
.ntmFlags
& NTMFLAGS_OPENTYPE
)
647 && font_type
!= TRUETYPE_FONTTYPE
)
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))
657 family
= intern_font_name (logical_font
->elfLogFont
.lfFaceName
);
658 if (! memq_no_quit (family
, *list
))
659 *list
= Fcons (family
, *list
);
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. */
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])
674 #define OTF_INT16_VAL(TABLE, OFFSET, PTR) \
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); \
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) \
687 if (GetFontData (context, TABLE, OFFSET, PTR, 4) != 4) \
688 goto font_table_error; \
691 #define OTF_TAG_VAL(TABLE, OFFSET, STR) \
693 if (GetFontData (context, TABLE, OFFSET, STR, 4) != 4) \
694 goto font_table_error; \
698 #define SNAME(VAL) SSDATA (SYMBOL_NAME (VAL))
700 /* Uniscribe APIs available only since Windows Vista. */
701 typedef HRESULT (WINAPI
*ScriptGetFontScriptTags_Proc
)
702 (HDC
, SCRIPT_CACHE
*, SCRIPT_ANALYSIS
*, int, OPENTYPE_TAG
*, int *);
704 typedef HRESULT (WINAPI
*ScriptGetFontLanguageTags_Proc
)
705 (HDC
, SCRIPT_CACHE
*, SCRIPT_ANALYSIS
*, OPENTYPE_TAG
, int, OPENTYPE_TAG
*, int *);
707 typedef HRESULT (WINAPI
*ScriptGetFontFeatureTags_Proc
)
708 (HDC
, SCRIPT_CACHE
*, SCRIPT_ANALYSIS
*, OPENTYPE_TAG
, OPENTYPE_TAG
, int, OPENTYPE_TAG
*, int *);
710 ScriptGetFontScriptTags_Proc script_get_font_scripts_fn
;
711 ScriptGetFontLanguageTags_Proc script_get_font_languages_fn
;
712 ScriptGetFontFeatureTags_Proc script_get_font_features_fn
;
714 static bool uniscribe_new_apis
;
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. */
722 uniscribe_check_features (Lisp_Object features
[2], OPENTYPE_TAG
*ftags
, int n
)
726 for (j
= 0; j
< 2; j
++)
728 bool negative
= false;
731 for (rest
= features
[j
]; CONSP (rest
); rest
= XCDR (rest
))
733 Lisp_Object feature
= XCAR (rest
);
735 /* The font must NOT have any of the features after nil.
736 See the doc string of 'font-spec', under ':otf'. */
741 OPENTYPE_TAG feature_tag
= OTF_TAG (SNAME (feature
));
744 for (i
= 0; i
< n
; i
++)
746 if (ftags
[i
] == feature_tag
)
748 /* Test fails if we find a feature that the font
756 /* Test fails if we do NOT find a feature that the font
758 if (i
>= n
&& !negative
)
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. */
774 uniscribe_check_otf_1 (HDC context
, Lisp_Object script
, Lisp_Object lang
,
775 Lisp_Object features
[2], int *retval
)
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;
786 rslt
= script_get_font_scripts_fn (context
, &cache
, NULL
, max_tags
,
790 DebPrint (("ScriptGetFontScriptTags failed with 0x%x\n", rslt
));
795 script_tag
= OTF_TAG ("DFLT");
797 script_tag
= OTF_TAG (SNAME (script
));
798 for (i
= 0; i
< ntags
; i
++)
799 if (tags
[i
] == script_tag
)
806 lang_tag
= OTF_TAG ("dflt");
809 rslt
= script_get_font_languages_fn (context
, &cache
, NULL
, script_tag
,
810 max_tags
, tags
, &ntags
);
813 DebPrint (("ScriptGetFontLanguageTags failed with 0x%x\n", rslt
));
818 lang_tag
= OTF_TAG ("dflt");
821 lang_tag
= OTF_TAG (SNAME (lang
));
822 for (i
= 0; i
< ntags
; i
++)
823 if (tags
[i
] == lang_tag
)
831 if (!NILP (features
[0]))
833 /* Are the 2 feature lists valid? */
834 if (!CONSP (features
[0])
835 || (!NILP (features
[1]) && !CONSP (features
[1])))
837 rslt
= script_get_font_features_fn (context
, &cache
, NULL
,
838 script_tag
, lang_tag
,
839 max_tags
, tags
, &ntags
);
842 DebPrint (("ScriptGetFontFeatureTags failed with 0x%x\n", rslt
));
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
))
860 ScriptFreeCache (&cache
);
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 ...)]?) */
868 uniscribe_check_otf (LOGFONT
*font
, Lisp_Object otf_spec
)
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;
876 HFONT check_font
, old_font
;
879 /* Check the spec is in the right format. */
880 if (!CONSP (otf_spec
) || XINT (Flength (otf_spec
)) < 3)
883 /* Break otf_spec into its components. */
884 script
= XCAR (otf_spec
);
885 rest
= XCDR (otf_spec
);
890 features
[0] = XCAR (rest
);
895 features
[1] = XCAR (rest
);
897 /* Set up graphics context so we can use the font. */
898 f
= XFRAME (selected_frame
);
899 context
= get_frame_dc (f
);
900 check_font
= CreateFontIndirect (font
);
901 old_font
= SelectObject (context
, check_font
);
903 /* If we are on Vista or later, use the new APIs. */
904 if (uniscribe_new_apis
905 && !w32_disable_new_uniscribe_apis
906 && uniscribe_check_otf_1 (context
, script
, lang
, features
, &retval
) != -1)
909 /* Set up tags we will use in the search. */
910 feature_tables
[0] = OTF_TAG ("GSUB");
911 feature_tables
[1] = OTF_TAG ("GPOS");
912 default_script
= OTF_TAG ("DFLT");
914 script_tag
= default_script
;
916 script_tag
= OTF_TAG (SNAME (script
));
918 lang_tag
= OTF_TAG (SNAME (lang
));
920 /* Scan GSUB and GPOS tables. */
921 for (i
= 0; i
< 2; i
++)
923 int j
, n_match_features
;
924 unsigned short scriptlist_table
, feature_table
, n_scripts
;
925 unsigned short script_table
, langsys_table
, n_langs
;
926 unsigned short feature_index
, n_features
;
927 DWORD tbl
= feature_tables
[i
];
928 DWORD feature_id
, *ftags
;
929 Lisp_Object farray
[2];
931 /* Skip if no features requested from this table. */
932 if (NILP (features
[i
]))
935 /* If features is not a cons, this font spec is messed up. */
936 if (!CONSP (features
[i
]))
939 /* Read GPOS/GSUB header. */
940 OTF_INT16_VAL (tbl
, 4, &scriptlist_table
);
941 OTF_INT16_VAL (tbl
, 6, &feature_table
);
942 OTF_INT16_VAL (tbl
, scriptlist_table
, &n_scripts
);
944 /* Find the appropriate script table. */
946 for (j
= 0; j
< n_scripts
; j
++)
949 OTF_DWORDTAG_VAL (tbl
, scriptlist_table
+ 2 + j
* 6, &script_id
);
950 if (script_id
== script_tag
)
952 OTF_INT16_VAL (tbl
, scriptlist_table
+ 6 + j
* 6, &script_table
);
955 #if 0 /* Causes false positives. */
956 /* If there is a DFLT script defined in the font, use it
957 if the specified script is not found. */
958 else if (script_id
== default_script
)
959 OTF_INT16_VAL (tbl
, scriptlist_table
+ 6 + j
* 6, &script_table
);
962 /* If no specific or default script table was found, then this font
963 does not support the script. */
967 /* Offset is from beginning of scriptlist_table. */
968 script_table
+= scriptlist_table
;
970 /* Get default langsys table. */
971 OTF_INT16_VAL (tbl
, script_table
, &langsys_table
);
973 /* If lang was specified, see if font contains a specific entry. */
976 OTF_INT16_VAL (tbl
, script_table
+ 2, &n_langs
);
978 for (j
= 0; j
< n_langs
; j
++)
981 OTF_DWORDTAG_VAL (tbl
, script_table
+ 4 + j
* 6, &lang_id
);
982 if (lang_id
== lang_tag
)
984 OTF_INT16_VAL (tbl
, script_table
+ 8 + j
* 6, &langsys_table
);
993 /* Offset is from beginning of script table. */
994 langsys_table
+= script_table
;
996 /* If there are no features to check, skip checking. */
997 if (NILP (features
[i
]))
999 if (!CONSP (features
[i
]))
1002 n_match_features
= 0;
1004 /* First get required feature (if any). */
1005 OTF_INT16_VAL (tbl
, langsys_table
+ 2, &feature_index
);
1006 if (feature_index
!= 0xFFFF)
1007 n_match_features
= 1;
1008 OTF_INT16_VAL (tbl
, langsys_table
+ 4, &n_features
);
1009 n_match_features
+= n_features
;
1011 SAFE_NALLOCA (ftags
, 1, n_match_features
);
1013 if (feature_index
!= 0xFFFF)
1015 OTF_DWORDTAG_VAL (tbl
, feature_table
+ 2 + feature_index
* 6,
1017 ftags
[k
++] = feature_id
;
1019 /* Now get all the other features. */
1020 for (j
= 0; j
< n_features
; j
++)
1022 OTF_INT16_VAL (tbl
, langsys_table
+ 6 + j
* 2, &feature_index
);
1023 OTF_DWORDTAG_VAL (tbl
, feature_table
+ 2 + feature_index
* 6,
1025 ftags
[k
++] = feature_id
;
1028 /* Check the features for this table. */
1029 farray
[0] = features
[i
];
1031 if (!uniscribe_check_features (farray
, ftags
, n_match_features
))
1041 /* restore graphics context. */
1042 SelectObject (context
, old_font
);
1043 DeleteObject (check_font
);
1044 release_frame_dc (f
, context
);
1050 otf_features (HDC context
, char *table
)
1052 Lisp_Object script_list
= Qnil
;
1053 unsigned short scriptlist_table
, n_scripts
, feature_table
;
1054 DWORD tbl
= OTF_TAG (table
);
1057 /* Look for scripts in the table. */
1058 OTF_INT16_VAL (tbl
, 4, &scriptlist_table
);
1059 OTF_INT16_VAL (tbl
, 6, &feature_table
);
1060 OTF_INT16_VAL (tbl
, scriptlist_table
, &n_scripts
);
1062 for (i
= n_scripts
- 1; i
>= 0; i
--)
1064 char script
[5], lang
[5];
1065 unsigned short script_table
, lang_count
, langsys_table
, feature_count
;
1066 Lisp_Object script_tag
, langsys_list
, langsys_tag
, feature_list
;
1067 unsigned short record_offset
= scriptlist_table
+ 2 + i
* 6;
1068 OTF_TAG_VAL (tbl
, record_offset
, script
);
1069 OTF_INT16_VAL (tbl
, record_offset
+ 4, &script_table
);
1071 /* Offset is from beginning of script table. */
1072 script_table
+= scriptlist_table
;
1074 script_tag
= intern (script
);
1075 langsys_list
= Qnil
;
1077 /* Optional default lang. */
1078 OTF_INT16_VAL (tbl
, script_table
, &langsys_table
);
1081 /* Offset is from beginning of script table. */
1082 langsys_table
+= script_table
;
1085 feature_list
= Qnil
;
1086 OTF_INT16_VAL (tbl
, langsys_table
+ 4, &feature_count
);
1087 for (k
= feature_count
- 1; k
>= 0; k
--)
1090 unsigned short index
;
1091 OTF_INT16_VAL (tbl
, langsys_table
+ 6 + k
* 2, &index
);
1092 OTF_TAG_VAL (tbl
, feature_table
+ 2 + index
* 6, feature
);
1093 feature_list
= Fcons (intern (feature
), feature_list
);
1095 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
1099 /* List of supported languages. */
1100 OTF_INT16_VAL (tbl
, script_table
+ 2, &lang_count
);
1102 for (j
= lang_count
- 1; j
>= 0; j
--)
1104 record_offset
= script_table
+ 4 + j
* 6;
1105 OTF_TAG_VAL (tbl
, record_offset
, lang
);
1106 OTF_INT16_VAL (tbl
, record_offset
+ 4, &langsys_table
);
1108 /* Offset is from beginning of script table. */
1109 langsys_table
+= script_table
;
1111 langsys_tag
= intern (lang
);
1112 feature_list
= Qnil
;
1113 OTF_INT16_VAL (tbl
, langsys_table
+ 4, &feature_count
);
1114 for (k
= feature_count
- 1; k
>= 0; k
--)
1117 unsigned short index
;
1118 OTF_INT16_VAL (tbl
, langsys_table
+ 6 + k
* 2, &index
);
1119 OTF_TAG_VAL (tbl
, feature_table
+ 2 + index
* 6, feature
);
1120 feature_list
= Fcons (intern (feature
), feature_list
);
1122 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
1127 script_list
= Fcons (Fcons (script_tag
, langsys_list
), script_list
);
1136 #undef OTF_INT16_VAL
1141 struct font_driver uniscribe_font_driver
=
1143 LISP_INITIALLY_ZERO
, /* Quniscribe */
1144 0, /* case insensitive */
1148 uniscribe_list_family
,
1149 NULL
, /* free_entity */
1152 NULL
, /* prepare_face */
1153 NULL
, /* done_face */
1155 uniscribe_encode_char
,
1156 w32font_text_extents
,
1158 NULL
, /* get_bitmap */
1159 NULL
, /* free_bitmap */
1160 NULL
, /* anchor_point */
1161 uniscribe_otf_capability
, /* Defined so (font-get FONTOBJ :otf) works. */
1162 NULL
, /* otf_drive - use shape instead. */
1163 NULL
, /* start_for_frame */
1164 NULL
, /* end_for_frame */
1167 NULL
, /* get_variation_glyphs */
1168 NULL
, /* filter_properties */
1169 NULL
, /* cached_font_ok */
1172 /* Note that this should be called at every startup, not just when dumping,
1173 as it needs to test for the existence of the Uniscribe library. */
1175 syms_of_w32uniscribe (void)
1179 /* Don't init uniscribe when dumping */
1183 /* Don't register if uniscribe is not available. */
1184 uniscribe
= GetModuleHandle ("usp10");
1188 uniscribe_font_driver
.type
= Quniscribe
;
1189 uniscribe_available
= 1;
1191 register_font_driver (&uniscribe_font_driver
, NULL
);
1193 script_get_font_scripts_fn
= (ScriptGetFontScriptTags_Proc
)
1194 GetProcAddress (uniscribe
, "ScriptGetFontScriptTags");
1195 script_get_font_languages_fn
= (ScriptGetFontLanguageTags_Proc
)
1196 GetProcAddress (uniscribe
, "ScriptGetFontLanguageTags");
1197 script_get_font_features_fn
= (ScriptGetFontFeatureTags_Proc
)
1198 GetProcAddress (uniscribe
, "ScriptGetFontFeatureTags");
1199 if (script_get_font_scripts_fn
1200 && script_get_font_languages_fn
1201 && script_get_font_features_fn
)
1202 uniscribe_new_apis
= true;
1204 uniscribe_new_apis
= false;