1 /* Font backend for the Microsoft W32 Uniscribe API.
2 Copyright (C) 2008, 2009 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 since
22 Windows 2000, though most users of older systems will have it
23 since it installs with Internet Explorer 5.0 and other software.
24 We only enable the feature if it is available, so there is no chance
25 of calling non-existant functions. */
27 #define _WIN32_WINNT 0x500
34 #include "dispextern.h"
35 #include "character.h"
37 #include "composite.h"
42 struct uniscribe_font_info
44 struct w32font_info w32_font
;
48 int uniscribe_available
= 0;
50 /* Defined in w32font.c, since it is required there as well. */
51 extern Lisp_Object Quniscribe
;
52 extern Lisp_Object Qopentype
;
54 extern int initialized
;
56 extern struct font_driver uniscribe_font_driver
;
58 /* EnumFontFamiliesEx callback. */
59 static int CALLBACK add_opentype_font_name_to_list
P_ ((ENUMLOGFONTEX
*,
62 /* Used by uniscribe_otf_capability. */
63 static Lisp_Object
otf_features (HDC context
, char *table
);
66 memq_no_quit (elt
, list
)
67 Lisp_Object elt
, list
;
69 while (CONSP (list
) && ! EQ (XCAR (list
), elt
))
71 return (CONSP (list
));
75 /* Font backend interface implementation. */
77 uniscribe_list (frame
, font_spec
)
78 Lisp_Object frame
, font_spec
;
80 Lisp_Object fonts
= w32font_list_internal (frame
, font_spec
, 1);
81 font_add_log ("uniscribe-list", font_spec
, fonts
);
86 uniscribe_match (frame
, font_spec
)
87 Lisp_Object frame
, font_spec
;
89 Lisp_Object entity
= w32font_match_internal (frame
, font_spec
, 1);
90 font_add_log ("uniscribe-match", font_spec
, entity
);
95 uniscribe_list_family (frame
)
98 Lisp_Object list
= Qnil
;
99 LOGFONT font_match_pattern
;
101 FRAME_PTR f
= XFRAME (frame
);
103 bzero (&font_match_pattern
, sizeof (font_match_pattern
));
104 /* Limit enumerated fonts to outline fonts to save time. */
105 font_match_pattern
.lfOutPrecision
= OUT_OUTLINE_PRECIS
;
107 dc
= get_frame_dc (f
);
109 EnumFontFamiliesEx (dc
, &font_match_pattern
,
110 (FONTENUMPROC
) add_opentype_font_name_to_list
,
112 release_frame_dc (f
, dc
);
118 uniscribe_open (f
, font_entity
, pixel_size
)
120 Lisp_Object font_entity
;
123 Lisp_Object font_object
124 = font_make_object (VECSIZE (struct uniscribe_font_info
),
125 font_entity
, pixel_size
);
126 struct uniscribe_font_info
*uniscribe_font
127 = (struct uniscribe_font_info
*) XFONT_OBJECT (font_object
);
129 ASET (font_object
, FONT_TYPE_INDEX
, Quniscribe
);
131 if (!w32font_open_internal (f
, font_entity
, pixel_size
, font_object
))
136 /* Initialize the cache for this font. */
137 uniscribe_font
->cache
= NULL
;
139 /* Uniscribe backend uses glyph indices. */
140 uniscribe_font
->w32_font
.glyph_idx
= ETO_GLYPH_INDEX
;
142 /* Mark the format as opentype */
143 uniscribe_font
->w32_font
.font
.props
[FONT_FORMAT_INDEX
] = Qopentype
;
144 uniscribe_font
->w32_font
.font
.driver
= &uniscribe_font_driver
;
150 uniscribe_close (f
, font
)
154 struct uniscribe_font_info
*uniscribe_font
155 = (struct uniscribe_font_info
*) font
;
157 if (uniscribe_font
->cache
)
158 ScriptFreeCache (&(uniscribe_font
->cache
));
160 w32font_close (f
, font
);
163 /* Return a list describing which scripts/languages FONT supports by
164 which GSUB/GPOS features of OpenType tables. */
166 uniscribe_otf_capability (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 `font-make-gstring'
193 for the format of LGSTRING. If the (N+1)th element of LGSTRING
194 is nil, input of shaping is from the 1st to (N)th elements. In
195 each input glyph, FROM, TO, CHAR, and CODE are already set.
197 This function updates all fields of the input glyphs. If the
198 output glyphs (M) are more than the input glyphs (N), (N+1)th
199 through (M)th elements of LGSTRING are updated possibly by making
200 a new glyph object and storing it in LGSTRING. If (M) is greater
201 than the length of LGSTRING, nil should be return. In that case,
202 this function is called again with the larger LGSTRING. */
204 uniscribe_shape (lgstring
)
205 Lisp_Object lgstring
;
208 struct uniscribe_font_info
* uniscribe_font
;
210 int nitems
, max_items
, i
, max_glyphs
, done_glyphs
;
212 WORD
*glyphs
, *clusters
;
214 SCRIPT_VISATTR
*attributes
;
219 struct frame
* f
= NULL
;
221 HFONT old_font
= NULL
;
223 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
224 uniscribe_font
= (struct uniscribe_font_info
*) font
;
226 /* Get the chars from lgstring in a form we can use with uniscribe. */
227 max_glyphs
= nchars
= LGSTRING_GLYPH_LEN (lgstring
);
229 chars
= (wchar_t *) alloca (nchars
* sizeof (wchar_t));
230 for (i
= 0; i
< nchars
; i
++)
232 /* lgstring can be bigger than the number of characters in it, in
233 the case where more glyphs are required to display those characters.
234 If that is the case, note the real number of characters. */
235 if (NILP (LGSTRING_GLYPH (lgstring
, i
)))
238 chars
[i
] = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring
, i
));
241 /* First we need to break up the glyph string into runs of glyphs that
242 can be treated together. First try a single run. */
244 items
= (SCRIPT_ITEM
*) xmalloc (sizeof (SCRIPT_ITEM
) * max_items
+ 1);
246 while ((result
= ScriptItemize (chars
, nchars
, max_items
, NULL
, NULL
,
247 items
, &nitems
)) == E_OUTOFMEMORY
)
249 /* If that wasn't enough, keep trying with one more run. */
251 items
= (SCRIPT_ITEM
*) xrealloc (items
,
252 sizeof (SCRIPT_ITEM
) * max_items
+ 1);
261 /* TODO: When we get BIDI support, we need to call ScriptLayout here.
262 Requires that we know the surrounding context. */
264 glyphs
= alloca (max_glyphs
* sizeof (WORD
));
265 clusters
= alloca (nchars
* sizeof (WORD
));
266 attributes
= alloca (max_glyphs
* sizeof (SCRIPT_VISATTR
));
267 advances
= alloca (max_glyphs
* sizeof (int));
268 offsets
= alloca (max_glyphs
* sizeof (GOFFSET
));
270 for (i
= 0; i
< nitems
; i
++)
272 int nglyphs
, nchars_in_run
, rtl
= items
[i
].a
.fRTL
? -1 : 1;
273 nchars_in_run
= items
[i
+1].iCharPos
- items
[i
].iCharPos
;
275 /* Context may be NULL here, in which case the cache should be
276 used without needing to select the font. */
277 result
= ScriptShape (context
, &(uniscribe_font
->cache
),
278 chars
+ items
[i
].iCharPos
, nchars_in_run
,
279 max_glyphs
- done_glyphs
, &(items
[i
].a
),
280 glyphs
, clusters
, attributes
, &nglyphs
);
282 if (result
== E_PENDING
&& !context
)
284 /* This assumes the selected frame is on the same display as the
285 one we are drawing. It would be better for the frame to be
287 f
= XFRAME (selected_frame
);
288 context
= get_frame_dc (f
);
289 old_font
= SelectObject (context
, FONT_HANDLE(font
));
291 result
= ScriptShape (context
, &(uniscribe_font
->cache
),
292 chars
+ items
[i
].iCharPos
, nchars_in_run
,
293 max_glyphs
- done_glyphs
, &(items
[i
].a
),
294 glyphs
, clusters
, attributes
, &nglyphs
);
297 if (result
== E_OUTOFMEMORY
)
299 /* Need a bigger lgstring. */
303 else if (FAILED (result
))
305 /* Can't shape this run - return results so far if any. */
308 else if (items
[i
].a
.fNoGlyphIndex
)
310 /* Glyph indices not supported by this font (or OS), means we
311 can't really do any meaningful shaping. */
316 result
= ScriptPlace (context
, &(uniscribe_font
->cache
),
317 glyphs
, nglyphs
, attributes
, &(items
[i
].a
),
318 advances
, offsets
, &overall_metrics
);
319 if (result
== E_PENDING
&& !context
)
321 /* Cache not complete... */
322 f
= XFRAME (selected_frame
);
323 context
= get_frame_dc (f
);
324 old_font
= SelectObject (context
, FONT_HANDLE(font
));
326 result
= ScriptPlace (context
, &(uniscribe_font
->cache
),
327 glyphs
, nglyphs
, attributes
, &(items
[i
].a
),
328 advances
, offsets
, &overall_metrics
);
330 if (SUCCEEDED (result
))
332 int j
, nclusters
, from
, to
;
334 from
= rtl
> 0 ? 0 : nchars_in_run
- 1;
337 for (j
= 0; j
< nglyphs
; j
++)
339 int lglyph_index
= j
+ done_glyphs
;
340 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, lglyph_index
);
346 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
347 LGSTRING_SET_GLYPH (lgstring
, lglyph_index
, lglyph
);
349 /* Copy to a 32-bit data type to shut up the
350 compiler warning in LGLYPH_SET_CODE about
351 comparison being always false. */
353 LGLYPH_SET_CODE (lglyph
, gl
);
355 /* Detect clusters, for linking codes back to characters. */
356 if (attributes
[j
].fClusterStart
)
358 while (from
>= 0 && from
< nchars_in_run
359 && clusters
[from
] < j
)
363 else if (from
>= nchars_in_run
)
364 from
= to
= nchars_in_run
- 1;
368 to
= rtl
> 0 ? nchars_in_run
- 1 : 0;
369 for (k
= from
+ rtl
; k
>= 0 && k
< nchars_in_run
;
381 LGLYPH_SET_CHAR (lglyph
, chars
[items
[i
].iCharPos
383 LGLYPH_SET_FROM (lglyph
, items
[i
].iCharPos
+ from
);
384 LGLYPH_SET_TO (lglyph
, items
[i
].iCharPos
+ to
);
387 LGLYPH_SET_WIDTH (lglyph
, advances
[j
]);
388 LGLYPH_SET_ASCENT (lglyph
, font
->ascent
);
389 LGLYPH_SET_DESCENT (lglyph
, font
->descent
);
391 result
= ScriptGetGlyphABCWidth (context
,
392 &(uniscribe_font
->cache
),
393 glyphs
[j
], &char_metric
);
394 if (result
== E_PENDING
&& !context
)
396 /* Cache incomplete... */
397 f
= XFRAME (selected_frame
);
398 context
= get_frame_dc (f
);
399 old_font
= SelectObject (context
, FONT_HANDLE(font
));
400 result
= ScriptGetGlyphABCWidth (context
,
401 &(uniscribe_font
->cache
),
402 glyphs
[j
], &char_metric
);
405 if (SUCCEEDED (result
))
407 LGLYPH_SET_LBEARING (lglyph
, char_metric
.abcA
);
408 LGLYPH_SET_RBEARING (lglyph
, (char_metric
.abcA
409 + char_metric
.abcB
));
413 LGLYPH_SET_LBEARING (lglyph
, 0);
414 LGLYPH_SET_RBEARING (lglyph
, advances
[j
]);
417 if (offsets
[j
].du
|| offsets
[j
].dv
)
420 vec
= Fmake_vector (make_number (3), Qnil
);
421 ASET (vec
, 0, make_number (offsets
[j
].du
));
422 ASET (vec
, 1, make_number (offsets
[j
].dv
));
423 /* Based on what ftfont.c does... */
424 ASET (vec
, 2, make_number (advances
[j
]));
425 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
428 LGLYPH_SET_ADJUSTMENT (lglyph
, Qnil
);
432 done_glyphs
+= nglyphs
;
439 SelectObject (context
, old_font
);
440 release_frame_dc (f
, context
);
446 return make_number (done_glyphs
);
449 /* Uniscribe implementation of encode_char for font backend.
450 Return a glyph code of FONT for characer C (Unicode code point).
451 If FONT doesn't have such a glyph, return FONT_INVALID_CODE. */
453 uniscribe_encode_char (font
, c
)
458 struct frame
*f
= NULL
;
459 HFONT old_font
= NULL
;
460 unsigned code
= FONT_INVALID_CODE
;
465 struct uniscribe_font_info
*uniscribe_font
466 = (struct uniscribe_font_info
*)font
;
475 DWORD surrogate
= c
- 0x10000;
477 /* High surrogate: U+D800 - U+DBFF. */
478 ch
[0] = 0xD800 + ((surrogate
>> 10) & 0x03FF);
479 /* Low surrogate: U+DC00 - U+DFFF. */
480 ch
[1] = 0xDC00 + (surrogate
& 0x03FF);
484 /* Non BMP characters must be handled by the uniscribe shaping
485 engine as GDI functions (except blindly displaying lines of
486 unicode text) and the promising looking ScriptGetCMap do not
487 convert surrogate pairs to glyph indexes correctly. */
489 items
= (SCRIPT_ITEM
*) alloca (sizeof (SCRIPT_ITEM
) * 2 + 1);
490 if (SUCCEEDED (ScriptItemize (ch
, len
, 2, NULL
, NULL
, items
, &nitems
)))
493 /* Surrogates seem to need 2 here, even though only one glyph is
494 returned. Indic characters can also produce 2 or more glyphs for
495 a single code point, but they need to use uniscribe_shape
496 above for correct display. */
497 WORD glyphs
[2], clusters
[2];
498 SCRIPT_VISATTR attrs
[2];
501 result
= ScriptShape (context
, &(uniscribe_font
->cache
),
502 ch
, len
, 2, &(items
[0].a
),
503 glyphs
, clusters
, attrs
, &nglyphs
);
505 if (result
== E_PENDING
)
507 /* Use selected frame until API is updated to pass
509 f
= XFRAME (selected_frame
);
510 context
= get_frame_dc (f
);
511 old_font
= SelectObject (context
, FONT_HANDLE(font
));
512 result
= ScriptShape (context
, &(uniscribe_font
->cache
),
513 ch
, len
, 2, &(items
[0].a
),
514 glyphs
, clusters
, attrs
, &nglyphs
);
517 if (SUCCEEDED (result
) && nglyphs
== 1)
519 /* Some fonts return .notdef glyphs instead of failing.
520 (Truetype spec reserves glyph code 0 for .notdef) */
524 else if (SUCCEEDED (result
) || result
== E_OUTOFMEMORY
)
526 /* This character produces zero or more than one glyph
527 when shaped. But we still need the return from here
528 to be valid for the shaping engine to be invoked
530 result
= ScriptGetCMap (context
, &(uniscribe_font
->cache
),
532 if (SUCCEEDED (result
) && glyphs
[0])
539 SelectObject (context
, old_font
);
540 release_frame_dc (f
, context
);
548 Lisp_Object uniscribe_get_cache (Lisp_Object frame);
549 void uniscribe_free_entity (Lisp_Object font_entity);
550 int uniscribe_has_char (Lisp_Object entity, int c);
551 int uniscribe_text_extents (struct font *font, unsigned *code,
552 int nglyphs, struct font_metrics *metrics);
553 int uniscribe_draw (struct glyph_string *s, int from, int to,
554 int x, int y, int with_background);
557 int uniscribe_prepare_face (FRAME_PTR f, struct face *face);
558 void uniscribe_done_face (FRAME_PTR f, struct face *face);
559 int uniscribe_get_bitmap (struct font *font, unsigned code,
560 struct font_bitmap *bitmap, int bits_per_pixel);
561 void uniscribe_free_bitmap (struct font *font, struct font_bitmap *bitmap);
562 void * uniscribe_get_outline (struct font *font, unsigned code);
563 void uniscribe_free_outline (struct font *font, void *outline);
564 int uniscribe_anchor_point (struct font *font, unsigned code,
565 int index, int *x, int *y);
566 int uniscribe_start_for_frame (FRAME_PTR f);
567 int uniscribe_end_for_frame (FRAME_PTR f);
572 /* Callback function for EnumFontFamiliesEx.
573 Adds the name of opentype fonts to a Lisp list (passed in as the
576 add_opentype_font_name_to_list (logical_font
, physical_font
, font_type
,
578 ENUMLOGFONTEX
*logical_font
;
579 NEWTEXTMETRICEX
*physical_font
;
583 Lisp_Object
* list
= (Lisp_Object
*) list_object
;
586 /* Skip vertical fonts (intended only for printing) */
587 if (logical_font
->elfLogFont
.lfFaceName
[0] == '@')
590 /* Skip non opentype fonts. Count old truetype fonts as opentype,
591 as some of them do contain GPOS and GSUB data that Uniscribe
593 if (!(physical_font
->ntmTm
.ntmFlags
& NTMFLAGS_OPENTYPE
)
594 && font_type
!= TRUETYPE_FONTTYPE
)
597 /* Skip fonts that have no unicode coverage. */
598 if (!physical_font
->ntmFontSig
.fsUsb
[3]
599 && !physical_font
->ntmFontSig
.fsUsb
[2]
600 && !physical_font
->ntmFontSig
.fsUsb
[1]
601 && !(physical_font
->ntmFontSig
.fsUsb
[0] & 0x3fffffff))
604 family
= intern_font_name (logical_font
->elfLogFont
.lfFaceName
);
605 if (! memq_no_quit (family
, *list
))
606 *list
= Fcons (family
, *list
);
612 /* :otf property handling.
613 Since the necessary Uniscribe APIs for getting font tag information
614 are only available in Vista, we need to parse the font data directly
615 according to the OpenType Specification. */
617 /* Push into DWORD backwards to cope with endianness. */
618 #define OTF_TAG(STR) \
619 ((STR[3] << 24) | (STR[2] << 16) | (STR[1] << 8) | STR[0])
621 #define OTF_INT16_VAL(TABLE, OFFSET, PTR) \
623 BYTE temp, data[2]; \
624 if (GetFontData (context, TABLE, OFFSET, data, 2) != 2) \
625 goto font_table_error; \
626 temp = data[0], data[0] = data[1], data[1] = temp; \
627 memcpy (PTR, data, 2); \
630 /* Do not reverse the bytes, because we will compare with a OTF_TAG value
631 that has them reversed already. */
632 #define OTF_DWORDTAG_VAL(TABLE, OFFSET, PTR) \
634 if (GetFontData (context, TABLE, OFFSET, PTR, 4) != 4) \
635 goto font_table_error; \
638 #define OTF_TAG_VAL(TABLE, OFFSET, STR) \
640 if (GetFontData (context, TABLE, OFFSET, STR, 4) != 4) \
641 goto font_table_error; \
645 static char* NOTHING
= " ";
647 #define SNAME(VAL) SDATA (SYMBOL_NAME (VAL))
649 /* Check if font supports the otf script/language/features specified.
650 OTF_SPEC is in the format
651 (script lang [(gsub_feature ...)|nil] [(gpos_feature ...)]?) */
652 int uniscribe_check_otf (font
, otf_spec
)
654 Lisp_Object otf_spec
;
656 Lisp_Object script
, lang
, rest
;
657 Lisp_Object features
[2];
658 DWORD feature_tables
[2];
659 DWORD script_tag
, default_script
, lang_tag
= 0;
662 HFONT check_font
, old_font
;
667 /* Check the spec is in the right format. */
668 if (!CONSP (otf_spec
) || Flength (otf_spec
) < 3)
671 /* Break otf_spec into its components. */
672 script
= XCAR (otf_spec
);
673 rest
= XCDR (otf_spec
);
678 features
[0] = XCAR (rest
);
683 features
[1] = XCAR (rest
);
685 /* Set up tags we will use in the search. */
686 feature_tables
[0] = OTF_TAG ("GSUB");
687 feature_tables
[1] = OTF_TAG ("GPOS");
688 default_script
= OTF_TAG ("DFLT");
690 script_tag
= default_script
;
692 script_tag
= OTF_TAG (SNAME (script
));
694 lang_tag
= OTF_TAG (SNAME (lang
));
696 /* Set up graphics context so we can use the font. */
697 f
= XFRAME (selected_frame
);
698 context
= get_frame_dc (f
);
699 check_font
= CreateFontIndirect (font
);
700 old_font
= SelectObject (context
, check_font
);
702 /* Everything else is contained within otf_spec so should get
703 marked along with it. */
706 /* Scan GSUB and GPOS tables. */
707 for (i
= 0; i
< 2; i
++)
709 int j
, n_match_features
;
710 unsigned short scriptlist_table
, feature_table
, n_scripts
;
711 unsigned short script_table
, langsys_table
, n_langs
;
712 unsigned short feature_index
, n_features
;
713 DWORD tbl
= feature_tables
[i
];
715 /* Skip if no features requested from this table. */
716 if (NILP (features
[i
]))
719 /* If features is not a cons, this font spec is messed up. */
720 if (!CONSP (features
[i
]))
723 /* Read GPOS/GSUB header. */
724 OTF_INT16_VAL (tbl
, 4, &scriptlist_table
);
725 OTF_INT16_VAL (tbl
, 6, &feature_table
);
726 OTF_INT16_VAL (tbl
, scriptlist_table
, &n_scripts
);
728 /* Find the appropriate script table. */
730 for (j
= 0; j
< n_scripts
; j
++)
733 OTF_DWORDTAG_VAL (tbl
, scriptlist_table
+ 2 + j
* 6, &script_id
);
734 if (script_id
== script_tag
)
736 OTF_INT16_VAL (tbl
, scriptlist_table
+ 6 + j
* 6, &script_table
);
739 #if 0 /* Causes false positives. */
740 /* If there is a DFLT script defined in the font, use it
741 if the specified script is not found. */
742 else if (script_id
== default_script
)
743 OTF_INT16_VAL (tbl
, scriptlist_table
+ 6 + j
* 6, &script_table
);
746 /* If no specific or default script table was found, then this font
747 does not support the script. */
751 /* Offset is from beginning of scriptlist_table. */
752 script_table
+= scriptlist_table
;
754 /* Get default langsys table. */
755 OTF_INT16_VAL (tbl
, script_table
, &langsys_table
);
757 /* If lang was specified, see if font contains a specific entry. */
760 OTF_INT16_VAL (tbl
, script_table
+ 2, &n_langs
);
762 for (j
= 0; j
< n_langs
; j
++)
765 OTF_DWORDTAG_VAL (tbl
, script_table
+ 4 + j
* 6, &lang_id
);
766 if (lang_id
== lang_tag
)
768 OTF_INT16_VAL (tbl
, script_table
+ 8 + j
* 6, &langsys_table
);
777 /* Offset is from beginning of script table. */
778 langsys_table
+= script_table
;
780 /* Check the features. Features may contain nil according to
781 documentation in font_prop_validate_otf, so count them. */
782 n_match_features
= 0;
783 for (rest
= features
[i
]; CONSP (rest
); rest
= XCDR (rest
))
785 Lisp_Object feature
= XCAR (rest
);
790 /* If there are no features to check, skip checking. */
791 if (!n_match_features
)
794 /* First check required feature (if any). */
795 OTF_INT16_VAL (tbl
, langsys_table
+ 2, &feature_index
);
796 if (feature_index
!= 0xFFFF)
799 OTF_TAG_VAL (tbl
, feature_table
+ 2 + feature_index
* 6, feature_id
);
800 OTF_TAG_VAL (tbl
, feature_table
+ 2 + feature_index
* 6, feature_id
);
801 /* Assume no duplicates in the font table. This allows us to mark
802 the features off by simply decrementing a counter. */
803 if (!NILP (Fmemq (intern (feature_id
), features
[i
])))
806 /* Now check all the other features. */
807 OTF_INT16_VAL (tbl
, langsys_table
+ 4, &n_features
);
808 for (j
= 0; j
< n_features
; j
++)
811 OTF_INT16_VAL (tbl
, langsys_table
+ 6 + j
* 2, &feature_index
);
812 OTF_TAG_VAL (tbl
, feature_table
+ 2 + feature_index
* 6, feature_id
);
813 /* Assume no duplicates in the font table. This allows us to mark
814 the features off by simply decrementing a counter. */
815 if (!NILP (Fmemq (intern (feature_id
), features
[i
])))
819 if (n_match_features
> 0)
827 /* restore graphics context. */
828 SelectObject (context
, old_font
);
829 DeleteObject (check_font
);
830 release_frame_dc (f
, context
);
836 otf_features (HDC context
, char *table
)
838 Lisp_Object script_list
= Qnil
;
839 unsigned short scriptlist_table
, n_scripts
, feature_table
;
840 DWORD tbl
= OTF_TAG (table
);
843 /* Look for scripts in the table. */
844 OTF_INT16_VAL (tbl
, 4, &scriptlist_table
);
845 OTF_INT16_VAL (tbl
, 6, &feature_table
);
846 OTF_INT16_VAL (tbl
, scriptlist_table
, &n_scripts
);
848 for (i
= 0; i
< n_scripts
; i
++)
850 char script
[5], lang
[5];
851 unsigned short script_table
, lang_count
, langsys_table
, feature_count
;
852 Lisp_Object script_tag
, langsys_list
, langsys_tag
, feature_list
;
853 unsigned short record_offset
= scriptlist_table
+ 2 + i
* 6;
854 OTF_TAG_VAL (tbl
, record_offset
, script
);
855 OTF_INT16_VAL (tbl
, record_offset
+ 4, &script_table
);
857 /* Offset is from beginning of script table. */
858 script_table
+= scriptlist_table
;
860 script_tag
= intern (script
);
863 /* Optional default lang. */
864 OTF_INT16_VAL (tbl
, script_table
, &langsys_table
);
867 /* Offset is from beginning of script table. */
868 langsys_table
+= script_table
;
872 OTF_INT16_VAL (tbl
, langsys_table
+ 4, &feature_count
);
873 for (k
= 0; k
< feature_count
; k
++)
876 unsigned short index
;
877 OTF_INT16_VAL (tbl
, langsys_table
+ 6 + k
* 2, &index
);
878 OTF_TAG_VAL (tbl
, feature_table
+ 2 + index
* 6, feature
);
879 feature_list
= Fcons (intern (feature
), feature_list
);
881 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
885 /* List of supported languages. */
886 OTF_INT16_VAL (tbl
, script_table
+ 2, &lang_count
);
888 for (j
= 0; j
< lang_count
; j
++)
890 record_offset
= script_table
+ 4 + j
* 6;
891 OTF_TAG_VAL (tbl
, record_offset
, lang
);
892 OTF_INT16_VAL (tbl
, record_offset
+ 4, &langsys_table
);
894 /* Offset is from beginning of script table. */
895 langsys_table
+= script_table
;
897 langsys_tag
= intern (lang
);
899 OTF_INT16_VAL (tbl
, langsys_table
+ 4, &feature_count
);
900 for (k
= 0; k
< feature_count
; k
++)
903 unsigned short index
;
904 OTF_INT16_VAL (tbl
, langsys_table
+ 6 + k
* 2, &index
);
905 OTF_TAG_VAL (tbl
, feature_table
+ 2 + index
* 6, feature
);
906 feature_list
= Fcons (intern (feature
), feature_list
);
908 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
913 script_list
= Fcons (Fcons (script_tag
, langsys_list
), script_list
);
927 struct font_driver uniscribe_font_driver
=
930 0, /* case insensitive */
934 uniscribe_list_family
,
935 NULL
, /* free_entity */
938 NULL
, /* prepare_face */
939 NULL
, /* done_face */
941 uniscribe_encode_char
,
942 w32font_text_extents
,
944 NULL
, /* get_bitmap */
945 NULL
, /* free_bitmap */
946 NULL
, /* get_outline */
947 NULL
, /* free_outline */
948 NULL
, /* anchor_point */
949 uniscribe_otf_capability
, /* Defined so (font-get FONTOBJ :otf) works. */
950 NULL
, /* otf_drive - use shape instead. */
951 NULL
, /* start_for_frame */
952 NULL
, /* end_for_frame */
956 /* Note that this should be called at every startup, not just when dumping,
957 as it needs to test for the existence of the Uniscribe library. */
959 syms_of_w32uniscribe ()
963 /* Don't init uniscribe when dumping */
967 /* Don't register if uniscribe is not available. */
968 uniscribe
= GetModuleHandle ("usp10");
972 uniscribe_font_driver
.type
= Quniscribe
;
973 uniscribe_available
= 1;
975 register_font_driver (&uniscribe_font_driver
, NULL
);
978 /* arch-tag: 9530f0e1-7471-47dd-a780-94330af87ea0
979 (do not change this comment) */