1 /* Font backend for the Microsoft W32 Uniscribe API.
2 Copyright (C) 2008, 2009, 2010, 2011 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-existent functions. */
27 #define _WIN32_WINNT 0x500
35 #include "dispextern.h"
36 #include "character.h"
38 #include "composite.h"
43 struct uniscribe_font_info
45 struct w32font_info w32_font
;
49 int uniscribe_available
= 0;
51 /* Defined in w32font.c, since it is required there as well. */
52 extern Lisp_Object Quniscribe
;
53 extern Lisp_Object Qopentype
;
55 extern int initialized
;
57 extern struct font_driver uniscribe_font_driver
;
59 /* EnumFontFamiliesEx callback. */
60 static int CALLBACK
add_opentype_font_name_to_list (ENUMLOGFONTEX
*,
63 /* Used by uniscribe_otf_capability. */
64 static Lisp_Object
otf_features (HDC context
, char *table
);
67 memq_no_quit (Lisp_Object elt
, Lisp_Object list
)
69 while (CONSP (list
) && ! EQ (XCAR (list
), elt
))
71 return (CONSP (list
));
75 /* Font backend interface implementation. */
77 uniscribe_list (Lisp_Object frame
, Lisp_Object font_spec
)
79 Lisp_Object fonts
= w32font_list_internal (frame
, font_spec
, 1);
80 FONT_ADD_LOG ("uniscribe-list", font_spec
, fonts
);
85 uniscribe_match (Lisp_Object frame
, Lisp_Object font_spec
)
87 Lisp_Object entity
= w32font_match_internal (frame
, font_spec
, 1);
88 FONT_ADD_LOG ("uniscribe-match", font_spec
, entity
);
93 uniscribe_list_family (Lisp_Object frame
)
95 Lisp_Object list
= Qnil
;
96 LOGFONT font_match_pattern
;
98 FRAME_PTR f
= XFRAME (frame
);
100 memset (&font_match_pattern
, 0, sizeof (font_match_pattern
));
101 /* Limit enumerated fonts to outline fonts to save time. */
102 font_match_pattern
.lfOutPrecision
= OUT_OUTLINE_PRECIS
;
104 dc
= get_frame_dc (f
);
106 EnumFontFamiliesEx (dc
, &font_match_pattern
,
107 (FONTENUMPROC
) add_opentype_font_name_to_list
,
109 release_frame_dc (f
, dc
);
115 uniscribe_open (FRAME_PTR f
, Lisp_Object font_entity
, int pixel_size
)
117 Lisp_Object font_object
118 = font_make_object (VECSIZE (struct uniscribe_font_info
),
119 font_entity
, pixel_size
);
120 struct uniscribe_font_info
*uniscribe_font
121 = (struct uniscribe_font_info
*) XFONT_OBJECT (font_object
);
123 ASET (font_object
, FONT_TYPE_INDEX
, Quniscribe
);
125 if (!w32font_open_internal (f
, font_entity
, pixel_size
, font_object
))
130 /* Initialize the cache for this font. */
131 uniscribe_font
->cache
= NULL
;
133 /* Uniscribe backend uses glyph indices. */
134 uniscribe_font
->w32_font
.glyph_idx
= ETO_GLYPH_INDEX
;
136 /* Mark the format as opentype */
137 uniscribe_font
->w32_font
.font
.props
[FONT_FORMAT_INDEX
] = Qopentype
;
138 uniscribe_font
->w32_font
.font
.driver
= &uniscribe_font_driver
;
144 uniscribe_close (FRAME_PTR f
, struct font
*font
)
146 struct uniscribe_font_info
*uniscribe_font
147 = (struct uniscribe_font_info
*) font
;
149 if (uniscribe_font
->cache
)
150 ScriptFreeCache (&(uniscribe_font
->cache
));
152 w32font_close (f
, font
);
155 /* Return a list describing which scripts/languages FONT supports by
156 which GSUB/GPOS features of OpenType tables. */
158 uniscribe_otf_capability (struct font
*font
)
163 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
164 Lisp_Object features
;
166 f
= XFRAME (selected_frame
);
167 context
= get_frame_dc (f
);
168 old_font
= SelectObject (context
, FONT_HANDLE (font
));
170 features
= otf_features (context
, "GSUB");
171 XSETCAR (capability
, features
);
172 features
= otf_features (context
, "GPOS");
173 XSETCDR (capability
, features
);
175 SelectObject (context
, old_font
);
176 release_frame_dc (f
, context
);
181 /* Uniscribe implementation of shape for font backend.
183 Shape text in LGSTRING. See the docstring of
184 `composition-get-gstring' for the format of LGSTRING. If the
185 (N+1)th element of LGSTRING is nil, input of shaping is from the
186 1st to (N)th elements. In each input glyph, FROM, TO, CHAR, and
187 CODE are already set.
189 This function updates all fields of the input glyphs. If the
190 output glyphs (M) are more than the input glyphs (N), (N+1)th
191 through (M)th elements of LGSTRING are updated possibly by making
192 a new glyph object and storing it in LGSTRING. If (M) is greater
193 than the length of LGSTRING, nil should be returned. In that case,
194 this function is called again with a larger LGSTRING. */
196 uniscribe_shape (Lisp_Object lgstring
)
199 struct uniscribe_font_info
* uniscribe_font
;
201 int nitems
, max_items
, i
, max_glyphs
, done_glyphs
;
203 WORD
*glyphs
, *clusters
;
205 SCRIPT_VISATTR
*attributes
;
210 struct frame
* f
= NULL
;
212 HFONT old_font
= NULL
;
214 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
215 uniscribe_font
= (struct uniscribe_font_info
*) font
;
217 /* Get the chars from lgstring in a form we can use with uniscribe. */
218 max_glyphs
= nchars
= LGSTRING_GLYPH_LEN (lgstring
);
220 chars
= (wchar_t *) alloca (nchars
* sizeof (wchar_t));
221 /* FIXME: This loop assumes that characters in the input LGSTRING
222 are all inside the BMP. Need to encode characters beyond the BMP
224 for (i
= 0; i
< nchars
; i
++)
226 /* lgstring can be bigger than the number of characters in it, in
227 the case where more glyphs are required to display those characters.
228 If that is the case, note the real number of characters. */
229 if (NILP (LGSTRING_GLYPH (lgstring
, i
)))
232 chars
[i
] = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring
, i
));
235 /* First we need to break up the glyph string into runs of glyphs that
236 can be treated together. First try a single run. */
238 items
= (SCRIPT_ITEM
*) xmalloc (sizeof (SCRIPT_ITEM
) * max_items
+ 1);
240 while ((result
= ScriptItemize (chars
, nchars
, max_items
, NULL
, NULL
,
241 items
, &nitems
)) == E_OUTOFMEMORY
)
243 /* If that wasn't enough, keep trying with one more run. */
245 items
= (SCRIPT_ITEM
*) xrealloc (items
,
246 sizeof (SCRIPT_ITEM
) * max_items
+ 1);
255 glyphs
= alloca (max_glyphs
* sizeof (WORD
));
256 clusters
= alloca (nchars
* sizeof (WORD
));
257 attributes
= alloca (max_glyphs
* sizeof (SCRIPT_VISATTR
));
258 advances
= alloca (max_glyphs
* sizeof (int));
259 offsets
= alloca (max_glyphs
* sizeof (GOFFSET
));
261 for (i
= 0; i
< nitems
; i
++)
263 int nglyphs
, nchars_in_run
;
264 nchars_in_run
= items
[i
+1].iCharPos
- items
[i
].iCharPos
;
265 /* Force ScriptShape to generate glyphs in the same order as
266 they are in the input LGSTRING, which is in the logical
268 items
[i
].a
.fLogicalOrder
= 1;
270 /* Context may be NULL here, in which case the cache should be
271 used without needing to select the font. */
272 result
= ScriptShape (context
, &(uniscribe_font
->cache
),
273 chars
+ items
[i
].iCharPos
, nchars_in_run
,
274 max_glyphs
- done_glyphs
, &(items
[i
].a
),
275 glyphs
, clusters
, attributes
, &nglyphs
);
277 if (result
== E_PENDING
&& !context
)
279 /* This assumes the selected frame is on the same display as the
280 one we are drawing. It would be better for the frame to be
282 f
= XFRAME (selected_frame
);
283 context
= get_frame_dc (f
);
284 old_font
= SelectObject (context
, FONT_HANDLE (font
));
286 result
= ScriptShape (context
, &(uniscribe_font
->cache
),
287 chars
+ items
[i
].iCharPos
, nchars_in_run
,
288 max_glyphs
- done_glyphs
, &(items
[i
].a
),
289 glyphs
, clusters
, attributes
, &nglyphs
);
292 if (result
== E_OUTOFMEMORY
)
294 /* Need a bigger lgstring. */
298 else if (FAILED (result
))
300 /* Can't shape this run - return results so far if any. */
303 else if (items
[i
].a
.fNoGlyphIndex
)
305 /* Glyph indices not supported by this font (or OS), means we
306 can't really do any meaningful shaping. */
311 result
= ScriptPlace (context
, &(uniscribe_font
->cache
),
312 glyphs
, nglyphs
, attributes
, &(items
[i
].a
),
313 advances
, offsets
, &overall_metrics
);
314 if (result
== E_PENDING
&& !context
)
316 /* Cache not complete... */
317 f
= XFRAME (selected_frame
);
318 context
= get_frame_dc (f
);
319 old_font
= SelectObject (context
, FONT_HANDLE (font
));
321 result
= ScriptPlace (context
, &(uniscribe_font
->cache
),
322 glyphs
, nglyphs
, attributes
, &(items
[i
].a
),
323 advances
, offsets
, &overall_metrics
);
325 if (SUCCEEDED (result
))
327 int j
, nclusters
, from
, to
;
332 for (j
= 0; j
< nglyphs
; j
++)
334 int lglyph_index
= j
+ done_glyphs
;
335 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, lglyph_index
);
341 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
342 LGSTRING_SET_GLYPH (lgstring
, lglyph_index
, lglyph
);
344 /* Copy to a 32-bit data type to shut up the
345 compiler warning in LGLYPH_SET_CODE about
346 comparison being always false. */
348 LGLYPH_SET_CODE (lglyph
, gl
);
350 /* Detect clusters, for linking codes back to
352 if (attributes
[j
].fClusterStart
)
354 while (from
< nchars_in_run
&& clusters
[from
] < j
)
356 if (from
>= nchars_in_run
)
357 from
= to
= nchars_in_run
- 1;
361 to
= nchars_in_run
- 1;
362 for (k
= from
+ 1; k
< nchars_in_run
; k
++)
373 LGLYPH_SET_CHAR (lglyph
, chars
[items
[i
].iCharPos
375 LGLYPH_SET_FROM (lglyph
, items
[i
].iCharPos
+ from
);
376 LGLYPH_SET_TO (lglyph
, items
[i
].iCharPos
+ to
);
379 LGLYPH_SET_WIDTH (lglyph
, advances
[j
]);
380 LGLYPH_SET_ASCENT (lglyph
, font
->ascent
);
381 LGLYPH_SET_DESCENT (lglyph
, font
->descent
);
383 result
= ScriptGetGlyphABCWidth (context
,
384 &(uniscribe_font
->cache
),
385 glyphs
[j
], &char_metric
);
386 if (result
== E_PENDING
&& !context
)
388 /* Cache incomplete... */
389 f
= XFRAME (selected_frame
);
390 context
= get_frame_dc (f
);
391 old_font
= SelectObject (context
, FONT_HANDLE (font
));
392 result
= ScriptGetGlyphABCWidth (context
,
393 &(uniscribe_font
->cache
),
394 glyphs
[j
], &char_metric
);
397 if (SUCCEEDED (result
))
399 LGLYPH_SET_LBEARING (lglyph
, char_metric
.abcA
);
400 LGLYPH_SET_RBEARING (lglyph
, (char_metric
.abcA
401 + char_metric
.abcB
));
405 LGLYPH_SET_LBEARING (lglyph
, 0);
406 LGLYPH_SET_RBEARING (lglyph
, advances
[j
]);
409 if (offsets
[j
].du
|| offsets
[j
].dv
)
412 vec
= Fmake_vector (make_number (3), Qnil
);
413 ASET (vec
, 0, make_number (offsets
[j
].du
));
414 ASET (vec
, 1, make_number (offsets
[j
].dv
));
415 /* Based on what ftfont.c does... */
416 ASET (vec
, 2, make_number (advances
[j
]));
417 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
420 LGLYPH_SET_ADJUSTMENT (lglyph
, Qnil
);
424 done_glyphs
+= nglyphs
;
431 SelectObject (context
, old_font
);
432 release_frame_dc (f
, context
);
438 return make_number (done_glyphs
);
441 /* Uniscribe implementation of encode_char for font backend.
442 Return a glyph code of FONT for character C (Unicode code point).
443 If FONT doesn't have such a glyph, return FONT_INVALID_CODE. */
445 uniscribe_encode_char (struct font
*font
, int c
)
448 struct frame
*f
= NULL
;
449 HFONT old_font
= NULL
;
450 unsigned code
= FONT_INVALID_CODE
;
455 struct uniscribe_font_info
*uniscribe_font
456 = (struct uniscribe_font_info
*)font
;
465 DWORD surrogate
= c
- 0x10000;
467 /* High surrogate: U+D800 - U+DBFF. */
468 ch
[0] = 0xD800 + ((surrogate
>> 10) & 0x03FF);
469 /* Low surrogate: U+DC00 - U+DFFF. */
470 ch
[1] = 0xDC00 + (surrogate
& 0x03FF);
474 /* Non BMP characters must be handled by the uniscribe shaping
475 engine as GDI functions (except blindly displaying lines of
476 unicode text) and the promising looking ScriptGetCMap do not
477 convert surrogate pairs to glyph indexes correctly. */
479 items
= (SCRIPT_ITEM
*) alloca (sizeof (SCRIPT_ITEM
) * 2 + 1);
480 if (SUCCEEDED (ScriptItemize (ch
, len
, 2, NULL
, NULL
, items
, &nitems
)))
483 /* Surrogates seem to need 2 here, even though only one glyph is
484 returned. Indic characters can also produce 2 or more glyphs for
485 a single code point, but they need to use uniscribe_shape
486 above for correct display. */
487 WORD glyphs
[2], clusters
[2];
488 SCRIPT_VISATTR attrs
[2];
491 /* Force ScriptShape to generate glyphs in the logical
493 items
[0].a
.fLogicalOrder
= 1;
495 result
= ScriptShape (context
, &(uniscribe_font
->cache
),
496 ch
, len
, 2, &(items
[0].a
),
497 glyphs
, clusters
, attrs
, &nglyphs
);
499 if (result
== E_PENDING
)
501 /* Use selected frame until API is updated to pass
503 f
= XFRAME (selected_frame
);
504 context
= get_frame_dc (f
);
505 old_font
= SelectObject (context
, FONT_HANDLE (font
));
506 result
= ScriptShape (context
, &(uniscribe_font
->cache
),
507 ch
, len
, 2, &(items
[0].a
),
508 glyphs
, clusters
, attrs
, &nglyphs
);
511 if (SUCCEEDED (result
) && nglyphs
== 1)
513 /* Some fonts return .notdef glyphs instead of failing.
514 (Truetype spec reserves glyph code 0 for .notdef) */
518 else if (SUCCEEDED (result
) || result
== E_OUTOFMEMORY
)
520 /* This character produces zero or more than one glyph
521 when shaped. But we still need the return from here
522 to be valid for the shaping engine to be invoked
524 result
= ScriptGetCMap (context
, &(uniscribe_font
->cache
),
526 if (SUCCEEDED (result
) && glyphs
[0])
533 SelectObject (context
, old_font
);
534 release_frame_dc (f
, context
);
542 Lisp_Object uniscribe_get_cache (Lisp_Object frame);
543 void uniscribe_free_entity (Lisp_Object font_entity);
544 int uniscribe_has_char (Lisp_Object entity, int c);
545 int uniscribe_text_extents (struct font *font, unsigned *code,
546 int nglyphs, struct font_metrics *metrics);
547 int uniscribe_draw (struct glyph_string *s, int from, int to,
548 int x, int y, int with_background);
551 int uniscribe_prepare_face (FRAME_PTR f, struct face *face);
552 void uniscribe_done_face (FRAME_PTR f, struct face *face);
553 int uniscribe_get_bitmap (struct font *font, unsigned code,
554 struct font_bitmap *bitmap, int bits_per_pixel);
555 void uniscribe_free_bitmap (struct font *font, struct font_bitmap *bitmap);
556 void * uniscribe_get_outline (struct font *font, unsigned code);
557 void uniscribe_free_outline (struct font *font, void *outline);
558 int uniscribe_anchor_point (struct font *font, unsigned code,
559 int index, int *x, int *y);
560 int uniscribe_start_for_frame (FRAME_PTR f);
561 int uniscribe_end_for_frame (FRAME_PTR f);
566 /* Callback function for EnumFontFamiliesEx.
567 Adds the name of opentype fonts to a Lisp list (passed in as the
570 add_opentype_font_name_to_list (ENUMLOGFONTEX
*logical_font
,
571 NEWTEXTMETRICEX
*physical_font
,
572 DWORD font_type
, LPARAM list_object
)
574 Lisp_Object
* list
= (Lisp_Object
*) list_object
;
577 /* Skip vertical fonts (intended only for printing) */
578 if (logical_font
->elfLogFont
.lfFaceName
[0] == '@')
581 /* Skip non opentype fonts. Count old truetype fonts as opentype,
582 as some of them do contain GPOS and GSUB data that Uniscribe
584 if (!(physical_font
->ntmTm
.ntmFlags
& NTMFLAGS_OPENTYPE
)
585 && font_type
!= TRUETYPE_FONTTYPE
)
588 /* Skip fonts that have no unicode coverage. */
589 if (!physical_font
->ntmFontSig
.fsUsb
[3]
590 && !physical_font
->ntmFontSig
.fsUsb
[2]
591 && !physical_font
->ntmFontSig
.fsUsb
[1]
592 && !(physical_font
->ntmFontSig
.fsUsb
[0] & 0x3fffffff))
595 family
= intern_font_name (logical_font
->elfLogFont
.lfFaceName
);
596 if (! memq_no_quit (family
, *list
))
597 *list
= Fcons (family
, *list
);
603 /* :otf property handling.
604 Since the necessary Uniscribe APIs for getting font tag information
605 are only available in Vista, we need to parse the font data directly
606 according to the OpenType Specification. */
608 /* Push into DWORD backwards to cope with endianness. */
609 #define OTF_TAG(STR) \
610 ((STR[3] << 24) | (STR[2] << 16) | (STR[1] << 8) | STR[0])
612 #define OTF_INT16_VAL(TABLE, OFFSET, PTR) \
614 BYTE temp, data[2]; \
615 if (GetFontData (context, TABLE, OFFSET, data, 2) != 2) \
616 goto font_table_error; \
617 temp = data[0], data[0] = data[1], data[1] = temp; \
618 memcpy (PTR, data, 2); \
621 /* Do not reverse the bytes, because we will compare with a OTF_TAG value
622 that has them reversed already. */
623 #define OTF_DWORDTAG_VAL(TABLE, OFFSET, PTR) \
625 if (GetFontData (context, TABLE, OFFSET, PTR, 4) != 4) \
626 goto font_table_error; \
629 #define OTF_TAG_VAL(TABLE, OFFSET, STR) \
631 if (GetFontData (context, TABLE, OFFSET, STR, 4) != 4) \
632 goto font_table_error; \
636 static char* NOTHING
= " ";
638 #define SNAME(VAL) SDATA (SYMBOL_NAME (VAL))
640 /* Check if font supports the otf script/language/features specified.
641 OTF_SPEC is in the format
642 (script lang [(gsub_feature ...)|nil] [(gpos_feature ...)]?) */
644 uniscribe_check_otf (LOGFONT
*font
, Lisp_Object otf_spec
)
646 Lisp_Object script
, lang
, rest
;
647 Lisp_Object features
[2];
648 DWORD feature_tables
[2];
649 DWORD script_tag
, default_script
, lang_tag
= 0;
652 HFONT check_font
, old_font
;
657 /* Check the spec is in the right format. */
658 if (!CONSP (otf_spec
) || XINT (Flength (otf_spec
)) < 3)
661 /* Break otf_spec into its components. */
662 script
= XCAR (otf_spec
);
663 rest
= XCDR (otf_spec
);
668 features
[0] = XCAR (rest
);
673 features
[1] = XCAR (rest
);
675 /* Set up tags we will use in the search. */
676 feature_tables
[0] = OTF_TAG ("GSUB");
677 feature_tables
[1] = OTF_TAG ("GPOS");
678 default_script
= OTF_TAG ("DFLT");
680 script_tag
= default_script
;
682 script_tag
= OTF_TAG (SNAME (script
));
684 lang_tag
= OTF_TAG (SNAME (lang
));
686 /* Set up graphics context so we can use the font. */
687 f
= XFRAME (selected_frame
);
688 context
= get_frame_dc (f
);
689 check_font
= CreateFontIndirect (font
);
690 old_font
= SelectObject (context
, check_font
);
692 /* Everything else is contained within otf_spec so should get
693 marked along with it. */
696 /* Scan GSUB and GPOS tables. */
697 for (i
= 0; i
< 2; i
++)
699 int j
, n_match_features
;
700 unsigned short scriptlist_table
, feature_table
, n_scripts
;
701 unsigned short script_table
, langsys_table
, n_langs
;
702 unsigned short feature_index
, n_features
;
703 DWORD tbl
= feature_tables
[i
];
705 /* Skip if no features requested from this table. */
706 if (NILP (features
[i
]))
709 /* If features is not a cons, this font spec is messed up. */
710 if (!CONSP (features
[i
]))
713 /* Read GPOS/GSUB header. */
714 OTF_INT16_VAL (tbl
, 4, &scriptlist_table
);
715 OTF_INT16_VAL (tbl
, 6, &feature_table
);
716 OTF_INT16_VAL (tbl
, scriptlist_table
, &n_scripts
);
718 /* Find the appropriate script table. */
720 for (j
= 0; j
< n_scripts
; j
++)
723 OTF_DWORDTAG_VAL (tbl
, scriptlist_table
+ 2 + j
* 6, &script_id
);
724 if (script_id
== script_tag
)
726 OTF_INT16_VAL (tbl
, scriptlist_table
+ 6 + j
* 6, &script_table
);
729 #if 0 /* Causes false positives. */
730 /* If there is a DFLT script defined in the font, use it
731 if the specified script is not found. */
732 else if (script_id
== default_script
)
733 OTF_INT16_VAL (tbl
, scriptlist_table
+ 6 + j
* 6, &script_table
);
736 /* If no specific or default script table was found, then this font
737 does not support the script. */
741 /* Offset is from beginning of scriptlist_table. */
742 script_table
+= scriptlist_table
;
744 /* Get default langsys table. */
745 OTF_INT16_VAL (tbl
, script_table
, &langsys_table
);
747 /* If lang was specified, see if font contains a specific entry. */
750 OTF_INT16_VAL (tbl
, script_table
+ 2, &n_langs
);
752 for (j
= 0; j
< n_langs
; j
++)
755 OTF_DWORDTAG_VAL (tbl
, script_table
+ 4 + j
* 6, &lang_id
);
756 if (lang_id
== lang_tag
)
758 OTF_INT16_VAL (tbl
, script_table
+ 8 + j
* 6, &langsys_table
);
767 /* Offset is from beginning of script table. */
768 langsys_table
+= script_table
;
770 /* Check the features. Features may contain nil according to
771 documentation in font_prop_validate_otf, so count them. */
772 n_match_features
= 0;
773 for (rest
= features
[i
]; CONSP (rest
); rest
= XCDR (rest
))
775 Lisp_Object feature
= XCAR (rest
);
780 /* If there are no features to check, skip checking. */
781 if (!n_match_features
)
784 /* First check required feature (if any). */
785 OTF_INT16_VAL (tbl
, langsys_table
+ 2, &feature_index
);
786 if (feature_index
!= 0xFFFF)
789 OTF_TAG_VAL (tbl
, feature_table
+ 2 + feature_index
* 6, feature_id
);
790 OTF_TAG_VAL (tbl
, feature_table
+ 2 + feature_index
* 6, feature_id
);
791 /* Assume no duplicates in the font table. This allows us to mark
792 the features off by simply decrementing a counter. */
793 if (!NILP (Fmemq (intern (feature_id
), features
[i
])))
796 /* Now check all the other features. */
797 OTF_INT16_VAL (tbl
, langsys_table
+ 4, &n_features
);
798 for (j
= 0; j
< n_features
; j
++)
801 OTF_INT16_VAL (tbl
, langsys_table
+ 6 + j
* 2, &feature_index
);
802 OTF_TAG_VAL (tbl
, feature_table
+ 2 + feature_index
* 6, feature_id
);
803 /* Assume no duplicates in the font table. This allows us to mark
804 the features off by simply decrementing a counter. */
805 if (!NILP (Fmemq (intern (feature_id
), features
[i
])))
809 if (n_match_features
> 0)
817 /* restore graphics context. */
818 SelectObject (context
, old_font
);
819 DeleteObject (check_font
);
820 release_frame_dc (f
, context
);
826 otf_features (HDC context
, char *table
)
828 Lisp_Object script_list
= Qnil
;
829 unsigned short scriptlist_table
, n_scripts
, feature_table
;
830 DWORD tbl
= OTF_TAG (table
);
833 /* Look for scripts in the table. */
834 OTF_INT16_VAL (tbl
, 4, &scriptlist_table
);
835 OTF_INT16_VAL (tbl
, 6, &feature_table
);
836 OTF_INT16_VAL (tbl
, scriptlist_table
, &n_scripts
);
838 for (i
= 0; i
< n_scripts
; i
++)
840 char script
[5], lang
[5];
841 unsigned short script_table
, lang_count
, langsys_table
, feature_count
;
842 Lisp_Object script_tag
, langsys_list
, langsys_tag
, feature_list
;
843 unsigned short record_offset
= scriptlist_table
+ 2 + i
* 6;
844 OTF_TAG_VAL (tbl
, record_offset
, script
);
845 OTF_INT16_VAL (tbl
, record_offset
+ 4, &script_table
);
847 /* Offset is from beginning of script table. */
848 script_table
+= scriptlist_table
;
850 script_tag
= intern (script
);
853 /* Optional default lang. */
854 OTF_INT16_VAL (tbl
, script_table
, &langsys_table
);
857 /* Offset is from beginning of script table. */
858 langsys_table
+= script_table
;
862 OTF_INT16_VAL (tbl
, langsys_table
+ 4, &feature_count
);
863 for (k
= 0; k
< feature_count
; k
++)
866 unsigned short index
;
867 OTF_INT16_VAL (tbl
, langsys_table
+ 6 + k
* 2, &index
);
868 OTF_TAG_VAL (tbl
, feature_table
+ 2 + index
* 6, feature
);
869 feature_list
= Fcons (intern (feature
), feature_list
);
871 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
875 /* List of supported languages. */
876 OTF_INT16_VAL (tbl
, script_table
+ 2, &lang_count
);
878 for (j
= 0; j
< lang_count
; j
++)
880 record_offset
= script_table
+ 4 + j
* 6;
881 OTF_TAG_VAL (tbl
, record_offset
, lang
);
882 OTF_INT16_VAL (tbl
, record_offset
+ 4, &langsys_table
);
884 /* Offset is from beginning of script table. */
885 langsys_table
+= script_table
;
887 langsys_tag
= intern (lang
);
889 OTF_INT16_VAL (tbl
, langsys_table
+ 4, &feature_count
);
890 for (k
= 0; k
< feature_count
; k
++)
893 unsigned short index
;
894 OTF_INT16_VAL (tbl
, langsys_table
+ 6 + k
* 2, &index
);
895 OTF_TAG_VAL (tbl
, feature_table
+ 2 + index
* 6, feature
);
896 feature_list
= Fcons (intern (feature
), feature_list
);
898 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
903 script_list
= Fcons (Fcons (script_tag
, langsys_list
), script_list
);
917 struct font_driver uniscribe_font_driver
=
920 0, /* case insensitive */
924 uniscribe_list_family
,
925 NULL
, /* free_entity */
928 NULL
, /* prepare_face */
929 NULL
, /* done_face */
931 uniscribe_encode_char
,
932 w32font_text_extents
,
934 NULL
, /* get_bitmap */
935 NULL
, /* free_bitmap */
936 NULL
, /* get_outline */
937 NULL
, /* free_outline */
938 NULL
, /* anchor_point */
939 uniscribe_otf_capability
, /* Defined so (font-get FONTOBJ :otf) works. */
940 NULL
, /* otf_drive - use shape instead. */
941 NULL
, /* start_for_frame */
942 NULL
, /* end_for_frame */
946 /* Note that this should be called at every startup, not just when dumping,
947 as it needs to test for the existence of the Uniscribe library. */
949 syms_of_w32uniscribe (void)
953 /* Don't init uniscribe when dumping */
957 /* Don't register if uniscribe is not available. */
958 uniscribe
= GetModuleHandle ("usp10");
962 uniscribe_font_driver
.type
= Quniscribe
;
963 uniscribe_available
= 1;
965 register_font_driver (&uniscribe_font_driver
, NULL
);