aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/macfont.m201
1 files changed, 166 insertions, 35 deletions
diff --git a/src/macfont.m b/src/macfont.m
index cbf1ab8e55d..b25640e0cb8 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -897,14 +897,152 @@ macfont_descriptor_entity (FontDescriptorRef desc, Lisp_Object extra,
897 return entity; 897 return entity;
898} 898}
899 899
900/* Cache for font family name symbols vs CFStrings. A value of nil
901means the cache has been invalidated. Otherwise the value is a Lisp
902hash table whose keys are symbols and the value for a key is either
903nil (no corresponding family name) or a Lisp save value wrapping the
904corresponding family name in CFString. */
905
906static Lisp_Object macfont_family_cache;
907
908static void
909macfont_invalidate_family_cache (void)
910{
911 if (HASH_TABLE_P (macfont_family_cache))
912 {
913 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
914 ptrdiff_t i, size = HASH_TABLE_SIZE (h);
915
916 for (i = 0; i < size; ++i)
917 if (!NILP (HASH_HASH (h, i)))
918 {
919 Lisp_Object value = HASH_VALUE (h, i);
920
921 if (SAVE_VALUEP (value))
922 CFRelease (XSAVE_POINTER (value, 0));
923 }
924 macfont_family_cache = Qnil;
925 }
926}
927
928static bool
929macfont_get_family_cache_if_present (Lisp_Object symbol, CFStringRef *string)
930{
931 if (HASH_TABLE_P (macfont_family_cache))
932 {
933 struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
934 ptrdiff_t i = hash_lookup (h, symbol, NULL);
935
936 if (i >= 0)
937 {
938 Lisp_Object value = HASH_VALUE (h, i);
939
940 *string = SAVE_VALUEP (value) ? XSAVE_POINTER (value, 0) : NULL;
941
942 return true;
943 }
944 }
945
946 return false;
947}
948
949static void
950macfont_set_family_cache (Lisp_Object symbol, CFStringRef string)
951{
952 struct Lisp_Hash_Table *h;
953 ptrdiff_t i;
954 EMACS_UINT hash;
955 Lisp_Object value;
956
957 if (!HASH_TABLE_P (macfont_family_cache))
958 {
959 Lisp_Object args[2];
960
961 args[0] = QCtest;
962 args[1] = Qeq;
963 macfont_family_cache = Fmake_hash_table (2, args);
964 }
965
966 h = XHASH_TABLE (macfont_family_cache);
967 i = hash_lookup (h, symbol, &hash);
968 value = string ? make_save_ptr ((void *) CFRetain (string)) : Qnil;
969 if (i >= 0)
970 {
971 Lisp_Object old_value = HASH_VALUE (h, i);
972
973 if (SAVE_VALUEP (old_value))
974 CFRelease (XSAVE_POINTER (old_value, 0));
975 set_hash_value_slot (h, i, value);
976 }
977 else
978 hash_put (h, symbol, value, hash);
979}
980
981/* Cache of all the available font family names except "LastResort"
982and those start with ".". NULL means the cache has been invalidated.
983Otherwise, the value is CFArray of CFStrings and the elements are
984sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
985OS X 10.6 and later). */
986
987static CFArrayRef macfont_available_families_cache = NULL;
988
989static void
990macfont_invalidate_available_families_cache (void)
991{
992 if (macfont_available_families_cache)
993 {
994 CFRelease (macfont_available_families_cache);
995 macfont_available_families_cache = NULL;
996 }
997}
998
999static void
1000macfont_handle_font_change_notification (CFNotificationCenterRef center,
1001 void *observer,
1002 CFStringRef name, const void *object,
1003 CFDictionaryRef userInfo)
1004{
1005 macfont_invalidate_family_cache ();
1006 macfont_invalidate_available_families_cache ();
1007}
1008
1009static void
1010macfont_init_font_change_handler (void)
1011{
1012 static bool initialized = false;
1013
1014 if (initialized)
1015 return;
1016
1017 initialized = true;
1018 CFNotificationCenterAddObserver
1019 (CFNotificationCenterGetLocalCenter (), NULL,
1020 macfont_handle_font_change_notification,
1021 kCTFontManagerRegisteredFontsChangedNotification,
1022 NULL, CFNotificationSuspensionBehaviorCoalesce);
1023}
1024
1025static CFArrayRef
1026macfont_copy_available_families_cache (void)
1027{
1028 macfont_init_font_change_handler ();
1029
1030 if (macfont_available_families_cache == NULL)
1031 macfont_available_families_cache = mac_font_create_available_families ();
1032
1033 return (macfont_available_families_cache
1034 ? CFRetain (macfont_available_families_cache) : NULL);
1035}
1036
900static CFStringRef 1037static CFStringRef
901macfont_create_family_with_symbol (Lisp_Object symbol) 1038macfont_create_family_with_symbol (Lisp_Object symbol)
902{ 1039{
903 static CFArrayRef families = NULL;
904 CFStringRef result = NULL, family_name; 1040 CFStringRef result = NULL, family_name;
905 int using_cache_p = 1;
906 CFComparatorFunction family_name_comparator; 1041 CFComparatorFunction family_name_comparator;
907 1042
1043 if (macfont_get_family_cache_if_present (symbol, &result))
1044 return result ? CFRetain (result) : NULL;
1045
908 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol)); 1046 family_name = cfstring_create_with_string_noencode (SYMBOL_NAME (symbol));
909 if (family_name == NULL) 1047 if (family_name == NULL)
910 return NULL; 1048 return NULL;
@@ -917,42 +1055,32 @@ macfont_create_family_with_symbol (Lisp_Object symbol)
917 == kCFCompareEqualTo) 1055 == kCFCompareEqualTo)
918 result = CFSTR ("LastResort"); 1056 result = CFSTR ("LastResort");
919 else 1057 else
920 while (1) 1058 {
921 { 1059 CFIndex i, count;
922 CFIndex i, count; 1060 CFArrayRef families = macfont_copy_available_families_cache ();
923
924 if (families == NULL)
925 {
926 families = mac_font_create_available_families ();
927 using_cache_p = 0;
928 if (families == NULL)
929 break;
930 }
931
932 count = CFArrayGetCount (families);
933 i = CFArrayBSearchValues (families, CFRangeMake (0, count),
934 (const void *) family_name,
935 family_name_comparator, NULL);
936 if (i < count)
937 {
938 CFStringRef name = CFArrayGetValueAtIndex (families, i);
939 1061
940 if ((*family_name_comparator) (name, family_name, NULL) 1062 if (families)
941 == kCFCompareEqualTo) 1063 {
942 result = CFRetain (name); 1064 count = CFArrayGetCount (families);
943 } 1065 i = CFArrayBSearchValues (families, CFRangeMake (0, count),
1066 (const void *) family_name,
1067 family_name_comparator, NULL);
1068 if (i < count)
1069 {
1070 CFStringRef name = CFArrayGetValueAtIndex (families, i);
944 1071
945 if (result || !using_cache_p) 1072 if ((*family_name_comparator) (name, family_name, NULL)
946 break; 1073 == kCFCompareEqualTo)
947 else 1074 result = CFRetain (name);
948 { 1075 }
949 CFRelease (families); 1076 CFRelease (families);
950 families = NULL; 1077 }
951 } 1078 }
952 }
953 1079
954 CFRelease (family_name); 1080 CFRelease (family_name);
955 1081
1082 macfont_set_family_cache (symbol, result);
1083
956 return result; 1084 return result;
957} 1085}
958 1086
@@ -2091,7 +2219,7 @@ macfont_list (struct frame *f, Lisp_Object spec)
2091 CFStringRef pref_family; 2219 CFStringRef pref_family;
2092 CFIndex families_count, pref_family_index = -1; 2220 CFIndex families_count, pref_family_index = -1;
2093 2221
2094 families = mac_font_create_available_families (); 2222 families = macfont_copy_available_families_cache ();
2095 if (families == NULL) 2223 if (families == NULL)
2096 goto err; 2224 goto err;
2097 2225
@@ -2380,7 +2508,7 @@ macfont_list_family (struct frame *frame)
2380 2508
2381 block_input (); 2509 block_input ();
2382 2510
2383 families = mac_font_create_available_families (); 2511 families = macfont_copy_available_families_cache ();
2384 if (families) 2512 if (families)
2385 { 2513 {
2386 CFIndex i, count = CFArrayGetCount (families); 2514 CFIndex i, count = CFArrayGetCount (families);
@@ -3923,4 +4051,7 @@ syms_of_macfont (void)
3923 4051
3924 /* The boolean-valued font property key specifying the use of leading. */ 4052 /* The boolean-valued font property key specifying the use of leading. */
3925 DEFSYM (QCminspace, ":minspace"); 4053 DEFSYM (QCminspace, ":minspace");
4054
4055 macfont_family_cache = Qnil;
4056 staticpro (&macfont_family_cache);
3926} 4057}