aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-02-20 11:38:59 +0800
committerPo Lu2023-02-20 11:38:59 +0800
commit34ba481c8ea86da7922129f684c18b7aba186947 (patch)
tree59a7d416cb2089cc958dca4a4a543d2efd61960e /src
parentb91396bace7e09ba1dc0430ce5e2b5b3000fe77a (diff)
downloademacs-34ba481c8ea86da7922129f684c18b7aba186947.tar.gz
emacs-34ba481c8ea86da7922129f684c18b7aba186947.zip
Improve SFNT driver lookup efficiency
* src/fontset.c (fontset_find_font): Add compatibility test to registry strangeness case. * src/sfnt.c (sfnt_read_cmap_table): Don't read subtable data if DATA is NULL. * src/sfntfont.c (struct sfnt_font_desc): New field `registry'. (sfnt_registry_for_subtable): New function. (sfntfont_identify_cmap): Move above sfnt_grok_registry. (sfnt_grok_registry): New function. (sfnt_enum_font_1): Call it. (sfntfont_registries_compatible_p): New function. (sfntfont_list_1): Check registry compatibility. (sfntfont_registry_for_desc): New function. (mark_sfntfont): Mark desc->registry.
Diffstat (limited to 'src')
-rw-r--r--src/fontset.c8
-rw-r--r--src/sfnt.c8
-rw-r--r--src/sfntfont.c398
3 files changed, 273 insertions, 141 deletions
diff --git a/src/fontset.c b/src/fontset.c
index 8182d639299..bcf200aeae8 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -683,7 +683,13 @@ fontset_find_font (Lisp_Object fontset, int c, struct face *face,
683 && !NILP (AREF (spec, FONT_REGISTRY_INDEX)) 683 && !NILP (AREF (spec, FONT_REGISTRY_INDEX))
684 && !NILP (AREF (font_object, FONT_REGISTRY_INDEX)) 684 && !NILP (AREF (font_object, FONT_REGISTRY_INDEX))
685 && !EQ (AREF (spec, FONT_REGISTRY_INDEX), 685 && !EQ (AREF (spec, FONT_REGISTRY_INDEX),
686 AREF (font_object, FONT_REGISTRY_INDEX))) 686 AREF (font_object, FONT_REGISTRY_INDEX))
687 /* See sfntfont_registries_compatible_p in
688 sfntfont.c. */
689 && !(EQ (AREF (spec, FONT_REGISTRY_INDEX),
690 Qiso8859_1)
691 && EQ (AREF (font_object, FONT_REGISTRY_INDEX),
692 Qiso10646_1)))
687 goto strangeness; 693 goto strangeness;
688 } 694 }
689 695
diff --git a/src/sfnt.c b/src/sfnt.c
index 06985c74a57..f3656422eef 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -837,7 +837,8 @@ sfnt_read_cmap_table_1 (int fd, uint32_t directory_offset,
837 table directory specified in SUBTABLE. 837 table directory specified in SUBTABLE.
838 838
839 Return the CMAP table and a list of encoding subtables in 839 Return the CMAP table and a list of encoding subtables in
840 *SUBTABLES and *DATA upon success, else NULL. */ 840 *SUBTABLES and *DATA upon success, else NULL. If DATA is NULL, do
841 not read the subtable data. */
841 842
842TEST_STATIC struct sfnt_cmap_table * 843TEST_STATIC struct sfnt_cmap_table *
843sfnt_read_cmap_table (int fd, struct sfnt_offset_subtable *subtable, 844sfnt_read_cmap_table (int fd, struct sfnt_offset_subtable *subtable,
@@ -902,6 +903,11 @@ sfnt_read_cmap_table (int fd, struct sfnt_offset_subtable *subtable,
902 sfnt_swap32 (&(*subtables)[i].offset); 903 sfnt_swap32 (&(*subtables)[i].offset);
903 } 904 }
904 905
906 /* If data is NULL, the caller only wants the table headers. */
907
908 if (!data)
909 return cmap;
910
905 /* Second, read each encoding subtable itself. */ 911 /* Second, read each encoding subtable itself. */
906 *data = xmalloc (cmap->num_subtables 912 *data = xmalloc (cmap->num_subtables
907 * sizeof **subtables); 913 * sizeof **subtables);
diff --git a/src/sfntfont.c b/src/sfntfont.c
index b9141b05aad..31557155e51 100644
--- a/src/sfntfont.c
+++ b/src/sfntfont.c
@@ -68,6 +68,9 @@ struct sfnt_font_desc
68 /* List of design languages. */ 68 /* List of design languages. */
69 Lisp_Object languages; 69 Lisp_Object languages;
70 70
71 /* Font registry that this font supports. */
72 Lisp_Object registry;
73
71 /* Numeric width, weight, slant and spacing. */ 74 /* Numeric width, weight, slant and spacing. */
72 int width, weight, slant, spacing; 75 int width, weight, slant, spacing;
73 76
@@ -511,6 +514,226 @@ sfnt_parse_languages (struct sfnt_meta_table *meta,
511 SAFE_FREE (); 514 SAFE_FREE ();
512} 515}
513 516
517/* Return the font registry corresponding to the encoding subtable
518 SUBTABLE.
519
520 Under X, the font registry is an atom registered with the Open
521 Group uniquely identifying the organization which defines the
522 font's character set.
523
524 In practice, the registry overlaps with the character set itself.
525 So Emacs just uses the ``registry'' field of each font object and
526 entity to represent both instead. */
527
528static Lisp_Object
529sfnt_registry_for_subtable (struct sfnt_cmap_encoding_subtable *subtable)
530{
531 switch (subtable->platform_id)
532 {
533 case SFNT_PLATFORM_UNICODE:
534 /* Reject variation selector and last resort tables. */
535 if ((subtable->platform_specific_id
536 == SFNT_UNICODE_VARIATION_SEQUENCES)
537 || (subtable->platform_specific_id
538 == SFNT_UNICODE_LAST_RESORT))
539 return Qnil;
540
541 return Qiso10646_1;
542
543 case SFNT_PLATFORM_MACINTOSH:
544
545 switch (subtable->platform_specific_id)
546 {
547 case SFNT_MACINTOSH_ROMAN:
548 /* X calls mac-roman ``apple-roman''. */
549 return Qapple_roman;
550
551 default:
552 /* Some other Macintosh charset not supported by Emacs. */
553 return Qnil;
554 }
555
556 case SFNT_PLATFORM_MICROSOFT:
557
558 /* Microsoft specific encodings. */
559
560 switch (subtable->platform_specific_id)
561 {
562 case SFNT_MICROSOFT_SYMBOL:
563 case SFNT_MICROSOFT_UNICODE_BMP:
564 /* Symbols in the Unicode PUA are still Unicode. */
565 return Qiso10646_1;
566
567 case SFNT_MICROSOFT_SHIFT_JIS:
568 return Qjisx0208_1983_0;
569
570 case SFNT_MICROSOFT_PRC:
571 return Qgbk;
572
573 case SFNT_MICROSOFT_JOHAB:
574 return Qksc5601_1987_0;
575
576 case SFNT_MICROSOFT_UNICODE_UCS_4:
577 return Qiso10646_1;
578 }
579
580 default:
581 return Qnil;
582 }
583}
584
585/* Return the type of characters that the cmap subtable SUBTABLE maps
586 from. Value is:
587
588 2 if SUBTABLE maps from Unicode characters, including those outside
589 the Unicode Basic Multilingual Plane (BMP).
590
591 1 if SUBTABLE maps from Unicode characters within the BMP.
592
593 0 if SUBTABLE maps from some other character set that Emacs knows
594 about.
595
596 3 if SUBTABLE cannot be used by Emacs. */
597
598static int
599sfntfont_identify_cmap (struct sfnt_cmap_encoding_subtable subtable)
600{
601 switch (subtable.platform_id)
602 {
603 case SFNT_PLATFORM_UNICODE:
604
605 /* Reject variation selector and last resort tables. */
606 if ((subtable.platform_specific_id
607 == SFNT_UNICODE_VARIATION_SEQUENCES)
608 || (subtable.platform_specific_id
609 == SFNT_UNICODE_LAST_RESORT))
610 return 3;
611
612 /* 1.0, 1.1, ISO-10646-1993, and 2.0_BMP tables are all within
613 the BMP. */
614 if (subtable.platform_specific_id < SFNT_UNICODE_2_0)
615 return 1;
616
617 return 2;
618
619 case SFNT_PLATFORM_MACINTOSH:
620
621 switch (subtable.platform_specific_id)
622 {
623 case SFNT_MACINTOSH_ROMAN:
624 /* mac-roman */
625 return 0;
626
627 default:
628 /* Some other Macintosh charset not supported by Emacs. */
629 return 3;
630 }
631
632 case SFNT_PLATFORM_MICROSOFT:
633
634 /* Microsoft specific encodings. */
635
636 switch (subtable.platform_specific_id)
637 {
638 case SFNT_MICROSOFT_SYMBOL:
639 /* Symbols in the Unicode PUA are still Unicode. */
640 return 1;
641
642 case SFNT_MICROSOFT_UNICODE_BMP:
643 return 1;
644
645 case SFNT_MICROSOFT_SHIFT_JIS:
646 /* PCK aka japanese-jisx0208. */
647 return 0;
648
649 case SFNT_MICROSOFT_PRC:
650 /* GBK, GB2312 or GB18030. */
651 return 0;
652
653 case SFNT_MICROSOFT_JOHAB:
654 /* KS C 5601-1992, aka korean-ksc5601. */
655 return 0;
656
657 case SFNT_MICROSOFT_UNICODE_UCS_4:
658 /* Unicode past the BMP. */
659 return 2;
660 }
661
662 default:
663 return 3;
664 }
665}
666
667/* Figure out which registry DESC, backed by FD, whose table directory
668 is SUBTABLE, is likely to support.
669
670 Read the header of each subtable in the character map and compute
671 the registry to use; then, set DESC->registry to that value. */
672
673static void
674sfnt_grok_registry (int fd, struct sfnt_font_desc *desc,
675 struct sfnt_offset_subtable *subtable)
676{
677 struct sfnt_cmap_table *cmap;
678 struct sfnt_cmap_encoding_subtable *subtables;
679 int i;
680
681 cmap = sfnt_read_cmap_table (fd, subtable, &subtables, NULL);
682
683 if (!cmap)
684 return;
685
686 /* Now pick the ``best'' character map the same way as sfntfont_open
687 does. The caveat is that since the subtable data has not been
688 read, Emacs cannot determine whether or not the encoding subtable
689 is valid.
690
691 Once platform_id is set, that value becomes much more
692 reliable. */
693
694 /* First look for a non-BMP Unicode cmap. */
695
696 for (i = 0; i < cmap->num_subtables; ++i)
697 {
698 if (sfntfont_identify_cmap (subtables[i]) == 2)
699 {
700 desc->registry
701 = sfnt_registry_for_subtable (&subtables[i]);
702 goto done;
703 }
704 }
705
706 /* Next, look for a BMP only Unicode cmap. */
707
708 for (i = 0; i < cmap->num_subtables; ++i)
709 {
710 if (sfntfont_identify_cmap (subtables[i]) == 1)
711 {
712 desc->registry
713 = sfnt_registry_for_subtable (&subtables[i]);
714 goto done;
715 }
716 }
717
718 /* Finally, use the first cmap that appears and can be
719 identified. */
720
721 for (i = 0; i < cmap->num_subtables; ++i)
722 {
723 if (sfntfont_identify_cmap (subtables[i]) == 0)
724 {
725 desc->registry
726 = sfnt_registry_for_subtable (&subtables[i]);
727 goto done;
728 }
729 }
730
731 /* There are no cmaps available to Emacs. */
732 done:
733 xfree (cmap);
734 xfree (subtables);
735}
736
514/* Enumerate the offset subtable SUBTABLES in the file FD, whose file 737/* Enumerate the offset subtable SUBTABLES in the file FD, whose file
515 name is FILE. OFFSET should be the offset of the subtable within 738 name is FILE. OFFSET should be the offset of the subtable within
516 the font file, and is recorded for future use. Value is 1 upon 739 the font file, and is recorded for future use. Value is 1 upon
@@ -591,6 +814,9 @@ sfnt_enum_font_1 (int fd, const char *file,
591 if (head->mac_style & 02 && desc->slant == 0) /* Italic */ 814 if (head->mac_style & 02 && desc->slant == 0) /* Italic */
592 desc->slant = 100; 815 desc->slant = 100;
593 816
817 /* Figure out what registry this font is likely to support. */
818 sfnt_grok_registry (fd, desc, subtables);
819
594 /* Set the style, link the desc onto system_fonts and return. */ 820 /* Set the style, link the desc onto system_fonts and return. */
595 desc->style = style; 821 desc->style = style;
596 desc->next = system_fonts; 822 desc->next = system_fonts;
@@ -803,88 +1029,6 @@ sfntfont_charset_for_cmap (struct sfnt_cmap_encoding_subtable subtable)
803 } 1029 }
804} 1030}
805 1031
806/* Return the type of characters that the cmap subtable SUBTABLE maps
807 from. Value is:
808
809 2 if SUBTABLE maps from Unicode characters, including those outside
810 the Unicode Basic Multilingual Plane (BMP).
811
812 1 if SUBTABLE maps from Unicode characters within the BMP.
813
814 0 if SUBTABLE maps from some other character set that Emacs knows
815 about.
816
817 3 if SUBTABLE cannot be used by Emacs. */
818
819static int
820sfntfont_identify_cmap (struct sfnt_cmap_encoding_subtable subtable)
821{
822 switch (subtable.platform_id)
823 {
824 case SFNT_PLATFORM_UNICODE:
825
826 /* Reject variation selector and last resort tables. */
827 if ((subtable.platform_specific_id
828 == SFNT_UNICODE_VARIATION_SEQUENCES)
829 || (subtable.platform_specific_id
830 == SFNT_UNICODE_LAST_RESORT))
831 return 3;
832
833 /* 1.0, 1.1, ISO-10646-1993, and 2.0_BMP tables are all within
834 the BMP. */
835 if (subtable.platform_specific_id < SFNT_UNICODE_2_0)
836 return 1;
837
838 return 2;
839
840 case SFNT_PLATFORM_MACINTOSH:
841
842 switch (subtable.platform_specific_id)
843 {
844 case SFNT_MACINTOSH_ROMAN:
845 /* mac-roman */
846 return 0;
847
848 default:
849 /* Some other Macintosh charset not supported by Emacs. */
850 return 3;
851 }
852
853 case SFNT_PLATFORM_MICROSOFT:
854
855 /* Microsoft specific encodings. */
856
857 switch (subtable.platform_specific_id)
858 {
859 case SFNT_MICROSOFT_SYMBOL:
860 /* Symbols in the Unicode PUA are still Unicode. */
861 return 1;
862
863 case SFNT_MICROSOFT_UNICODE_BMP:
864 return 1;
865
866 case SFNT_MICROSOFT_SHIFT_JIS:
867 /* PCK aka japanese-jisx0208. */
868 return 0;
869
870 case SFNT_MICROSOFT_PRC:
871 /* GBK, GB2312 or GB18030. */
872 return 0;
873
874 case SFNT_MICROSOFT_JOHAB:
875 /* KS C 5601-1992, aka korean-ksc5601. */
876 return 0;
877
878 case SFNT_MICROSOFT_UNICODE_UCS_4:
879 /* Unicode past the BMP. */
880 return 2;
881 }
882
883 default:
884 return 3;
885 }
886}
887
888/* Pick the best character map in the cmap table CMAP. Use the 1032/* Pick the best character map in the cmap table CMAP. Use the
889 subtables in SUBTABLES and DATA. Return the subtable data and the 1033 subtables in SUBTABLES and DATA. Return the subtable data and the
890 subtable in *SUBTABLE upon success, NULL otherwise. */ 1034 subtable in *SUBTABLE upon success, NULL otherwise. */
@@ -1082,6 +1226,24 @@ sfntfont_lookup_char (struct sfnt_font_desc *desc, Lisp_Object character,
1082 return present; 1226 return present;
1083} 1227}
1084 1228
1229/* Return whether or not the specified registry A is ``compatible''
1230 with registry B.
1231
1232 Compatibility does not refer to whether or not the font registries
1233 have an identical character set or repertory of characters.
1234
1235 Instead, it refers to whether or not Emacs expects looking for A to
1236 result in fonts used with B. */
1237
1238static bool
1239sfntfont_registries_compatible_p (Lisp_Object a, Lisp_Object b)
1240{
1241 if (EQ (a, Qiso8859_1) && EQ (b, Qiso10646_1))
1242 return true;
1243
1244 return EQ (a, b);
1245}
1246
1085/* Return whether or not the font description DESC satisfactorily 1247/* Return whether or not the font description DESC satisfactorily
1086 matches the font specification FONT_SPEC. */ 1248 matches the font specification FONT_SPEC. */
1087 1249
@@ -1127,6 +1289,17 @@ sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec)
1127 desc->family))) 1289 desc->family)))
1128 return false; 1290 return false;
1129 1291
1292 /* If a registry is set and wrong, then reject the font desc
1293 immediately. This detects 50% of mismatches from fontset.c.
1294
1295 If DESC->registry is nil, then the registry couldn't be
1296 determined beforehand. */
1297
1298 tem = AREF (spec, FONT_REGISTRY_INDEX);
1299 if (!NILP (tem) && !NILP (desc->registry)
1300 && !sfntfont_registries_compatible_p (tem, desc->registry))
1301 return false;
1302
1130 /* Check that the adstyle specified matches. */ 1303 /* Check that the adstyle specified matches. */
1131 1304
1132 tem = AREF (spec, FONT_ADSTYLE_INDEX); 1305 tem = AREF (spec, FONT_ADSTYLE_INDEX);
@@ -1264,63 +1437,9 @@ sfntfont_registry_for_desc (struct sfnt_font_desc *desc)
1264 xfree (cmap); 1437 xfree (cmap);
1265 1438
1266 if (desc->subtable.platform_id != 500) 1439 if (desc->subtable.platform_id != 500)
1267 { 1440 /* desc->subtable.platform_id is now set. CMAP is already free,
1268 /* desc->subtable.platform_id is now set. CMAP is already free, 1441 because it is not actually used. */
1269 because it is not actually used. */ 1442 return sfnt_registry_for_subtable (&desc->subtable);
1270
1271 switch (desc->subtable.platform_id)
1272 {
1273 case SFNT_PLATFORM_UNICODE:
1274 /* Reject variation selector and last resort tables. */
1275 if ((desc->subtable.platform_specific_id
1276 == SFNT_UNICODE_VARIATION_SEQUENCES)
1277 || (desc->subtable.platform_specific_id
1278 == SFNT_UNICODE_LAST_RESORT))
1279 return Qnil;
1280
1281 return Qiso10646_1;
1282
1283 case SFNT_PLATFORM_MACINTOSH:
1284
1285 switch (desc->subtable.platform_specific_id)
1286 {
1287 case SFNT_MACINTOSH_ROMAN:
1288 /* X calls mac-roman ``apple-roman''. */
1289 return Qapple_roman;
1290
1291 default:
1292 /* Some other Macintosh charset not supported by Emacs. */
1293 return Qnil;
1294 }
1295
1296 case SFNT_PLATFORM_MICROSOFT:
1297
1298 /* Microsoft specific encodings. */
1299
1300 switch (desc->subtable.platform_specific_id)
1301 {
1302 case SFNT_MICROSOFT_SYMBOL:
1303 case SFNT_MICROSOFT_UNICODE_BMP:
1304 /* Symbols in the Unicode PUA are still Unicode. */
1305 return Qiso10646_1;
1306
1307 case SFNT_MICROSOFT_SHIFT_JIS:
1308 return Qjisx0208_1983_0;
1309
1310 case SFNT_MICROSOFT_PRC:
1311 return Qgbk;
1312
1313 case SFNT_MICROSOFT_JOHAB:
1314 return Qksc5601_1987_0;
1315
1316 case SFNT_MICROSOFT_UNICODE_UCS_4:
1317 return Qiso10646_1;
1318 }
1319
1320 default:
1321 return Qnil;
1322 }
1323 }
1324 1443
1325 return Qnil; 1444 return Qnil;
1326} 1445}
@@ -2793,6 +2912,7 @@ mark_sfntfont (void)
2793 mark_object (desc->style); 2912 mark_object (desc->style);
2794 mark_object (desc->adstyle); 2913 mark_object (desc->adstyle);
2795 mark_object (desc->languages); 2914 mark_object (desc->languages);
2915 mark_object (desc->registry);
2796 mark_object (desc->char_cache); 2916 mark_object (desc->char_cache);
2797 mark_object (desc->designer); 2917 mark_object (desc->designer);
2798 } 2918 }