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