0f2d882ca850919619e93de1168a283164afc971
[platform/upstream/libSkiaSharp.git] / src / ports / SkFontConfigInterface_direct.cpp
1 /*
2  * Copyright 2009 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */
9
10 #include <unistd.h>
11 #include <fcntl.h>
12
13 #include <fontconfig/fontconfig.h>
14
15 #include "SkBuffer.h"
16 #include "SkFontConfigInterface.h"
17 #include "SkLazyPtr.h"
18 #include "SkStream.h"
19 #include "SkString.h"
20
21 size_t SkFontConfigInterface::FontIdentity::writeToMemory(void* addr) const {
22     size_t size = sizeof(fID) + sizeof(fTTCIndex);
23     size += sizeof(int32_t) + sizeof(int32_t) + sizeof(uint8_t); // weight, width, italic
24     size += sizeof(int32_t) + fString.size();    // store length+data
25     if (addr) {
26         SkWBuffer buffer(addr, size);
27
28         buffer.write32(fID);
29         buffer.write32(fTTCIndex);
30         buffer.write32(fString.size());
31         buffer.write32(fStyle.weight());
32         buffer.write32(fStyle.width());
33         buffer.write8(fStyle.slant());
34         buffer.write(fString.c_str(), fString.size());
35         buffer.padToAlign4();
36
37         SkASSERT(buffer.pos() == size);
38     }
39     return size;
40 }
41
42 size_t SkFontConfigInterface::FontIdentity::readFromMemory(const void* addr,
43                                                            size_t size) {
44     SkRBuffer buffer(addr, size);
45
46     (void)buffer.readU32(&fID);
47     (void)buffer.readS32(&fTTCIndex);
48     uint32_t strLen, weight, width;
49     (void)buffer.readU32(&strLen);
50     (void)buffer.readU32(&weight);
51     (void)buffer.readU32(&width);
52     uint8_t u8;
53     (void)buffer.readU8(&u8);
54     SkFontStyle::Slant slant = (SkFontStyle::Slant)u8;
55     fStyle = SkFontStyle(weight, width, slant);
56     fString.resize(strLen);
57     (void)buffer.read(fString.writable_str(), strLen);
58     buffer.skipToAlign4();
59
60     return buffer.pos();    // the actual number of bytes read
61 }
62
63 #ifdef SK_DEBUG
64 static void make_iden(SkFontConfigInterface::FontIdentity* iden) {
65     iden->fID = 10;
66     iden->fTTCIndex = 2;
67     iden->fString.set("Hello world");
68     iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant);
69 }
70
71 static void test_writeToMemory(const SkFontConfigInterface::FontIdentity& iden0,
72                                int initValue) {
73     SkFontConfigInterface::FontIdentity iden1;
74
75     size_t size0 = iden0.writeToMemory(NULL);
76
77     SkAutoMalloc storage(size0);
78     memset(storage.get(), initValue, size0);
79
80     size_t size1 = iden0.writeToMemory(storage.get());
81     SkASSERT(size0 == size1);
82
83     SkASSERT(iden0 != iden1);
84     size_t size2 = iden1.readFromMemory(storage.get(), size1);
85     SkASSERT(size2 == size1);
86     SkASSERT(iden0 == iden1);
87 }
88
89 static void fontconfiginterface_unittest() {
90     SkFontConfigInterface::FontIdentity iden0, iden1;
91
92     SkASSERT(iden0 == iden1);
93
94     make_iden(&iden0);
95     SkASSERT(iden0 != iden1);
96
97     make_iden(&iden1);
98     SkASSERT(iden0 == iden1);
99
100     test_writeToMemory(iden0, 0);
101     test_writeToMemory(iden0, 0);
102 }
103 #endif
104
105 class SkFontConfigInterfaceDirect : public SkFontConfigInterface {
106 public:
107             SkFontConfigInterfaceDirect();
108     virtual ~SkFontConfigInterfaceDirect();
109
110     virtual bool matchFamilyName(const char familyName[],
111                                  SkTypeface::Style requested,
112                                  FontIdentity* outFontIdentifier,
113                                  SkString* outFamilyName,
114                                  SkTypeface::Style* outStyle) SK_OVERRIDE;
115     SkStreamAsset* openStream(const FontIdentity&) SK_OVERRIDE;
116
117     // new APIs
118     SkDataTable* getFamilyNames() SK_OVERRIDE;
119     virtual bool matchFamilySet(const char inFamilyName[],
120                                 SkString* outFamilyName,
121                                 SkTArray<FontIdentity>*) SK_OVERRIDE;
122
123 private:
124     SkMutex mutex_;
125 };
126
127 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface(SkBaseMutex* mutex) {
128     SkAutoMutexAcquire ac(mutex);
129     static SkFontConfigInterfaceDirect* singleton = NULL;
130     if (singleton == NULL) {
131         singleton = SkNEW(SkFontConfigInterfaceDirect);
132     }
133     return singleton;
134 }
135
136 ///////////////////////////////////////////////////////////////////////////////
137
138 // Returns the string from the pattern, or NULL
139 static const char* get_name(FcPattern* pattern, const char field[],
140                             int index = 0) {
141     const char* name;
142     if (FcPatternGetString(pattern, field, index,
143                            (FcChar8**)&name) != FcResultMatch) {
144         name = NULL;
145     }
146     return name;
147 }
148
149 ///////////////////////////////////////////////////////////////////////////////
150
151 namespace {
152
153 // Equivalence classes, used to match the Liberation and other fonts
154 // with their metric-compatible replacements.  See the discussion in
155 // GetFontEquivClass().
156 enum FontEquivClass
157 {
158     OTHER,
159     SANS,
160     SERIF,
161     MONO,
162     SYMBOL,
163     PGOTHIC,
164     GOTHIC,
165     PMINCHO,
166     MINCHO,
167     SIMSUN,
168     NSIMSUN,
169     SIMHEI,
170     PMINGLIU,
171     MINGLIU,
172     PMINGLIUHK,
173     MINGLIUHK,
174     CAMBRIA,
175     CALIBRI,
176 };
177
178 // Match the font name against a whilelist of fonts, returning the equivalence
179 // class.
180 FontEquivClass GetFontEquivClass(const char* fontname)
181 {
182     // It would be nice for fontconfig to tell us whether a given suggested
183     // replacement is a "strong" match (that is, an equivalent font) or
184     // a "weak" match (that is, fontconfig's next-best attempt at finding a
185     // substitute).  However, I played around with the fontconfig API for
186     // a good few hours and could not make it reveal this information.
187     //
188     // So instead, we hardcode.  Initially this function emulated
189     //   /etc/fonts/conf.d/30-metric-aliases.conf
190     // from my Ubuntu system, but we're better off being very conservative.
191
192     // Arimo, Tinos and Cousine are a set of fonts metric-compatible with
193     // Arial, Times New Roman and Courier New  with a character repertoire
194     // much larger than Liberation. Note that Cousine is metrically
195     // compatible with Courier New, but the former is sans-serif while
196     // the latter is serif.
197
198
199     struct FontEquivMap {
200         FontEquivClass clazz;
201         const char name[40];
202     };
203
204     static const FontEquivMap kFontEquivMap[] = {
205         { SANS, "Arial" },
206         { SANS, "Arimo" },
207         { SANS, "Liberation Sans" },
208
209         { SERIF, "Times New Roman" },
210         { SERIF, "Tinos" },
211         { SERIF, "Liberation Serif" },
212
213         { MONO, "Courier New" },
214         { MONO, "Cousine" },
215         { MONO, "Liberation Mono" },
216
217         { SYMBOL, "Symbol" },
218         { SYMBOL, "Symbol Neu" },
219
220         // MS Pゴシック
221         { PGOTHIC, "MS PGothic" },
222         { PGOTHIC, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0"
223                    "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" },
224         { PGOTHIC, "Noto Sans CJK JP" },
225         { PGOTHIC, "IPAPGothic" },
226         { PGOTHIC, "MotoyaG04Gothic" },
227
228         // MS ゴシック
229         { GOTHIC, "MS Gothic" },
230         { GOTHIC, "\xef\xbc\xad\xef\xbc\xb3 "
231                   "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" },
232         { GOTHIC, "IPAGothic" },
233         { GOTHIC, "MotoyaG04GothicMono" },
234
235         // MS P明朝
236         { PMINCHO, "MS PMincho" },
237         { PMINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0"
238                    "\xe6\x98\x8e\xe6\x9c\x9d"},
239         { PMINCHO, "IPAPMincho" },
240         { PMINCHO, "MotoyaG04Mincho" },
241
242         // MS 明朝
243         { MINCHO, "MS Mincho" },
244         { MINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xe6\x98\x8e\xe6\x9c\x9d" },
245         { MINCHO, "IPAMincho" },
246         { MINCHO, "MotoyaG04MinchoMono" },
247
248         // 宋体
249         { SIMSUN, "Simsun" },
250         { SIMSUN, "\xe5\xae\x8b\xe4\xbd\x93" },
251         { SIMSUN, "MSung GB18030" },
252         { SIMSUN, "Song ASC" },
253
254         // 新宋体
255         { NSIMSUN, "NSimsun" },
256         { NSIMSUN, "\xe6\x96\xb0\xe5\xae\x8b\xe4\xbd\x93" },
257         { NSIMSUN, "MSung GB18030" },
258         { NSIMSUN, "N Song ASC" },
259
260         // 黑体
261         { SIMHEI, "Simhei" },
262         { SIMHEI, "\xe9\xbb\x91\xe4\xbd\x93" },
263         { SIMHEI, "Noto Sans CJK SC" },
264         { SIMHEI, "MYingHeiGB18030" },
265         { SIMHEI, "MYingHeiB5HK" },
266
267         // 新細明體
268         { PMINGLIU, "PMingLiU"},
269         { PMINGLIU, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" },
270         { PMINGLIU, "MSung B5HK"},
271
272         // 細明體
273         { MINGLIU, "MingLiU"},
274         { MINGLIU, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" },
275         { MINGLIU, "MSung B5HK"},
276
277         // 新細明體
278         { PMINGLIUHK, "PMingLiU_HKSCS"},
279         { PMINGLIUHK, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" },
280         { PMINGLIUHK, "MSung B5HK"},
281
282         // 細明體
283         { MINGLIUHK, "MingLiU_HKSCS"},
284         { MINGLIUHK, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" },
285         { MINGLIUHK, "MSung B5HK"},
286
287         // Cambria
288         { CAMBRIA, "Cambria" },
289         { CAMBRIA, "Caladea" },
290
291         // Calibri
292         { CALIBRI, "Calibri" },
293         { CALIBRI, "Carlito" },
294     };
295
296     static const size_t kFontCount =
297         sizeof(kFontEquivMap)/sizeof(kFontEquivMap[0]);
298
299     // TODO(jungshik): If this loop turns out to be hot, turn
300     // the array to a static (hash)map to speed it up.
301     for (size_t i = 0; i < kFontCount; ++i) {
302         if (strcasecmp(kFontEquivMap[i].name, fontname) == 0)
303             return kFontEquivMap[i].clazz;
304     }
305     return OTHER;
306 }
307
308
309 // Return true if |font_a| and |font_b| are visually and at the metrics
310 // level interchangeable.
311 bool IsMetricCompatibleReplacement(const char* font_a, const char* font_b)
312 {
313     FontEquivClass class_a = GetFontEquivClass(font_a);
314     FontEquivClass class_b = GetFontEquivClass(font_b);
315
316     return class_a != OTHER && class_a == class_b;
317 }
318
319 // Normally we only return exactly the font asked for. In last-resort
320 // cases, the request either doesn't specify a font or is one of the
321 // basic font names like "Sans", "Serif" or "Monospace". This function
322 // tells you whether a given request is for such a fallback.
323 bool IsFallbackFontAllowed(const SkString& family) {
324   const char* family_cstr = family.c_str();
325   return family.isEmpty() ||
326          strcasecmp(family_cstr, "sans") == 0 ||
327          strcasecmp(family_cstr, "serif") == 0 ||
328          strcasecmp(family_cstr, "monospace") == 0;
329 }
330
331 static bool valid_pattern(FcPattern* pattern) {
332 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS
333     FcBool is_scalable;
334     if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch
335         || !is_scalable) {
336         return false;
337     }
338 #endif
339
340     // fontconfig can also return fonts which are unreadable
341     const char* c_filename = get_name(pattern, FC_FILE);
342     if (!c_filename) {
343         return false;
344     }
345     if (access(c_filename, R_OK) != 0) {
346         return false;
347     }
348     return true;
349 }
350
351 // Find matching font from |font_set| for the given font family.
352 FcPattern* MatchFont(FcFontSet* font_set,
353                      const char* post_config_family,
354                      const SkString& family) {
355   // Older versions of fontconfig have a bug where they cannot select
356   // only scalable fonts so we have to manually filter the results.
357   FcPattern* match = NULL;
358   for (int i = 0; i < font_set->nfont; ++i) {
359     FcPattern* current = font_set->fonts[i];
360     if (valid_pattern(current)) {
361       match = current;
362       break;
363     }
364   }
365
366   if (match && !IsFallbackFontAllowed(family)) {
367     bool acceptable_substitute = false;
368     for (int id = 0; id < 255; ++id) {
369       const char* post_match_family = get_name(match, FC_FAMILY, id);
370       if (!post_match_family)
371         break;
372       acceptable_substitute =
373           (strcasecmp(post_config_family, post_match_family) == 0 ||
374            // Workaround for Issue 12530:
375            //   requested family: "Bitstream Vera Sans"
376            //   post_config_family: "Arial"
377            //   post_match_family: "Bitstream Vera Sans"
378            // -> We should treat this case as a good match.
379            strcasecmp(family.c_str(), post_match_family) == 0) ||
380            IsMetricCompatibleReplacement(family.c_str(), post_match_family);
381       if (acceptable_substitute)
382         break;
383     }
384     if (!acceptable_substitute)
385       return NULL;
386   }
387
388   return match;
389 }
390
391 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|.
392 SkTypeface::Style GetFontStyle(FcPattern* font) {
393     int resulting_bold;
394     if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold))
395         resulting_bold = FC_WEIGHT_NORMAL;
396
397     int resulting_italic;
398     if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic))
399         resulting_italic = FC_SLANT_ROMAN;
400
401     // If we ask for an italic font, fontconfig might take a roman font and set
402     // the undocumented property FC_MATRIX to a skew matrix. It'll then say
403     // that the font is italic or oblique. So, if we see a matrix, we don't
404     // believe that it's italic.
405     FcValue matrix;
406     const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0;
407
408     // If we ask for an italic font, fontconfig might take a roman font and set
409     // FC_EMBOLDEN.
410     FcValue embolden;
411     const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) == 0;
412
413     int styleBits = 0;
414     if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) {
415         styleBits |= SkTypeface::kBold;
416     }
417     if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) {
418         styleBits |= SkTypeface::kItalic;
419     }
420
421     return (SkTypeface::Style)styleBits;
422 }
423
424 }  // anonymous namespace
425
426 ///////////////////////////////////////////////////////////////////////////////
427
428 #define kMaxFontFamilyLength    2048
429
430 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() {
431     SkAutoMutexAcquire ac(mutex_);
432
433     FcInit();
434
435     SkDEBUGCODE(fontconfiginterface_unittest();)
436 }
437
438 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
439 }
440
441 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[],
442                                                   SkTypeface::Style style,
443                                                   FontIdentity* outIdentity,
444                                                   SkString* outFamilyName,
445                                                   SkTypeface::Style* outStyle) {
446     SkString familyStr(familyName ? familyName : "");
447     if (familyStr.size() > kMaxFontFamilyLength) {
448         return false;
449     }
450
451     SkAutoMutexAcquire ac(mutex_);
452
453     FcPattern* pattern = FcPatternCreate();
454
455     if (familyName) {
456         FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
457     }
458     FcPatternAddInteger(pattern, FC_WEIGHT,
459                         (style & SkTypeface::kBold) ? FC_WEIGHT_BOLD
460                                                     : FC_WEIGHT_NORMAL);
461     FcPatternAddInteger(pattern, FC_SLANT,
462                         (style & SkTypeface::kItalic) ? FC_SLANT_ITALIC
463                                                       : FC_SLANT_ROMAN);
464     FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
465
466     FcConfigSubstitute(NULL, pattern, FcMatchPattern);
467     FcDefaultSubstitute(pattern);
468
469     // Font matching:
470     // CSS often specifies a fallback list of families:
471     //    font-family: a, b, c, serif;
472     // However, fontconfig will always do its best to find *a* font when asked
473     // for something so we need a way to tell if the match which it has found is
474     // "good enough" for us. Otherwise, we can return NULL which gets piped up
475     // and lets WebKit know to try the next CSS family name. However, fontconfig
476     // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
477     // wish to support that.
478     //
479     // Thus, if a specific family is requested we set @family_requested. Then we
480     // record two strings: the family name after config processing and the
481     // family name after resolving. If the two are equal, it's a good match.
482     //
483     // So consider the case where a user has mapped Arial to Helvetica in their
484     // config.
485     //    requested family: "Arial"
486     //    post_config_family: "Helvetica"
487     //    post_match_family: "Helvetica"
488     //      -> good match
489     //
490     // and for a missing font:
491     //    requested family: "Monaco"
492     //    post_config_family: "Monaco"
493     //    post_match_family: "Times New Roman"
494     //      -> BAD match
495     //
496     // However, we special-case fallback fonts; see IsFallbackFontAllowed().
497
498     const char* post_config_family = get_name(pattern, FC_FAMILY);
499     if (!post_config_family) {
500         // we can just continue with an empty name, e.g. default font
501         post_config_family = "";
502     }
503
504     FcResult result;
505     FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
506     if (!font_set) {
507         FcPatternDestroy(pattern);
508         return false;
509     }
510
511     FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
512     if (!match) {
513         FcPatternDestroy(pattern);
514         FcFontSetDestroy(font_set);
515         return false;
516     }
517
518     FcPatternDestroy(pattern);
519
520     // From here out we just extract our results from 'match'
521
522     post_config_family = get_name(match, FC_FAMILY);
523     if (!post_config_family) {
524         FcFontSetDestroy(font_set);
525         return false;
526     }
527
528     const char* c_filename = get_name(match, FC_FILE);
529     if (!c_filename) {
530         FcFontSetDestroy(font_set);
531         return false;
532     }
533
534     int face_index;
535     if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
536         FcFontSetDestroy(font_set);
537         return false;
538     }
539
540     FcFontSetDestroy(font_set);
541
542     if (outIdentity) {
543         outIdentity->fTTCIndex = face_index;
544         outIdentity->fString.set(c_filename);
545     }
546     if (outFamilyName) {
547         outFamilyName->set(post_config_family);
548     }
549     if (outStyle) {
550         *outStyle = GetFontStyle(match);
551     }
552     return true;
553 }
554
555 SkStreamAsset* SkFontConfigInterfaceDirect::openStream(const FontIdentity& identity) {
556     return SkStream::NewFromFile(identity.fString.c_str());
557 }
558
559 ///////////////////////////////////////////////////////////////////////////////
560
561 static bool find_name(const SkTDArray<const char*>& list, const char* str) {
562     int count = list.count();
563     for (int i = 0; i < count; ++i) {
564         if (!strcmp(list[i], str)) {
565             return true;
566         }
567     }
568     return false;
569 }
570
571 SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() {
572     SkAutoMutexAcquire ac(mutex_);
573
574     FcPattern* pat = FcPatternCreate();
575     SkAutoTCallVProc<FcPattern, FcPatternDestroy> autoDestroyPat(pat);
576     if (NULL == pat) {
577         return NULL;
578     }
579
580     FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, (char *)0);
581     SkAutoTCallVProc<FcObjectSet, FcObjectSetDestroy> autoDestroyOs(os);
582     if (NULL == os) {
583         return NULL;
584     }
585
586     FcFontSet* fs = FcFontList(NULL, pat, os);
587     SkAutoTCallVProc<FcFontSet, FcFontSetDestroy> autoDestroyFs(fs);
588     if (NULL == fs) {
589         return NULL;
590     }
591
592     SkTDArray<const char*> names;
593     SkTDArray<size_t> sizes;
594     for (int i = 0; i < fs->nfont; ++i) {
595         FcPattern* match = fs->fonts[i];
596         const char* famName = get_name(match, FC_FAMILY);
597         if (famName && !find_name(names, famName)) {
598             *names.append() = famName;
599             *sizes.append() = strlen(famName) + 1;
600         }
601     }
602
603     return SkDataTable::NewCopyArrays((const void*const*)names.begin(),
604                                       sizes.begin(), names.count());
605 }
606
607 bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[],
608                                                  SkString* outFamilyName,
609                                                  SkTArray<FontIdentity>* ids) {
610     SkAutoMutexAcquire ac(mutex_);
611
612 #if 0
613     SkString familyStr(familyName ? familyName : "");
614     if (familyStr.size() > kMaxFontFamilyLength) {
615         return false;
616     }
617
618     SkAutoMutexAcquire ac(mutex_);
619
620     FcPattern* pattern = FcPatternCreate();
621
622     if (familyName) {
623         FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
624     }
625     FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
626
627     FcConfigSubstitute(NULL, pattern, FcMatchPattern);
628     FcDefaultSubstitute(pattern);
629
630     // Font matching:
631     // CSS often specifies a fallback list of families:
632     //    font-family: a, b, c, serif;
633     // However, fontconfig will always do its best to find *a* font when asked
634     // for something so we need a way to tell if the match which it has found is
635     // "good enough" for us. Otherwise, we can return NULL which gets piped up
636     // and lets WebKit know to try the next CSS family name. However, fontconfig
637     // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
638     // wish to support that.
639     //
640     // Thus, if a specific family is requested we set @family_requested. Then we
641     // record two strings: the family name after config processing and the
642     // family name after resolving. If the two are equal, it's a good match.
643     //
644     // So consider the case where a user has mapped Arial to Helvetica in their
645     // config.
646     //    requested family: "Arial"
647     //    post_config_family: "Helvetica"
648     //    post_match_family: "Helvetica"
649     //      -> good match
650     //
651     // and for a missing font:
652     //    requested family: "Monaco"
653     //    post_config_family: "Monaco"
654     //    post_match_family: "Times New Roman"
655     //      -> BAD match
656     //
657     // However, we special-case fallback fonts; see IsFallbackFontAllowed().
658
659     const char* post_config_family = get_name(pattern, FC_FAMILY);
660
661     FcResult result;
662     FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
663     if (!font_set) {
664         FcPatternDestroy(pattern);
665         return false;
666     }
667
668     FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
669     if (!match) {
670         FcPatternDestroy(pattern);
671         FcFontSetDestroy(font_set);
672         return false;
673     }
674
675     FcPatternDestroy(pattern);
676
677     // From here out we just extract our results from 'match'
678
679     if (FcPatternGetString(match, FC_FAMILY, 0, &post_config_family) != FcResultMatch) {
680         FcFontSetDestroy(font_set);
681         return false;
682     }
683
684     FcChar8* c_filename;
685     if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) {
686         FcFontSetDestroy(font_set);
687         return false;
688     }
689
690     int face_index;
691     if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
692         FcFontSetDestroy(font_set);
693         return false;
694     }
695
696     FcFontSetDestroy(font_set);
697
698     if (outIdentity) {
699         outIdentity->fTTCIndex = face_index;
700         outIdentity->fString.set((const char*)c_filename);
701     }
702     if (outFamilyName) {
703         outFamilyName->set((const char*)post_config_family);
704     }
705     if (outStyle) {
706         *outStyle = GetFontStyle(match);
707     }
708     return true;
709
710 ////////////////////
711
712         int count;
713         FcPattern** match = MatchFont(font_set, post_config_family, &count);
714         if (!match) {
715             FcPatternDestroy(pattern);
716             FcFontSetDestroy(font_set);
717             return NULL;
718         }
719
720         FcPatternDestroy(pattern);
721
722         SkTDArray<FcPattern*> trimmedMatches;
723         for (int i = 0; i < count; ++i) {
724             const char* justName = find_just_name(get_name(match[i], FC_FILE));
725             if (!is_lower(*justName)) {
726                 *trimmedMatches.append() = match[i];
727             }
728         }
729
730         SkFontStyleSet_FC* sset = SkNEW_ARGS(SkFontStyleSet_FC,
731                                              (trimmedMatches.begin(),
732                                               trimmedMatches.count()));
733 #endif
734     return false;
735 }