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