SkFontMgr_fontconfig.cpp revision 0b1de2626a289ab21bd3b93277ed34d022824b3d
1/*
2 * Copyright 2014 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#include "SkDataTable.h"
9#include "SkFontDescriptor.h"
10#include "SkFontHost_FreeType_common.h"
11#include "SkFontMgr.h"
12#include "SkFontStyle.h"
13#include "SkMath.h"
14#include "SkString.h"
15#include "SkStream.h"
16#include "SkTDArray.h"
17#include "SkThread.h"
18#include "SkTypefaceCache.h"
19#include "SkOSFile.h"
20
21#include <fontconfig/fontconfig.h>
22
23// FC_POSTSCRIPT_NAME was added with b561ff20 which ended up in 2.10.92
24// Ubuntu 12.04 is on 2.8.0, 13.10 is on 2.10.93
25// Debian 7 is on 2.9.0, 8 is on 2.11
26// OpenSUSE 12.2 is on 2.9.0, 12.3 is on 2.10.2, 13.1 2.11.0
27// Fedora 19 is on 2.10.93
28#ifndef FC_POSTSCRIPT_NAME
29#    define FC_POSTSCRIPT_NAME  "postscriptname"
30#endif
31
32#ifdef SK_DEBUG
33#    include "SkTLS.h"
34#endif
35
36/** Since FontConfig is poorly documented, this gives a high level overview:
37 *
38 *  FcConfig is a handle to a FontConfig configuration instance. Each 'configuration' is independent
39 *  from any others which may exist. There exists a default global configuration which is created
40 *  and destroyed by FcInit and FcFini, but this default should not normally be used.
41 *  Instead, one should use FcConfigCreate and FcInit* to have a named local state.
42 *
43 *  FcPatterns are {objectName -> [element]} (maps from object names to a list of elements).
44 *  Each element is some internal data plus an FcValue which is a variant (a union with a type tag).
45 *  Lists of elements are not typed, except by convention. Any collection of FcValues must be
46 *  assumed to be heterogeneous by the code, but the code need not do anything particularly
47 *  interesting if the values go against convention.
48 *
49 *  Somewhat like DirectWrite, FontConfig supports synthetics through FC_EMBOLDEN and FC_MATRIX.
50 *  Like all synthetic information, such information must be passed with the font data.
51 */
52
53namespace {
54
55// Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a global mutex.
56// See http://skbug.com/1497 for background.
57SK_DECLARE_STATIC_MUTEX(gFCMutex);
58
59#ifdef SK_DEBUG
60    void *CreateThreadFcLocked() { return SkNEW_ARGS(bool, (false)); }
61    void DeleteThreadFcLocked(void* v) { SkDELETE(static_cast<bool*>(v)); }
62#   define THREAD_FC_LOCKED \
63        static_cast<bool*>(SkTLS::Get(CreateThreadFcLocked, DeleteThreadFcLocked))
64#endif
65
66struct FCLocker {
67    // Assume FcGetVersion() has always been thread safe.
68
69    FCLocker() {
70        if (FcGetVersion() < 21091) {
71            gFCMutex.acquire();
72        } else {
73            SkDEBUGCODE(bool* threadLocked = THREAD_FC_LOCKED);
74            SkASSERT(false == *threadLocked);
75            SkDEBUGCODE(*threadLocked = true);
76        }
77    }
78
79    ~FCLocker() {
80        AssertHeld();
81        if (FcGetVersion() < 21091) {
82            gFCMutex.release();
83        } else {
84            SkDEBUGCODE(*THREAD_FC_LOCKED = false);
85        }
86    }
87
88    static void AssertHeld() { SkDEBUGCODE(
89        if (FcGetVersion() < 21091) {
90            gFCMutex.assertHeld();
91        } else {
92            SkASSERT(true == *THREAD_FC_LOCKED);
93        }
94    ) }
95};
96
97} // namespace
98
99template<typename T, void (*D)(T*)> void FcTDestroy(T* t) {
100    FCLocker::AssertHeld();
101    D(t);
102}
103template <typename T, T* (*C)(), void (*D)(T*)> class SkAutoFc
104    : public SkAutoTCallVProc<T, FcTDestroy<T, D> > {
105public:
106    SkAutoFc() : SkAutoTCallVProc<T, FcTDestroy<T, D> >(C()) {
107        T* obj = this->operator T*();
108        SK_ALWAYSBREAK(NULL != obj);
109    }
110    explicit SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, D> >(obj) {}
111};
112
113typedef SkAutoFc<FcCharSet, FcCharSetCreate, FcCharSetDestroy> SkAutoFcCharSet;
114typedef SkAutoFc<FcConfig, FcConfigCreate, FcConfigDestroy> SkAutoFcConfig;
115typedef SkAutoFc<FcFontSet, FcFontSetCreate, FcFontSetDestroy> SkAutoFcFontSet;
116typedef SkAutoFc<FcLangSet, FcLangSetCreate, FcLangSetDestroy> SkAutoFcLangSet;
117typedef SkAutoFc<FcObjectSet, FcObjectSetCreate, FcObjectSetDestroy> SkAutoFcObjectSet;
118typedef SkAutoFc<FcPattern, FcPatternCreate, FcPatternDestroy> SkAutoFcPattern;
119
120static int get_int(FcPattern* pattern, const char object[], int missing) {
121    int value;
122    if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) {
123        return missing;
124    }
125    return value;
126}
127
128static const char* get_string(FcPattern* pattern, const char object[], const char* missing = "") {
129    FcChar8* value;
130    if (FcPatternGetString(pattern, object, 0, &value) != FcResultMatch) {
131        return missing;
132    }
133    return (const char*)value;
134}
135
136enum SkWeakReturn {
137    kIsWeak_WeakReturn,
138    kIsStrong_WeakReturn,
139    kNoId_WeakReturn
140};
141/** Ideally there  would exist a call like
142 *  FcResult FcPatternIsWeak(pattern, object, id, FcBool* isWeak);
143 *
144 *  However, there is no such call and as of Fc 2.11.0 even FcPatternEquals ignores the weak bit.
145 *  Currently, the only reliable way of finding the weak bit is by its effect on matching.
146 *  The weak bit only affects the matching of FC_FAMILY and FC_POSTSCRIPT_NAME object values.
147 *  A element with the weak bit is scored after FC_LANG, without the weak bit is scored before.
148 *  Note that the weak bit is stored on the element, not on the value it holds.
149 */
150static SkWeakReturn is_weak(FcPattern* pattern, const char object[], int id) {
151    FCLocker::AssertHeld();
152
153    FcResult result;
154
155    // Create a copy of the pattern with only the value 'pattern'['object'['id']] in it.
156    // Internally, FontConfig pattern objects are linked lists, so faster to remove from head.
157    SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, NULL));
158    SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
159    FcBool hasId = true;
160    for (int i = 0; hasId && i < id; ++i) {
161        hasId = FcPatternRemove(minimal, object, 0);
162    }
163    if (!hasId) {
164        return kNoId_WeakReturn;
165    }
166    FcValue value;
167    result = FcPatternGet(minimal, object, 0, &value);
168    if (result != FcResultMatch) {
169        return kNoId_WeakReturn;
170    }
171    while (hasId) {
172        hasId = FcPatternRemove(minimal, object, 1);
173    }
174
175    // Create a font set with two patterns.
176    // 1. the same 'object' as minimal and a lang object with only 'nomatchlang'.
177    // 2. a different 'object' from minimal and a lang object with only 'matchlang'.
178    SkAutoFcFontSet fontSet;
179
180    SkAutoFcLangSet strongLangSet;
181    FcLangSetAdd(strongLangSet, (const FcChar8*)"nomatchlang");
182    SkAutoFcPattern strong(FcPatternDuplicate(minimal));
183    FcPatternAddLangSet(strong, FC_LANG, strongLangSet);
184
185    SkAutoFcLangSet weakLangSet;
186    FcLangSetAdd(weakLangSet, (const FcChar8*)"matchlang");
187    SkAutoFcPattern weak;
188    FcPatternAddString(weak, object, (const FcChar8*)"nomatchstring");
189    FcPatternAddLangSet(weak, FC_LANG, weakLangSet);
190
191    FcFontSetAdd(fontSet, strong.detach());
192    FcFontSetAdd(fontSet, weak.detach());
193
194    // Add 'matchlang' to the copy of the pattern.
195    FcPatternAddLangSet(minimal, FC_LANG, weakLangSet);
196
197    // Run a match against the copy of the pattern.
198    // If the 'id' was weak, then we should match the pattern with 'matchlang'.
199    // If the 'id' was strong, then we should match the pattern with 'nomatchlang'.
200
201    // Note that this config is only used for FcFontRenderPrepare, which we don't even want.
202    // However, there appears to be no way to match/sort without it.
203    SkAutoFcConfig config;
204    FcFontSet* fontSets[1] = { fontSet };
205    SkAutoFcPattern match(FcFontSetMatch(config, fontSets, SK_ARRAY_COUNT(fontSets),
206                                         minimal, &result));
207
208    FcLangSet* matchLangSet;
209    FcPatternGetLangSet(match, FC_LANG, 0, &matchLangSet);
210    return FcLangEqual == FcLangSetHasLang(matchLangSet, (const FcChar8*)"matchlang")
211                        ? kIsWeak_WeakReturn : kIsStrong_WeakReturn;
212}
213
214/** Removes weak elements from either FC_FAMILY or FC_POSTSCRIPT_NAME objects in the property.
215 *  This can be quite expensive, and should not be used more than once per font lookup.
216 *  This removes all of the weak elements after the last strong element.
217 */
218static void remove_weak(FcPattern* pattern, const char object[]) {
219    FCLocker::AssertHeld();
220
221    SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, NULL));
222    SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
223
224    int lastStrongId = -1;
225    int numIds;
226    SkWeakReturn result;
227    for (int id = 0; ; ++id) {
228        result = is_weak(minimal, object, 0);
229        if (kNoId_WeakReturn == result) {
230            numIds = id;
231            break;
232        }
233        if (kIsStrong_WeakReturn == result) {
234            lastStrongId = id;
235        }
236        SkAssertResult(FcPatternRemove(minimal, object, 0));
237    }
238
239    // If they were all weak, then leave the pattern alone.
240    if (lastStrongId < 0) {
241        return;
242    }
243
244    // Remove everything after the last strong.
245    for (int id = lastStrongId + 1; id < numIds; ++id) {
246        SkAssertResult(FcPatternRemove(pattern, object, lastStrongId + 1));
247    }
248}
249
250static int map_range(SkFixed value,
251                     SkFixed old_min, SkFixed old_max,
252                     SkFixed new_min, SkFixed new_max)
253{
254    SkASSERT(old_min < old_max);
255    SkASSERT(new_min <= new_max);
256    return new_min + SkMulDiv(value - old_min, new_max - new_min, old_max - old_min);
257}
258
259static int ave(SkFixed a, SkFixed b) {
260    return SkFixedAve(a, b);
261}
262
263struct MapRanges {
264    SkFixed old_val;
265    SkFixed new_val;
266};
267
268static SkFixed map_ranges_fixed(SkFixed val, MapRanges const ranges[], int rangesCount) {
269    // -Inf to [0]
270    if (val < ranges[0].old_val) {
271        return ranges[0].new_val;
272    }
273
274    // Linear from [i] to ave([i], [i+1]), then from ave([i], [i+1]) to [i+1]
275    for (int i = 0; i < rangesCount - 1; ++i) {
276        if (val < ave(ranges[i].old_val, ranges[i+1].old_val)) {
277            return map_range(val, ranges[i].old_val, ave(ranges[i].old_val, ranges[i+1].old_val),
278                                  ranges[i].new_val, ave(ranges[i].new_val, ranges[i+1].new_val));
279        }
280        if (val < ranges[i+1].old_val) {
281            return map_range(val, ave(ranges[i].old_val, ranges[i+1].old_val), ranges[i+1].old_val,
282                                  ave(ranges[i].new_val, ranges[i+1].new_val), ranges[i+1].new_val);
283        }
284    }
285
286    // From [n] to +Inf
287    // if (fcweight < Inf)
288    return ranges[rangesCount-1].new_val;
289}
290
291static int map_ranges(int val, MapRanges const ranges[], int rangesCount) {
292    return SkFixedRoundToInt(map_ranges_fixed(SkIntToFixed(val), ranges, rangesCount));
293}
294
295template<int n> struct SkTFixed {
296    SK_COMPILE_ASSERT(-32768 <= n && n <= 32767, SkTFixed_n_not_in_range);
297    static const SkFixed value = static_cast<SkFixed>(n << 16);
298};
299
300static SkFontStyle skfontstyle_from_fcpattern(FcPattern* pattern) {
301    typedef SkFontStyle SkFS;
302
303    static const MapRanges weightRanges[] = {
304        { SkTFixed<FC_WEIGHT_THIN>::value,       SkTFixed<SkFS::kThin_Weight>::value },
305        { SkTFixed<FC_WEIGHT_EXTRALIGHT>::value, SkTFixed<SkFS::kExtraLight_Weight>::value },
306        { SkTFixed<FC_WEIGHT_LIGHT>::value,      SkTFixed<SkFS::kLight_Weight>::value },
307        { SkTFixed<FC_WEIGHT_REGULAR>::value,    SkTFixed<SkFS::kNormal_Weight>::value },
308        { SkTFixed<FC_WEIGHT_MEDIUM>::value,     SkTFixed<SkFS::kMedium_Weight>::value },
309        { SkTFixed<FC_WEIGHT_DEMIBOLD>::value,   SkTFixed<SkFS::kSemiBold_Weight>::value },
310        { SkTFixed<FC_WEIGHT_BOLD>::value,       SkTFixed<SkFS::kBold_Weight>::value },
311        { SkTFixed<FC_WEIGHT_EXTRABOLD>::value,  SkTFixed<SkFS::kExtraBold_Weight>::value },
312        { SkTFixed<FC_WEIGHT_BLACK>::value,      SkTFixed<SkFS::kBlack_Weight>::value },
313        { SkTFixed<FC_WEIGHT_EXTRABLACK>::value, SkTFixed<1000>::value },
314    };
315    int weight = map_ranges(get_int(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR),
316                            weightRanges, SK_ARRAY_COUNT(weightRanges));
317
318    static const MapRanges widthRanges[] = {
319        { SkTFixed<FC_WIDTH_ULTRACONDENSED>::value, SkTFixed<SkFS::kUltraCondensed_Width>::value },
320        { SkTFixed<FC_WIDTH_EXTRACONDENSED>::value, SkTFixed<SkFS::kExtraCondensed_Width>::value },
321        { SkTFixed<FC_WIDTH_CONDENSED>::value,      SkTFixed<SkFS::kCondensed_Width>::value },
322        { SkTFixed<FC_WIDTH_SEMICONDENSED>::value,  SkTFixed<SkFS::kSemiCondensed_Width>::value },
323        { SkTFixed<FC_WIDTH_NORMAL>::value,         SkTFixed<SkFS::kNormal_Width>::value },
324        { SkTFixed<FC_WIDTH_SEMIEXPANDED>::value,   SkTFixed<SkFS::kSemiExpanded_Width>::value },
325        { SkTFixed<FC_WIDTH_EXPANDED>::value,       SkTFixed<SkFS::kExpanded_Width>::value },
326        { SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value,  SkTFixed<SkFS::kExtraExpanded_Width>::value },
327        { SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value,  SkTFixed<SkFS::kUltaExpanded_Width>::value },
328    };
329    int width = map_ranges(get_int(pattern, FC_WIDTH, FC_WIDTH_NORMAL),
330                           widthRanges, SK_ARRAY_COUNT(widthRanges));
331
332    SkFS::Slant slant = get_int(pattern, FC_SLANT, FC_SLANT_ROMAN) > 0
333                             ? SkFS::kItalic_Slant
334                             : SkFS::kUpright_Slant;
335
336    return SkFontStyle(weight, width, slant);
337}
338
339static void fcpattern_from_skfontstyle(SkFontStyle style, FcPattern* pattern) {
340    FCLocker::AssertHeld();
341
342    typedef SkFontStyle SkFS;
343
344    static const MapRanges weightRanges[] = {
345        { SkTFixed<SkFS::kThin_Weight>::value,       SkTFixed<FC_WEIGHT_THIN>::value },
346        { SkTFixed<SkFS::kExtraLight_Weight>::value, SkTFixed<FC_WEIGHT_EXTRALIGHT>::value },
347        { SkTFixed<SkFS::kLight_Weight>::value,      SkTFixed<FC_WEIGHT_LIGHT>::value },
348        { SkTFixed<SkFS::kNormal_Weight>::value,     SkTFixed<FC_WEIGHT_REGULAR>::value },
349        { SkTFixed<SkFS::kMedium_Weight>::value,     SkTFixed<FC_WEIGHT_MEDIUM>::value },
350        { SkTFixed<SkFS::kSemiBold_Weight>::value,   SkTFixed<FC_WEIGHT_DEMIBOLD>::value },
351        { SkTFixed<SkFS::kBold_Weight>::value,       SkTFixed<FC_WEIGHT_BOLD>::value },
352        { SkTFixed<SkFS::kExtraBold_Weight>::value,  SkTFixed<FC_WEIGHT_EXTRABOLD>::value },
353        { SkTFixed<SkFS::kBlack_Weight>::value,      SkTFixed<FC_WEIGHT_BLACK>::value },
354        { SkTFixed<1000>::value,                     SkTFixed<FC_WEIGHT_EXTRABLACK>::value },
355    };
356    int weight = map_ranges(style.weight(), weightRanges, SK_ARRAY_COUNT(weightRanges));
357
358    static const MapRanges widthRanges[] = {
359        { SkTFixed<SkFS::kUltraCondensed_Width>::value, SkTFixed<FC_WIDTH_ULTRACONDENSED>::value },
360        { SkTFixed<SkFS::kExtraCondensed_Width>::value, SkTFixed<FC_WIDTH_EXTRACONDENSED>::value },
361        { SkTFixed<SkFS::kCondensed_Width>::value,      SkTFixed<FC_WIDTH_CONDENSED>::value },
362        { SkTFixed<SkFS::kSemiCondensed_Width>::value,  SkTFixed<FC_WIDTH_SEMICONDENSED>::value },
363        { SkTFixed<SkFS::kNormal_Width>::value,         SkTFixed<FC_WIDTH_NORMAL>::value },
364        { SkTFixed<SkFS::kSemiExpanded_Width>::value,   SkTFixed<FC_WIDTH_SEMIEXPANDED>::value },
365        { SkTFixed<SkFS::kExpanded_Width>::value,       SkTFixed<FC_WIDTH_EXPANDED>::value },
366        { SkTFixed<SkFS::kExtraExpanded_Width>::value,  SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value },
367        { SkTFixed<SkFS::kUltaExpanded_Width>::value,   SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value },
368    };
369    int width = map_ranges(style.width(), widthRanges, SK_ARRAY_COUNT(widthRanges));
370
371    FcPatternAddInteger(pattern, FC_WEIGHT, weight);
372    FcPatternAddInteger(pattern, FC_WIDTH, width);
373    FcPatternAddInteger(pattern, FC_SLANT, style.isItalic() ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
374}
375
376class SkTypeface_stream : public SkTypeface_FreeType {
377public:
378    /** @param data takes ownership of the font data.*/
379    SkTypeface_stream(SkFontData* data, const SkFontStyle& style, bool fixedWidth)
380        : INHERITED(style, SkTypefaceCache::NewFontID(), fixedWidth)
381        , fData(data)
382    { };
383
384    void onGetFamilyName(SkString* familyName) const override {
385        familyName->reset();
386    }
387
388    void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
389        *serialize = true;
390    }
391
392    SkStreamAsset* onOpenStream(int* ttcIndex) const override {
393        *ttcIndex = fData->getIndex();
394        return fData->duplicateStream();
395    }
396
397    SkFontData* onCreateFontData() const override {
398        return new SkFontData(*fData.get());
399    }
400
401private:
402    const SkAutoTDelete<const SkFontData> fData;
403
404    typedef SkTypeface_FreeType INHERITED;
405};
406
407class SkTypeface_fontconfig : public SkTypeface_FreeType {
408public:
409    /** @param pattern takes ownership of the reference. */
410    static SkTypeface_fontconfig* Create(FcPattern* pattern) {
411        return SkNEW_ARGS(SkTypeface_fontconfig, (pattern));
412    }
413    mutable SkAutoFcPattern fPattern;
414
415    void onGetFamilyName(SkString* familyName) const override {
416        *familyName = get_string(fPattern, FC_FAMILY);
417    }
418
419    void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
420        FCLocker lock;
421        desc->setFamilyName(get_string(fPattern, FC_FAMILY));
422        desc->setFullName(get_string(fPattern, FC_FULLNAME));
423        desc->setPostscriptName(get_string(fPattern, FC_POSTSCRIPT_NAME));
424        *serialize = false;
425    }
426
427    SkStreamAsset* onOpenStream(int* ttcIndex) const override {
428        FCLocker lock;
429        *ttcIndex = get_int(fPattern, FC_INDEX, 0);
430        return SkStream::NewFromFile(get_string(fPattern, FC_FILE));
431    }
432
433    virtual ~SkTypeface_fontconfig() {
434        // Hold the lock while unrefing the pattern.
435        FCLocker lock;
436        fPattern.reset();
437    }
438
439private:
440    /** @param pattern takes ownership of the reference. */
441    SkTypeface_fontconfig(FcPattern* pattern)
442        : INHERITED(skfontstyle_from_fcpattern(pattern),
443                    SkTypefaceCache::NewFontID(),
444                    FC_PROPORTIONAL != get_int(pattern, FC_SPACING, FC_PROPORTIONAL))
445        , fPattern(pattern)
446    { };
447
448    typedef SkTypeface_FreeType INHERITED;
449};
450
451class SkFontMgr_fontconfig : public SkFontMgr {
452    mutable SkAutoFcConfig fFC;
453    SkAutoTUnref<SkDataTable> fFamilyNames;
454    SkTypeface_FreeType::Scanner fScanner;
455
456    class StyleSet : public SkFontStyleSet {
457    public:
458        /** @param parent does not take ownership of the reference.
459         *  @param fontSet takes ownership of the reference.
460         */
461        StyleSet(const SkFontMgr_fontconfig* parent, FcFontSet* fontSet)
462            : fFontMgr(SkRef(parent)), fFontSet(fontSet)
463        { }
464
465        virtual ~StyleSet() {
466            // Hold the lock while unrefing the font set.
467            FCLocker lock;
468            fFontSet.reset();
469        }
470
471        int count() override { return fFontSet->nfont; }
472
473        void getStyle(int index, SkFontStyle* style, SkString* styleName) override {
474            if (index < 0 || fFontSet->nfont <= index) {
475                return;
476            }
477
478            FCLocker lock;
479            if (style) {
480                *style = skfontstyle_from_fcpattern(fFontSet->fonts[index]);
481            }
482            if (styleName) {
483                *styleName = get_string(fFontSet->fonts[index], FC_STYLE);
484            }
485        }
486
487        SkTypeface* createTypeface(int index) override {
488            FCLocker lock;
489
490            FcPattern* match = fFontSet->fonts[index];
491            return fFontMgr->createTypefaceFromFcPattern(match);
492        }
493
494        SkTypeface* matchStyle(const SkFontStyle& style) override {
495            FCLocker lock;
496
497            SkAutoFcPattern pattern;
498            fcpattern_from_skfontstyle(style, pattern);
499            FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern);
500            FcDefaultSubstitute(pattern);
501
502            FcResult result;
503            FcFontSet* fontSets[1] = { fFontSet };
504            SkAutoFcPattern match(FcFontSetMatch(fFontMgr->fFC,
505                                                 fontSets, SK_ARRAY_COUNT(fontSets),
506                                                 pattern, &result));
507            if (NULL == match) {
508                return NULL;
509            }
510
511            return fFontMgr->createTypefaceFromFcPattern(match);
512        }
513
514    private:
515        SkAutoTUnref<const SkFontMgr_fontconfig> fFontMgr;
516        SkAutoFcFontSet fFontSet;
517    };
518
519    static bool FindName(const SkTDArray<const char*>& list, const char* str) {
520        int count = list.count();
521        for (int i = 0; i < count; ++i) {
522            if (!strcmp(list[i], str)) {
523                return true;
524            }
525        }
526        return false;
527    }
528
529    static SkDataTable* GetFamilyNames(FcConfig* fcconfig) {
530        FCLocker lock;
531
532        SkTDArray<const char*> names;
533        SkTDArray<size_t> sizes;
534
535        static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
536        for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
537            // Return value of FcConfigGetFonts must not be destroyed.
538            FcFontSet* allFonts(FcConfigGetFonts(fcconfig, fcNameSet[setIndex]));
539            if (NULL == allFonts) {
540                continue;
541            }
542
543            for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
544                FcPattern* current = allFonts->fonts[fontIndex];
545                for (int id = 0; ; ++id) {
546                    FcChar8* fcFamilyName;
547                    FcResult result = FcPatternGetString(current, FC_FAMILY, id, &fcFamilyName);
548                    if (FcResultNoId == result) {
549                        break;
550                    }
551                    if (FcResultMatch != result) {
552                        continue;
553                    }
554                    const char* familyName = reinterpret_cast<const char*>(fcFamilyName);
555                    if (familyName && !FindName(names, familyName)) {
556                        *names.append() = familyName;
557                        *sizes.append() = strlen(familyName) + 1;
558                    }
559                }
560            }
561        }
562
563        return SkDataTable::NewCopyArrays((void const *const *)names.begin(),
564                                          sizes.begin(), names.count());
565    }
566
567    static bool FindByFcPattern(SkTypeface* cached, const SkFontStyle&, void* ctx) {
568        SkTypeface_fontconfig* cshFace = static_cast<SkTypeface_fontconfig*>(cached);
569        FcPattern* ctxPattern = static_cast<FcPattern*>(ctx);
570        return FcTrue == FcPatternEqual(cshFace->fPattern, ctxPattern);
571    }
572
573    mutable SkMutex fTFCacheMutex;
574    mutable SkTypefaceCache fTFCache;
575    /** Creates a typeface using a typeface cache.
576     *  @param pattern a complete pattern from FcFontRenderPrepare.
577     */
578    SkTypeface* createTypefaceFromFcPattern(FcPattern* pattern) const {
579        FCLocker::AssertHeld();
580        SkAutoMutexAcquire ama(fTFCacheMutex);
581        SkTypeface* face = fTFCache.findByProcAndRef(FindByFcPattern, pattern);
582        if (NULL == face) {
583            FcPatternReference(pattern);
584            face = SkTypeface_fontconfig::Create(pattern);
585            if (face) {
586                fTFCache.add(face, SkFontStyle());
587            }
588        }
589        return face;
590    }
591
592public:
593    /** Takes control of the reference to 'config'. */
594    explicit SkFontMgr_fontconfig(FcConfig* config)
595        : fFC(config ? config : FcInitLoadConfigAndFonts())
596        , fFamilyNames(GetFamilyNames(fFC)) { }
597
598    virtual ~SkFontMgr_fontconfig() {
599        // Hold the lock while unrefing the config.
600        FCLocker lock;
601        fFC.reset();
602    }
603
604protected:
605    int onCountFamilies() const override {
606        return fFamilyNames->count();
607    }
608
609    void onGetFamilyName(int index, SkString* familyName) const override {
610        familyName->set(fFamilyNames->atStr(index));
611    }
612
613    SkFontStyleSet* onCreateStyleSet(int index) const override {
614        return this->onMatchFamily(fFamilyNames->atStr(index));
615    }
616
617    /** True if any string object value in the font is the same
618     *         as a string object value in the pattern.
619     */
620    static bool AnyMatching(FcPattern* font, FcPattern* pattern, const char* object) {
621        FcChar8* fontString;
622        FcChar8* patternString;
623        FcResult result;
624        // Set an arbitrary limit on the number of pattern object values to consider.
625        // TODO: re-write this to avoid N*M
626        static const int maxId = 16;
627        for (int patternId = 0; patternId < maxId; ++patternId) {
628            result = FcPatternGetString(pattern, object, patternId, &patternString);
629            if (FcResultNoId == result) {
630                break;
631            }
632            if (FcResultMatch != result) {
633                continue;
634            }
635            for (int fontId = 0; fontId < maxId; ++fontId) {
636                result = FcPatternGetString(font, object, fontId, &fontString);
637                if (FcResultNoId == result) {
638                    break;
639                }
640                if (FcResultMatch != result) {
641                    continue;
642                }
643                if (0 == FcStrCmpIgnoreCase(patternString, fontString)) {
644                    return true;
645                }
646            }
647        }
648        return false;
649    }
650
651    static bool FontAccessible(FcPattern* font) {
652        // FontConfig can return fonts which are unreadable.
653        const char* filename = get_string(font, FC_FILE, NULL);
654        if (NULL == filename) {
655            return false;
656        }
657        return sk_exists(filename, kRead_SkFILE_Flag);
658    }
659
660    static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) {
661        return AnyMatching(font, pattern, FC_FAMILY);
662    }
663
664    static bool FontContainsCharacter(FcPattern* font, uint32_t character) {
665        FcResult result;
666        FcCharSet* matchCharSet;
667        for (int charSetId = 0; ; ++charSetId) {
668            result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchCharSet);
669            if (FcResultNoId == result) {
670                break;
671            }
672            if (FcResultMatch != result) {
673                continue;
674            }
675            if (FcCharSetHasChar(matchCharSet, character)) {
676                return true;
677            }
678        }
679        return false;
680    }
681
682    SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
683        FCLocker lock;
684
685        SkAutoFcPattern pattern;
686        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
687        FcConfigSubstitute(fFC, pattern, FcMatchPattern);
688        FcDefaultSubstitute(pattern);
689
690        FcPattern* matchPattern;
691        SkAutoFcPattern strongPattern(NULL);
692        if (familyName) {
693            strongPattern.reset(FcPatternDuplicate(pattern));
694            remove_weak(strongPattern, FC_FAMILY);
695            matchPattern = strongPattern;
696        } else {
697            matchPattern = pattern;
698        }
699
700        SkAutoFcFontSet matches;
701        // TODO: Some families have 'duplicates' due to symbolic links.
702        // The patterns are exactly the same except for the FC_FILE.
703        // It should be possible to collapse these patterns by normalizing.
704        static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
705        for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
706            // Return value of FcConfigGetFonts must not be destroyed.
707            FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex]));
708            if (NULL == allFonts) {
709                continue;
710            }
711
712            for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
713                FcPattern* font = allFonts->fonts[fontIndex];
714                if (FontAccessible(font) && FontFamilyNameMatches(font, matchPattern)) {
715                    FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font));
716                }
717            }
718        }
719
720        return SkNEW_ARGS(StyleSet, (this, matches.detach()));
721    }
722
723    virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
724                                           const SkFontStyle& style) const override
725    {
726        FCLocker lock;
727
728        SkAutoFcPattern pattern;
729        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
730        fcpattern_from_skfontstyle(style, pattern);
731        FcConfigSubstitute(fFC, pattern, FcMatchPattern);
732        FcDefaultSubstitute(pattern);
733
734        // We really want to match strong (prefered) and same (acceptable) only here.
735        // If a family name was specified, assume that any weak matches after the last strong match
736        // are weak (default) and ignore them.
737        // The reason for is that after substitution the pattern for 'sans-serif' looks like
738        // "wwwwwwwwwwwwwwswww" where there are many weak but preferred names, followed by defaults.
739        // So it is possible to have weakly matching but preferred names.
740        // In aliases, bindings are weak by default, so this is easy and common.
741        // If no family name was specified, we'll probably only get weak matches, but that's ok.
742        FcPattern* matchPattern;
743        SkAutoFcPattern strongPattern(NULL);
744        if (familyName) {
745            strongPattern.reset(FcPatternDuplicate(pattern));
746            remove_weak(strongPattern, FC_FAMILY);
747            matchPattern = strongPattern;
748        } else {
749            matchPattern = pattern;
750        }
751
752        FcResult result;
753        SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
754        if (NULL == font || !FontAccessible(font) || !FontFamilyNameMatches(font, matchPattern)) {
755            return NULL;
756        }
757
758        return createTypefaceFromFcPattern(font);
759    }
760
761    virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
762                                                    const SkFontStyle& style,
763                                                    const char* bcp47[],
764                                                    int bcp47Count,
765                                                    SkUnichar character) const override
766    {
767        FCLocker lock;
768
769        SkAutoFcPattern pattern;
770        if (familyName) {
771            FcValue familyNameValue;
772            familyNameValue.type = FcTypeString;
773            familyNameValue.u.s = reinterpret_cast<const FcChar8*>(familyName);
774            FcPatternAddWeak(pattern, FC_FAMILY, familyNameValue, FcFalse);
775        }
776        fcpattern_from_skfontstyle(style, pattern);
777
778        SkAutoFcCharSet charSet;
779        FcCharSetAddChar(charSet, character);
780        FcPatternAddCharSet(pattern, FC_CHARSET, charSet);
781
782        if (bcp47Count > 0) {
783            SkASSERT(bcp47);
784            SkAutoFcLangSet langSet;
785            for (int i = bcp47Count; i --> 0;) {
786                FcLangSetAdd(langSet, (const FcChar8*)bcp47[i]);
787            }
788            FcPatternAddLangSet(pattern, FC_LANG, langSet);
789        }
790
791        FcConfigSubstitute(fFC, pattern, FcMatchPattern);
792        FcDefaultSubstitute(pattern);
793
794        FcResult result;
795        SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
796        if (NULL == font || !FontAccessible(font) || !FontContainsCharacter(font, character)) {
797            return NULL;
798        }
799
800        return createTypefaceFromFcPattern(font);
801    }
802
803    virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
804                                         const SkFontStyle& style) const override
805    {
806        //TODO: should the SkTypeface_fontconfig know its family?
807        const SkTypeface_fontconfig* fcTypeface =
808                static_cast<const SkTypeface_fontconfig*>(typeface);
809        return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY), style);
810    }
811
812    SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
813        SkAutoTDelete<SkStreamAsset> stream(bareStream);
814        const size_t length = stream->getLength();
815        if (length <= 0 || (1u << 30) < length) {
816            return NULL;
817        }
818
819        SkFontStyle style;
820        bool isFixedWidth = false;
821        if (!fScanner.scanFont(stream, ttcIndex, NULL, &style, &isFixedWidth, NULL)) {
822            return NULL;
823        }
824
825        return SkNEW_ARGS(SkTypeface_stream, (new SkFontData(stream.detach(), ttcIndex, NULL, 0),
826                                              style, isFixedWidth));
827    }
828
829    SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
830        return this->createFromStream(SkNEW_ARGS(SkMemoryStream, (data)), ttcIndex);
831    }
832
833    SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
834        return this->createFromStream(SkStream::NewFromFile(path), ttcIndex);
835    }
836
837    SkTypeface* onCreateFromFontData(SkFontData* fontData) const override {
838        SkStreamAsset* stream(fontData->getStream());
839        const size_t length = stream->getLength();
840        if (length <= 0 || (1u << 30) < length) {
841            return NULL;
842        }
843
844        const int ttcIndex = fontData->getIndex();
845        SkFontStyle style;
846        bool isFixedWidth = false;
847        if (!fScanner.scanFont(stream, ttcIndex, NULL, &style, &isFixedWidth, NULL)) {
848            return NULL;
849        }
850
851        return SkNEW_ARGS(SkTypeface_stream, (fontData, style, isFixedWidth));
852    }
853
854    virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
855                                               unsigned styleBits) const override {
856        bool bold = styleBits & SkTypeface::kBold;
857        bool italic = styleBits & SkTypeface::kItalic;
858        SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
859                                             : SkFontStyle::kNormal_Weight,
860                                        SkFontStyle::kNormal_Width,
861                                        italic ? SkFontStyle::kItalic_Slant
862                                               : SkFontStyle::kUpright_Slant);
863        SkAutoTUnref<SkTypeface> typeface(this->matchFamilyStyle(familyName, style));
864        if (typeface.get()) {
865            return typeface.detach();
866        }
867
868        return this->matchFamilyStyle(NULL, style);
869    }
870};
871
872SK_API SkFontMgr* SkFontMgr_New_FontConfig(FcConfig* fc) {
873    return new SkFontMgr_fontconfig(fc);
874}
875