This source file includes following definitions.
- memq_no_quit
- uniscribe_list
- uniscribe_match
- uniscribe_list_family
- uniscribe_open
- uniscribe_close
- uniscribe_otf_capability
- uniscribe_shape
- uniscribe_encode_char
- add_opentype_font_name_to_list
- uniscribe_check_features
- uniscribe_check_otf_1
- uniscribe_check_otf
- otf_features
- w32hb_list
- w32hb_match
- free_cb
- w32hb_get_font_table
- w32hb_get_font
- w32hb_encode_char
- w32hb_begin_font
- w32hb_get_variation_glyphs
- syms_of_w32uniscribe
- load_harfbuzz_funcs
- syms_of_w32uniscribe_for_pdumper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22
23
24
25
26
27
28
29 #undef _WIN32_WINNT
30 #define _WIN32_WINNT 0x0600
31 #include <windows.h>
32 #include <usp10.h>
33 #ifdef HAVE_HARFBUZZ
34 # include <hb.h>
35 # include <hb-ot.h>
36 # if GNUC_PREREQ (4, 3, 0)
37 # define bswap_32(v) __builtin_bswap32(v)
38 # else
39 # include <byteswap.h>
40 # endif
41 #endif
42
43 #include "lisp.h"
44 #include "w32term.h"
45 #include "frame.h"
46 #include "composite.h"
47 #include "font.h"
48 #include "w32font.h"
49 #include "pdumper.h"
50 #include "w32common.h"
51
52
53 struct uniscribe_font_info
54 {
55 struct w32font_info w32_font;
56
57
58
59 void *cache;
60
61 double scale;
62 };
63
64 int uniscribe_available = 0;
65
66
67 static int CALLBACK ALIGN_STACK add_opentype_font_name_to_list (ENUMLOGFONTEX *,
68 NEWTEXTMETRICEX *,
69 DWORD, LPARAM);
70 #ifdef HAVE_HARFBUZZ
71
72 struct font_driver harfbuzz_font_driver;
73 int harfbuzz_available = 0;
74
75
76
77 DEF_DLL_FN (hb_blob_t *, hb_blob_create,
78 (const char *, unsigned int, hb_memory_mode_t, void *,
79 hb_destroy_func_t));
80 DEF_DLL_FN (hb_face_t *, hb_face_create_for_tables,
81 (hb_reference_table_func_t, void *, hb_destroy_func_t));
82 DEF_DLL_FN (unsigned, hb_face_get_glyph_count, (const hb_face_t *));
83 DEF_DLL_FN (hb_font_t *, hb_font_create, (hb_face_t *));
84 DEF_DLL_FN (void, hb_font_destroy, (hb_font_t *));
85 DEF_DLL_FN (void, hb_face_destroy, (hb_face_t *));
86 DEF_DLL_FN (unsigned int, hb_face_get_upem, (hb_face_t *));
87 DEF_DLL_FN (hb_bool_t, hb_font_get_nominal_glyph,
88 (hb_font_t *, hb_codepoint_t, hb_codepoint_t *));
89 DEF_DLL_FN (hb_bool_t, hb_font_get_variation_glyph,
90 (hb_font_t *, hb_codepoint_t, hb_codepoint_t, hb_codepoint_t *));
91 DEF_DLL_FN (void, hb_ot_font_set_funcs, (hb_font_t *));
92
93 #define hb_blob_create fn_hb_blob_create
94 #define hb_face_create_for_tables fn_hb_face_create_for_tables
95 #define hb_face_get_glyph_count fn_hb_face_get_glyph_count
96 #define hb_font_create fn_hb_font_create
97 #define hb_font_destroy fn_hb_font_destroy
98 #define hb_face_destroy fn_hb_face_destroy
99 #define hb_face_get_upem fn_hb_face_get_upem
100 #define hb_font_get_nominal_glyph fn_hb_font_get_nominal_glyph
101 #define hb_font_get_variation_glyph fn_hb_font_get_variation_glyph
102 #define hb_ot_font_set_funcs fn_hb_ot_font_set_funcs
103 #endif
104
105
106 static Lisp_Object otf_features (HDC context, const char *table);
107
108 static int
109 memq_no_quit (Lisp_Object elt, Lisp_Object list)
110 {
111 while (CONSP (list) && ! EQ (XCAR (list), elt))
112 list = XCDR (list);
113 return (CONSP (list));
114 }
115
116
117
118 static Lisp_Object
119 uniscribe_list (struct frame *f, Lisp_Object font_spec)
120 {
121 Lisp_Object fonts = w32font_list_internal (f, font_spec, true);
122 FONT_ADD_LOG ("uniscribe-list", font_spec, fonts);
123 return fonts;
124 }
125
126 static Lisp_Object
127 uniscribe_match (struct frame *f, Lisp_Object font_spec)
128 {
129 Lisp_Object entity = w32font_match_internal (f, font_spec, true);
130 FONT_ADD_LOG ("uniscribe-match", font_spec, entity);
131 return entity;
132 }
133
134 static Lisp_Object
135 uniscribe_list_family (struct frame *f)
136 {
137 Lisp_Object list = Qnil;
138 LOGFONT font_match_pattern;
139 HDC dc;
140
141 memset (&font_match_pattern, 0, sizeof (font_match_pattern));
142
143 font_match_pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
144
145
146
147
148
149 Lisp_Object prev_quit = Vinhibit_quit;
150 Vinhibit_quit = Qt;
151 dc = get_frame_dc (f);
152
153 EnumFontFamiliesEx (dc, &font_match_pattern,
154 (FONTENUMPROC) add_opentype_font_name_to_list,
155 (LPARAM) &list, 0);
156 release_frame_dc (f, dc);
157 Vinhibit_quit = prev_quit;
158
159 return list;
160 }
161
162 static Lisp_Object
163 uniscribe_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
164 {
165 Lisp_Object font_object
166 = font_make_object (VECSIZE (struct uniscribe_font_info),
167 font_entity, pixel_size);
168 struct uniscribe_font_info *uniscribe_font
169 = (struct uniscribe_font_info *) XFONT_OBJECT (font_object);
170
171 if (!NILP (AREF (font_entity, FONT_TYPE_INDEX)))
172 ASET (font_object, FONT_TYPE_INDEX, AREF (font_entity, FONT_TYPE_INDEX));
173 else
174 ASET (font_object, FONT_TYPE_INDEX, Quniscribe);
175
176 if (!w32font_open_internal (f, font_entity, pixel_size, font_object))
177 {
178 return Qnil;
179 }
180
181
182 uniscribe_font->cache = NULL;
183
184
185 uniscribe_font->w32_font.glyph_idx = ETO_GLYPH_INDEX;
186
187 #ifdef HAVE_HARFBUZZ
188 if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qharfbuzz))
189 uniscribe_font->w32_font.font.driver = &harfbuzz_font_driver;
190 else
191 #endif
192 uniscribe_font->w32_font.font.driver = &uniscribe_font_driver;
193
194 return font_object;
195 }
196
197 static void
198 uniscribe_close (struct font *font)
199 {
200 struct uniscribe_font_info *uniscribe_font
201 = (struct uniscribe_font_info *) font;
202
203 #ifdef HAVE_HARFBUZZ
204 if (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver
205 && uniscribe_font->cache)
206 hb_font_destroy ((hb_font_t *) uniscribe_font->cache);
207 else
208 #endif
209 if (uniscribe_font->cache)
210 ScriptFreeCache ((SCRIPT_CACHE) &(uniscribe_font->cache));
211
212 uniscribe_font->cache = NULL;
213
214 w32font_close (font);
215 }
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238 static Lisp_Object
239 uniscribe_otf_capability (struct font *font)
240 {
241 HDC context;
242 HFONT old_font;
243 struct frame *f;
244 Lisp_Object capability = Fcons (Qnil, Qnil);
245 Lisp_Object features;
246
247 f = XFRAME (selected_frame);
248
249
250
251 Lisp_Object prev_quit = Vinhibit_quit;
252 Vinhibit_quit = Qt;
253 context = get_frame_dc (f);
254 old_font = SelectObject (context, FONT_HANDLE (font));
255
256 features = otf_features (context, "GSUB");
257 XSETCAR (capability, features);
258 features = otf_features (context, "GPOS");
259 XSETCDR (capability, features);
260
261 SelectObject (context, old_font);
262 release_frame_dc (f, context);
263 Vinhibit_quit = prev_quit;
264
265 return capability;
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285 static Lisp_Object
286 uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
287 {
288 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
289 struct uniscribe_font_info *uniscribe_font
290 = (struct uniscribe_font_info *) font;
291 EMACS_UINT nchars;
292 int nitems, max_items, i, max_glyphs, done_glyphs;
293 wchar_t *chars;
294 WORD *glyphs, *clusters;
295 SCRIPT_ITEM *items;
296 SCRIPT_VISATTR *attributes;
297 int *advances;
298 GOFFSET *offsets;
299 ABC overall_metrics;
300 HRESULT result;
301 struct frame * f = NULL;
302 HDC context = NULL;
303 HFONT old_font = NULL;
304
305
306 max_glyphs = nchars = LGSTRING_GLYPH_LEN (lgstring);
307 done_glyphs = 0;
308 chars = (wchar_t *) alloca (nchars * sizeof (wchar_t));
309
310
311
312 for (i = 0; i < nchars; i++)
313 {
314
315
316
317 if (NILP (LGSTRING_GLYPH (lgstring, i)))
318 nchars = i;
319 else
320 chars[i] = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
321 }
322
323
324
325 max_items = 2;
326 items = xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1);
327
328 while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL,
329 items, &nitems)) == E_OUTOFMEMORY)
330 {
331
332 max_items++;
333 items = (SCRIPT_ITEM *) xrealloc (items,
334 sizeof (SCRIPT_ITEM) * max_items + 1);
335 }
336
337 if (FAILED (result))
338 {
339 xfree (items);
340 return Qnil;
341 }
342
343 glyphs = alloca (max_glyphs * sizeof (WORD));
344 clusters = alloca (nchars * sizeof (WORD));
345 attributes = alloca (max_glyphs * sizeof (SCRIPT_VISATTR));
346 advances = alloca (max_glyphs * sizeof (int));
347 offsets = alloca (max_glyphs * sizeof (GOFFSET));
348
349 for (i = 0; i < nitems; i++)
350 {
351 int nglyphs, nchars_in_run;
352 nchars_in_run = items[i+1].iCharPos - items[i].iCharPos;
353
354
355
356 items[i].a.fLogicalOrder = 1;
357
358
359
360 result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
361 chars + items[i].iCharPos, nchars_in_run,
362 max_glyphs - done_glyphs, &(items[i].a),
363 glyphs, clusters, attributes, &nglyphs);
364
365 if (result == E_PENDING && !context)
366 {
367
368
369
370 f = XFRAME (selected_frame);
371 context = get_frame_dc (f);
372 old_font = SelectObject (context, FONT_HANDLE (font));
373
374 result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
375 chars + items[i].iCharPos, nchars_in_run,
376 max_glyphs - done_glyphs, &(items[i].a),
377 glyphs, clusters, attributes, &nglyphs);
378 }
379
380 if (result == E_OUTOFMEMORY)
381 {
382
383 lgstring = Qnil;
384 break;
385 }
386 else if (FAILED (result))
387 {
388
389 break;
390 }
391 else if (items[i].a.fNoGlyphIndex)
392 {
393
394
395 break;
396 }
397 else
398 {
399 result = ScriptPlace (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
400 glyphs, nglyphs, attributes, &(items[i].a),
401 advances, offsets, &overall_metrics);
402 if (result == E_PENDING && !context)
403 {
404
405 f = XFRAME (selected_frame);
406 context = get_frame_dc (f);
407 old_font = SelectObject (context, FONT_HANDLE (font));
408
409 result = ScriptPlace (context,
410 (SCRIPT_CACHE) &(uniscribe_font->cache),
411 glyphs, nglyphs, attributes, &(items[i].a),
412 advances, offsets, &overall_metrics);
413 }
414 if (SUCCEEDED (result))
415 {
416 int j, from, to, adj_offset = 0;
417 int cluster_offset = 0;
418
419 from = 0;
420 to = from;
421
422 for (j = 0; j < nglyphs; j++)
423 {
424 int lglyph_index = j + done_glyphs;
425 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, lglyph_index);
426 ABC char_metric;
427 unsigned gl;
428
429 if (NILP (lglyph))
430 {
431 lglyph = LGLYPH_NEW ();
432 LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph);
433 }
434
435
436
437 gl = glyphs[j];
438 LGLYPH_SET_CODE (lglyph, gl);
439
440
441
442 if (attributes[j].fClusterStart)
443 {
444 while (from < nchars_in_run && clusters[from] < j)
445 from++;
446 if (from >= nchars_in_run)
447 from = to = nchars_in_run - 1;
448 else
449 {
450 int k;
451 to = nchars_in_run - 1;
452 for (k = from + 1; k < nchars_in_run; k++)
453 {
454 if (clusters[k] > j)
455 {
456 to = k - 1;
457 break;
458 }
459 }
460 }
461 cluster_offset = 0;
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479 if (items[i].a.fRTL)
480 {
481 int j1 = j;
482
483 adj_offset = 0;
484 while (j1 < nglyphs && !attributes[j1].fClusterStart)
485 {
486 adj_offset += advances[j1];
487 j1++;
488 }
489 }
490 }
491
492 int char_idx = items[i].iCharPos + from + cluster_offset;
493 if (from + cluster_offset > to)
494 char_idx = items[i].iCharPos + to;
495 cluster_offset++;
496 LGLYPH_SET_CHAR (lglyph, chars[char_idx]);
497 LGLYPH_SET_FROM (lglyph, items[i].iCharPos + from);
498 LGLYPH_SET_TO (lglyph, items[i].iCharPos + to);
499
500
501 LGLYPH_SET_WIDTH (lglyph, advances[j]);
502 LGLYPH_SET_ASCENT (lglyph, font->ascent);
503 LGLYPH_SET_DESCENT (lglyph, font->descent);
504
505 result = ScriptGetGlyphABCWidth
506 (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
507 glyphs[j], &char_metric);
508 if (result == E_PENDING && !context)
509 {
510
511 f = XFRAME (selected_frame);
512 context = get_frame_dc (f);
513 old_font = SelectObject (context, FONT_HANDLE (font));
514 result = ScriptGetGlyphABCWidth
515 (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
516 glyphs[j], &char_metric);
517 }
518
519 if (SUCCEEDED (result))
520 {
521 int lbearing = char_metric.abcA;
522 int rbearing = char_metric.abcA + char_metric.abcB;
523
524 LGLYPH_SET_LBEARING (lglyph, lbearing);
525 LGLYPH_SET_RBEARING (lglyph, rbearing);
526 }
527 else
528 {
529 LGLYPH_SET_LBEARING (lglyph, 0);
530 LGLYPH_SET_RBEARING (lglyph, advances[j]);
531 }
532
533 if (offsets[j].du || offsets[j].dv
534
535
536
537 || (!attributes[j].fClusterStart && items[i].a.fRTL))
538 {
539 Lisp_Object vec = make_uninit_vector (3);
540
541 if (items[i].a.fRTL)
542 {
543
544
545
546
547
548
549 ASET (vec, 0, make_fixnum (-offsets[j].du
550 + adj_offset));
551
552
553 adj_offset -= 2 * advances[j];
554 }
555 else
556 ASET (vec, 0, make_fixnum (offsets[j].du + adj_offset));
557
558
559
560
561 ASET (vec, 1, make_fixnum (-offsets[j].dv));
562
563 ASET (vec, 2, make_fixnum (advances[j]));
564 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
565 }
566 else
567 {
568 LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
569
570
571 if (items[i].a.fRTL)
572 adj_offset -= advances[j];
573 }
574 }
575 }
576 }
577 done_glyphs += nglyphs;
578 }
579
580 xfree (items);
581
582 if (context)
583 {
584 SelectObject (context, old_font);
585 release_frame_dc (f, context);
586 }
587
588 if (NILP (lgstring))
589 return Qnil;
590 else
591 return make_fixnum (done_glyphs);
592 }
593
594
595
596
597 static unsigned
598 uniscribe_encode_char (struct font *font, int c)
599 {
600 HDC context = NULL;
601 struct frame *f = NULL;
602 HFONT old_font = NULL;
603 unsigned code = FONT_INVALID_CODE;
604 wchar_t ch[2];
605 int len;
606 SCRIPT_ITEM* items;
607 int nitems;
608 struct uniscribe_font_info *uniscribe_font
609 = (struct uniscribe_font_info *)font;
610
611 if (c < 0x10000)
612 {
613 ch[0] = (wchar_t) c;
614 len = 1;
615 }
616 else
617 {
618 DWORD surrogate = c - 0x10000;
619
620
621 ch[0] = 0xD800 + ((surrogate >> 10) & 0x03FF);
622
623 ch[1] = 0xDC00 + (surrogate & 0x03FF);
624 len = 2;
625 }
626
627
628
629
630
631 {
632 items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1);
633 if (SUCCEEDED (ScriptItemize (ch, len, 2, NULL, NULL, items, &nitems)))
634 {
635 HRESULT result;
636
637
638
639
640 WORD glyphs[2], clusters[2];
641 SCRIPT_VISATTR attrs[2];
642 int nglyphs;
643
644
645
646 items[0].a.fLogicalOrder = 1;
647
648 result = ScriptShape (context,
649 (SCRIPT_CACHE) &(uniscribe_font->cache),
650 ch, len, 2, &(items[0].a),
651 glyphs, clusters, attrs, &nglyphs);
652
653 if (result == E_PENDING)
654 {
655
656
657 f = XFRAME (selected_frame);
658 context = get_frame_dc (f);
659 old_font = SelectObject (context, FONT_HANDLE (font));
660 result = ScriptShape (context,
661 (SCRIPT_CACHE) &(uniscribe_font->cache),
662 ch, len, 2, &(items[0].a),
663 glyphs, clusters, attrs, &nglyphs);
664 }
665
666 if (SUCCEEDED (result) && nglyphs == 1)
667 {
668
669
670 if (glyphs[0])
671 code = glyphs[0];
672 }
673 else if (SUCCEEDED (result) || result == E_OUTOFMEMORY)
674 {
675
676
677
678
679 result = ScriptGetCMap (context,
680 (SCRIPT_CACHE) &(uniscribe_font->cache),
681 ch, len, 0, glyphs);
682 if (SUCCEEDED (result) && glyphs[0])
683 code = glyphs[0];
684 }
685 }
686 }
687 if (context)
688 {
689 SelectObject (context, old_font);
690 release_frame_dc (f, context);
691 }
692
693 return code;
694 }
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723 static int CALLBACK ALIGN_STACK
724 add_opentype_font_name_to_list (ENUMLOGFONTEX *logical_font,
725 NEWTEXTMETRICEX *physical_font,
726 DWORD font_type, LPARAM list_object)
727 {
728 Lisp_Object* list = (Lisp_Object *) list_object;
729 Lisp_Object family;
730
731
732 if (logical_font->elfLogFont.lfFaceName[0] == '@')
733 return 1;
734
735
736
737
738 if (!(physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE)
739 && font_type != TRUETYPE_FONTTYPE)
740 return 1;
741
742
743 if (!physical_font->ntmFontSig.fsUsb[3]
744 && !physical_font->ntmFontSig.fsUsb[2]
745 && !physical_font->ntmFontSig.fsUsb[1]
746 && !(physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff))
747 return 1;
748
749 family = intern_font_name (logical_font->elfLogFont.lfFaceName);
750 if (! memq_no_quit (family, *list))
751 *list = Fcons (family, *list);
752
753 return 1;
754 }
755
756
757
758
759
760
761
762
763 #define OTF_TAG(STR) \
764 ((STR[3] << 24) | (STR[2] << 16) | (STR[1] << 8) | STR[0])
765
766 #define OTF_INT16_VAL(TABLE, OFFSET, PTR) \
767 do { \
768 BYTE temp, data[2]; \
769 if (GetFontData (context, TABLE, OFFSET, data, 2) != 2) \
770 goto font_table_error; \
771 temp = data[0], data[0] = data[1], data[1] = temp; \
772 memcpy (PTR, data, 2); \
773 } while (0)
774
775
776
777 #define OTF_DWORDTAG_VAL(TABLE, OFFSET, PTR) \
778 do { \
779 if (GetFontData (context, TABLE, OFFSET, PTR, 4) != 4) \
780 goto font_table_error; \
781 } while (0)
782
783 #define OTF_TAG_VAL(TABLE, OFFSET, STR) \
784 do { \
785 if (GetFontData (context, TABLE, OFFSET, STR, 4) != 4) \
786 goto font_table_error; \
787 STR[4] = '\0'; \
788 } while (0)
789
790 #define SNAME(VAL) SSDATA (SYMBOL_NAME (VAL))
791
792
793 typedef HRESULT (WINAPI *ScriptGetFontScriptTags_Proc)
794 (HDC, SCRIPT_CACHE *, SCRIPT_ANALYSIS *, int, OPENTYPE_TAG *, int *);
795
796 typedef HRESULT (WINAPI *ScriptGetFontLanguageTags_Proc)
797 (HDC, SCRIPT_CACHE *, SCRIPT_ANALYSIS *, OPENTYPE_TAG, int, OPENTYPE_TAG *, int *);
798
799 typedef HRESULT (WINAPI *ScriptGetFontFeatureTags_Proc)
800 (HDC, SCRIPT_CACHE *, SCRIPT_ANALYSIS *, OPENTYPE_TAG, OPENTYPE_TAG, int, OPENTYPE_TAG *, int *);
801
802 ScriptGetFontScriptTags_Proc script_get_font_scripts_fn;
803 ScriptGetFontLanguageTags_Proc script_get_font_languages_fn;
804 ScriptGetFontFeatureTags_Proc script_get_font_features_fn;
805
806 static bool uniscribe_new_apis;
807
808
809
810
811
812
813 static bool
814 uniscribe_check_features (Lisp_Object features[2], OPENTYPE_TAG *ftags, int n)
815 {
816 int j;
817
818 for (j = 0; j < 2; j++)
819 {
820 bool negative = false;
821 Lisp_Object rest;
822
823 for (rest = features[j]; CONSP (rest); rest = XCDR (rest))
824 {
825 Lisp_Object feature = XCAR (rest);
826
827
828
829 if (NILP (feature))
830 negative = true;
831 else
832 {
833 OPENTYPE_TAG feature_tag = OTF_TAG (SNAME (feature));
834 int i;
835
836 for (i = 0; i < n; i++)
837 {
838 if (ftags[i] == feature_tag)
839 {
840
841
842 if (negative)
843 return false;
844 break;
845 }
846 }
847
848
849
850 if (i >= n && !negative)
851 return false;
852 }
853 }
854 }
855
856 return true;
857 }
858
859
860
861
862
863
864
865 static int
866 uniscribe_check_otf_1 (HDC context, Lisp_Object script, Lisp_Object lang,
867 Lisp_Object features[2], int *retval)
868 {
869 SCRIPT_CACHE cache = NULL;
870 OPENTYPE_TAG tags[32], script_tag, lang_tag;
871 int max_tags = ARRAYELTS (tags);
872 int ntags, i, ret = 0;
873 HRESULT rslt;
874
875 *retval = 0;
876
877 rslt = script_get_font_scripts_fn (context, &cache, NULL, max_tags,
878 tags, &ntags);
879 if (FAILED (rslt))
880 {
881 DebPrint (("ScriptGetFontScriptTags failed with 0x%x\n", rslt));
882 ret = -1;
883 goto no_support;
884 }
885 if (NILP (script))
886 script_tag = OTF_TAG ("DFLT");
887 else
888 script_tag = OTF_TAG (SNAME (script));
889 for (i = 0; i < ntags; i++)
890 if (tags[i] == script_tag)
891 break;
892
893 if (i >= ntags)
894 goto no_support;
895
896 if (NILP (lang))
897 lang_tag = OTF_TAG ("dflt");
898 else
899 {
900 rslt = script_get_font_languages_fn (context, &cache, NULL, script_tag,
901 max_tags, tags, &ntags);
902 if (FAILED (rslt))
903 {
904 DebPrint (("ScriptGetFontLanguageTags failed with 0x%x\n", rslt));
905 ret = -1;
906 goto no_support;
907 }
908 if (ntags == 0)
909 lang_tag = OTF_TAG ("dflt");
910 else
911 {
912 lang_tag = OTF_TAG (SNAME (lang));
913 for (i = 0; i < ntags; i++)
914 if (tags[i] == lang_tag)
915 break;
916
917 if (i >= ntags)
918 goto no_support;
919 }
920 }
921
922 if (!NILP (features[0]))
923 {
924
925 if (!CONSP (features[0])
926 || (!NILP (features[1]) && !CONSP (features[1])))
927 goto no_support;
928 rslt = script_get_font_features_fn (context, &cache, NULL,
929 script_tag, lang_tag,
930 max_tags, tags, &ntags);
931 if (FAILED (rslt))
932 {
933 DebPrint (("ScriptGetFontFeatureTags failed with 0x%x\n", rslt));
934 ret = -1;
935 goto no_support;
936 }
937
938
939
940
941
942 if (!uniscribe_check_features (features, tags, ntags))
943 goto no_support;
944 }
945
946 ret = 1;
947 *retval = 1;
948
949 no_support:
950 if (cache)
951 ScriptFreeCache (&cache);
952 return ret;
953 }
954
955
956
957
958 int
959 uniscribe_check_otf (LOGFONT *font, Lisp_Object otf_spec)
960 {
961 Lisp_Object script, lang, rest;
962 Lisp_Object features[2];
963 DWORD feature_tables[2];
964 DWORD script_tag, default_script, lang_tag = 0;
965 struct frame * f;
966 HDC context;
967 HFONT check_font, old_font;
968 int i, retval = 0;
969
970
971 if (!CONSP (otf_spec) || XFIXNUM (Flength (otf_spec)) < 3)
972 return 0;
973
974
975 script = XCAR (otf_spec);
976 rest = XCDR (otf_spec);
977
978 lang = XCAR (rest);
979 rest = XCDR (rest);
980
981 features[0] = XCAR (rest);
982 rest = XCDR (rest);
983 if (NILP (rest))
984 features[1] = Qnil;
985 else
986 features[1] = XCAR (rest);
987
988
989 f = XFRAME (selected_frame);
990 context = get_frame_dc (f);
991 check_font = CreateFontIndirect (font);
992 old_font = SelectObject (context, check_font);
993
994
995 if (uniscribe_new_apis
996 && !w32_disable_new_uniscribe_apis
997 && uniscribe_check_otf_1 (context, script, lang, features, &retval) != -1)
998 goto done;
999
1000
1001 feature_tables[0] = OTF_TAG ("GSUB");
1002 feature_tables[1] = OTF_TAG ("GPOS");
1003 default_script = OTF_TAG ("DFLT");
1004 if (NILP (script))
1005 script_tag = default_script;
1006 else
1007 script_tag = OTF_TAG (SNAME (script));
1008 if (!NILP (lang))
1009 lang_tag = OTF_TAG (SNAME (lang));
1010
1011
1012 for (i = 0; i < 2; i++)
1013 {
1014 int j, n_match_features;
1015 unsigned short scriptlist_table, feature_table, n_scripts;
1016 unsigned short script_table, langsys_table, n_langs;
1017 unsigned short feature_index, n_features;
1018 DWORD tbl = feature_tables[i];
1019 DWORD feature_id, *ftags;
1020 Lisp_Object farray[2];
1021
1022
1023 if (NILP (features[i]))
1024 continue;
1025
1026
1027 if (!CONSP (features[i]))
1028 goto no_support;
1029
1030
1031 OTF_INT16_VAL (tbl, 4, &scriptlist_table);
1032 OTF_INT16_VAL (tbl, 6, &feature_table);
1033 OTF_INT16_VAL (tbl, scriptlist_table, &n_scripts);
1034
1035
1036 script_table = 0;
1037 for (j = 0; j < n_scripts; j++)
1038 {
1039 DWORD script_id;
1040 OTF_DWORDTAG_VAL (tbl, scriptlist_table + 2 + j * 6, &script_id);
1041 if (script_id == script_tag)
1042 {
1043 OTF_INT16_VAL (tbl, scriptlist_table + 6 + j * 6, &script_table);
1044 break;
1045 }
1046 #if 0
1047
1048
1049 else if (script_id == default_script)
1050 OTF_INT16_VAL (tbl, scriptlist_table + 6 + j * 6, &script_table);
1051 #endif
1052 }
1053
1054
1055 if (!script_table)
1056 goto no_support;
1057
1058
1059 script_table += scriptlist_table;
1060
1061
1062 OTF_INT16_VAL (tbl, script_table, &langsys_table);
1063
1064
1065 if (!NILP (lang))
1066 {
1067 OTF_INT16_VAL (tbl, script_table + 2, &n_langs);
1068
1069 for (j = 0; j < n_langs; j++)
1070 {
1071 DWORD lang_id;
1072 OTF_DWORDTAG_VAL (tbl, script_table + 4 + j * 6, &lang_id);
1073 if (lang_id == lang_tag)
1074 {
1075 OTF_INT16_VAL (tbl, script_table + 8 + j * 6, &langsys_table);
1076 break;
1077 }
1078 }
1079 }
1080
1081 if (!langsys_table)
1082 goto no_support;
1083
1084
1085 langsys_table += script_table;
1086
1087
1088 if (NILP (features[i]))
1089 continue;
1090 if (!CONSP (features[i]))
1091 goto no_support;
1092
1093 n_match_features = 0;
1094
1095
1096 OTF_INT16_VAL (tbl, langsys_table + 2, &feature_index);
1097 if (feature_index != 0xFFFF)
1098 n_match_features = 1;
1099 OTF_INT16_VAL (tbl, langsys_table + 4, &n_features);
1100 n_match_features += n_features;
1101 USE_SAFE_ALLOCA;
1102 SAFE_NALLOCA (ftags, 1, n_match_features);
1103 int k = 0;
1104 if (feature_index != 0xFFFF)
1105 {
1106 OTF_DWORDTAG_VAL (tbl, feature_table + 2 + feature_index * 6,
1107 &feature_id);
1108 ftags[k++] = feature_id;
1109 }
1110
1111 for (j = 0; j < n_features; j++)
1112 {
1113 OTF_INT16_VAL (tbl, langsys_table + 6 + j * 2, &feature_index);
1114 OTF_DWORDTAG_VAL (tbl, feature_table + 2 + feature_index * 6,
1115 &feature_id);
1116 ftags[k++] = feature_id;
1117 }
1118
1119
1120 farray[0] = features[i];
1121 farray[1] = Qnil;
1122 if (!uniscribe_check_features (farray, ftags, n_match_features))
1123 goto no_support;
1124 SAFE_FREE ();
1125 }
1126
1127 retval = 1;
1128
1129 done:
1130 no_support:
1131 font_table_error:
1132
1133 SelectObject (context, old_font);
1134 DeleteObject (check_font);
1135 release_frame_dc (f, context);
1136
1137 return retval;
1138 }
1139
1140 static Lisp_Object
1141 otf_features (HDC context, const char *table)
1142 {
1143 Lisp_Object script_list = Qnil;
1144 unsigned short scriptlist_table, n_scripts, feature_table;
1145 DWORD tbl = OTF_TAG (table);
1146 int i, j, k;
1147
1148
1149 OTF_INT16_VAL (tbl, 4, &scriptlist_table);
1150 OTF_INT16_VAL (tbl, 6, &feature_table);
1151 OTF_INT16_VAL (tbl, scriptlist_table, &n_scripts);
1152
1153 for (i = n_scripts - 1; i >= 0; i--)
1154 {
1155 char script[5], lang[5];
1156 unsigned short script_table, lang_count, langsys_table, feature_count;
1157 Lisp_Object script_tag, langsys_list, langsys_tag, feature_list;
1158 unsigned short record_offset = scriptlist_table + 2 + i * 6;
1159 OTF_TAG_VAL (tbl, record_offset, script);
1160 OTF_INT16_VAL (tbl, record_offset + 4, &script_table);
1161
1162
1163 script_table += scriptlist_table;
1164
1165 script_tag = intern (script);
1166 langsys_list = Qnil;
1167
1168
1169 OTF_INT16_VAL (tbl, script_table, &langsys_table);
1170 if (langsys_table)
1171 {
1172
1173 langsys_table += script_table;
1174
1175 langsys_tag = Qnil;
1176 feature_list = Qnil;
1177 OTF_INT16_VAL (tbl, langsys_table + 4, &feature_count);
1178 for (k = feature_count - 1; k >= 0; k--)
1179 {
1180 char feature[5];
1181 unsigned short index;
1182 OTF_INT16_VAL (tbl, langsys_table + 6 + k * 2, &index);
1183 OTF_TAG_VAL (tbl, feature_table + 2 + index * 6, feature);
1184 feature_list = Fcons (intern (feature), feature_list);
1185 }
1186 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1187 langsys_list);
1188 }
1189
1190
1191 OTF_INT16_VAL (tbl, script_table + 2, &lang_count);
1192
1193 for (j = lang_count - 1; j >= 0; j--)
1194 {
1195 record_offset = script_table + 4 + j * 6;
1196 OTF_TAG_VAL (tbl, record_offset, lang);
1197 OTF_INT16_VAL (tbl, record_offset + 4, &langsys_table);
1198
1199
1200 langsys_table += script_table;
1201
1202 langsys_tag = intern (lang);
1203 feature_list = Qnil;
1204 OTF_INT16_VAL (tbl, langsys_table + 4, &feature_count);
1205 for (k = feature_count - 1; k >= 0; k--)
1206 {
1207 char feature[5];
1208 unsigned short index;
1209 OTF_INT16_VAL (tbl, langsys_table + 6 + k * 2, &index);
1210 OTF_TAG_VAL (tbl, feature_table + 2 + index * 6, feature);
1211 feature_list = Fcons (intern (feature), feature_list);
1212 }
1213 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1214 langsys_list);
1215
1216 }
1217
1218 script_list = Fcons (Fcons (script_tag, langsys_list), script_list);
1219 }
1220
1221 return script_list;
1222
1223 font_table_error:
1224 return Qnil;
1225 }
1226
1227 #ifdef HAVE_HARFBUZZ
1228
1229
1230 static Lisp_Object
1231 w32hb_list (struct frame *f, Lisp_Object font_spec)
1232 {
1233 Lisp_Object fonts = w32font_list_internal (f, font_spec, true);
1234 FONT_ADD_LOG ("harfbuzz-list", font_spec, fonts);
1235
1236 for (Lisp_Object tail = fonts; CONSP (tail); tail = XCDR (tail))
1237 ASET (XCAR (tail), FONT_TYPE_INDEX, Qharfbuzz);
1238
1239 return fonts;
1240 }
1241
1242
1243 static Lisp_Object
1244 w32hb_match (struct frame *f, Lisp_Object font_spec)
1245 {
1246 Lisp_Object entity = w32font_match_internal (f, font_spec, true);
1247 FONT_ADD_LOG ("harfbuzz-match", font_spec, entity);
1248
1249 if (! NILP (entity))
1250 ASET (entity, FONT_TYPE_INDEX, Qharfbuzz);
1251 return entity;
1252 }
1253
1254
1255
1256
1257
1258 static void
1259 free_cb (void *ptr)
1260 {
1261 free (ptr);
1262 }
1263
1264
1265
1266 static hb_blob_t *
1267 w32hb_get_font_table (hb_face_t *face, hb_tag_t tag, void *data)
1268 {
1269 struct frame *f = XFRAME (selected_frame);
1270 HDC context = get_frame_dc (f);
1271 HFONT old_font = SelectObject (context, (HFONT) data);
1272 char *font_data = NULL;
1273 DWORD font_data_size = 0, val;
1274 DWORD table = bswap_32 (tag);
1275 hb_blob_t *blob = NULL;
1276
1277 val = GetFontData (context, table, 0, font_data, font_data_size);
1278 if (val != GDI_ERROR)
1279 {
1280 font_data_size = val;
1281
1282
1283 font_data = malloc (font_data_size);
1284 if (font_data)
1285 {
1286 val = GetFontData (context, table, 0, font_data, font_data_size);
1287 if (val != GDI_ERROR)
1288 blob = hb_blob_create (font_data, font_data_size,
1289 HB_MEMORY_MODE_READONLY, font_data, free_cb);
1290 }
1291 }
1292
1293
1294 SelectObject (context, old_font);
1295 release_frame_dc (f, context);
1296
1297 return blob;
1298 }
1299
1300
1301
1302
1303 static hb_font_t *
1304 w32hb_get_font (struct font *font, double *scale)
1305 {
1306 hb_font_t *hb_font = NULL;
1307 HFONT font_handle = FONT_HANDLE (font);
1308 hb_face_t *hb_face =
1309 hb_face_create_for_tables (w32hb_get_font_table, font_handle, NULL);
1310 if (hb_face_get_glyph_count (hb_face) > 0)
1311 {
1312 hb_font = hb_font_create (hb_face);
1313
1314
1315 hb_ot_font_set_funcs (hb_font);
1316 }
1317
1318 struct uniscribe_font_info *uniscribe_font =
1319 (struct uniscribe_font_info *) font;
1320 unsigned upem = hb_face_get_upem (hb_face);
1321 eassert (upem > 0);
1322
1323 LONG font_point_size =
1324 uniscribe_font->w32_font.metrics.tmHeight
1325 - uniscribe_font->w32_font.metrics.tmInternalLeading;
1326
1327
1328 *scale = font_point_size * 1.0 / upem;
1329
1330 hb_face_destroy (hb_face);
1331
1332
1333 return hb_font;
1334 }
1335
1336
1337 static unsigned
1338 w32hb_encode_char (struct font *font, int c)
1339 {
1340 struct uniscribe_font_info *uniscribe_font
1341 = (struct uniscribe_font_info *) font;
1342 eassert (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver);
1343 hb_font_t *hb_font = uniscribe_font->cache;
1344
1345
1346
1347 if (!hb_font)
1348 {
1349 double scale;
1350 hb_font = w32hb_get_font (font, &scale);
1351 if (!hb_font)
1352 return FONT_INVALID_CODE;
1353
1354 uniscribe_font->cache = hb_font;
1355 eassert (scale > 0.0);
1356 uniscribe_font->scale = scale;
1357 }
1358 hb_codepoint_t glyph;
1359 if (hb_font_get_nominal_glyph (hb_font, c, &glyph))
1360 return glyph;
1361 return FONT_INVALID_CODE;
1362 }
1363
1364
1365
1366
1367
1368
1369
1370
1371 static hb_font_t *
1372 w32hb_begin_font (struct font *font, double *position_unit)
1373 {
1374 struct uniscribe_font_info *uniscribe_font
1375 = (struct uniscribe_font_info *) font;
1376 eassert (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver);
1377
1378
1379
1380 if (!uniscribe_font->cache)
1381 {
1382 double scale;
1383 uniscribe_font->cache = w32hb_get_font (font, &scale);
1384 eassert (scale > 0.0);
1385 uniscribe_font->scale = scale;
1386 }
1387 *position_unit = uniscribe_font->scale;
1388 return (hb_font_t *) uniscribe_font->cache;
1389 }
1390
1391
1392
1393
1394
1395
1396
1397 static int
1398 w32hb_get_variation_glyphs (struct font *font, int c, unsigned variations[256])
1399 {
1400 struct uniscribe_font_info *uniscribe_font
1401 = (struct uniscribe_font_info *) font;
1402 eassert (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver);
1403
1404
1405
1406 if (!uniscribe_font->cache)
1407 {
1408 double scale;
1409 uniscribe_font->cache = w32hb_get_font (font, &scale);
1410 eassert (scale > 0.0);
1411 uniscribe_font->scale = scale;
1412 }
1413
1414 int i, n = 0;
1415 hb_font_t *hb_font = uniscribe_font->cache;
1416 for (i = 0; i < 16; i++)
1417 {
1418 if (hb_font_get_variation_glyph (hb_font, c, 0xFE00 + i, &variations[i]))
1419 n++;
1420 else
1421 variations[i] = 0;
1422 }
1423 for ( ; i < 256; i++)
1424 {
1425 if (hb_font_get_variation_glyph (hb_font, c, 0xE0100 + (i - 16),
1426 &variations[i]))
1427 n++;
1428 else
1429 variations[i] = 0;
1430 }
1431
1432 return n;
1433 }
1434 #endif
1435
1436 #undef OTF_INT16_VAL
1437 #undef OTF_TAG_VAL
1438 #undef OTF_TAG
1439
1440
1441 struct font_driver uniscribe_font_driver =
1442 {
1443 LISPSYM_INITIALLY (Quniscribe),
1444 0,
1445 w32font_get_cache,
1446 uniscribe_list,
1447 uniscribe_match,
1448 uniscribe_list_family,
1449 NULL,
1450 uniscribe_open,
1451 uniscribe_close,
1452 NULL,
1453 NULL,
1454 w32font_has_char,
1455 uniscribe_encode_char,
1456 w32font_text_extents,
1457 w32font_draw,
1458 NULL,
1459 NULL,
1460 NULL,
1461 uniscribe_otf_capability,
1462 NULL,
1463 NULL,
1464 NULL,
1465 uniscribe_shape,
1466 NULL,
1467 NULL,
1468 NULL,
1469 NULL,
1470 };
1471
1472
1473
1474 void syms_of_w32uniscribe (void);
1475
1476 static void syms_of_w32uniscribe_for_pdumper (void);
1477
1478 void
1479 syms_of_w32uniscribe (void)
1480 {
1481 pdumper_do_now_and_after_load (syms_of_w32uniscribe_for_pdumper);
1482 }
1483
1484 #ifdef HAVE_HARFBUZZ
1485 static bool
1486 load_harfbuzz_funcs (HMODULE library)
1487 {
1488 LOAD_DLL_FN (library, hb_blob_create);
1489 LOAD_DLL_FN (library, hb_face_create_for_tables);
1490 LOAD_DLL_FN (library, hb_face_get_glyph_count);
1491 LOAD_DLL_FN (library, hb_font_create);
1492 LOAD_DLL_FN (library, hb_font_destroy);
1493 LOAD_DLL_FN (library, hb_face_get_upem);
1494 LOAD_DLL_FN (library, hb_face_destroy);
1495 LOAD_DLL_FN (library, hb_font_get_nominal_glyph);
1496 LOAD_DLL_FN (library, hb_font_get_variation_glyph);
1497 LOAD_DLL_FN (library, hb_ot_font_set_funcs);
1498 return hbfont_init_w32_funcs (library);
1499 }
1500 #endif
1501
1502 static void
1503 syms_of_w32uniscribe_for_pdumper (void)
1504 {
1505
1506 if (!initialized)
1507 return;
1508
1509
1510 HMODULE uniscribe = GetModuleHandle ("usp10");
1511 if (!uniscribe)
1512 return;
1513
1514 uniscribe_available = 1;
1515
1516 register_font_driver (&uniscribe_font_driver, NULL);
1517
1518 script_get_font_scripts_fn = (ScriptGetFontScriptTags_Proc)
1519 get_proc_addr (uniscribe, "ScriptGetFontScriptTags");
1520 script_get_font_languages_fn = (ScriptGetFontLanguageTags_Proc)
1521 get_proc_addr (uniscribe, "ScriptGetFontLanguageTags");
1522 script_get_font_features_fn = (ScriptGetFontFeatureTags_Proc)
1523 get_proc_addr (uniscribe, "ScriptGetFontFeatureTags");
1524 if (script_get_font_scripts_fn
1525 && script_get_font_languages_fn
1526 && script_get_font_features_fn)
1527 uniscribe_new_apis = true;
1528 else
1529 uniscribe_new_apis = false;
1530
1531 #ifdef HAVE_HARFBUZZ
1532
1533
1534
1535
1536
1537 HMODULE harfbuzz = LoadLibrary ("libharfbuzz-0.dll");
1538
1539 if (!harfbuzz)
1540 return;
1541
1542 if (!load_harfbuzz_funcs (harfbuzz))
1543 return;
1544
1545 Fput (Quniscribe, Qfont_driver_superseded_by, Qharfbuzz);
1546 harfbuzz_available = 1;
1547 harfbuzz_font_driver = uniscribe_font_driver;
1548 harfbuzz_font_driver.type = Qharfbuzz;
1549 harfbuzz_font_driver.list = w32hb_list;
1550 harfbuzz_font_driver.match = w32hb_match;
1551 harfbuzz_font_driver.encode_char = w32hb_encode_char;
1552 harfbuzz_font_driver.otf_capability = hbfont_otf_capability;
1553 harfbuzz_font_driver.shape = hbfont_shape;
1554 harfbuzz_font_driver.get_variation_glyphs = w32hb_get_variation_glyphs;
1555 harfbuzz_font_driver.combining_capability = hbfont_combining_capability;
1556 harfbuzz_font_driver.begin_hb_font = w32hb_begin_font;
1557 register_font_driver (&harfbuzz_font_driver, NULL);
1558 #endif
1559 }