This source file includes following definitions.
- sfnt_setup_coding_system
- sfnt_safe_decode_coding_object_1
- sfnt_safe_decode_coding_object_2
- sfnt_safe_decode_coding_object
- sfnt_decode_font_string
- sfnt_decode_family_style
- sfnt_decode_foundry_name
- sfnt_decode_instance_name
- sfnt_parse_style
- sfnt_parse_languages
- sfnt_registry_for_subtable
- sfntfont_identify_cmap
- sfnt_grok_registry
- sfnt_replace_fonts_p
- sfnt_enum_font_1
- sfnt_enum_font
- sfntfont_charset_for_name
- sfntfont_charset_for_cmap
- sfntfont_select_cmap
- sfntfont_read_cmap
- sfntfont_glyph_valid
- sfntfont_lookup_char
- sfntfont_registries_compatible_p
- sfntfont_list_1
- sfntfont_registry_for_desc
- sfntfont_desc_to_entity
- sfntfont_list
- sfntfont_match
- sfntfont_get_glyph
- sfntfont_free_glyph
- sfntfont_get_metrics
- sfntfont_dereference_outline
- sfntfont_get_glyph_outline
- sfntfont_free_outline_cache
- sfntfont_dereference_raster
- sfntfont_get_glyph_raster
- sfntfont_free_raster_cache
- sfntfont_lookup_glyph
- sfntfont_probe_widths
- sfntfont_setup_interpreter
- sfnt_close_tables
- sfnt_open_tables
- sfnt_reference_font_tables
- sfnt_dereference_font_tables
- sfntfont_open
- sfntfont_encode_char
- sfntfont_measure_pcm
- sfntfont_text_extents
- sfntfont_close
- sfntfont_draw
- sfntfont_list_family
- sfntfont_get_variation_glyphs
- sfntfont_detect_sigbus
- sfntfont_unmap_blob
- sfntfont_get_font_table
- sfntfont_begin_hb_font
- syms_of_sfntfont
- mark_sfntfont
- init_sfntfont
- init_sfntfont_vendor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include <fcntl.h>
23 #include <ctype.h>
24
25 #include "lisp.h"
26
27 #include "blockinput.h"
28 #include "charset.h"
29 #include "coding.h"
30 #include "font.h"
31 #include "frame.h"
32 #include "math.h"
33 #include "sfnt.h"
34 #include "sfntfont.h"
35
36 #ifdef HAVE_HARFBUZZ
37 #include <hb.h>
38 #include <hb-ot.h>
39 #endif
40
41
42 #include TERM_HEADER
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 struct sfnt_font_tables
58 {
59
60 struct sfnt_cmap_table *cmap;
61 struct sfnt_hhea_table *hhea;
62 struct sfnt_maxp_table *maxp;
63 struct sfnt_head_table *head;
64 struct sfnt_hmtx_table *hmtx;
65 struct sfnt_glyf_table *glyf;
66 struct sfnt_loca_table_short *loca_short;
67 struct sfnt_loca_table_long *loca_long;
68 struct sfnt_prep_table *prep;
69 struct sfnt_fpgm_table *fpgm;
70 struct sfnt_cvt_table *cvt;
71 struct sfnt_fvar_table *fvar;
72 struct sfnt_avar_table *avar;
73 struct sfnt_gvar_table *gvar;
74 struct sfnt_cvar_table *cvar;
75
76
77 struct sfnt_cmap_encoding_subtable_data *cmap_data;
78
79
80 struct sfnt_cmap_encoding_subtable cmap_subtable;
81
82
83 struct sfnt_uvs_context *uvs;
84
85 #ifdef HAVE_MMAP
86
87 bool glyf_table_mapped;
88 #endif
89
90 #ifdef HAVE_HARFBUZZ
91
92 int fd;
93
94
95 struct sfnt_offset_subtable *directory;
96 #endif
97 };
98
99
100
101 struct sfnt_font_desc
102 {
103
104 struct sfnt_font_desc *next;
105
106
107 Lisp_Object family;
108
109
110 Lisp_Object style;
111
112
113 Lisp_Object designer;
114
115
116 Lisp_Object adstyle;
117
118
119 Lisp_Object languages;
120
121
122 Lisp_Object registry;
123
124
125
126
127 Lisp_Object instances;
128
129
130 int width, weight, slant, spacing;
131
132
133 char *path;
134
135
136
137 Lisp_Object char_cache;
138
139
140 bool cmap_invalid;
141
142
143
144 struct sfnt_cmap_encoding_subtable subtable;
145
146
147 off_t offset;
148
149
150
151 int num_glyphs;
152
153
154 int refcount;
155
156
157 struct sfnt_font_tables *tables;
158 };
159
160
161
162 static struct sfnt_font_desc *system_fonts;
163
164
165
166
167
168
169
170
171
172
173 static int
174 sfnt_setup_coding_system (enum sfnt_platform_id id, int platform_specific_id,
175 struct coding_system *coding)
176 {
177 Lisp_Object system;
178
179 system = Qnil;
180
181
182
183 switch (id)
184 {
185 case SFNT_PLATFORM_UNICODE:
186 system = Qutf_16be;
187 break;
188
189 case SFNT_PLATFORM_MACINTOSH:
190
191 if (platform_specific_id == SFNT_MACINTOSH_ROMAN)
192 system = Qmac_roman;
193 else
194
195 system = Qnil;
196
197 break;
198
199 case SFNT_PLATFORM_MICROSOFT:
200 system = Qutf_16be;
201
202
203 if (platform_specific_id == SFNT_MICROSOFT_BIG_FIVE)
204 system = Qchinese_big5;
205
206 break;
207
208 default:
209 system = Qnil;
210 }
211
212 if (NILP (system))
213 return 1;
214
215 setup_coding_system (system, coding);
216 return 0;
217 }
218
219
220 static struct coding_system *sfnt_font_coding;
221
222
223
224 static Lisp_Object sfnt_font_src_object;
225
226
227 static ptrdiff_t sfnt_font_from, sfnt_font_from_byte;
228
229
230 static ptrdiff_t sfnt_font_to, sfnt_font_to_byte;
231
232
233
234 static Lisp_Object sfnt_font_dst_object;
235
236
237 static bool sfnt_font_signal;
238
239 static Lisp_Object
240 sfnt_safe_decode_coding_object_1 (void)
241 {
242 decode_coding_object (sfnt_font_coding,
243 sfnt_font_src_object,
244 sfnt_font_from,
245 sfnt_font_from_byte,
246 sfnt_font_to,
247 sfnt_font_to_byte,
248 sfnt_font_dst_object);
249 return Qnil;
250 }
251
252 static Lisp_Object
253 sfnt_safe_decode_coding_object_2 (Lisp_Object error)
254 {
255 sfnt_font_signal = true;
256
257 return Qnil;
258 }
259
260
261
262
263 static int
264 sfnt_safe_decode_coding_object (struct coding_system *coding,
265 Lisp_Object src_object,
266 ptrdiff_t from, ptrdiff_t from_byte,
267 ptrdiff_t to, ptrdiff_t to_byte,
268 Lisp_Object dst_object)
269 {
270 sfnt_font_coding = coding;
271 sfnt_font_src_object = src_object;
272 sfnt_font_from = from;
273 sfnt_font_from_byte = from_byte;
274 sfnt_font_to = to;
275 sfnt_font_to_byte = to_byte;
276 sfnt_font_dst_object = dst_object;
277 sfnt_font_signal = false;
278
279 internal_condition_case (sfnt_safe_decode_coding_object_1,
280 Qt,
281 sfnt_safe_decode_coding_object_2);
282
283 return (int) sfnt_font_signal;
284 }
285
286
287
288
289
290
291
292
293 static Lisp_Object
294 sfnt_decode_font_string (unsigned char *data, enum sfnt_platform_id id,
295 int platform_specific_id, int language_id,
296 size_t length)
297 {
298 struct coding_system coding;
299
300 memset (&coding, 0, sizeof coding);
301 sfnt_setup_coding_system (id, platform_specific_id, &coding);
302 coding.mode |= CODING_MODE_SAFE_ENCODING;
303 coding.mode |= CODING_MODE_LAST_BLOCK;
304
305 coding.common_flags &= ~CODING_ANNOTATION_MASK;
306 coding.source = data;
307
308 if (sfnt_safe_decode_coding_object (&coding, Qnil, 0, 0,
309 length, length, Qt))
310 return Qnil;
311
312 return coding.dst_object;
313 }
314
315
316
317
318 static int
319 sfnt_decode_family_style (struct sfnt_name_table *name,
320 Lisp_Object *family, Lisp_Object *style)
321 {
322 struct sfnt_name_record family_rec, style_rec;
323 unsigned char *family_data, *style_data;
324
325
326
327
328
329
330
331
332
333
334
335 family_data = sfnt_find_name (name, SFNT_NAME_PREFERRED_FAMILY,
336 &family_rec);
337
338 if (!family_data)
339 family_data = sfnt_find_name (name, SFNT_NAME_FONT_FAMILY,
340 &family_rec);
341
342 style_data = sfnt_find_name (name, SFNT_NAME_PREFERRED_SUBFAMILY,
343 &style_rec);
344
345 if (!style_data)
346 style_data = sfnt_find_name (name, SFNT_NAME_FONT_SUBFAMILY,
347 &style_rec);
348
349 if (!family_data || !style_data)
350 return 1;
351
352
353 *family = sfnt_decode_font_string (family_data,
354 family_rec.platform_id,
355 family_rec.platform_specific_id,
356 family_rec.language_id,
357 family_rec.length);
358 *style = sfnt_decode_font_string (style_data,
359 style_rec.platform_id,
360 style_rec.platform_specific_id,
361 style_rec.language_id,
362 style_rec.length);
363
364
365 return (!NILP (*family) && !NILP (*style)) ? 0 : 1;
366 }
367
368
369
370
371 static Lisp_Object
372 sfnt_decode_foundry_name (struct sfnt_name_table *name)
373 {
374 struct sfnt_name_record designer_rec;
375 unsigned char *designer_data;
376
377 designer_data = sfnt_find_name (name, SFNT_NAME_DESIGNER,
378 &designer_rec);
379
380 if (!designer_data)
381 return Qnil;
382
383 return sfnt_decode_font_string (designer_data,
384 designer_rec.platform_id,
385 designer_rec.platform_specific_id,
386 designer_rec.language_id,
387 designer_rec.length);
388 }
389
390
391
392
393 static Lisp_Object
394 sfnt_decode_instance_name (struct sfnt_instance *instance,
395 struct sfnt_name_table *name)
396 {
397 struct sfnt_name_record name_rec;
398 unsigned char *name_data;
399
400 name_data = sfnt_find_name (name, instance->name_id,
401 &name_rec);
402
403 if (!name_data)
404 return Qnil;
405
406 return sfnt_decode_font_string (name_data,
407 name_rec.platform_id,
408 name_rec.platform_specific_id,
409 name_rec.language_id,
410 name_rec.length);
411 }
412
413 struct sfnt_style_desc
414 {
415
416 const char *c_string;
417
418
419 int value;
420 };
421
422
423 static struct sfnt_style_desc sfnt_weight_descriptions[] =
424 {
425 { "thin", 0, },
426 { "extralight", 40, },
427 { "ultralight", 40, },
428 { "light", 50, },
429 { "demilight", 55, },
430 { "semilight", 55, },
431 { "book", 75, },
432 { "medium", 100, },
433 { "demibold", 180, },
434 { "semibold", 180, },
435 { "bold", 200, },
436 { "extrabold", 205, },
437 { "ultrabold", 205, },
438 { "black", 210, },
439 { "heavy", 210, },
440 { "extrablack", 215, },
441 { "ultrablack", 215, },
442 };
443
444
445 static struct sfnt_style_desc sfnt_slant_descriptions[] =
446 {
447 { "italic", 200, },
448 { "oblique", 210, },
449 };
450
451
452 static struct sfnt_style_desc sfnt_width_descriptions[] =
453 {
454 { "ultracondensed", 50, },
455 { "extracondensed", 63, },
456 { "condensed", 75, },
457 { "semicondensed", 87, },
458 { "semiexpanded", 113, },
459 { "expanded", 125, },
460 { "extraexpanded", 150, },
461 { "ultraexpanded", 200, },
462 };
463
464
465
466
467
468
469 static void
470 sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc)
471 {
472 char *style, *single, *saveptr;
473 int i;
474 USE_SAFE_ALLOCA;
475
476
477
478 desc->weight = 80;
479 desc->slant = 100;
480 desc->width = 100;
481
482
483
484
485
486 SAFE_ALLOCA_STRING (style, Fdowncase (style_name));
487 saveptr = NULL;
488
489 while ((single = strtok_r (style, " ", &saveptr)))
490 {
491 style = NULL;
492
493 if (desc->weight == 80)
494 {
495
496
497 for (i = 0; i < ARRAYELTS (sfnt_weight_descriptions); ++i)
498 {
499 if (!strcmp (sfnt_weight_descriptions[i].c_string,
500 single))
501 {
502
503
504 desc->weight = sfnt_weight_descriptions[i].value;
505 goto next;
506 }
507 }
508 }
509
510 if (desc->slant == 100)
511 {
512
513
514 for (i = 0; i < ARRAYELTS (sfnt_slant_descriptions); ++i)
515 {
516 if (!strcmp (sfnt_slant_descriptions[i].c_string,
517 single))
518 {
519
520
521 desc->slant = sfnt_slant_descriptions[i].value;
522 goto next;
523 }
524 }
525 }
526
527 if (desc->width == 100)
528 {
529
530
531 for (i = 0; i < ARRAYELTS (sfnt_width_descriptions); ++i)
532 {
533 if (!strcmp (sfnt_width_descriptions[i].c_string,
534 single))
535 {
536
537
538 desc->width = sfnt_width_descriptions[i].value;
539 goto next;
540 }
541 }
542 }
543
544
545
546
547 if (strlen (single))
548 {
549 if (islower (single[0]))
550 single[0] = toupper (single[0]);
551
552 if (NILP (desc->adstyle))
553 desc->adstyle = build_string (single);
554 else
555 desc->adstyle = CALLN (Fconcat, desc->adstyle,
556 build_string (" "),
557 build_string (single));
558 }
559
560 next:
561 continue;
562 }
563
564 SAFE_FREE ();
565 }
566
567
568
569
570
571 static void
572 sfnt_parse_languages (struct sfnt_meta_table *meta,
573 struct sfnt_font_desc *desc)
574 {
575 char *data, *metadata, *tag;
576 struct sfnt_meta_data_map map;
577 char *saveptr;
578
579
580
581
582
583
584
585
586
587
588 saveptr = NULL;
589 data = sfnt_find_metadata (meta, SFNT_META_DATA_TAG_DLNG,
590 &map);
591
592 if (!data)
593 {
594
595 data = sfnt_find_metadata (meta, SFNT_META_DATA_TAG_SLNG,
596 &map);
597
598 if (!data)
599 return;
600 }
601
602 USE_SAFE_ALLOCA;
603
604
605
606 if (map.data_length >= SIZE_MAX)
607 memory_full (SIZE_MAX);
608
609 metadata = SAFE_ALLOCA ((size_t) map.data_length + 1);
610 memcpy (metadata, data, map.data_length);
611 metadata[map.data_length] = '\0';
612
613
614
615 while ((tag = strtok_r (metadata, ",", &saveptr)))
616 {
617 metadata = NULL;
618
619 if (strstr (tag, "Hans") || strstr (tag, "Hant"))
620 desc->languages = Fcons (Qzh, desc->languages);
621
622 if (strstr (tag, "Japn"))
623 desc->languages = Fcons (Qja, desc->languages);
624
625 if (strstr (tag, "Kore"))
626 desc->languages = Fcons (Qko, desc->languages);
627 }
628
629 SAFE_FREE ();
630 }
631
632
633
634
635
636
637
638
639
640
641
642
643 static Lisp_Object
644 sfnt_registry_for_subtable (struct sfnt_cmap_encoding_subtable *subtable)
645 {
646 switch (subtable->platform_id)
647 {
648 case SFNT_PLATFORM_UNICODE:
649
650 if ((subtable->platform_specific_id
651 == SFNT_UNICODE_VARIATION_SEQUENCES)
652 || (subtable->platform_specific_id
653 == SFNT_UNICODE_LAST_RESORT))
654 return Qnil;
655
656 return Qiso10646_1;
657
658 case SFNT_PLATFORM_MACINTOSH:
659
660 switch (subtable->platform_specific_id)
661 {
662 case SFNT_MACINTOSH_ROMAN:
663
664 return Qapple_roman;
665
666 default:
667
668 return Qnil;
669 }
670
671 case SFNT_PLATFORM_MICROSOFT:
672
673
674
675 switch (subtable->platform_specific_id)
676 {
677 case SFNT_MICROSOFT_SYMBOL:
678 case SFNT_MICROSOFT_UNICODE_BMP:
679
680 return Qiso10646_1;
681
682 case SFNT_MICROSOFT_SHIFT_JIS:
683 return Qjisx0208_1983_0;
684
685 case SFNT_MICROSOFT_PRC:
686 return Qgbk;
687
688 case SFNT_MICROSOFT_JOHAB:
689 return Qksc5601_1987_0;
690
691 case SFNT_MICROSOFT_UNICODE_UCS_4:
692 return Qiso10646_1;
693 }
694
695 default:
696 return Qnil;
697 }
698 }
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713 static int
714 sfntfont_identify_cmap (struct sfnt_cmap_encoding_subtable subtable)
715 {
716 switch (subtable.platform_id)
717 {
718 case SFNT_PLATFORM_UNICODE:
719
720
721 if ((subtable.platform_specific_id
722 == SFNT_UNICODE_VARIATION_SEQUENCES)
723 || (subtable.platform_specific_id
724 == SFNT_UNICODE_LAST_RESORT))
725 return 3;
726
727
728
729 if (subtable.platform_specific_id < SFNT_UNICODE_2_0)
730 return 1;
731
732 return 2;
733
734 case SFNT_PLATFORM_MACINTOSH:
735
736 switch (subtable.platform_specific_id)
737 {
738 case SFNT_MACINTOSH_ROMAN:
739
740 return 0;
741
742 default:
743
744 return 3;
745 }
746
747 case SFNT_PLATFORM_MICROSOFT:
748
749
750
751 switch (subtable.platform_specific_id)
752 {
753 case SFNT_MICROSOFT_SYMBOL:
754
755 return 1;
756
757 case SFNT_MICROSOFT_UNICODE_BMP:
758 return 1;
759
760 case SFNT_MICROSOFT_SHIFT_JIS:
761
762 return 0;
763
764 case SFNT_MICROSOFT_PRC:
765
766 return 0;
767
768 case SFNT_MICROSOFT_JOHAB:
769
770 return 0;
771
772 case SFNT_MICROSOFT_UNICODE_UCS_4:
773
774 return 2;
775 }
776
777 default:
778 return 3;
779 }
780 }
781
782
783
784
785
786
787
788 static void
789 sfnt_grok_registry (int fd, struct sfnt_font_desc *desc,
790 struct sfnt_offset_subtable *subtable)
791 {
792 struct sfnt_cmap_table *cmap;
793 struct sfnt_cmap_encoding_subtable *subtables;
794 int i;
795
796 cmap = sfnt_read_cmap_table (fd, subtable, &subtables, NULL);
797
798 if (!cmap)
799 return;
800
801
802
803
804
805
806
807
808
809
810
811 for (i = 0; i < cmap->num_subtables; ++i)
812 {
813 if (sfntfont_identify_cmap (subtables[i]) == 2)
814 {
815 desc->registry
816 = sfnt_registry_for_subtable (&subtables[i]);
817 goto done;
818 }
819 }
820
821
822
823 for (i = 0; i < cmap->num_subtables; ++i)
824 {
825 if (sfntfont_identify_cmap (subtables[i]) == 1)
826 {
827 desc->registry
828 = sfnt_registry_for_subtable (&subtables[i]);
829 goto done;
830 }
831 }
832
833
834
835
836 for (i = 0; i < cmap->num_subtables; ++i)
837 {
838 if (sfntfont_identify_cmap (subtables[i]) == 0)
839 {
840 desc->registry
841 = sfnt_registry_for_subtable (&subtables[i]);
842 goto done;
843 }
844 }
845
846
847 done:
848 xfree (cmap);
849 xfree (subtables);
850 }
851
852
853
854
855
856
857
858
859
860
861
862 static bool
863 sfnt_replace_fonts_p (struct sfnt_font_desc *prev,
864 struct sfnt_font_desc *desc)
865 {
866 int i, j, width, weight, slant, count_instance;
867 Lisp_Object tem, tem1;
868 bool family_equal_p;
869
870 family_equal_p = !NILP (Fstring_equal (prev->family,
871 desc->family));
872
873 if ((!NILP (desc->instances)
874 || !NILP (Fstring_equal (prev->style, desc->style)))
875 && family_equal_p)
876 {
877
878 if (!NILP (desc->instances) && !NILP (prev->instances))
879 {
880
881
882
883
884 count_instance = 0;
885 for (i = 0; i < ASIZE (prev->instances); ++i)
886 {
887 tem = AREF (prev->instances, i);
888
889 if (NILP (tem))
890 continue;
891
892 for (j = 0; j < ASIZE (desc->instances); ++j)
893 {
894 tem1 = AREF (desc->instances, j);
895
896 if (NILP (tem1))
897 continue;
898
899 if (!NILP (Fequal (tem1, tem)))
900 {
901
902
903 ASET (prev->instances, i, Qnil);
904 goto next;
905 }
906 }
907
908
909
910 count_instance++;
911
912 next:
913 ;
914 }
915
916
917
918
919 return !count_instance;
920 }
921
922 return true;
923 }
924
925 if (NILP (prev->instances) || !family_equal_p)
926 return false;
927
928
929
930
931 count_instance = 0;
932 for (i = 0; i < ASIZE (prev->instances); ++i)
933 {
934 tem = AREF (prev->instances, i);
935
936 if (NILP (tem))
937 continue;
938
939 width = XFIXNUM (AREF (tem, 2));
940 weight = XFIXNUM (AREF (tem, 3));
941 slant = XFIXNUM (AREF (tem, 4));
942
943 if (desc->width == width
944 && desc->weight == weight
945 && desc->slant == slant)
946 {
947
948 ASET (prev->instances, i, Qnil);
949 continue;
950 }
951
952 count_instance++;
953 }
954
955
956 return count_instance < 1;
957 }
958
959
960
961
962
963
964 static int
965 sfnt_enum_font_1 (int fd, const char *file,
966 struct sfnt_offset_subtable *subtables,
967 off_t offset)
968 {
969 struct sfnt_font_desc *desc, **next, *prev;
970 struct sfnt_head_table *head;
971 struct sfnt_name_table *name;
972 struct sfnt_meta_table *meta;
973 struct sfnt_maxp_table *maxp;
974 struct sfnt_fvar_table *fvar;
975 struct sfnt_font_desc temp;
976 Lisp_Object family, style, instance, style1;
977 int i;
978
979
980 desc = xzalloc (sizeof *desc + strlen (file) + 1);
981 desc->path = (char *) (desc + 1);
982 memcpy (desc->path, file, strlen (file) + 1);
983 desc->offset = offset;
984
985
986 if (subtables->scaler_type != SFNT_SCALER_TRUE
987 && subtables->scaler_type != SFNT_SCALER_VER1)
988 goto bail1;
989
990
991 head = sfnt_read_head_table (fd, subtables);
992 if (!head)
993 goto bail1;
994
995 name = sfnt_read_name_table (fd, subtables);
996 if (!name)
997 goto bail2;
998
999 maxp = sfnt_read_maxp_table (fd, subtables);
1000 if (!maxp)
1001 goto bail3;
1002
1003
1004 meta = sfnt_read_meta_table (fd, subtables);
1005
1006
1007 if (sfnt_decode_family_style (name, &family, &style))
1008 goto bail4;
1009
1010
1011
1012 fvar = sfnt_read_fvar_table (fd, subtables);
1013
1014
1015 desc->family = family;
1016 desc->designer = sfnt_decode_foundry_name (name);
1017 desc->char_cache = Qnil;
1018 desc->subtable.platform_id = 500;
1019
1020
1021 desc->num_glyphs = maxp->num_glyphs;
1022
1023
1024 sfnt_parse_style (style, desc);
1025
1026
1027 if (meta)
1028 sfnt_parse_languages (meta, desc);
1029
1030
1031
1032 if (!NILP (Fstring_search (Fdowncase (family),
1033 build_string ("mono"),
1034 Qnil)))
1035 desc->spacing = 100;
1036
1037
1038
1039
1040 if (head->mac_style & 01 && desc->weight == 80)
1041 desc->weight = 200;
1042
1043 if (head->mac_style & 02 && desc->slant == 0)
1044 desc->slant = 100;
1045
1046
1047 sfnt_grok_registry (fd, desc, subtables);
1048
1049 if (fvar && fvar->instance_count)
1050 {
1051
1052
1053
1054
1055
1056
1057
1058
1059 desc->instances = make_vector (fvar->instance_count, Qnil);
1060
1061 for (i = 0; i < fvar->instance_count; ++i)
1062 {
1063 style1 = sfnt_decode_instance_name (&fvar->instance[i],
1064 name);
1065
1066 if (NILP (style1))
1067 continue;
1068
1069
1070 temp.adstyle = Qnil;
1071 sfnt_parse_style (style1, &temp);
1072
1073
1074 instance = make_vector (5, Qnil);
1075 ASET (instance, 0, style1);
1076 ASET (instance, 1, temp.adstyle);
1077 ASET (instance, 2, make_fixnum (temp.width));
1078 ASET (instance, 3, make_fixnum (temp.weight));
1079 ASET (instance, 4, make_fixnum (temp.slant));
1080
1081
1082 ASET (desc->instances, i, instance);
1083 }
1084 }
1085
1086
1087 desc->style = style;
1088 desc->next = system_fonts;
1089 system_fonts = desc;
1090
1091
1092
1093
1094
1095 next = &system_fonts->next;
1096 prev = *next;
1097 for (; *next; prev = *next)
1098 {
1099 if (sfnt_replace_fonts_p (prev, desc))
1100 {
1101 *next = prev->next;
1102 xfree (prev);
1103 }
1104 else
1105 next = &prev->next;
1106 }
1107
1108 xfree (fvar);
1109 xfree (meta);
1110 xfree (maxp);
1111 xfree (name);
1112 xfree (head);
1113 return 0;
1114
1115 bail4:
1116 xfree (meta);
1117 xfree (maxp);
1118 bail3:
1119 xfree (name);
1120 bail2:
1121 xfree (head);
1122 bail1:
1123 xfree (desc);
1124 return 1;
1125 }
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135 int
1136 sfnt_enum_font (const char *file)
1137 {
1138 int fd, rc;
1139 struct sfnt_offset_subtable *subtables;
1140 struct sfnt_ttc_header *ttc;
1141 size_t i;
1142
1143
1144 fd = emacs_open (file, O_RDONLY, 0);
1145
1146 if (fd == -1)
1147 goto bail;
1148
1149
1150 subtables = sfnt_read_table_directory (fd);
1151
1152 if (subtables == (struct sfnt_offset_subtable *) -1)
1153 {
1154
1155
1156
1157 if (lseek (fd, 0, SEEK_SET))
1158 goto bail0;
1159
1160 ttc = sfnt_read_ttc_header (fd);
1161
1162 if (!ttc)
1163 goto bail0;
1164
1165
1166
1167 for (i = 0; i < ttc->num_fonts; ++i)
1168 {
1169 if (lseek (fd, ttc->offset_table[i], SEEK_SET)
1170 != ttc->offset_table[i])
1171 continue;
1172
1173 subtables = sfnt_read_table_directory (fd);
1174
1175 if (!subtables
1176
1177
1178
1179
1180 || (subtables == (struct sfnt_offset_subtable *) -1))
1181 continue;
1182
1183 sfnt_enum_font_1 (fd, file, subtables,
1184 ttc->offset_table[i]);
1185 xfree (subtables);
1186 }
1187
1188
1189
1190
1191 emacs_close (fd);
1192 xfree (ttc);
1193 return 0;
1194 }
1195
1196 if (!subtables)
1197 goto bail0;
1198
1199
1200 rc = sfnt_enum_font_1 (fd, file, subtables, 0);
1201 xfree (subtables);
1202 emacs_close (fd);
1203 return rc;
1204
1205 bail0:
1206 emacs_close (fd);
1207 bail:
1208 return 1;
1209 }
1210
1211
1212
1213
1214
1215 static struct charset *
1216 sfntfont_charset_for_name (Lisp_Object symbol)
1217 {
1218 ptrdiff_t idx;
1219 int id;
1220
1221 idx = CHARSET_SYMBOL_HASH_INDEX (symbol);
1222
1223 if (idx == -1)
1224 return NULL;
1225
1226
1227
1228 id = XFIXNUM (AREF (HASH_VALUE (XHASH_TABLE (Vcharset_hash_table),
1229 idx),
1230 charset_id));
1231
1232 return CHARSET_FROM_ID (id);
1233 }
1234
1235
1236
1237
1238 static struct charset *
1239 sfntfont_charset_for_cmap (struct sfnt_cmap_encoding_subtable subtable)
1240 {
1241 switch (subtable.platform_id)
1242 {
1243 case SFNT_PLATFORM_UNICODE:
1244
1245 if ((subtable.platform_specific_id
1246 == SFNT_UNICODE_VARIATION_SEQUENCES)
1247 || (subtable.platform_specific_id
1248 == SFNT_UNICODE_LAST_RESORT))
1249 return NULL;
1250
1251
1252
1253 if (subtable.platform_specific_id < SFNT_UNICODE_2_0)
1254 return sfntfont_charset_for_name (Qunicode_bmp);
1255
1256 return sfntfont_charset_for_name (Qunicode);
1257
1258 case SFNT_PLATFORM_MACINTOSH:
1259
1260 switch (subtable.platform_specific_id)
1261 {
1262 case SFNT_MACINTOSH_ROMAN:
1263 return sfntfont_charset_for_name (Qmac_roman);
1264
1265 default:
1266
1267 return NULL;
1268 }
1269
1270 case SFNT_PLATFORM_MICROSOFT:
1271
1272
1273
1274 switch (subtable.platform_specific_id)
1275 {
1276 case SFNT_MICROSOFT_SYMBOL:
1277
1278 return sfntfont_charset_for_name (Qunicode);
1279
1280 case SFNT_MICROSOFT_UNICODE_BMP:
1281 return sfntfont_charset_for_name (Qunicode_bmp);
1282
1283 case SFNT_MICROSOFT_SHIFT_JIS:
1284
1285 return sfntfont_charset_for_name (Qjapanese_jisx0208);
1286
1287 case SFNT_MICROSOFT_PRC:
1288
1289 return sfntfont_charset_for_name (Qgbk);
1290
1291 case SFNT_MICROSOFT_JOHAB:
1292
1293 return sfntfont_charset_for_name (Qkorean_ksc5601);
1294
1295 case SFNT_MICROSOFT_UNICODE_UCS_4:
1296
1297 return sfntfont_charset_for_name (Qucs);
1298 }
1299
1300 default:
1301 return NULL;
1302 }
1303 }
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 static struct sfnt_cmap_encoding_subtable_data *
1314 sfntfont_select_cmap (struct sfnt_cmap_table *cmap,
1315 struct sfnt_cmap_encoding_subtable *subtables,
1316 struct sfnt_cmap_encoding_subtable_data **data,
1317 struct sfnt_cmap_encoding_subtable *subtable,
1318 struct sfnt_cmap_format_14 **format14)
1319 {
1320 int i, j;
1321
1322
1323
1324 for (i = 0; i < cmap->num_subtables; ++i)
1325 {
1326 if (data[i] && sfntfont_identify_cmap (subtables[i]) == 2)
1327 {
1328 *subtable = subtables[i];
1329
1330 if (!format14)
1331 return data[i];
1332
1333
1334
1335
1336
1337 for (j = 0; j < cmap->num_subtables; ++j)
1338 {
1339 if (data[j]
1340 && subtables[j].platform_id == SFNT_PLATFORM_UNICODE
1341 && (subtables[j].platform_specific_id
1342 == SFNT_UNICODE_VARIATION_SEQUENCES)
1343 && data[j]->format == 14)
1344 *format14 = (struct sfnt_cmap_format_14 *) data[j];
1345 }
1346
1347 return data[i];
1348 }
1349 }
1350
1351
1352
1353 for (i = 0; i < cmap->num_subtables; ++i)
1354 {
1355 if (data[i] && sfntfont_identify_cmap (subtables[i]) == 1)
1356 {
1357 *subtable = subtables[i];
1358
1359 if (!format14)
1360 return data[i];
1361
1362
1363
1364
1365
1366 for (j = 0; j < cmap->num_subtables; ++j)
1367 {
1368 if (data[j]
1369 && subtables[j].platform_id == SFNT_PLATFORM_UNICODE
1370 && (subtables[j].platform_specific_id
1371 == SFNT_UNICODE_VARIATION_SEQUENCES)
1372 && data[j]->format == 14)
1373 *format14 = (struct sfnt_cmap_format_14 *) data[j];
1374 }
1375
1376 return data[i];
1377 }
1378 }
1379
1380
1381
1382
1383 for (i = 0; i < cmap->num_subtables; ++i)
1384 {
1385 if (data[i] && sfntfont_identify_cmap (subtables[i]) == 0)
1386 {
1387 *subtable = subtables[i];
1388 return data[i];
1389 }
1390 }
1391
1392
1393 return NULL;
1394 }
1395
1396
1397
1398
1399
1400 static void
1401 sfntfont_read_cmap (struct sfnt_font_desc *desc,
1402 struct sfnt_cmap_encoding_subtable_data **cmap,
1403 struct sfnt_cmap_encoding_subtable *subtable)
1404 {
1405 struct sfnt_offset_subtable *font;
1406 struct sfnt_cmap_encoding_subtable *subtables;
1407 struct sfnt_cmap_encoding_subtable_data **data;
1408 struct sfnt_cmap_table *table;
1409 int fd, i;
1410
1411
1412 fd = emacs_open (desc->path, O_RDONLY, 0);
1413
1414 if (fd < 0)
1415 return;
1416
1417
1418
1419 if (desc->offset
1420 && lseek (fd, desc->offset, SEEK_SET) != desc->offset)
1421 {
1422 emacs_close (fd);
1423 return;
1424 }
1425
1426 font = sfnt_read_table_directory (fd);
1427
1428
1429
1430
1431
1432 if (!font || (font == (struct sfnt_offset_subtable *) -1))
1433 {
1434 emacs_close (fd);
1435 return;
1436 }
1437
1438 table = sfnt_read_cmap_table (fd, font, &subtables,
1439 &data);
1440 xfree (font);
1441
1442 if (!table)
1443 {
1444 emacs_close (fd);
1445 return;
1446 }
1447
1448
1449
1450 *cmap = sfntfont_select_cmap (table, subtables, data,
1451 subtable, NULL);
1452
1453
1454
1455 for (i = 0; i < table->num_subtables; ++i)
1456 {
1457 if (data[i] != *cmap)
1458 xfree (data[i]);
1459 }
1460
1461 xfree (data);
1462 xfree (subtables);
1463 xfree (table);
1464 emacs_close (fd);
1465 }
1466
1467
1468
1469
1470
1471 static bool
1472 sfntfont_glyph_valid (struct sfnt_font_desc *desc,
1473 sfnt_char font_character,
1474 struct sfnt_cmap_encoding_subtable_data *cmap)
1475 {
1476 sfnt_glyph glyph;
1477
1478 glyph = sfnt_lookup_glyph (font_character, cmap);
1479
1480 if (!glyph)
1481 return false;
1482
1483 return glyph <= desc->num_glyphs;
1484 }
1485
1486
1487
1488
1489
1490
1491
1492
1493 static bool
1494 sfntfont_lookup_char (struct sfnt_font_desc *desc, Lisp_Object character,
1495 struct sfnt_cmap_encoding_subtable_data **cmap,
1496 struct sfnt_cmap_encoding_subtable *subtable)
1497 {
1498 Lisp_Object cached;
1499 sfnt_char font_character;
1500 struct charset *charset;
1501 bool present;
1502
1503
1504 if (XFIXNUM (character) > INT_MAX || XFIXNUM (character) < 0)
1505 return false;
1506
1507 if (!NILP (desc->char_cache))
1508 {
1509 cached = char_table_ref (desc->char_cache,
1510 XFIXNUM (character));
1511 if (!NILP (cached))
1512 return (EQ (cached, Qlambda) ? false : true);
1513 }
1514
1515 if (!*cmap && !desc->cmap_invalid)
1516 sfntfont_read_cmap (desc, cmap, subtable);
1517
1518
1519 if (!*cmap)
1520 {
1521
1522
1523 desc->cmap_invalid = true;
1524 return false;
1525 }
1526
1527
1528
1529 charset = sfntfont_charset_for_cmap (*subtable);
1530 if (!charset)
1531
1532 return false;
1533
1534 font_character = ENCODE_CHAR (charset, (int) XFIXNUM (character));
1535
1536 if (font_character == CHARSET_INVALID_CODE (charset))
1537 return false;
1538
1539
1540
1541
1542 present = sfntfont_glyph_valid (desc, font_character, *cmap);
1543
1544
1545
1546
1547 if (NILP (desc->char_cache))
1548 desc->char_cache = Fmake_char_table (Qfont_lookup_cache,
1549 Qnil);
1550
1551 Fset_char_table_range (desc->char_cache, character,
1552 present ? Qt : Qlambda);
1553 return present;
1554 }
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565 static bool
1566 sfntfont_registries_compatible_p (Lisp_Object a, Lisp_Object b)
1567 {
1568 if (EQ (a, Qiso8859_1) && EQ (b, Qiso10646_1))
1569 return true;
1570
1571 return EQ (a, b);
1572 }
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582 static int
1583 sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec,
1584 int *instances, int size)
1585 {
1586 Lisp_Object tem, extra, tail;
1587 struct sfnt_cmap_encoding_subtable_data *cmap;
1588 size_t i;
1589 struct sfnt_cmap_encoding_subtable subtable;
1590 int instance, num_instance;
1591 Lisp_Object item;
1592
1593
1594
1595
1596
1597
1598 tem = AREF (spec, FONT_FAMILY_INDEX);
1599
1600
1601
1602
1603 if (SYMBOLP (tem) && CONSP (Vsfnt_default_family_alist))
1604 {
1605 tail = Vsfnt_default_family_alist;
1606 FOR_EACH_TAIL_SAFE (tail)
1607 {
1608 if (!CONSP (XCAR (tail)))
1609 continue;
1610
1611 if (STRINGP (XCAR (XCAR (tail)))
1612 && STRINGP (XCDR (XCAR (tail)))
1613 && !NILP (Fstring_equal (SYMBOL_NAME (tem),
1614 XCAR (XCAR (tail)))))
1615 {
1616
1617 tem = Fintern (XCDR (XCAR (tail)), Qnil);
1618 break;
1619 }
1620 }
1621 }
1622
1623 if (!NILP (tem) && NILP (Fstring_equal (SYMBOL_NAME (tem),
1624 desc->family)))
1625 return 0;
1626
1627 instance = -1;
1628
1629
1630
1631
1632
1633
1634
1635 tem = AREF (spec, FONT_REGISTRY_INDEX);
1636 if (!NILP (tem) && !NILP (desc->registry)
1637 && !sfntfont_registries_compatible_p (tem, desc->registry))
1638 return 0;
1639
1640
1641
1642
1643 if (NILP (desc->instances))
1644 {
1645 tem = AREF (spec, FONT_ADSTYLE_INDEX);
1646 if (!NILP (tem) && NILP (Fequal (tem, desc->adstyle)))
1647 return 0;
1648
1649 if (FONT_WIDTH_NUMERIC (spec) != -1
1650 && FONT_WIDTH_NUMERIC (spec) != desc->width)
1651 return 0;
1652
1653 if (FONT_WEIGHT_NUMERIC (spec) != -1
1654 && FONT_WEIGHT_NUMERIC (spec) != desc->weight)
1655 return 0;
1656
1657 if (FONT_SLANT_NUMERIC (spec) != -1
1658 && FONT_SLANT_NUMERIC (spec) != desc->slant)
1659 return 0;
1660 }
1661 else
1662 {
1663 num_instance = 0;
1664
1665
1666
1667
1668 for (i = 0; i < ASIZE (desc->instances); ++i)
1669 {
1670 item = AREF (desc->instances, i);
1671
1672 if (NILP (item))
1673 continue;
1674
1675
1676
1677 tem = AREF (spec, FONT_ADSTYLE_INDEX);
1678 if (!NILP (tem) && NILP (Fequal (tem, AREF (item, 1))))
1679 continue;
1680
1681
1682
1683 if (FONT_WIDTH_NUMERIC (spec) != -1
1684 && (FONT_WIDTH_NUMERIC (spec)
1685 != XFIXNUM (AREF (item, 2))))
1686 continue;
1687
1688 if (FONT_WEIGHT_NUMERIC (spec) != -1
1689 && (FONT_WEIGHT_NUMERIC (spec)
1690 != XFIXNUM (AREF (item, 3))))
1691 continue;
1692
1693 if (FONT_SLANT_NUMERIC (spec) != -1
1694 && (FONT_SLANT_NUMERIC (spec)
1695 != XFIXNUM (AREF (item, 4))))
1696 continue;
1697
1698 if (num_instance == size)
1699 break;
1700
1701
1702
1703 instances[num_instance++] = i;
1704 }
1705
1706 instance = num_instance;
1707 }
1708
1709
1710 extra = AREF (spec, FONT_EXTRA_INDEX);
1711
1712 if (NILP (extra))
1713 return instance;
1714
1715 tem = assq_no_quit (QCscript, extra);
1716 cmap = NULL;
1717
1718 if (!NILP (tem))
1719 {
1720
1721
1722
1723 tem = assq_no_quit (XCDR (tem), Vscript_representative_chars);
1724
1725 if (CONSP (tem) && VECTORP (XCDR (tem)))
1726 {
1727 tem = XCDR (tem);
1728
1729
1730
1731 for (i = 0; i < ASIZE (tem); ++i)
1732 {
1733 if (FIXNUMP (AREF (tem, i)))
1734 {
1735 if (!sfntfont_lookup_char (desc, AREF (tem, i),
1736 &cmap, &subtable))
1737 goto fail;
1738
1739
1740
1741 break;
1742 }
1743 }
1744 }
1745 else if (CONSP (tem) && CONSP (XCDR (tem)))
1746 {
1747 tem = XCDR (tem);
1748
1749
1750
1751 FOR_EACH_TAIL_SAFE (tem)
1752 {
1753 if (FIXNUMP (XCAR (tem))
1754 && !sfntfont_lookup_char (desc, XCAR (tem), &cmap,
1755 &subtable))
1756 goto fail;
1757 }
1758
1759
1760 if (!NILP (tem))
1761 goto fail;
1762 }
1763
1764 else if (NILP (tem))
1765 goto fail;
1766 }
1767
1768
1769 tem = assq_no_quit (QClang, extra);
1770 if (!NILP (tem) && NILP (Fmemq (tem, desc->languages)))
1771 goto fail;
1772
1773
1774 if (cmap)
1775 desc->subtable = subtable;
1776
1777 xfree (cmap);
1778 return instance;
1779
1780 fail:
1781
1782 xfree (cmap);
1783 return 0;
1784 }
1785
1786
1787 static Lisp_Object sfnt_vendor_name;
1788
1789
1790 static const struct font_driver *sfnt_font_driver;
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801 static Lisp_Object
1802 sfntfont_registry_for_desc (struct sfnt_font_desc *desc)
1803 {
1804 struct sfnt_cmap_encoding_subtable_data *cmap;
1805
1806 cmap = NULL;
1807
1808 if (desc->cmap_invalid)
1809 return Qnil;
1810
1811 if (desc->subtable.platform_id == 500)
1812 {
1813
1814 sfntfont_read_cmap (desc, &cmap, &desc->subtable);
1815
1816 if (!cmap)
1817 {
1818 desc->cmap_invalid = true;
1819 return Qnil;
1820 }
1821 }
1822
1823 xfree (cmap);
1824
1825 if (desc->subtable.platform_id != 500)
1826
1827
1828 return sfnt_registry_for_subtable (&desc->subtable);
1829
1830 return Qnil;
1831 }
1832
1833
1834
1835
1836
1837
1838 static Lisp_Object
1839 sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance)
1840 {
1841 Lisp_Object entity, vector;
1842
1843 entity = font_make_entity ();
1844
1845 ASET (entity, FONT_TYPE_INDEX, sfnt_vendor_name);
1846
1847 if (!NILP (desc->designer))
1848 ASET (entity, FONT_FOUNDRY_INDEX,
1849 Fintern (desc->designer, Qnil));
1850
1851 ASET (entity, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil));
1852 ASET (entity, FONT_ADSTYLE_INDEX, Qnil);
1853 ASET (entity, FONT_REGISTRY_INDEX,
1854 sfntfont_registry_for_desc (desc));
1855
1856
1857 ASET (entity, FONT_SIZE_INDEX, make_fixnum (0));
1858 ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0));
1859 ASET (entity, FONT_SPACING_INDEX,
1860 make_fixnum (desc->spacing));
1861
1862 if (instance >= 1)
1863 {
1864 if (NILP (desc->instances)
1865 || instance > ASIZE (desc->instances))
1866 emacs_abort ();
1867
1868 vector = AREF (desc->instances, instance - 1);
1869 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
1870 AREF (vector, 2));
1871 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
1872 AREF (vector, 3));
1873 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
1874 AREF (vector, 4));
1875 ASET (entity, FONT_ADSTYLE_INDEX, AREF (vector, 1));
1876 }
1877 else
1878 {
1879 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
1880 make_fixnum (desc->width));
1881 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
1882 make_fixnum (desc->weight));
1883 FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
1884 make_fixnum (desc->slant));
1885 ASET (entity, FONT_ADSTYLE_INDEX, desc->adstyle);
1886 }
1887
1888
1889
1890
1891 ASET (entity, FONT_EXTRA_INDEX,
1892 (instance >= 1
1893 ? list2 (Fcons (Qfont_entity, make_mint_ptr (desc)),
1894 Fcons (Qfont_instance, make_fixnum (instance - 1)))
1895 : list1 (Fcons (Qfont_entity, make_mint_ptr (desc)))));
1896
1897 return entity;
1898 }
1899
1900
1901
1902
1903 Lisp_Object
1904 sfntfont_list (struct frame *f, Lisp_Object font_spec)
1905 {
1906 Lisp_Object matching, tem;
1907 struct sfnt_font_desc *desc;
1908 int i, rc, instances[100];
1909
1910 matching = Qnil;
1911
1912 block_input ();
1913
1914
1915
1916 tem = assq_no_quit (QCotf, AREF (font_spec, FONT_EXTRA_INDEX));
1917 if (CONSP (tem) && !NILP (XCDR (tem)))
1918 {
1919 unblock_input ();
1920 return Qnil;
1921 }
1922
1923
1924
1925 for (desc = system_fonts; desc; desc = desc->next)
1926 {
1927 rc = sfntfont_list_1 (desc, font_spec, instances,
1928 ARRAYELTS (instances));
1929
1930 if (rc < 0)
1931 matching = Fcons (sfntfont_desc_to_entity (desc, 0),
1932 matching);
1933 else if (rc)
1934 {
1935
1936
1937 for (i = 0; i < rc; ++i)
1938 matching = Fcons (sfntfont_desc_to_entity (desc,
1939 instances[i] + 1),
1940 matching);
1941 }
1942 }
1943
1944 unblock_input ();
1945
1946 return matching;
1947 }
1948
1949
1950
1951 Lisp_Object
1952 sfntfont_match (struct frame *f, Lisp_Object font_spec)
1953 {
1954 Lisp_Object matches;
1955
1956 matches = sfntfont_list (f, font_spec);
1957
1958 if (!NILP (matches))
1959 return XCAR (matches);
1960
1961 return Qnil;
1962 }
1963
1964
1965
1966 enum
1967 {
1968 SFNT_OUTLINE_CACHE_SIZE = 256,
1969 SFNT_RASTER_CACHE_SIZE = 128,
1970 };
1971
1972
1973
1974
1975
1976
1977
1978
1979 struct sfnt_outline_cache
1980 {
1981
1982 struct sfnt_outline_cache *next, *last;
1983
1984
1985 struct sfnt_glyph_outline *outline;
1986
1987
1988 struct sfnt_glyph_metrics metrics;
1989
1990
1991 sfnt_glyph glyph;
1992 };
1993
1994 struct sfnt_raster_cache
1995 {
1996
1997 struct sfnt_raster_cache *next, *last;
1998
1999
2000 struct sfnt_raster *raster;
2001
2002
2003 sfnt_glyph glyph;
2004 };
2005
2006 struct sfntfont_get_glyph_outline_dcontext
2007 {
2008
2009 struct sfnt_loca_table_long *loca_long;
2010 struct sfnt_loca_table_short *loca_short;
2011
2012
2013 struct sfnt_glyf_table *glyf;
2014
2015
2016 struct sfnt_hmtx_table *hmtx;
2017 struct sfnt_hhea_table *hhea;
2018 struct sfnt_maxp_table *maxp;
2019
2020
2021 struct sfnt_blend *blend;
2022 };
2023
2024
2025
2026
2027 static struct sfnt_glyph *
2028 sfntfont_get_glyph (sfnt_glyph glyph_id, void *dcontext,
2029 bool *need_free)
2030 {
2031 struct sfntfont_get_glyph_outline_dcontext *tables;
2032 struct sfnt_glyph *glyph;
2033 struct sfnt_metrics_distortion distortion;
2034
2035 tables = dcontext;
2036 *need_free = true;
2037
2038 glyph = sfnt_read_glyph (glyph_id, tables->glyf,
2039 tables->loca_short,
2040 tables->loca_long);
2041
2042 if (tables->blend && glyph)
2043 {
2044 if (glyph->simple)
2045 sfnt_vary_simple_glyph (tables->blend, glyph_id, glyph,
2046 &distortion);
2047 else
2048 sfnt_vary_compound_glyph (tables->blend, glyph_id, glyph,
2049 &distortion);
2050 }
2051
2052
2053 return glyph;
2054 }
2055
2056
2057
2058 static void
2059 sfntfont_free_glyph (struct sfnt_glyph *glyph, void *dcontext)
2060 {
2061 sfnt_free_glyph (glyph);
2062 }
2063
2064
2065
2066
2067
2068
2069 static int
2070 sfntfont_get_metrics (sfnt_glyph glyph, struct sfnt_glyph_metrics *metrics,
2071 void *dcontext)
2072 {
2073 struct sfntfont_get_glyph_outline_dcontext *tables;
2074
2075 tables = dcontext;
2076 return sfnt_lookup_glyph_metrics (glyph, -1, metrics,
2077 tables->hmtx, tables->hhea,
2078 NULL, tables->maxp);
2079 }
2080
2081
2082
2083
2084 static void
2085 sfntfont_dereference_outline (struct sfnt_glyph_outline *outline)
2086 {
2087 eassert (outline->refcount > 0);
2088
2089 if (--outline->refcount)
2090 return;
2091
2092 xfree (outline);
2093 }
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118 static struct sfnt_glyph_outline *
2119 sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
2120 struct sfnt_outline_cache *cache,
2121 sfnt_fixed scale, int *cache_size,
2122 struct sfnt_blend *blend,
2123 int index,
2124 struct sfnt_glyf_table *glyf,
2125 struct sfnt_head_table *head,
2126 struct sfnt_hmtx_table *hmtx,
2127 struct sfnt_hhea_table *hhea,
2128 struct sfnt_maxp_table *maxp,
2129 struct sfnt_loca_table_short *loca_short,
2130 struct sfnt_loca_table_long *loca_long,
2131 struct sfnt_interpreter *interpreter,
2132 struct sfnt_glyph_metrics *metrics,
2133 struct sfnt_graphics_state *state)
2134 {
2135 struct sfnt_outline_cache *start;
2136 struct sfnt_glyph_outline *outline;
2137 struct sfnt_glyph *glyph;
2138 struct sfntfont_get_glyph_outline_dcontext dcontext;
2139 struct sfnt_instructed_outline *value;
2140 const char *error;
2141 struct sfnt_glyph_metrics temp;
2142 struct sfnt_metrics_distortion distortion;
2143
2144 start = cache->next;
2145 distortion.advance = 0;
2146
2147
2148 for (; start != cache; start = start->next)
2149 {
2150 if (start->glyph == glyph_code)
2151 {
2152
2153
2154
2155 start->last->next = start->next;
2156 start->next->last = start->last;
2157
2158 start->next = cache->next;
2159 start->last = cache;
2160 start->next->last = start;
2161 start->last->next = start;
2162 start->outline->refcount++;
2163
2164 if (metrics)
2165 *metrics = start->metrics;
2166
2167 return start->outline;
2168 }
2169 }
2170
2171
2172 glyph = sfnt_read_glyph (glyph_code, glyf,
2173 loca_short, loca_long);
2174
2175 if (!glyph)
2176 return NULL;
2177
2178
2179
2180 if (index != -1)
2181 {
2182 if (glyph->simple)
2183 {
2184 if (sfnt_vary_simple_glyph (blend, glyph_code,
2185 glyph, &distortion))
2186 {
2187 sfnt_free_glyph (glyph);
2188 return NULL;
2189 }
2190 }
2191 else if (sfnt_vary_compound_glyph (blend, glyph_code,
2192 glyph, &distortion))
2193 {
2194 sfnt_free_glyph (glyph);
2195 return NULL;
2196 }
2197 }
2198
2199
2200
2201 outline = NULL;
2202
2203 dcontext.loca_long = loca_long;
2204 dcontext.loca_short = loca_short;
2205 dcontext.glyf = glyf;
2206 dcontext.hhea = hhea;
2207 dcontext.hmtx = hmtx;
2208 dcontext.maxp = maxp;
2209 dcontext.blend = (index != -1 ? blend : NULL);
2210
2211
2212
2213 if (sfnt_lookup_glyph_metrics (glyph_code, -1, &temp, hmtx, hhea,
2214 head, maxp))
2215 goto fail;
2216
2217
2218 temp.advance += distortion.advance;
2219
2220 if (interpreter)
2221 {
2222 if (glyph->simple)
2223 {
2224
2225
2226 interpreter->state = *state;
2227
2228 error = sfnt_interpret_simple_glyph (glyph, interpreter,
2229 &temp, &value);
2230 }
2231 else
2232
2233
2234
2235 error = sfnt_interpret_compound_glyph (glyph, interpreter,
2236 state,
2237 sfntfont_get_glyph,
2238 sfntfont_free_glyph,
2239 hmtx, hhea, maxp,
2240 &temp, &dcontext,
2241 &value);
2242
2243 if (!error)
2244 {
2245 outline = sfnt_build_instructed_outline (value);
2246 xfree (value);
2247 }
2248 }
2249
2250 if (!outline)
2251 {
2252 if (!interpreter)
2253 outline = sfnt_build_glyph_outline (glyph, scale,
2254 &temp,
2255 sfntfont_get_glyph,
2256 sfntfont_free_glyph,
2257 sfntfont_get_metrics,
2258 &dcontext);
2259 else
2260 outline = sfnt_build_glyph_outline (glyph, scale,
2261 &temp,
2262 sfntfont_get_glyph,
2263 sfntfont_free_glyph,
2264 sfntfont_get_metrics,
2265 &dcontext);
2266 }
2267
2268
2269
2270
2271 sfnt_scale_metrics (&temp, scale);
2272
2273 fail:
2274
2275 xfree (glyph);
2276
2277 if (!outline)
2278 return NULL;
2279
2280 if (index != -1)
2281
2282
2283
2284
2285 temp.lbearing = outline->xmin - outline->origin;
2286
2287 start = xmalloc (sizeof *start);
2288 start->glyph = glyph_code;
2289 start->outline = outline;
2290 start->metrics = temp;
2291
2292
2293
2294 outline->refcount = 2;
2295
2296
2297 start->next = cache->next;
2298 start->last = cache;
2299 start->next->last = start;
2300 start->last->next = start;
2301
2302
2303 (*cache_size)++;
2304
2305
2306
2307 if (*cache_size > SFNT_OUTLINE_CACHE_SIZE)
2308 {
2309 start = cache->last;
2310 eassert (start != cache);
2311
2312
2313 start->last->next = start->next;
2314 start->next->last = start->last;
2315 sfntfont_dereference_outline (start->outline);
2316 xfree (start);
2317
2318 (*cache_size)--;
2319 }
2320
2321
2322
2323 if (metrics)
2324 *metrics = temp;
2325
2326 return outline;
2327 }
2328
2329
2330
2331
2332 static void
2333 sfntfont_free_outline_cache (struct sfnt_outline_cache *cache)
2334 {
2335 struct sfnt_outline_cache *next, *last;
2336
2337
2338 if (!cache->next)
2339 return;
2340
2341 for (next = cache->next; next != cache;)
2342 {
2343 last = next;
2344 next = next->next;
2345
2346 sfntfont_dereference_outline (last->outline);
2347 xfree (last);
2348 }
2349
2350 cache->next = cache;
2351 cache->last = cache;
2352 }
2353
2354
2355
2356
2357 static void
2358 sfntfont_dereference_raster (struct sfnt_raster *raster)
2359 {
2360 eassert (raster->refcount > 0);
2361
2362 if (--raster->refcount)
2363 return;
2364
2365 xfree (raster);
2366 }
2367
2368
2369
2370
2371
2372 static struct sfnt_raster *
2373 sfntfont_get_glyph_raster (sfnt_glyph glyph_code,
2374 struct sfnt_raster_cache *cache,
2375 struct sfnt_glyph_outline *outline,
2376 int *cache_size)
2377 {
2378 struct sfnt_raster_cache *start;
2379 struct sfnt_raster *raster;
2380
2381
2382 start = cache->next;
2383
2384 for (; start != cache; start = start->next)
2385 {
2386 if (start->glyph == glyph_code)
2387 {
2388
2389
2390
2391 start->last->next = start->next;
2392 start->next->last = start->last;
2393
2394 start->next = cache->next;
2395 start->last = cache;
2396 start->next->last = start;
2397 start->last->next = start;
2398 start->raster->refcount++;
2399
2400 return start->raster;
2401 }
2402 }
2403
2404
2405 raster = sfnt_raster_glyph_outline (outline);
2406
2407 if (!raster)
2408 return NULL;
2409
2410 start = xmalloc (sizeof *start);
2411 start->glyph = glyph_code;
2412 start->raster = raster;
2413
2414
2415
2416 raster->refcount = 2;
2417
2418
2419 start->next = cache->next;
2420 start->last = cache;
2421 start->next->last = start;
2422 start->last->next = start;
2423
2424
2425 (*cache_size)++;
2426
2427
2428
2429 if (*cache_size > SFNT_OUTLINE_CACHE_SIZE)
2430 {
2431 start = cache->last;
2432 eassert (start != cache);
2433
2434
2435 start->last->next = start->next;
2436 start->next->last = start->last;
2437 sfntfont_dereference_raster (start->raster);
2438 xfree (start);
2439
2440 (*cache_size)--;
2441 }
2442
2443
2444 return raster;
2445 }
2446
2447
2448
2449
2450 static void
2451 sfntfont_free_raster_cache (struct sfnt_raster_cache *cache)
2452 {
2453 struct sfnt_raster_cache *next, *last;
2454
2455
2456 if (!cache->next)
2457 return;
2458
2459 for (next = cache->next; next != cache;)
2460 {
2461 last = next;
2462 next = next->next;
2463
2464 sfntfont_dereference_raster (last->raster);
2465 xfree (last);
2466 }
2467
2468 cache->next = cache;
2469 cache->last = cache;
2470 }
2471
2472
2473
2474
2475
2476 struct sfnt_font_info
2477 {
2478
2479 struct font font;
2480
2481 #ifdef HAVE_MMAP
2482
2483 struct sfnt_font_info *next;
2484 #endif
2485
2486
2487
2488 struct sfnt_font_desc *desc;
2489
2490
2491 struct sfnt_cmap_table *cmap;
2492 struct sfnt_hhea_table *hhea;
2493 struct sfnt_maxp_table *maxp;
2494 struct sfnt_head_table *head;
2495 struct sfnt_hmtx_table *hmtx;
2496 struct sfnt_glyf_table *glyf;
2497 struct sfnt_loca_table_short *loca_short;
2498 struct sfnt_loca_table_long *loca_long;
2499 struct sfnt_prep_table *prep;
2500 struct sfnt_fpgm_table *fpgm;
2501 struct sfnt_cvt_table *cvt;
2502
2503
2504 struct sfnt_cmap_encoding_subtable_data *cmap_data;
2505
2506
2507 struct sfnt_cmap_encoding_subtable cmap_subtable;
2508
2509
2510 struct sfnt_uvs_context *uvs;
2511
2512
2513 struct sfnt_outline_cache outline_cache;
2514
2515
2516 int outline_cache_size;
2517
2518
2519 struct sfnt_raster_cache raster_cache;
2520
2521
2522 int raster_cache_size;
2523
2524
2525 struct sfnt_interpreter *interpreter;
2526
2527
2528
2529 struct sfnt_graphics_state state;
2530
2531
2532 sfnt_fixed scale;
2533
2534
2535 struct sfnt_blend blend;
2536
2537
2538
2539 int instance;
2540
2541 #ifdef HAVE_MMAP
2542
2543 bool glyf_table_mapped;
2544 #endif
2545
2546 #ifdef HAVE_HARFBUZZ
2547
2548 hb_font_t *hb_font;
2549
2550
2551 int fd;
2552
2553
2554 struct sfnt_offset_subtable *directory;
2555 #endif
2556 };
2557
2558 #ifdef HAVE_MMAP
2559
2560
2561
2562 static struct sfnt_font_info *open_fonts;
2563
2564 #endif
2565
2566
2567
2568
2569 static sfnt_glyph
2570 sfntfont_lookup_glyph (struct sfnt_font_info *font_info, int c)
2571 {
2572 struct charset *charset;
2573 sfnt_char character;
2574 sfnt_glyph glyph;
2575
2576 charset = CHARSET_FROM_ID (font_info->font.encoding_charset);
2577
2578 if (!charset)
2579 return 0;
2580
2581 character = ENCODE_CHAR (charset, c);
2582
2583 if (character == CHARSET_INVALID_CODE (charset))
2584 return 0;
2585
2586
2587 glyph = sfnt_lookup_glyph (character, font_info->cmap_data);
2588
2589 return glyph;
2590 }
2591
2592
2593
2594
2595
2596 static void
2597 sfntfont_probe_widths (struct sfnt_font_info *font_info)
2598 {
2599 int i, num_characters, total_width;
2600 sfnt_glyph glyph;
2601 struct sfnt_glyph_metrics metrics;
2602
2603 num_characters = 0;
2604 total_width = 0;
2605
2606
2607 font_info->font.average_width = font_info->font.pixel_size;
2608 font_info->font.space_width = font_info->font.pixel_size;
2609 font_info->font.min_width = 1;
2610
2611
2612
2613 for (i = 0; i < 127; ++i)
2614 {
2615 glyph = sfntfont_lookup_glyph (font_info, i);
2616
2617 if (!glyph)
2618 continue;
2619
2620
2621 if (sfnt_lookup_glyph_metrics (glyph, font_info->font.pixel_size,
2622 &metrics, font_info->hmtx,
2623 font_info->hhea, font_info->head,
2624 font_info->maxp))
2625 continue;
2626
2627
2628 num_characters++;
2629
2630
2631 total_width += SFNT_CEIL_FIXED (metrics.advance) / 65536;
2632
2633
2634 if (font_info->font.min_width == 1
2635 || font_info->font.min_width > metrics.advance / 65536)
2636 font_info->font.min_width = metrics.advance / 65536;
2637
2638
2639
2640 if (i == 32)
2641 font_info->font.space_width
2642 = SFNT_CEIL_FIXED (metrics.advance) / 65536;
2643 }
2644
2645
2646 if (num_characters)
2647 font_info->font.average_width = total_width / num_characters;
2648 }
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659 static void
2660 sfntfont_setup_interpreter (struct sfnt_font_info *info,
2661 struct sfnt_font_desc *desc,
2662 int point_size)
2663 {
2664 struct sfnt_cvt_table *cvt;
2665 struct sfnt_fpgm_table *fpgm;
2666 struct sfnt_prep_table *prep;
2667 struct sfnt_interpreter *interpreter;
2668 const char *error;
2669 struct sfnt_graphics_state state;
2670
2671
2672
2673 cvt = info->cvt ;
2674 fpgm = info->fpgm;
2675 prep = info->prep;
2676
2677
2678
2679
2680 if (!fpgm && !prep)
2681 goto bail;
2682
2683
2684
2685
2686
2687
2688
2689 if (!info->maxp->max_stack_elements)
2690 goto bail;
2691
2692
2693
2694
2695 interpreter = sfnt_make_interpreter (info->maxp, cvt, info->head,
2696 desc->tables->fvar,
2697 info->font.pixel_size,
2698 point_size);
2699
2700
2701 if (!interpreter)
2702 goto bail;
2703
2704 if (fpgm)
2705 {
2706
2707
2708
2709
2710
2711 error = sfnt_interpret_font_program (interpreter, fpgm);
2712
2713 if (error)
2714 {
2715
2716 message_with_string ("While interpreting font program: %s",
2717 build_string (error), true);
2718 goto bail1;
2719 }
2720
2721
2722 state = interpreter->state;
2723 }
2724
2725 if (prep)
2726 {
2727
2728
2729 error = sfnt_interpret_control_value_program (interpreter, prep,
2730 &state);
2731
2732 if (error)
2733 {
2734
2735 message_with_string ("While interpreting preprogram: %s",
2736 build_string (error), true);
2737 goto bail1;
2738 }
2739 }
2740
2741
2742 info->fpgm = fpgm;
2743 info->prep = prep;
2744 info->cvt = cvt;
2745 info->state = state;
2746 info->interpreter = interpreter;
2747
2748 return;
2749
2750 bail1:
2751 xfree (interpreter);
2752 bail:
2753 return;
2754 }
2755
2756
2757
2758
2759 static void
2760 sfnt_close_tables (struct sfnt_font_tables *tables)
2761 {
2762 int rc;
2763
2764 xfree (tables->cmap);
2765 xfree (tables->hhea);
2766 xfree (tables->maxp);
2767 xfree (tables->head);
2768 xfree (tables->hmtx);
2769 #ifdef HAVE_MMAP
2770 if (tables->glyf_table_mapped)
2771 {
2772 rc = sfnt_unmap_glyf_table (tables->glyf);
2773
2774 if (rc)
2775 emacs_abort ();
2776 }
2777 else
2778 #endif
2779 xfree (tables->glyf);
2780 xfree (tables->loca_short);
2781 xfree (tables->loca_long);
2782 xfree (tables->prep);
2783 xfree (tables->fpgm);
2784 xfree (tables->cvt);
2785 xfree (tables->fvar);
2786 xfree (tables->avar);
2787 xfree (tables->gvar);
2788 xfree (tables->cvar);
2789 xfree (tables->cmap_data);
2790
2791 if (tables->uvs)
2792 sfnt_free_uvs_context (tables->uvs);
2793
2794 #ifdef HAVE_HARFBUZZ
2795
2796
2797 if (tables->fd != -1)
2798 {
2799 emacs_close (tables->fd);
2800 tables->fd = -1;
2801 }
2802
2803
2804 xfree (tables->directory);
2805 tables->directory = NULL;
2806 #endif
2807 }
2808
2809
2810
2811
2812 static struct sfnt_font_tables *
2813 sfnt_open_tables (struct sfnt_font_desc *desc)
2814 {
2815 struct sfnt_font_tables *tables;
2816 struct sfnt_offset_subtable *subtable;
2817 int fd, i, rc;
2818 struct sfnt_cmap_encoding_subtable *subtables;
2819 struct sfnt_cmap_encoding_subtable_data **data;
2820 struct sfnt_cmap_format_14 *format14;
2821
2822 tables = xzalloc (sizeof *tables);
2823
2824
2825 fd = emacs_open (desc->path, O_RDONLY, 0);
2826
2827 if (fd == -1)
2828 goto bail;
2829
2830
2831
2832 if (desc->offset
2833 && lseek (fd, desc->offset, SEEK_SET) != desc->offset)
2834 goto bail;
2835
2836
2837 subtable = sfnt_read_table_directory (fd);
2838
2839 if (!subtable || (subtable == (struct sfnt_offset_subtable *) -1))
2840 goto bail1;
2841
2842
2843
2844
2845
2846 tables->cmap = sfnt_read_cmap_table (fd, subtable, &subtables,
2847 &data);
2848 if (!tables->cmap)
2849 goto bail2;
2850
2851 format14 = NULL;
2852 tables->cmap_data
2853 = sfntfont_select_cmap (tables->cmap,
2854 subtables, data,
2855 &tables->cmap_subtable,
2856 &format14);
2857
2858 if (format14)
2859 {
2860
2861
2862
2863
2864
2865 tables->uvs = sfnt_create_uvs_context (format14, fd);
2866 xfree (format14);
2867 }
2868
2869 for (i = 0; i < tables->cmap->num_subtables; ++i)
2870 {
2871 if (data[i] != tables->cmap_data
2872
2873 && data[i] != (struct sfnt_cmap_encoding_subtable_data *) format14)
2874 xfree (data[i]);
2875 }
2876
2877 xfree (subtables);
2878 xfree (data);
2879
2880 if (!tables->cmap_data)
2881 goto bail3;
2882
2883
2884 tables->hhea = sfnt_read_hhea_table (fd, subtable);
2885 tables->maxp = sfnt_read_maxp_table (fd, subtable);
2886
2887 #ifdef HAVE_MMAP
2888
2889
2890
2891
2892 tables->glyf = sfnt_map_glyf_table (fd, subtable);
2893
2894
2895
2896 if (!tables->glyf)
2897 #endif
2898 tables->glyf = sfnt_read_glyf_table (fd, subtable);
2899 #ifdef HAVE_MMAP
2900 else
2901 tables->glyf_table_mapped = true;
2902 #endif
2903
2904 tables->head = sfnt_read_head_table (fd, subtable);
2905
2906
2907 if (!tables->hhea || !tables->maxp || !tables->glyf
2908 || !tables->head)
2909 goto bail4;
2910
2911
2912
2913
2914 if (tables->head->index_to_loc_format)
2915 {
2916 tables->loca_long
2917 = sfnt_read_loca_table_long (fd, subtable);
2918
2919 if (!tables->loca_long)
2920 goto bail4;
2921 }
2922 else
2923 {
2924 tables->loca_short
2925 = sfnt_read_loca_table_short (fd, subtable);
2926
2927 if (!tables->loca_short)
2928 goto bail4;
2929 }
2930
2931
2932 tables->hmtx = sfnt_read_hmtx_table (fd, subtable,
2933 tables->hhea,
2934 tables->maxp);
2935 if (!tables->hmtx)
2936 goto bail5;
2937
2938
2939
2940 tables->prep = sfnt_read_prep_table (fd, subtable);
2941 tables->fpgm = sfnt_read_fpgm_table (fd, subtable);
2942 tables->cvt = sfnt_read_cvt_table (fd, subtable);
2943
2944
2945 tables->fvar = sfnt_read_fvar_table (fd, subtable);
2946 tables->avar = sfnt_read_avar_table (fd, subtable);
2947 tables->gvar = sfnt_read_gvar_table (fd, subtable);
2948
2949 if (tables->cvt && tables->fvar)
2950 tables->cvar = sfnt_read_cvar_table (fd, subtable, tables->fvar,
2951 tables->cvt);
2952
2953 #ifdef HAVE_HARFBUZZ
2954
2955
2956 tables->directory = subtable;
2957 tables->fd = fd;
2958 #else
2959
2960 xfree (subtable);
2961 emacs_close (fd);
2962 #endif
2963
2964 return tables;
2965
2966 bail5:
2967 xfree (tables->loca_long);
2968 xfree (tables->loca_short);
2969 bail4:
2970 xfree (tables->hhea);
2971 xfree (tables->maxp);
2972
2973 #ifdef HAVE_MMAP
2974 if (tables->glyf_table_mapped)
2975 {
2976 rc = sfnt_unmap_glyf_table (tables->glyf);
2977
2978 if (rc)
2979 emacs_abort ();
2980 }
2981 else
2982 #endif
2983 xfree (tables->glyf);
2984
2985 xfree (tables->head);
2986
2987
2988
2989 xfree (tables->cmap_data);
2990 bail3:
2991 if (tables->uvs)
2992 sfnt_free_uvs_context (tables->uvs);
2993
2994 xfree (tables->cmap);
2995 bail2:
2996 xfree (subtable);
2997 bail1:
2998 emacs_close (fd);
2999 bail:
3000 xfree (tables);
3001 return NULL;
3002 }
3003
3004
3005
3006
3007 static struct sfnt_font_tables *
3008 sfnt_reference_font_tables (struct sfnt_font_desc *desc)
3009 {
3010 if (desc->refcount)
3011 {
3012 desc->refcount++;
3013 return desc->tables;
3014 }
3015
3016 desc->tables = sfnt_open_tables (desc);
3017
3018 if (!desc->tables)
3019 return NULL;
3020
3021 desc->refcount++;
3022 return desc->tables;
3023 }
3024
3025
3026
3027
3028 static void
3029 sfnt_dereference_font_tables (struct sfnt_font_desc *desc)
3030 {
3031 if (!desc->refcount)
3032 emacs_abort ();
3033
3034 if (--desc->refcount)
3035 return;
3036
3037 sfnt_close_tables (desc->tables);
3038 desc->tables = NULL;
3039 return;
3040 }
3041
3042
3043
3044
3045 Lisp_Object
3046 sfntfont_open (struct frame *f, Lisp_Object font_entity,
3047 int pixel_size)
3048 {
3049 struct sfnt_font_info *font_info;
3050 struct font *font;
3051 struct sfnt_font_desc *desc;
3052 Lisp_Object font_object;
3053 struct charset *charset;
3054 int point_size, instance, i;
3055 Display_Info *dpyinfo;
3056 struct sfnt_font_tables *tables;
3057 Lisp_Object tem;
3058
3059 if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0)
3060 pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX));
3061 else if (pixel_size == 0)
3062 {
3063
3064
3065
3066 if (FRAME_FONT (f))
3067 pixel_size = FRAME_FONT (f)->pixel_size;
3068 else
3069 pixel_size = 12;
3070 }
3071
3072
3073
3074 tem = AREF (font_entity, FONT_EXTRA_INDEX);
3075 if (NILP (tem))
3076 return Qnil;
3077
3078 desc = xmint_pointer (XCDR (XCAR (tem)));
3079
3080
3081
3082
3083 instance = -1;
3084 if (!NILP (XCDR (tem)))
3085 instance = XFIXNUM (XCDR (XCAR (XCDR (tem))));
3086
3087
3088 font_object = font_make_object (VECSIZE (struct sfnt_font_info),
3089 font_entity, pixel_size);
3090 font_info = (struct sfnt_font_info *) XFONT_OBJECT (font_object);
3091
3092 block_input ();
3093
3094
3095
3096 font_info->cmap = NULL;
3097 font_info->hhea = NULL;
3098 font_info->maxp = NULL;
3099 font_info->head = NULL;
3100 font_info->glyf = NULL;
3101 font_info->hmtx = NULL;
3102 font_info->loca_short = NULL;
3103 font_info->loca_long = NULL;
3104 font_info->cmap_data = NULL;
3105 font_info->prep = NULL;
3106 font_info->fpgm = NULL;
3107 font_info->cvt = NULL;
3108 font_info->uvs = NULL;
3109
3110 font_info->outline_cache.next = &font_info->outline_cache;
3111 font_info->outline_cache.last = &font_info->outline_cache;
3112 font_info->outline_cache_size = 0;
3113 font_info->raster_cache.next = &font_info->raster_cache;
3114 font_info->raster_cache.last = &font_info->raster_cache;
3115 font_info->raster_cache_size = 0;
3116 font_info->interpreter = NULL;
3117 font_info->scale = 0;
3118 font_info->instance = -1;
3119 font_info->blend.coords = NULL;
3120 #ifdef HAVE_MMAP
3121 font_info->glyf_table_mapped = false;
3122 #endif
3123 #ifdef HAVE_HARFBUZZ
3124 font_info->hb_font = NULL;
3125 font_info->fd = -1;
3126 font_info->directory = NULL;
3127 #endif
3128
3129
3130
3131
3132
3133 tables = sfnt_reference_font_tables (desc);
3134
3135 if (!tables)
3136 goto bail;
3137
3138
3139
3140 font_info->cmap = tables->cmap;
3141 font_info->hhea = tables->hhea;
3142 font_info->maxp = tables->maxp;
3143 font_info->head = tables->head;
3144 font_info->hmtx = tables->hmtx;
3145 font_info->glyf = tables->glyf;
3146 font_info->loca_short = tables->loca_short;
3147 font_info->loca_long = tables->loca_long;
3148 font_info->prep = tables->prep;
3149 font_info->fpgm = tables->fpgm;
3150 font_info->cvt = tables->cvt ;
3151 font_info->cmap_data = tables->cmap_data;
3152 font_info->cmap_subtable = tables->cmap_subtable;
3153 font_info->uvs = tables->uvs;
3154
3155
3156 font_info->scale = sfnt_get_scale (font_info->head, pixel_size);
3157
3158
3159 font = &font_info->font;
3160 font->pixel_size = pixel_size;
3161 font->driver = sfnt_font_driver;
3162 font->encoding_charset = font->repertory_charset = -1;
3163
3164
3165 charset = sfntfont_charset_for_cmap (font_info->cmap_subtable);
3166
3167 if (!charset)
3168 goto bail6;
3169
3170
3171 font->encoding_charset = charset->id;
3172 font->repertory_charset = charset->id;
3173
3174
3175 font->ascent
3176 = ceil (font_info->hhea->ascent
3177 * pixel_size * 1.0 / font_info->head->units_per_em);
3178 font->descent
3179 = -floor (font_info->hhea->descent
3180 * pixel_size * 1.0 / font_info->head->units_per_em);
3181 font->height = font->ascent + font->descent;
3182
3183
3184 font->max_width = (font_info->hhea->advance_width_max
3185 * pixel_size * 1.0 / font_info->head->units_per_em);
3186
3187
3188 ASET (font_object, FONT_TYPE_INDEX, sfnt_vendor_name);
3189
3190 if (!NILP (desc->designer))
3191 ASET (font_object, FONT_FOUNDRY_INDEX,
3192 Fintern (desc->designer, Qnil));
3193
3194 ASET (font_object, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil));
3195 ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
3196 ASET (font_object, FONT_REGISTRY_INDEX,
3197 sfntfont_registry_for_desc (desc));
3198
3199
3200 ASET (font_object, FONT_SIZE_INDEX, make_fixnum (0));
3201 ASET (font_object, FONT_AVGWIDTH_INDEX, make_fixnum (0));
3202 ASET (font_object, FONT_SPACING_INDEX,
3203 make_fixnum (desc->spacing));
3204
3205
3206
3207 FONT_SET_STYLE (font_object, FONT_WIDTH_INDEX,
3208 make_fixnum (desc->width));
3209 FONT_SET_STYLE (font_object, FONT_WEIGHT_INDEX,
3210 make_fixnum (desc->weight));
3211 FONT_SET_STYLE (font_object, FONT_SLANT_INDEX,
3212 make_fixnum (desc->slant));
3213
3214 ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
3215
3216
3217 sfntfont_probe_widths (font_info);
3218
3219
3220 font_info->font.baseline_offset = 0;
3221 font_info->font.relative_compose = 0;
3222 font_info->font.default_ascent = 0;
3223 font_info->font.vertical_centering = 0;
3224 font_info->font.underline_position = -1;
3225 font_info->font.underline_thickness = 0;
3226
3227
3228 dpyinfo = FRAME_DISPLAY_INFO (f);
3229 point_size = PIXEL_TO_POINT (pixel_size, (dpyinfo->resx
3230 * dpyinfo->resy
3231 / 2));
3232 sfntfont_setup_interpreter (font_info, desc, point_size);
3233
3234
3235
3236
3237 if (instance != -1
3238 && desc->tables->fvar && desc->tables->gvar
3239
3240 && instance < desc->tables->fvar->instance_count)
3241 {
3242 tem = AREF (desc->instances, instance);
3243
3244 if (!NILP (tem))
3245 {
3246 sfnt_init_blend (&font_info->blend, desc->tables->fvar,
3247 desc->tables->gvar, desc->tables->avar,
3248 desc->tables->cvar);
3249
3250
3251 for (i = 0; i < desc->tables->fvar->axis_count; ++i)
3252 font_info->blend.coords[i]
3253 = desc->tables->fvar->instance[instance].coords[i];
3254
3255 sfnt_normalize_blend (&font_info->blend);
3256
3257
3258
3259
3260
3261 for (i = 0; i < desc->tables->fvar->axis_count; ++i)
3262 {
3263 if (font_info->blend.norm_coords[i])
3264 break;
3265 }
3266
3267 if (i == desc->tables->fvar->axis_count)
3268 {
3269 sfnt_free_blend (&font_info->blend);
3270 goto cancel_blend;
3271 }
3272
3273
3274
3275 if (font_info->interpreter)
3276 sfnt_vary_interpreter (font_info->interpreter,
3277 &font_info->blend);
3278
3279 font_info->instance = instance;
3280
3281
3282
3283
3284 FONT_SET_STYLE (font_object, FONT_WIDTH_INDEX,
3285 AREF (tem, 2));
3286 FONT_SET_STYLE (font_object, FONT_WEIGHT_INDEX,
3287 AREF (tem, 3));
3288 FONT_SET_STYLE (font_object, FONT_SLANT_INDEX,
3289 AREF (tem, 4));
3290 ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
3291 }
3292 }
3293
3294 cancel_blend:
3295
3296 font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
3297
3298 #ifdef HAVE_HARFBUZZ
3299
3300
3301
3302 font_info->fd = tables->fd;
3303 font_info->directory = tables->directory;
3304 #endif
3305
3306
3307
3308 font_info->desc = desc;
3309
3310 #ifdef HAVE_MMAP
3311
3312 font_info->next = open_fonts;
3313 open_fonts = font_info;
3314 #endif
3315
3316
3317 unblock_input ();
3318 return font_object;
3319
3320 bail6:
3321 sfnt_dereference_font_tables (desc);
3322 font_info->desc = NULL;
3323 bail:
3324 unblock_input ();
3325 return Qnil;
3326 }
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336 unsigned int
3337 sfntfont_encode_char (struct font *font, int c)
3338 {
3339 sfnt_glyph glyph;
3340
3341
3342 glyph = sfntfont_lookup_glyph ((struct sfnt_font_info *) font, c);
3343
3344 if (!glyph)
3345 return FONT_INVALID_CODE;
3346
3347 return glyph;
3348 }
3349
3350
3351
3352
3353
3354
3355
3356
3357 static int
3358 sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph,
3359 struct font_metrics *pcm)
3360 {
3361 struct sfnt_glyph_metrics metrics;
3362 struct sfnt_glyph_outline *outline;
3363
3364
3365
3366 outline = sfntfont_get_glyph_outline (glyph, &font->outline_cache,
3367 font->scale,
3368 &font->outline_cache_size,
3369 &font->blend,
3370 font->instance,
3371 font->glyf, font->head,
3372 font->hmtx, font->hhea,
3373 font->maxp,
3374 font->loca_short,
3375 font->loca_long,
3376 font->interpreter, &metrics,
3377 &font->state);
3378
3379 if (!outline)
3380 return 1;
3381
3382
3383 pcm->lbearing = SFNT_FLOOR_FIXED (metrics.lbearing) / 65536;
3384 pcm->rbearing = SFNT_CEIL_FIXED (outline->xmax) / 65536;
3385
3386
3387 pcm->width = SFNT_CEIL_FIXED (metrics.advance) / 65536;
3388 pcm->ascent = SFNT_CEIL_FIXED (outline->ymax) / 65536;
3389 pcm->descent = SFNT_CEIL_FIXED (-outline->ymin) / 65536;
3390
3391 sfntfont_dereference_outline (outline);
3392 return 0;
3393 }
3394
3395
3396
3397
3398 void
3399 sfntfont_text_extents (struct font *font, const unsigned int *code,
3400 int nglyphs, struct font_metrics *metrics)
3401 {
3402 int i, total_width;
3403 struct font_metrics pcm;
3404
3405 total_width = 0;
3406
3407
3408 memset (metrics, 0, sizeof *metrics);
3409
3410
3411 for (i = 0; i < nglyphs; ++i)
3412 {
3413 if (!sfntfont_measure_pcm ((struct sfnt_font_info *) font,
3414 code[i], &pcm))
3415 {
3416
3417
3418
3419 if (total_width + pcm.lbearing < metrics->lbearing)
3420 metrics->lbearing = total_width + pcm.lbearing;
3421
3422 if (total_width + pcm.rbearing > metrics->rbearing)
3423 metrics->rbearing = total_width + pcm.rbearing;
3424
3425 if (pcm.ascent > metrics->ascent)
3426 metrics->ascent = pcm.ascent;
3427
3428 if (pcm.descent > metrics->descent)
3429 metrics->descent = pcm.descent;
3430
3431 total_width += pcm.width;
3432 }
3433 }
3434
3435 metrics->width = total_width;
3436 }
3437
3438
3439
3440
3441 void
3442 sfntfont_close (struct font *font)
3443 {
3444 struct sfnt_font_info *info;
3445 #ifdef HAVE_MMAP
3446 struct sfnt_font_info **next;
3447 #endif
3448
3449 info = (struct sfnt_font_info *) font;
3450
3451
3452 if (info->desc)
3453 sfnt_dereference_font_tables (info->desc);
3454 info->desc = NULL;
3455
3456
3457 xfree (info->interpreter);
3458
3459
3460
3461
3462 info->cmap = NULL;
3463 info->hhea = NULL;
3464 info->maxp = NULL;
3465 info->head = NULL;
3466 info->hhea = NULL;
3467 info->glyf = NULL;
3468 info->loca_short = NULL;
3469 info->loca_long = NULL;
3470 info->cmap_data = NULL;
3471 info->prep = NULL;
3472 info->fpgm = NULL;
3473 info->cvt = NULL;
3474 info->interpreter = NULL;
3475 info->uvs = NULL;
3476
3477
3478 if (info->instance != -1 && info->blend.coords)
3479 sfnt_free_blend (&info->blend);
3480 info->instance = -1;
3481
3482 #ifdef HAVE_MMAP
3483
3484
3485
3486 next = &open_fonts;
3487 while (*next && (*next) != info)
3488 next = &(*next)->next;
3489
3490 if (*next)
3491 *next = info->next;
3492 info->next = NULL;
3493
3494 #endif
3495
3496 #ifdef HAVE_HARFBUZZ
3497
3498
3499
3500 info->directory = NULL;
3501 info->fd = -1;
3502
3503
3504
3505 if (info->hb_font)
3506 {
3507 hb_font_destroy (info->hb_font);
3508 info->hb_font = NULL;
3509 }
3510 #endif
3511
3512 sfntfont_free_outline_cache (&info->outline_cache);
3513 sfntfont_free_raster_cache (&info->raster_cache);
3514 }
3515
3516
3517
3518
3519
3520
3521 static sfntfont_put_glyph_proc sfnt_put_glyphs;
3522
3523
3524
3525
3526
3527
3528
3529 int
3530 sfntfont_draw (struct glyph_string *s, int from, int to,
3531 int x, int y, bool with_background)
3532 {
3533 int length;
3534 struct sfnt_raster **rasters;
3535 int *x_coords, current_x, i;
3536 struct sfnt_glyph_outline *outline;
3537 struct font *font;
3538 struct sfnt_font_info *info;
3539 struct sfnt_glyph_metrics metrics;
3540
3541 length = to - from;
3542 font = s->font;
3543 info = (struct sfnt_font_info *) font;
3544
3545 rasters = alloca (length * sizeof *rasters);
3546 x_coords = alloca (length * sizeof *x_coords);
3547 current_x = x;
3548
3549
3550 for (i = from; i < to; ++i)
3551 {
3552
3553 outline = sfntfont_get_glyph_outline (s->char2b[i],
3554 &info->outline_cache,
3555 info->scale,
3556 &info->outline_cache_size,
3557 &info->blend,
3558 info->instance,
3559 info->glyf, info->head,
3560 info->hmtx, info->hhea,
3561 info->maxp,
3562 info->loca_short,
3563 info->loca_long,
3564 info->interpreter,
3565 &metrics,
3566 &info->state);
3567 x_coords[i - from] = 0;
3568
3569 if (!outline)
3570 {
3571 rasters[i - from] = NULL;
3572 continue;
3573 }
3574
3575
3576 rasters[i - from] = sfntfont_get_glyph_raster (s->char2b[i],
3577 &info->raster_cache,
3578 outline,
3579 &info->raster_cache_size);
3580 sfntfont_dereference_outline (outline);
3581
3582 if (!rasters[i - from])
3583 continue;
3584
3585
3586 x_coords[i - from] = current_x;
3587
3588 if (s->padding_p)
3589 current_x += 1;
3590 else
3591 current_x += SFNT_CEIL_FIXED (metrics.advance) / 65536;
3592 }
3593
3594
3595
3596 sfnt_put_glyphs (s, from, to, x, y, with_background,
3597 rasters, x_coords);
3598
3599
3600 for (i = 0; i < from - to; ++i)
3601 {
3602 if (rasters[i])
3603 sfntfont_dereference_raster (rasters[i]);
3604 }
3605
3606 return 1;
3607 }
3608
3609
3610
3611
3612
3613
3614
3615
3616 Lisp_Object
3617 sfntfont_list_family (struct frame *f)
3618 {
3619 Lisp_Object families;
3620 struct sfnt_font_desc *desc;
3621
3622 families = Qnil;
3623
3624 for (desc = system_fonts; desc; desc = desc->next)
3625
3626 families = Fcons (desc->family, families);
3627
3628
3629
3630 return families;
3631 }
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653 int
3654 sfntfont_get_variation_glyphs (struct font *font, int c,
3655 unsigned variations[256])
3656 {
3657 struct sfnt_font_info *info;
3658 size_t i;
3659 int n;
3660 struct sfnt_mapped_variation_selector_record *record;
3661
3662 info = (struct sfnt_font_info *) font;
3663 n = 0;
3664
3665
3666
3667 if (!info->uvs)
3668 return 0;
3669
3670
3671
3672 memset (variations, 0, sizeof *variations * 256);
3673
3674
3675
3676 i = 0;
3677 while (i < info->uvs->num_records
3678 && info->uvs->records[i].selector < 0xfe00)
3679 ++i;
3680
3681
3682
3683 while (i < info->uvs->num_records
3684 && info->uvs->records[i].selector <= 0xfe0f)
3685 {
3686 record = &info->uvs->records[i];
3687
3688
3689
3690
3691 if (!record->nondefault_uvs)
3692 goto next_selector;
3693
3694
3695
3696 if (record->selector < 0xfe00)
3697 return 0;
3698
3699
3700
3701
3702 variations[info->uvs->records[i].selector - 0xfe00]
3703 = sfnt_variation_glyph_for_char (record->nondefault_uvs, c);
3704
3705 if (variations[info->uvs->records[i].selector - 0xfe00])
3706 ++n;
3707
3708 next_selector:
3709 ++i;
3710 }
3711
3712
3713
3714 i = 0;
3715 while (i < info->uvs->num_records
3716 && info->uvs->records[i].selector < 0xe0100)
3717 ++i;
3718
3719
3720
3721 while (i < info->uvs->num_records
3722 && info->uvs->records[i].selector <= 0xe01ef)
3723 {
3724 record = &info->uvs->records[i];
3725
3726
3727
3728
3729 if (!record->nondefault_uvs)
3730 goto next_selector_1;
3731
3732
3733
3734 if (record->selector < 0xe0100)
3735 return 0;
3736
3737
3738
3739
3740 variations[info->uvs->records[i].selector - 0xe0100 + 16]
3741 = sfnt_variation_glyph_for_char (record->nondefault_uvs, c);
3742
3743 if (variations[info->uvs->records[i].selector - 0xe0100 + 16])
3744 ++n;
3745
3746 next_selector_1:
3747 ++i;
3748 }
3749
3750 return n;
3751 }
3752
3753
3754
3755
3756
3757 #ifdef HAVE_MMAP
3758
3759
3760
3761
3762 bool
3763 sfntfont_detect_sigbus (void *addr)
3764 {
3765 struct sfnt_font_info *info;
3766
3767 for (info = open_fonts; info; info = info->next)
3768 {
3769 if (info->glyf_table_mapped
3770 && (unsigned char *) addr >= info->glyf->glyphs
3771 && (unsigned char *) addr < (info->glyf->glyphs
3772 + info->glyf->size))
3773 return true;
3774 }
3775
3776 return false;
3777 }
3778
3779 #endif
3780
3781
3782
3783
3784
3785 #ifdef HAVE_HARFBUZZ
3786
3787 #ifdef HAVE_MMAP
3788
3789
3790
3791 static void
3792 sfntfont_unmap_blob (void *ptr)
3793 {
3794 if (sfnt_unmap_table (ptr))
3795 emacs_abort ();
3796
3797 xfree (ptr);
3798 }
3799
3800 #endif
3801
3802
3803
3804
3805 static hb_blob_t *
3806 sfntfont_get_font_table (hb_face_t *face, hb_tag_t tag, void *data)
3807 {
3808 size_t size;
3809 struct sfnt_font_info *info;
3810 #ifdef HAVE_MMAP
3811 struct sfnt_mapped_table *table;
3812 hb_blob_t *blob;
3813
3814 info = data;
3815 table = xmalloc (sizeof *table);
3816
3817 if (!sfnt_map_table (info->fd, info->directory, tag,
3818 table))
3819 {
3820
3821
3822
3823
3824 blob = hb_blob_create (table->data, table->length,
3825 HB_MEMORY_MODE_READONLY,
3826 table, sfntfont_unmap_blob);
3827
3828
3829
3830 return blob;
3831 }
3832
3833 xfree (table);
3834 #else
3835
3836
3837 info = data;
3838 #endif
3839
3840 data = sfnt_read_table (info->fd, info->directory, tag,
3841 &size);
3842
3843 if (!data)
3844 return NULL;
3845
3846 return hb_blob_create (data, size, HB_MEMORY_MODE_WRITABLE,
3847 data, xfree);
3848 }
3849
3850
3851
3852
3853
3854 hb_font_t *
3855 sfntfont_begin_hb_font (struct font *font, double *position_unit)
3856 {
3857 struct sfnt_font_info *info;
3858 hb_face_t *face;
3859 int factor;
3860
3861 info = (struct sfnt_font_info *) font;
3862
3863 if (info->hb_font)
3864 {
3865
3866 *position_unit = 1.0 / 64.0;
3867 return info->hb_font;
3868 }
3869
3870
3871 face = hb_face_create_for_tables (sfntfont_get_font_table, font,
3872 NULL);
3873
3874 if (hb_face_get_glyph_count (face) > 0)
3875 {
3876 info->hb_font = hb_font_create (face);
3877 if (!info->hb_font)
3878 goto bail;
3879
3880 factor = font->pixel_size;
3881
3882
3883 hb_font_set_scale (info->hb_font, factor * 64, factor * 64);
3884 hb_font_set_ppem (info->hb_font, factor, factor);
3885
3886 #ifdef HAVE_HB_FONT_SET_VAR_NAMED_INSTANCE
3887
3888 if (info->instance != -1)
3889 hb_font_set_var_named_instance (info->hb_font,
3890 info->instance);
3891 #endif
3892
3893
3894
3895 hb_ot_font_set_funcs (info->hb_font);
3896 }
3897
3898 bail:
3899 hb_face_destroy (face);
3900
3901
3902 *position_unit = 1.0 / 64.0;
3903 return info->hb_font;
3904 }
3905
3906 #endif
3907
3908
3909
3910 void
3911 syms_of_sfntfont (void)
3912 {
3913 DEFSYM (Qutf_16be, "utf-16be");
3914 DEFSYM (Qmac_roman, "mac-roman");
3915 DEFSYM (Qchinese_big5, "chinese-big5");
3916 DEFSYM (Qunicode_bmp, "unicode-bmp");
3917 DEFSYM (Qucs, "ucs");
3918 DEFSYM (Qjapanese_jisx0208, "japanese-jisx0208");
3919 DEFSYM (Qgbk, "gbk");
3920 DEFSYM (Qkorean_ksc5601, "korean-ksc5601");
3921 DEFSYM (Qapple_roman, "apple-roman");
3922 DEFSYM (Qjisx0208_1983_0, "jisx0208.1983-0");
3923 DEFSYM (Qksc5601_1987_0, "ksc5601.1987-0");
3924 DEFSYM (Qzh, "zh");
3925 DEFSYM (Qja, "ja");
3926 DEFSYM (Qko, "ko");
3927 DEFSYM (Qfont_instance, "font-instance");
3928
3929
3930 DEFSYM (Qfont_lookup_cache, "font-lookup-cache");
3931
3932
3933 sfnt_vendor_name = Qnil;
3934 staticpro (&sfnt_vendor_name);
3935
3936
3937
3938 DEFVAR_LISP ("sfnt-default-family-alist", Vsfnt_default_family_alist,
3939 doc:
3940
3941
3942
3943
3944 );
3945 Vsfnt_default_family_alist = Qnil;
3946 }
3947
3948 void
3949 mark_sfntfont (void)
3950 {
3951 struct sfnt_font_desc *desc;
3952
3953
3954 for (desc = system_fonts; desc; desc = desc->next)
3955 {
3956 mark_object (desc->family);
3957 mark_object (desc->style);
3958 mark_object (desc->adstyle);
3959 mark_object (desc->instances);
3960 mark_object (desc->languages);
3961 mark_object (desc->registry);
3962 mark_object (desc->char_cache);
3963 mark_object (desc->designer);
3964 }
3965 }
3966
3967 void
3968 init_sfntfont (void)
3969 {
3970
3971 }
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983 void
3984 init_sfntfont_vendor (Lisp_Object vendor_name,
3985 const struct font_driver *driver,
3986 sfntfont_put_glyph_proc put_glyphs)
3987 {
3988 sfnt_vendor_name = vendor_name;
3989 sfnt_font_driver = driver;
3990 sfnt_put_glyphs = put_glyphs;
3991 }