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
376static SkTypeface::Style sktypefacestyle_from_fcpattern(FcPattern* pattern) {
377    int fcweight = get_int(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR);
378    int fcslant = get_int(pattern, FC_SLANT, FC_SLANT_ROMAN);
379    return (SkTypeface::Style)((fcweight >= FC_WEIGHT_BOLD ? SkTypeface::kBold : 0) |
380                                (fcslant > FC_SLANT_ROMAN ? SkTypeface::kItalic : 0));
381}
382
383class SkTypeface_stream : public SkTypeface_FreeType {
384public:
385    /** @param stream does not take ownership of the reference, does take ownership of the stream.*/
386    SkTypeface_stream(SkTypeface::Style style, bool fixedWidth, int ttcIndex, SkStreamAsset* stream)
387        : INHERITED(style, SkTypefaceCache::NewFontID(), fixedWidth)
388        , fStream(SkRef(stream))
389        , fIndex(ttcIndex)
390    { };
391
392    virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
393        familyName->reset();
394    }
395
396    virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const SK_OVERRIDE {
397        desc->setFontIndex(fIndex);
398        *serialize = true;
399    }
400
401    virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
402        *ttcIndex = fIndex;
403        return fStream->duplicate();
404    }
405
406private:
407    SkAutoTUnref<SkStreamAsset> fStream;
408    int fIndex;
409
410    typedef SkTypeface_FreeType INHERITED;
411};
412
413class SkTypeface_fontconfig : public SkTypeface_FreeType {
414public:
415    /** @param pattern takes ownership of the reference. */
416    static SkTypeface_fontconfig* Create(FcPattern* pattern) {
417        return SkNEW_ARGS(SkTypeface_fontconfig, (pattern));
418    }
419    mutable SkAutoFcPattern fPattern;
420
421    virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
422        *familyName = get_string(fPattern, FC_FAMILY);
423    }
424
425    virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const SK_OVERRIDE {
426        FCLocker lock;
427        desc->setFamilyName(get_string(fPattern, FC_FAMILY));
428        desc->setFullName(get_string(fPattern, FC_FULLNAME));
429        desc->setPostscriptName(get_string(fPattern, FC_POSTSCRIPT_NAME));
430        desc->setFontFileName(get_string(fPattern, FC_FILE));
431        desc->setFontIndex(get_int(fPattern, FC_INDEX, 0));
432        *serialize = false;
433    }
434
435    virtual SkStream* onOpenStream(int* ttcIndex) const SK_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(sktypefacestyle_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
463    class StyleSet : public SkFontStyleSet {
464    public:
465        /** @param parent does not take ownership of the reference.
466         *  @param fontSet takes ownership of the reference.
467         */
468        StyleSet(const SkFontMgr_fontconfig* parent, FcFontSet* fontSet)
469            : fFontMgr(SkRef(parent)), fFontSet(fontSet)
470        { }
471
472        virtual ~StyleSet() {
473            // Hold the lock while unrefing the font set.
474            FCLocker lock;
475            fFontSet.reset();
476        }
477
478        virtual int count() SK_OVERRIDE { return fFontSet->nfont; }
479
480        virtual void getStyle(int index, SkFontStyle* style, SkString* styleName) SK_OVERRIDE {
481            if (index < 0 || fFontSet->nfont <= index) {
482                return;
483            }
484
485            FCLocker lock;
486            if (style) {
487                *style = skfontstyle_from_fcpattern(fFontSet->fonts[index]);
488            }
489            if (styleName) {
490                *styleName = get_string(fFontSet->fonts[index], FC_STYLE);
491            }
492        }
493
494        virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
495            FCLocker lock;
496
497            FcPattern* match = fFontSet->fonts[index];
498            return fFontMgr->createTypefaceFromFcPattern(match);
499        }
500
501        virtual SkTypeface* matchStyle(const SkFontStyle& style) SK_OVERRIDE {
502            FCLocker lock;
503
504            SkAutoFcPattern pattern;
505            fcpattern_from_skfontstyle(style, pattern);
506            FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern);
507            FcDefaultSubstitute(pattern);
508
509            FcResult result;
510            FcFontSet* fontSets[1] = { fFontSet };
511            SkAutoFcPattern match(FcFontSetMatch(fFontMgr->fFC,
512                                                 fontSets, SK_ARRAY_COUNT(fontSets),
513                                                 pattern, &result));
514            if (NULL == match) {
515                return NULL;
516            }
517
518            return fFontMgr->createTypefaceFromFcPattern(match);
519        }
520
521    private:
522        SkAutoTUnref<const SkFontMgr_fontconfig> fFontMgr;
523        SkAutoFcFontSet fFontSet;
524    };
525
526    static bool FindName(const SkTDArray<const char*>& list, const char* str) {
527        int count = list.count();
528        for (int i = 0; i < count; ++i) {
529            if (!strcmp(list[i], str)) {
530                return true;
531            }
532        }
533        return false;
534    }
535
536    static SkDataTable* GetFamilyNames(FcConfig* fcconfig) {
537        FCLocker lock;
538
539        SkTDArray<const char*> names;
540        SkTDArray<size_t> sizes;
541
542        static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
543        for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
544            // Return value of FcConfigGetFonts must not be destroyed.
545            FcFontSet* allFonts(FcConfigGetFonts(fcconfig, fcNameSet[setIndex]));
546            if (NULL == allFonts) {
547                continue;
548            }
549
550            for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
551                FcPattern* current = allFonts->fonts[fontIndex];
552                for (int id = 0; ; ++id) {
553                    FcChar8* fcFamilyName;
554                    FcResult result = FcPatternGetString(current, FC_FAMILY, id, &fcFamilyName);
555                    if (FcResultNoId == result) {
556                        break;
557                    }
558                    if (FcResultMatch != result) {
559                        continue;
560                    }
561                    const char* familyName = reinterpret_cast<const char*>(fcFamilyName);
562                    if (familyName && !FindName(names, familyName)) {
563                        *names.append() = familyName;
564                        *sizes.append() = strlen(familyName) + 1;
565                    }
566                }
567            }
568        }
569
570        return SkDataTable::NewCopyArrays((void const *const *)names.begin(),
571                                          sizes.begin(), names.count());
572    }
573
574    static bool FindByFcPattern(SkTypeface* cached, SkTypeface::Style, void* ctx) {
575        SkTypeface_fontconfig* cshFace = static_cast<SkTypeface_fontconfig*>(cached);
576        FcPattern* ctxPattern = static_cast<FcPattern*>(ctx);
577        return FcTrue == FcPatternEqual(cshFace->fPattern, ctxPattern);
578    }
579
580    mutable SkMutex fTFCacheMutex;
581    mutable SkTypefaceCache fTFCache;
582    /** Creates a typeface using a typeface cache.
583     *  @param pattern a complete pattern from FcFontRenderPrepare.
584     */
585    SkTypeface* createTypefaceFromFcPattern(FcPattern* pattern) const {
586        FCLocker::AssertHeld();
587        SkAutoMutexAcquire ama(fTFCacheMutex);
588        SkTypeface* face = fTFCache.findByProcAndRef(FindByFcPattern, pattern);
589        if (NULL == face) {
590            FcPatternReference(pattern);
591            face = SkTypeface_fontconfig::Create(pattern);
592            if (face) {
593                fTFCache.add(face, SkTypeface::kNormal, true);
594            }
595        }
596        return face;
597    }
598
599public:
600    SkFontMgr_fontconfig()
601        : fFC(FcInitLoadConfigAndFonts())
602        , fFamilyNames(GetFamilyNames(fFC)) { }
603
604    /** Takes control of the reference to 'config'. */
605    explicit SkFontMgr_fontconfig(FcConfig* config)
606        : fFC(config)
607        , fFamilyNames(GetFamilyNames(fFC)) { }
608
609    virtual ~SkFontMgr_fontconfig() {
610        // Hold the lock while unrefing the config.
611        FCLocker lock;
612        fFC.reset();
613    }
614
615protected:
616    virtual int onCountFamilies() const SK_OVERRIDE {
617        return fFamilyNames->count();
618    }
619
620    virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
621        familyName->set(fFamilyNames->atStr(index));
622    }
623
624    virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
625        return this->onMatchFamily(fFamilyNames->atStr(index));
626    }
627
628    /** True if any string object value in the font is the same
629     *         as a string object value in the pattern.
630     */
631    static bool AnyMatching(FcPattern* font, FcPattern* pattern, const char* object) {
632        FcChar8* fontString;
633        FcChar8* patternString;
634        FcResult result;
635        // Set an arbitrary limit on the number of pattern object values to consider.
636        // TODO: re-write this to avoid N*M
637        static const int maxId = 16;
638        for (int patternId = 0; patternId < maxId; ++patternId) {
639            result = FcPatternGetString(pattern, object, patternId, &patternString);
640            if (FcResultNoId == result) {
641                break;
642            }
643            if (FcResultMatch != result) {
644                continue;
645            }
646            for (int fontId = 0; fontId < maxId; ++fontId) {
647                result = FcPatternGetString(font, object, fontId, &fontString);
648                if (FcResultNoId == result) {
649                    break;
650                }
651                if (FcResultMatch != result) {
652                    continue;
653                }
654                if (0 == FcStrCmpIgnoreCase(patternString, fontString)) {
655                    return true;
656                }
657            }
658        }
659        return false;
660    }
661
662    static bool FontAccessible(FcPattern* font) {
663        // FontConfig can return fonts which are unreadable.
664        const char* filename = get_string(font, FC_FILE, NULL);
665        if (NULL == filename) {
666            return false;
667        }
668        return sk_exists(filename, kRead_SkFILE_Flag);
669    }
670
671    static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) {
672        return AnyMatching(font, pattern, FC_FAMILY);
673    }
674
675    static bool FontContainsCharacter(FcPattern* font, uint32_t character) {
676        FcResult result;
677        FcCharSet* matchCharSet;
678        for (int charSetId = 0; ; ++charSetId) {
679            result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchCharSet);
680            if (FcResultNoId == result) {
681                break;
682            }
683            if (FcResultMatch != result) {
684                continue;
685            }
686            if (FcCharSetHasChar(matchCharSet, character)) {
687                return true;
688            }
689        }
690        return false;
691    }
692
693    virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
694        FCLocker lock;
695
696        SkAutoFcPattern pattern;
697        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
698        FcConfigSubstitute(fFC, pattern, FcMatchPattern);
699        FcDefaultSubstitute(pattern);
700
701        FcPattern* matchPattern;
702        SkAutoFcPattern strongPattern(NULL);
703        if (familyName) {
704            strongPattern.reset(FcPatternDuplicate(pattern));
705            remove_weak(strongPattern, FC_FAMILY);
706            matchPattern = strongPattern;
707        } else {
708            matchPattern = pattern;
709        }
710
711        SkAutoFcFontSet matches;
712        // TODO: Some families have 'duplicates' due to symbolic links.
713        // The patterns are exactly the same except for the FC_FILE.
714        // It should be possible to collapse these patterns by normalizing.
715        static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
716        for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
717            // Return value of FcConfigGetFonts must not be destroyed.
718            FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex]));
719            if (NULL == allFonts) {
720                continue;
721            }
722
723            for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
724                FcPattern* font = allFonts->fonts[fontIndex];
725                if (FontAccessible(font) && FontFamilyNameMatches(font, matchPattern)) {
726                    FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font));
727                }
728            }
729        }
730
731        return SkNEW_ARGS(StyleSet, (this, matches.detach()));
732    }
733
734    virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
735                                           const SkFontStyle& style) const SK_OVERRIDE
736    {
737        FCLocker lock;
738
739        SkAutoFcPattern pattern;
740        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
741        fcpattern_from_skfontstyle(style, pattern);
742        FcConfigSubstitute(fFC, pattern, FcMatchPattern);
743        FcDefaultSubstitute(pattern);
744
745        // We really want to match strong (prefered) and same (acceptable) only here.
746        // If a family name was specified, assume that any weak matches after the last strong match
747        // are weak (default) and ignore them.
748        // The reason for is that after substitution the pattern for 'sans-serif' looks like
749        // "wwwwwwwwwwwwwwswww" where there are many weak but preferred names, followed by defaults.
750        // So it is possible to have weakly matching but preferred names.
751        // In aliases, bindings are weak by default, so this is easy and common.
752        // If no family name was specified, we'll probably only get weak matches, but that's ok.
753        FcPattern* matchPattern;
754        SkAutoFcPattern strongPattern(NULL);
755        if (familyName) {
756            strongPattern.reset(FcPatternDuplicate(pattern));
757            remove_weak(strongPattern, FC_FAMILY);
758            matchPattern = strongPattern;
759        } else {
760            matchPattern = pattern;
761        }
762
763        FcResult result;
764        SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
765        if (NULL == font || !FontAccessible(font) || !FontFamilyNameMatches(font, matchPattern)) {
766            return NULL;
767        }
768
769        return createTypefaceFromFcPattern(font);
770    }
771
772#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
773    virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
774                                                    const SkFontStyle& style,
775                                                    const char* bcp47[],
776                                                    int bcp47Count,
777                                                    SkUnichar character) const SK_OVERRIDE
778    {
779#else
780    virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
781                                                    const SkFontStyle& style,
782                                                    const char bcp47_val[],
783                                                    SkUnichar character) const SK_OVERRIDE
784    {
785        const char** bcp47 = &bcp47_val;
786        int bcp47Count = bcp47_val ? 1 : 0;
787#endif
788        FCLocker lock;
789
790        SkAutoFcPattern pattern;
791        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
792        fcpattern_from_skfontstyle(style, pattern);
793
794        SkAutoFcCharSet charSet;
795        FcCharSetAddChar(charSet, character);
796        FcPatternAddCharSet(pattern, FC_CHARSET, charSet);
797
798        if (bcp47Count > 0) {
799            SkASSERT(bcp47);
800            SkAutoFcLangSet langSet;
801            for (int i = bcp47Count; i --> 0;) {
802                FcLangSetAdd(langSet, (const FcChar8*)bcp47[i]);
803            }
804            FcPatternAddLangSet(pattern, FC_LANG, langSet);
805        }
806
807        FcConfigSubstitute(fFC, pattern, FcMatchPattern);
808        FcDefaultSubstitute(pattern);
809
810        FcResult result;
811        SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
812        if (NULL == font || !FontAccessible(font) || !FontContainsCharacter(font, character)) {
813            return NULL;
814        }
815
816        return createTypefaceFromFcPattern(font);
817    }
818
819    virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
820                                         const SkFontStyle& style) const SK_OVERRIDE
821    {
822        //TODO: should the SkTypeface_fontconfig know its family?
823        const SkTypeface_fontconfig* fcTypeface =
824                static_cast<const SkTypeface_fontconfig*>(typeface);
825        return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY), style);
826    }
827
828    /** @param stream does not take ownership of the reference. */
829    virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
830        const size_t length = stream->getLength();
831        if (length <= 0 || (1u << 30) < length) {
832            return NULL;
833        }
834
835        SkTypeface::Style style = SkTypeface::kNormal;
836        bool isFixedWidth = false;
837        if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, NULL, &style, &isFixedWidth)) {
838            return NULL;
839        }
840
841        return SkNEW_ARGS(SkTypeface_stream, (style, isFixedWidth, ttcIndex,
842                                              static_cast<SkStreamAsset*>(stream)));
843    }
844
845    virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
846        SkAutoTUnref<SkStreamAsset> stream(SkNEW_ARGS(SkMemoryStream, (data)));
847        return this->createFromStream(stream, ttcIndex);
848    }
849
850    virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
851        SkAutoTUnref<SkStreamAsset> stream(SkStream::NewFromFile(path));
852        return this->createFromStream(stream, ttcIndex);
853    }
854
855    virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
856                                               unsigned styleBits) const SK_OVERRIDE {
857        bool bold = styleBits & SkTypeface::kBold;
858        bool italic = styleBits & SkTypeface::kItalic;
859        SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
860                                             : SkFontStyle::kNormal_Weight,
861                                        SkFontStyle::kNormal_Width,
862                                        italic ? SkFontStyle::kItalic_Slant
863                                               : SkFontStyle::kUpright_Slant);
864        SkAutoTUnref<SkTypeface> typeface(this->matchFamilyStyle(familyName, style));
865        if (typeface.get()) {
866            return typeface.detach();
867        }
868
869        return this->matchFamilyStyle(NULL, style);
870    }
871};
872
873SkFontMgr* SkFontMgr::Factory() {
874    return SkNEW(SkFontMgr_fontconfig);
875}
876