+/* This small function is static in fontset.c. If it can be made public for
+ all ports, remove this, but otherwise it doesn't seem worth the ifdefs. */
+static void
+accumulate_script_ranges (Lisp_Object arg, Lisp_Object range, Lisp_Object val)
+{
+ if (EQ (XCAR (arg), val))
+ {
+ if (CONSP (range))
+ XSETCDR (arg, Fcons (Fcons (XCAR (range), XCDR (range)), XCDR (arg)));
+ else
+ XSETCDR (arg, Fcons (Fcons (range, range), XCDR (arg)));
+ }
+}
+
+
+/* Use the Unicode range information in Vchar_script_table to convert a script
+ name into an NSCharacterSet. */
+static NSCharacterSet
+*ns_script_to_charset (NSString *scriptName)
+{
+ NSMutableCharacterSet *charset = [NSMutableCharacterSet new];
+ Lisp_Object script = intern ([scriptName UTF8String]);
+ Lisp_Object script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
+
+ if (! NILP (Fmemq (script, script_list)))
+ {
+ Lisp_Object ranges, range_list;
+
+ ranges = Fcons (script, Qnil);
+ map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
+ ranges);
+ range_list = Fnreverse (XCDR (ranges));
+ if (! NILP (range_list))
+ {
+ for (; CONSP (range_list); range_list = XCDR (range_list))
+ {
+ int start = XINT (XCAR (XCAR (range_list)));
+ int end = XINT (XCDR (XCAR (range_list)));
+ if (NSFONT_TRACE)
+ debug_print (XCAR (range_list));
+ if (end < 0x10000)
+ [charset addCharactersInRange:
+ NSMakeRange (start, end-start)];
+ }
+ }
+ }
+ return charset;
+}
+
+
+/* Return an array of font families containing characters for the given
+ script, for the given coverage criterion, including at least LastResort.
+ Results are cached by script for faster access.
+ If none are found, we reduce the percentage and try again, until 5%.
+ This provides a font with at least some characters if such can be found.
+ We don't use isSupersetOfSet: because (a) it doesn't work on Tiger, and
+ (b) need approximate match as fonts covering full Unicode ranges are rare. */
+static NSSet
+*ns_get_covering_families (NSString *script, float pct)
+{
+ static NSMutableDictionary *scriptToFamilies = nil;
+ NSMutableSet *families;
+
+ if (NSFONT_TRACE)
+ NSLog(@"Request covering families for script: '%@'", script);
+
+ if (scriptToFamilies == nil)
+ scriptToFamilies = [[NSMutableDictionary alloc] init];
+
+ if ((families = [scriptToFamilies objectForKey: script]) == nil)
+ {
+ NSFontManager *fontMgr = [NSFontManager sharedFontManager];
+ NSArray *allFamilies = [fontMgr availableFontFamilies];
+
+ if ([script length] == 0)
+ families = [NSMutableSet setWithArray: allFamilies];
+ else
+ {
+ NSCharacterSet *charset = ns_script_to_charset (script);
+ NSString *family;
+ families = [NSMutableSet setWithCapacity: 10];
+ while (1)
+ {
+ NSEnumerator *allFamiliesEnum = [allFamilies objectEnumerator];
+ while (family = [allFamiliesEnum nextObject])
+ {
+ NSCharacterSet *fset = [[fontMgr fontWithFamily: family
+ traits: 0 weight: 5 size: 12.0] coveredCharacterSet];
+ /* Some fonts on OS X, maybe many on GNUstep, return nil. */
+ if (fset == nil)
+ fset = [NSCharacterSet characterSetWithRange:
+ NSMakeRange (0, 127)];
+ if (ns_charset_covers(fset, charset, pct))
+ [families addObject: family];
+ }
+ pct -= 0.2;
+ if ([families count] > 0 || pct < 0.05)
+ break;
+ }
+ [charset release];
+ }
+#ifdef NS_IMPL_COCOA
+ if ([families count] == 0)
+ [families addObject: @"LastResort"];
+#endif
+ [scriptToFamilies setObject: families forKey: script];
+ }
+
+ if (NSFONT_TRACE)
+ NSLog(@" returning %d families", [families count]);
+ return families;
+}
+
+
+/* Implementation for list() and match(). List() can return nil, match()
+must return something. Strategy is to drop family name from attribute
+matching set for match. */