1a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman/*
2a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman * Copyright 2014 Google Inc.
3a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *
4a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman * Use of this source code is governed by a BSD-style license that can be
5a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman * found in the LICENSE file.
6a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman */
7a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
8a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include "SkDataTable.h"
9f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkFixed.h"
10a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include "SkFontDescriptor.h"
11a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include "SkFontHost_FreeType_common.h"
12a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include "SkFontMgr.h"
13a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include "SkFontStyle.h"
14a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include "SkMath.h"
151b24933e52f50773de29332387a12721811f3012mtklein#include "SkMutex.h"
16f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkOSFile.h"
17f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkRefCnt.h"
18a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include "SkStream.h"
19f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkString.h"
20a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include "SkTDArray.h"
21f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkTemplates.h"
22f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkTypeface.h"
23a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include "SkTypefaceCache.h"
24f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkTypes.h"
25a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
26a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#include <fontconfig/fontconfig.h>
27f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include <string.h>
28f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman
29f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungemanclass SkData;
30a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
31a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman// FC_POSTSCRIPT_NAME was added with b561ff20 which ended up in 2.10.92
32a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman// Ubuntu 12.04 is on 2.8.0, 13.10 is on 2.10.93
33a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman// Debian 7 is on 2.9.0, 8 is on 2.11
34a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman// OpenSUSE 12.2 is on 2.9.0, 12.3 is on 2.10.2, 13.1 2.11.0
35a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman// Fedora 19 is on 2.10.93
36a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#ifndef FC_POSTSCRIPT_NAME
37a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#    define FC_POSTSCRIPT_NAME  "postscriptname"
38a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#endif
39a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
40a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#ifdef SK_DEBUG
41a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#    include "SkTLS.h"
42a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#endif
43a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
44a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman/** Since FontConfig is poorly documented, this gives a high level overview:
45a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *
46a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  FcConfig is a handle to a FontConfig configuration instance. Each 'configuration' is independent
47a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  from any others which may exist. There exists a default global configuration which is created
48a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  and destroyed by FcInit and FcFini, but this default should not normally be used.
49a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  Instead, one should use FcConfigCreate and FcInit* to have a named local state.
50a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *
51a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  FcPatterns are {objectName -> [element]} (maps from object names to a list of elements).
52a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  Each element is some internal data plus an FcValue which is a variant (a union with a type tag).
53a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  Lists of elements are not typed, except by convention. Any collection of FcValues must be
54a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  assumed to be heterogeneous by the code, but the code need not do anything particularly
55a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  interesting if the values go against convention.
56a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *
57a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  Somewhat like DirectWrite, FontConfig supports synthetics through FC_EMBOLDEN and FC_MATRIX.
58a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  Like all synthetic information, such information must be passed with the font data.
59a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman */
60a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
61a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemannamespace {
62a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
63a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman// Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a global mutex.
646950de6c4166fabb35e6c756fc009e0cf1c47819halcanary// See https://bug.skia.org/1497 for background.
65a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanSK_DECLARE_STATIC_MUTEX(gFCMutex);
66a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
67a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#ifdef SK_DEBUG
68385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid* CreateThreadFcLocked() { return new bool(false); }
69385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryvoid DeleteThreadFcLocked(void* v) { delete static_cast<bool*>(v); }
70a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#   define THREAD_FC_LOCKED \
71a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        static_cast<bool*>(SkTLS::Get(CreateThreadFcLocked, DeleteThreadFcLocked))
72a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman#endif
73a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
74a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstruct FCLocker {
75a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // Assume FcGetVersion() has always been thread safe.
76a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
77a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FCLocker() {
78a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (FcGetVersion() < 21091) {
79a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            gFCMutex.acquire();
80a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        } else {
81a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            SkDEBUGCODE(bool* threadLocked = THREAD_FC_LOCKED);
82a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            SkASSERT(false == *threadLocked);
83a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            SkDEBUGCODE(*threadLocked = true);
84a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
85a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
86a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
87a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    ~FCLocker() {
88a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        AssertHeld();
89a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (FcGetVersion() < 21091) {
90a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            gFCMutex.release();
91a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        } else {
92a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            SkDEBUGCODE(*THREAD_FC_LOCKED = false);
93a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
94a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
95a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
96a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static void AssertHeld() { SkDEBUGCODE(
97a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (FcGetVersion() < 21091) {
98a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            gFCMutex.assertHeld();
99a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        } else {
100a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            SkASSERT(true == *THREAD_FC_LOCKED);
101a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
102a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    ) }
103a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman};
104a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
105a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman} // namespace
106a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
1076bc2c94de334efb40e1a09e31112262dec77532bbungemantemplate<typename T, void (*D)(T*)> void FcTDestroy(T* t) {
108a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FCLocker::AssertHeld();
1096bc2c94de334efb40e1a09e31112262dec77532bbungeman    D(t);
110a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
1116bc2c94de334efb40e1a09e31112262dec77532bbungemantemplate <typename T, T* (*C)(), void (*D)(T*)> class SkAutoFc
1126bc2c94de334efb40e1a09e31112262dec77532bbungeman    : public SkAutoTCallVProc<T, FcTDestroy<T, D> > {
113a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanpublic:
1146bc2c94de334efb40e1a09e31112262dec77532bbungeman    SkAutoFc() : SkAutoTCallVProc<T, FcTDestroy<T, D> >(C()) {
1156bc2c94de334efb40e1a09e31112262dec77532bbungeman        T* obj = this->operator T*();
116f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen        SkASSERT_RELEASE(nullptr != obj);
1176bc2c94de334efb40e1a09e31112262dec77532bbungeman    }
1186bc2c94de334efb40e1a09e31112262dec77532bbungeman    explicit SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, D> >(obj) {}
119a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman};
120a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
1216bc2c94de334efb40e1a09e31112262dec77532bbungemantypedef SkAutoFc<FcCharSet, FcCharSetCreate, FcCharSetDestroy> SkAutoFcCharSet;
1226bc2c94de334efb40e1a09e31112262dec77532bbungemantypedef SkAutoFc<FcConfig, FcConfigCreate, FcConfigDestroy> SkAutoFcConfig;
1236bc2c94de334efb40e1a09e31112262dec77532bbungemantypedef SkAutoFc<FcFontSet, FcFontSetCreate, FcFontSetDestroy> SkAutoFcFontSet;
1246bc2c94de334efb40e1a09e31112262dec77532bbungemantypedef SkAutoFc<FcLangSet, FcLangSetCreate, FcLangSetDestroy> SkAutoFcLangSet;
1256bc2c94de334efb40e1a09e31112262dec77532bbungemantypedef SkAutoFc<FcObjectSet, FcObjectSetCreate, FcObjectSetDestroy> SkAutoFcObjectSet;
1266bc2c94de334efb40e1a09e31112262dec77532bbungemantypedef SkAutoFc<FcPattern, FcPatternCreate, FcPatternDestroy> SkAutoFcPattern;
127a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
128a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic int get_int(FcPattern* pattern, const char object[], int missing) {
129a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    int value;
130a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) {
131a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return missing;
132a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
133a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    return value;
134a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
135a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
136a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic const char* get_string(FcPattern* pattern, const char object[], const char* missing = "") {
137a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcChar8* value;
138a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    if (FcPatternGetString(pattern, object, 0, &value) != FcResultMatch) {
139a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return missing;
140a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
141a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    return (const char*)value;
142a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
143a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
144a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanenum SkWeakReturn {
145a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    kIsWeak_WeakReturn,
146a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    kIsStrong_WeakReturn,
147a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    kNoId_WeakReturn
148a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman};
149a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman/** Ideally there  would exist a call like
150a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  FcResult FcPatternIsWeak(pattern, object, id, FcBool* isWeak);
151a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *
152a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  However, there is no such call and as of Fc 2.11.0 even FcPatternEquals ignores the weak bit.
153a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  Currently, the only reliable way of finding the weak bit is by its effect on matching.
154a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  The weak bit only affects the matching of FC_FAMILY and FC_POSTSCRIPT_NAME object values.
155a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  A element with the weak bit is scored after FC_LANG, without the weak bit is scored before.
156a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  Note that the weak bit is stored on the element, not on the value it holds.
157a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman */
158a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic SkWeakReturn is_weak(FcPattern* pattern, const char object[], int id) {
159a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FCLocker::AssertHeld();
160a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
161a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcResult result;
162a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
163a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // Create a copy of the pattern with only the value 'pattern'['object'['id']] in it.
164a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // Internally, FontConfig pattern objects are linked lists, so faster to remove from head.
16596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, nullptr));
166a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
167a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcBool hasId = true;
168a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    for (int i = 0; hasId && i < id; ++i) {
169a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        hasId = FcPatternRemove(minimal, object, 0);
170a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
171a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    if (!hasId) {
172a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return kNoId_WeakReturn;
173a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
174a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcValue value;
175a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    result = FcPatternGet(minimal, object, 0, &value);
176a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    if (result != FcResultMatch) {
177a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return kNoId_WeakReturn;
178a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
179a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    while (hasId) {
180a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        hasId = FcPatternRemove(minimal, object, 1);
181a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
182a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
183a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // Create a font set with two patterns.
184a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // 1. the same 'object' as minimal and a lang object with only 'nomatchlang'.
185a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // 2. a different 'object' from minimal and a lang object with only 'matchlang'.
1866bc2c94de334efb40e1a09e31112262dec77532bbungeman    SkAutoFcFontSet fontSet;
187a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
1886bc2c94de334efb40e1a09e31112262dec77532bbungeman    SkAutoFcLangSet strongLangSet;
189a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcLangSetAdd(strongLangSet, (const FcChar8*)"nomatchlang");
190a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkAutoFcPattern strong(FcPatternDuplicate(minimal));
191a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcPatternAddLangSet(strong, FC_LANG, strongLangSet);
192a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
1936bc2c94de334efb40e1a09e31112262dec77532bbungeman    SkAutoFcLangSet weakLangSet;
194a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcLangSetAdd(weakLangSet, (const FcChar8*)"matchlang");
1956bc2c94de334efb40e1a09e31112262dec77532bbungeman    SkAutoFcPattern weak;
196a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcPatternAddString(weak, object, (const FcChar8*)"nomatchstring");
197a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcPatternAddLangSet(weak, FC_LANG, weakLangSet);
198a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
199a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcFontSetAdd(fontSet, strong.detach());
200a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcFontSetAdd(fontSet, weak.detach());
201a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
202a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // Add 'matchlang' to the copy of the pattern.
203a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcPatternAddLangSet(minimal, FC_LANG, weakLangSet);
204a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
205a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // Run a match against the copy of the pattern.
206a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // If the 'id' was weak, then we should match the pattern with 'matchlang'.
207a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // If the 'id' was strong, then we should match the pattern with 'nomatchlang'.
208a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
209a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // Note that this config is only used for FcFontRenderPrepare, which we don't even want.
210a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // However, there appears to be no way to match/sort without it.
2116bc2c94de334efb40e1a09e31112262dec77532bbungeman    SkAutoFcConfig config;
212a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcFontSet* fontSets[1] = { fontSet };
213a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkAutoFcPattern match(FcFontSetMatch(config, fontSets, SK_ARRAY_COUNT(fontSets),
214a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                         minimal, &result));
215a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
216a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcLangSet* matchLangSet;
217a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcPatternGetLangSet(match, FC_LANG, 0, &matchLangSet);
218a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    return FcLangEqual == FcLangSetHasLang(matchLangSet, (const FcChar8*)"matchlang")
219a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                        ? kIsWeak_WeakReturn : kIsStrong_WeakReturn;
220a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
221a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
222a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman/** Removes weak elements from either FC_FAMILY or FC_POSTSCRIPT_NAME objects in the property.
223a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  This can be quite expensive, and should not be used more than once per font lookup.
224a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman *  This removes all of the weak elements after the last strong element.
225a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman */
226a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic void remove_weak(FcPattern* pattern, const char object[]) {
227a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FCLocker::AssertHeld();
228a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
22996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, nullptr));
230a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
231a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
232a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    int lastStrongId = -1;
233a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    int numIds;
234a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkWeakReturn result;
235a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    for (int id = 0; ; ++id) {
236a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        result = is_weak(minimal, object, 0);
237a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (kNoId_WeakReturn == result) {
238a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            numIds = id;
239a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            break;
240a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
241a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (kIsStrong_WeakReturn == result) {
242a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            lastStrongId = id;
243a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
244a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkAssertResult(FcPatternRemove(minimal, object, 0));
245a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
246a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
247a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // If they were all weak, then leave the pattern alone.
248a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    if (lastStrongId < 0) {
249a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return;
250a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
251a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
252a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // Remove everything after the last strong.
253a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    for (int id = lastStrongId + 1; id < numIds; ++id) {
254a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkAssertResult(FcPatternRemove(pattern, object, lastStrongId + 1));
255a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
256a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
257a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
258a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic int map_range(SkFixed value,
259a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                     SkFixed old_min, SkFixed old_max,
260a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                     SkFixed new_min, SkFixed new_max)
261a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman{
262a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkASSERT(old_min < old_max);
263a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkASSERT(new_min <= new_max);
264a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    return new_min + SkMulDiv(value - old_min, new_max - new_min, old_max - old_min);
265a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
266a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
267a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic int ave(SkFixed a, SkFixed b) {
268a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    return SkFixedAve(a, b);
269a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
270a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
271a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstruct MapRanges {
272a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkFixed old_val;
273a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkFixed new_val;
274a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman};
275a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
276a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic SkFixed map_ranges_fixed(SkFixed val, MapRanges const ranges[], int rangesCount) {
277a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // -Inf to [0]
278a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    if (val < ranges[0].old_val) {
279a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return ranges[0].new_val;
280a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
281a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
282a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // Linear from [i] to ave([i], [i+1]), then from ave([i], [i+1]) to [i+1]
283a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    for (int i = 0; i < rangesCount - 1; ++i) {
284a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (val < ave(ranges[i].old_val, ranges[i+1].old_val)) {
285a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            return map_range(val, ranges[i].old_val, ave(ranges[i].old_val, ranges[i+1].old_val),
286a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                  ranges[i].new_val, ave(ranges[i].new_val, ranges[i+1].new_val));
287a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
288a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (val < ranges[i+1].old_val) {
289a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            return map_range(val, ave(ranges[i].old_val, ranges[i+1].old_val), ranges[i+1].old_val,
290a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                  ave(ranges[i].new_val, ranges[i+1].new_val), ranges[i+1].new_val);
291a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
292a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
293a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
294a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // From [n] to +Inf
295a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    // if (fcweight < Inf)
296a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    return ranges[rangesCount-1].new_val;
297a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
298a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
299a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic int map_ranges(int val, MapRanges const ranges[], int rangesCount) {
300a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    return SkFixedRoundToInt(map_ranges_fixed(SkIntToFixed(val), ranges, rangesCount));
301a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
302a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
303a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemantemplate<int n> struct SkTFixed {
30499fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert(-32768 <= n && n <= 32767, "SkTFixed_n_not_in_range");
305a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static const SkFixed value = static_cast<SkFixed>(n << 16);
306a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman};
307a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
308a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic SkFontStyle skfontstyle_from_fcpattern(FcPattern* pattern) {
309a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    typedef SkFontStyle SkFS;
310a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
311a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static const MapRanges weightRanges[] = {
312a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_THIN>::value,       SkTFixed<SkFS::kThin_Weight>::value },
313a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_EXTRALIGHT>::value, SkTFixed<SkFS::kExtraLight_Weight>::value },
314a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_LIGHT>::value,      SkTFixed<SkFS::kLight_Weight>::value },
315a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_REGULAR>::value,    SkTFixed<SkFS::kNormal_Weight>::value },
316a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_MEDIUM>::value,     SkTFixed<SkFS::kMedium_Weight>::value },
317a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_DEMIBOLD>::value,   SkTFixed<SkFS::kSemiBold_Weight>::value },
318a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_BOLD>::value,       SkTFixed<SkFS::kBold_Weight>::value },
319a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_EXTRABOLD>::value,  SkTFixed<SkFS::kExtraBold_Weight>::value },
320a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_BLACK>::value,      SkTFixed<SkFS::kBlack_Weight>::value },
321a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WEIGHT_EXTRABLACK>::value, SkTFixed<1000>::value },
322a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    };
323a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    int weight = map_ranges(get_int(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR),
324a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                            weightRanges, SK_ARRAY_COUNT(weightRanges));
325a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
326a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static const MapRanges widthRanges[] = {
327a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WIDTH_ULTRACONDENSED>::value, SkTFixed<SkFS::kUltraCondensed_Width>::value },
328a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WIDTH_EXTRACONDENSED>::value, SkTFixed<SkFS::kExtraCondensed_Width>::value },
329a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WIDTH_CONDENSED>::value,      SkTFixed<SkFS::kCondensed_Width>::value },
330a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WIDTH_SEMICONDENSED>::value,  SkTFixed<SkFS::kSemiCondensed_Width>::value },
331a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WIDTH_NORMAL>::value,         SkTFixed<SkFS::kNormal_Width>::value },
332a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WIDTH_SEMIEXPANDED>::value,   SkTFixed<SkFS::kSemiExpanded_Width>::value },
333a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WIDTH_EXPANDED>::value,       SkTFixed<SkFS::kExpanded_Width>::value },
334a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value,  SkTFixed<SkFS::kExtraExpanded_Width>::value },
335a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value,  SkTFixed<SkFS::kUltaExpanded_Width>::value },
336a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    };
337a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    int width = map_ranges(get_int(pattern, FC_WIDTH, FC_WIDTH_NORMAL),
338a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                           widthRanges, SK_ARRAY_COUNT(widthRanges));
339a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
340a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkFS::Slant slant = get_int(pattern, FC_SLANT, FC_SLANT_ROMAN) > 0
341a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                             ? SkFS::kItalic_Slant
342a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                             : SkFS::kUpright_Slant;
343a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
344a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    return SkFontStyle(weight, width, slant);
345a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
346a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
347a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanstatic void fcpattern_from_skfontstyle(SkFontStyle style, FcPattern* pattern) {
348a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FCLocker::AssertHeld();
349a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
350a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    typedef SkFontStyle SkFS;
351a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
352a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static const MapRanges weightRanges[] = {
353a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kThin_Weight>::value,       SkTFixed<FC_WEIGHT_THIN>::value },
354a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kExtraLight_Weight>::value, SkTFixed<FC_WEIGHT_EXTRALIGHT>::value },
355a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kLight_Weight>::value,      SkTFixed<FC_WEIGHT_LIGHT>::value },
356a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kNormal_Weight>::value,     SkTFixed<FC_WEIGHT_REGULAR>::value },
357a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kMedium_Weight>::value,     SkTFixed<FC_WEIGHT_MEDIUM>::value },
358a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kSemiBold_Weight>::value,   SkTFixed<FC_WEIGHT_DEMIBOLD>::value },
359a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kBold_Weight>::value,       SkTFixed<FC_WEIGHT_BOLD>::value },
360a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kExtraBold_Weight>::value,  SkTFixed<FC_WEIGHT_EXTRABOLD>::value },
361a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kBlack_Weight>::value,      SkTFixed<FC_WEIGHT_BLACK>::value },
362a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<1000>::value,                     SkTFixed<FC_WEIGHT_EXTRABLACK>::value },
363a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    };
364a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    int weight = map_ranges(style.weight(), weightRanges, SK_ARRAY_COUNT(weightRanges));
365a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
366a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static const MapRanges widthRanges[] = {
367a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kUltraCondensed_Width>::value, SkTFixed<FC_WIDTH_ULTRACONDENSED>::value },
368a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kExtraCondensed_Width>::value, SkTFixed<FC_WIDTH_EXTRACONDENSED>::value },
369a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kCondensed_Width>::value,      SkTFixed<FC_WIDTH_CONDENSED>::value },
370a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kSemiCondensed_Width>::value,  SkTFixed<FC_WIDTH_SEMICONDENSED>::value },
371a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kNormal_Width>::value,         SkTFixed<FC_WIDTH_NORMAL>::value },
372a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kSemiExpanded_Width>::value,   SkTFixed<FC_WIDTH_SEMIEXPANDED>::value },
373a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kExpanded_Width>::value,       SkTFixed<FC_WIDTH_EXPANDED>::value },
374a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kExtraExpanded_Width>::value,  SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value },
375a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { SkTFixed<SkFS::kUltaExpanded_Width>::value,   SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value },
376a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    };
377a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    int width = map_ranges(style.width(), widthRanges, SK_ARRAY_COUNT(widthRanges));
378a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
379a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcPatternAddInteger(pattern, FC_WEIGHT, weight);
380a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcPatternAddInteger(pattern, FC_WIDTH, width);
381a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    FcPatternAddInteger(pattern, FC_SLANT, style.isItalic() ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
382a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
383a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
384a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanclass SkTypeface_stream : public SkTypeface_FreeType {
385a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanpublic:
38641868fe5625fc3bd70daa3f461c881b5db6a9265bungeman    /** @param data takes ownership of the font data.*/
38741868fe5625fc3bd70daa3f461c881b5db6a9265bungeman    SkTypeface_stream(SkFontData* data, const SkFontStyle& style, bool fixedWidth)
388a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        : INHERITED(style, SkTypefaceCache::NewFontID(), fixedWidth)
38941868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        , fData(data)
390a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    { };
391a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
39236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onGetFamilyName(SkString* familyName) const override {
393b374d6a62c0259387d90cad74753d8bad9ee1beabungeman        familyName->reset();
394b374d6a62c0259387d90cad74753d8bad9ee1beabungeman    }
395b374d6a62c0259387d90cad74753d8bad9ee1beabungeman
39636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
397a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        *serialize = true;
398a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
399a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
40036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkStreamAsset* onOpenStream(int* ttcIndex) const override {
40141868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        *ttcIndex = fData->getIndex();
40241868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        return fData->duplicateStream();
40341868fe5625fc3bd70daa3f461c881b5db6a9265bungeman    }
40441868fe5625fc3bd70daa3f461c881b5db6a9265bungeman
40541868fe5625fc3bd70daa3f461c881b5db6a9265bungeman    SkFontData* onCreateFontData() const override {
40641868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        return new SkFontData(*fData.get());
407a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
408a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
409a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanprivate:
41041868fe5625fc3bd70daa3f461c881b5db6a9265bungeman    const SkAutoTDelete<const SkFontData> fData;
411a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
412a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    typedef SkTypeface_FreeType INHERITED;
413a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman};
414a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
415a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanclass SkTypeface_fontconfig : public SkTypeface_FreeType {
416a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanpublic:
417a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    /** @param pattern takes ownership of the reference. */
418a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static SkTypeface_fontconfig* Create(FcPattern* pattern) {
419385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return new SkTypeface_fontconfig(pattern);
420a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
421a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    mutable SkAutoFcPattern fPattern;
422a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
42336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onGetFamilyName(SkString* familyName) const override {
424b374d6a62c0259387d90cad74753d8bad9ee1beabungeman        *familyName = get_string(fPattern, FC_FAMILY);
425b374d6a62c0259387d90cad74753d8bad9ee1beabungeman    }
426b374d6a62c0259387d90cad74753d8bad9ee1beabungeman
42736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
428a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FCLocker lock;
429a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        desc->setFamilyName(get_string(fPattern, FC_FAMILY));
430a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        desc->setFullName(get_string(fPattern, FC_FULLNAME));
431a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        desc->setPostscriptName(get_string(fPattern, FC_POSTSCRIPT_NAME));
432a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        *serialize = false;
433a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
434a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
43536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkStreamAsset* onOpenStream(int* ttcIndex) const override {
436a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FCLocker lock;
437a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        *ttcIndex = get_int(fPattern, FC_INDEX, 0);
438a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return SkStream::NewFromFile(get_string(fPattern, FC_FILE));
439a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
440a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
441a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    virtual ~SkTypeface_fontconfig() {
442a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // Hold the lock while unrefing the pattern.
443a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FCLocker lock;
444a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        fPattern.reset();
445a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
446a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
447a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanprivate:
448a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    /** @param pattern takes ownership of the reference. */
449a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkTypeface_fontconfig(FcPattern* pattern)
450a4c4a2d8cd65abb1e5ac20813831cdb9ace6c7eebungeman        : INHERITED(skfontstyle_from_fcpattern(pattern),
451a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    SkTypefaceCache::NewFontID(),
452a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    FC_PROPORTIONAL != get_int(pattern, FC_SPACING, FC_PROPORTIONAL))
453a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        , fPattern(pattern)
454a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    { };
455a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
456a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    typedef SkTypeface_FreeType INHERITED;
457a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman};
458a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
459a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanclass SkFontMgr_fontconfig : public SkFontMgr {
460a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    mutable SkAutoFcConfig fFC;
461a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkAutoTUnref<SkDataTable> fFamilyNames;
46214df8339841f246a7337a8fb0d90f1b7ee689619bungeman    SkTypeface_FreeType::Scanner fScanner;
463a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
464a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    class StyleSet : public SkFontStyleSet {
465a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    public:
466a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        /** @param parent does not take ownership of the reference.
467a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman         *  @param fontSet takes ownership of the reference.
468a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman         */
469a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        StyleSet(const SkFontMgr_fontconfig* parent, FcFontSet* fontSet)
470a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            : fFontMgr(SkRef(parent)), fFontSet(fontSet)
471a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        { }
472a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
473a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        virtual ~StyleSet() {
474a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            // Hold the lock while unrefing the font set.
475a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FCLocker lock;
476a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            fFontSet.reset();
477a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
478a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
47936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        int count() override { return fFontSet->nfont; }
480a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
48136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        void getStyle(int index, SkFontStyle* style, SkString* styleName) override {
482a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            if (index < 0 || fFontSet->nfont <= index) {
483a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                return;
484a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
485a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
486a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FCLocker lock;
487a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            if (style) {
488a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                *style = skfontstyle_from_fcpattern(fFontSet->fonts[index]);
489a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
490a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            if (styleName) {
491a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                *styleName = get_string(fFontSet->fonts[index], FC_STYLE);
492a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
493a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
494a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
49536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        SkTypeface* createTypeface(int index) override {
496a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FCLocker lock;
497a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
498a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FcPattern* match = fFontSet->fonts[index];
499a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            return fFontMgr->createTypefaceFromFcPattern(match);
500a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
501a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
50236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        SkTypeface* matchStyle(const SkFontStyle& style) override {
503a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FCLocker lock;
504a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
5056bc2c94de334efb40e1a09e31112262dec77532bbungeman            SkAutoFcPattern pattern;
506a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            fcpattern_from_skfontstyle(style, pattern);
507a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern);
508a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FcDefaultSubstitute(pattern);
509a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
510a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FcResult result;
511a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FcFontSet* fontSets[1] = { fFontSet };
512a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            SkAutoFcPattern match(FcFontSetMatch(fFontMgr->fFC,
513a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                                 fontSets, SK_ARRAY_COUNT(fontSets),
514a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                                 pattern, &result));
51596fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (nullptr == match) {
51696fcdcc219d2a0d3579719b84b28bede76efba64halcanary                return nullptr;
517a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
518a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
519a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            return fFontMgr->createTypefaceFromFcPattern(match);
520a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
521a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
522a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    private:
523a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkAutoTUnref<const SkFontMgr_fontconfig> fFontMgr;
524a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkAutoFcFontSet fFontSet;
525a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    };
526a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
527a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static bool FindName(const SkTDArray<const char*>& list, const char* str) {
528a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        int count = list.count();
529a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        for (int i = 0; i < count; ++i) {
530a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            if (!strcmp(list[i], str)) {
531a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                return true;
532a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
533a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
534a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return false;
535a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
536a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
537a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static SkDataTable* GetFamilyNames(FcConfig* fcconfig) {
538a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FCLocker lock;
539a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
540a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkTDArray<const char*> names;
541a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkTDArray<size_t> sizes;
542a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
543a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
544a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
545a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            // Return value of FcConfigGetFonts must not be destroyed.
546a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FcFontSet* allFonts(FcConfigGetFonts(fcconfig, fcNameSet[setIndex]));
54796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (nullptr == allFonts) {
548a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                continue;
549a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
550a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
551a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
552a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                FcPattern* current = allFonts->fonts[fontIndex];
553a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                for (int id = 0; ; ++id) {
554a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    FcChar8* fcFamilyName;
555a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    FcResult result = FcPatternGetString(current, FC_FAMILY, id, &fcFamilyName);
556a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    if (FcResultNoId == result) {
557a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                        break;
558a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    }
559a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    if (FcResultMatch != result) {
560a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                        continue;
561a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    }
562a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    const char* familyName = reinterpret_cast<const char*>(fcFamilyName);
563a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    if (familyName && !FindName(names, familyName)) {
564a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                        *names.append() = familyName;
565a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                        *sizes.append() = strlen(familyName) + 1;
566a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    }
567a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                }
568a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
569a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
570a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
571a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return SkDataTable::NewCopyArrays((void const *const *)names.begin(),
572a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                          sizes.begin(), names.count());
573a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
574a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
575a4c4a2d8cd65abb1e5ac20813831cdb9ace6c7eebungeman    static bool FindByFcPattern(SkTypeface* cached, const SkFontStyle&, void* ctx) {
576a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkTypeface_fontconfig* cshFace = static_cast<SkTypeface_fontconfig*>(cached);
577a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcPattern* ctxPattern = static_cast<FcPattern*>(ctx);
578a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return FcTrue == FcPatternEqual(cshFace->fPattern, ctxPattern);
579a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
580a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
581a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    mutable SkMutex fTFCacheMutex;
582a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    mutable SkTypefaceCache fTFCache;
583a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    /** Creates a typeface using a typeface cache.
584a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman     *  @param pattern a complete pattern from FcFontRenderPrepare.
585a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman     */
586a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    SkTypeface* createTypefaceFromFcPattern(FcPattern* pattern) const {
587a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FCLocker::AssertHeld();
588a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkAutoMutexAcquire ama(fTFCacheMutex);
589a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkTypeface* face = fTFCache.findByProcAndRef(FindByFcPattern, pattern);
59096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == face) {
591a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FcPatternReference(pattern);
592a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            face = SkTypeface_fontconfig::Create(pattern);
593a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            if (face) {
59460b6e9dbbc492f987a5b887dff60aec107ab70d0mtklein                fTFCache.add(face, SkFontStyle());
595a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
596a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
597a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return face;
598a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
599a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
600a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanpublic:
601a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    /** Takes control of the reference to 'config'. */
602a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    explicit SkFontMgr_fontconfig(FcConfig* config)
6030b1de2626a289ab21bd3b93277ed34d022824b3dbungeman        : fFC(config ? config : FcInitLoadConfigAndFonts())
604a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        , fFamilyNames(GetFamilyNames(fFC)) { }
605a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
606a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    virtual ~SkFontMgr_fontconfig() {
607a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // Hold the lock while unrefing the config.
608a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FCLocker lock;
609a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        fFC.reset();
610a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
611a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
612a6785ccb540b1b752ab536cdf579a698eadbf7d2bungemanprotected:
61336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    int onCountFamilies() const override {
614a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return fFamilyNames->count();
615a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
616a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
61736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onGetFamilyName(int index, SkString* familyName) const override {
618a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        familyName->set(fFamilyNames->atStr(index));
619a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
620a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
62136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkFontStyleSet* onCreateStyleSet(int index) const override {
622a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return this->onMatchFamily(fFamilyNames->atStr(index));
623a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
624a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
625a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    /** True if any string object value in the font is the same
626a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman     *         as a string object value in the pattern.
627a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman     */
628a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    static bool AnyMatching(FcPattern* font, FcPattern* pattern, const char* object) {
629a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcChar8* fontString;
630a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcChar8* patternString;
631a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcResult result;
632a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // Set an arbitrary limit on the number of pattern object values to consider.
633a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // TODO: re-write this to avoid N*M
634a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        static const int maxId = 16;
635a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        for (int patternId = 0; patternId < maxId; ++patternId) {
636a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            result = FcPatternGetString(pattern, object, patternId, &patternString);
637a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            if (FcResultNoId == result) {
638a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                break;
639a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
640a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            if (FcResultMatch != result) {
641a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                continue;
642a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
643a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            for (int fontId = 0; fontId < maxId; ++fontId) {
644a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                result = FcPatternGetString(font, object, fontId, &fontString);
645a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                if (FcResultNoId == result) {
646a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    break;
647a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                }
648a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                if (FcResultMatch != result) {
649a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    continue;
650a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                }
651a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                if (0 == FcStrCmpIgnoreCase(patternString, fontString)) {
652a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                    return true;
653a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                }
654a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
655a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
656a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return false;
657a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
658a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
6596bc2c94de334efb40e1a09e31112262dec77532bbungeman    static bool FontAccessible(FcPattern* font) {
660a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // FontConfig can return fonts which are unreadable.
66196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        const char* filename = get_string(font, FC_FILE, nullptr);
66296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == filename) {
663a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            return false;
664a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
665a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        return sk_exists(filename, kRead_SkFILE_Flag);
666a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
667a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
6686bc2c94de334efb40e1a09e31112262dec77532bbungeman    static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) {
6696bc2c94de334efb40e1a09e31112262dec77532bbungeman        return AnyMatching(font, pattern, FC_FAMILY);
6706bc2c94de334efb40e1a09e31112262dec77532bbungeman    }
6716bc2c94de334efb40e1a09e31112262dec77532bbungeman
6726bc2c94de334efb40e1a09e31112262dec77532bbungeman    static bool FontContainsCharacter(FcPattern* font, uint32_t character) {
6736bc2c94de334efb40e1a09e31112262dec77532bbungeman        FcResult result;
6746bc2c94de334efb40e1a09e31112262dec77532bbungeman        FcCharSet* matchCharSet;
6756bc2c94de334efb40e1a09e31112262dec77532bbungeman        for (int charSetId = 0; ; ++charSetId) {
6766bc2c94de334efb40e1a09e31112262dec77532bbungeman            result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchCharSet);
6776bc2c94de334efb40e1a09e31112262dec77532bbungeman            if (FcResultNoId == result) {
6786bc2c94de334efb40e1a09e31112262dec77532bbungeman                break;
6796bc2c94de334efb40e1a09e31112262dec77532bbungeman            }
6806bc2c94de334efb40e1a09e31112262dec77532bbungeman            if (FcResultMatch != result) {
6816bc2c94de334efb40e1a09e31112262dec77532bbungeman                continue;
6826bc2c94de334efb40e1a09e31112262dec77532bbungeman            }
6836bc2c94de334efb40e1a09e31112262dec77532bbungeman            if (FcCharSetHasChar(matchCharSet, character)) {
6846bc2c94de334efb40e1a09e31112262dec77532bbungeman                return true;
6856bc2c94de334efb40e1a09e31112262dec77532bbungeman            }
6866bc2c94de334efb40e1a09e31112262dec77532bbungeman        }
6876bc2c94de334efb40e1a09e31112262dec77532bbungeman        return false;
688a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
689a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
69036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
691a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FCLocker lock;
692a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
6936bc2c94de334efb40e1a09e31112262dec77532bbungeman        SkAutoFcPattern pattern;
694a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
695a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcConfigSubstitute(fFC, pattern, FcMatchPattern);
696a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcDefaultSubstitute(pattern);
697a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
698a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcPattern* matchPattern;
69996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        SkAutoFcPattern strongPattern(nullptr);
700a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (familyName) {
701a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            strongPattern.reset(FcPatternDuplicate(pattern));
702a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            remove_weak(strongPattern, FC_FAMILY);
703a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            matchPattern = strongPattern;
704a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        } else {
705a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            matchPattern = pattern;
706a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
707a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
7086bc2c94de334efb40e1a09e31112262dec77532bbungeman        SkAutoFcFontSet matches;
709a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // TODO: Some families have 'duplicates' due to symbolic links.
710a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // The patterns are exactly the same except for the FC_FILE.
711a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // It should be possible to collapse these patterns by normalizing.
712a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
713a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
714a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            // Return value of FcConfigGetFonts must not be destroyed.
715a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex]));
71696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (nullptr == allFonts) {
717a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                continue;
718a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
719a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
720a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
7216bc2c94de334efb40e1a09e31112262dec77532bbungeman                FcPattern* font = allFonts->fonts[fontIndex];
7226bc2c94de334efb40e1a09e31112262dec77532bbungeman                if (FontAccessible(font) && FontFamilyNameMatches(font, matchPattern)) {
7236bc2c94de334efb40e1a09e31112262dec77532bbungeman                    FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font));
724a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                }
725a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            }
726a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
727a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
728385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return new StyleSet(this, matches.detach());
729a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
730a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
731a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
73236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                                           const SkFontStyle& style) const override
733a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    {
734a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FCLocker lock;
735a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
7366bc2c94de334efb40e1a09e31112262dec77532bbungeman        SkAutoFcPattern pattern;
737a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
738a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        fcpattern_from_skfontstyle(style, pattern);
739a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcConfigSubstitute(fFC, pattern, FcMatchPattern);
740a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcDefaultSubstitute(pattern);
741a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
742a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // We really want to match strong (prefered) and same (acceptable) only here.
743a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // If a family name was specified, assume that any weak matches after the last strong match
744a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // are weak (default) and ignore them.
745a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // The reason for is that after substitution the pattern for 'sans-serif' looks like
746a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // "wwwwwwwwwwwwwwswww" where there are many weak but preferred names, followed by defaults.
747a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // So it is possible to have weakly matching but preferred names.
748a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // In aliases, bindings are weak by default, so this is easy and common.
749a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        // If no family name was specified, we'll probably only get weak matches, but that's ok.
750a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcPattern* matchPattern;
75196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        SkAutoFcPattern strongPattern(nullptr);
752a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (familyName) {
753a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            strongPattern.reset(FcPatternDuplicate(pattern));
754a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            remove_weak(strongPattern, FC_FAMILY);
755a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            matchPattern = strongPattern;
756a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        } else {
757a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            matchPattern = pattern;
758a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
759a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
760a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        FcResult result;
7616bc2c94de334efb40e1a09e31112262dec77532bbungeman        SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
76296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == font || !FontAccessible(font) || !FontFamilyNameMatches(font, matchPattern)) {
76396fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
7646bc2c94de334efb40e1a09e31112262dec77532bbungeman        }
7656bc2c94de334efb40e1a09e31112262dec77532bbungeman
7666bc2c94de334efb40e1a09e31112262dec77532bbungeman        return createTypefaceFromFcPattern(font);
7676bc2c94de334efb40e1a09e31112262dec77532bbungeman    }
7686bc2c94de334efb40e1a09e31112262dec77532bbungeman
7696bc2c94de334efb40e1a09e31112262dec77532bbungeman    virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
7706bc2c94de334efb40e1a09e31112262dec77532bbungeman                                                    const SkFontStyle& style,
771c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman                                                    const char* bcp47[],
772c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman                                                    int bcp47Count,
77336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                                                    SkUnichar character) const override
7746bc2c94de334efb40e1a09e31112262dec77532bbungeman    {
7756bc2c94de334efb40e1a09e31112262dec77532bbungeman        FCLocker lock;
7766bc2c94de334efb40e1a09e31112262dec77532bbungeman
7776bc2c94de334efb40e1a09e31112262dec77532bbungeman        SkAutoFcPattern pattern;
7786837b38a62a1621ff43c7e1085b1a3bd208fcd49bungeman        if (familyName) {
7796837b38a62a1621ff43c7e1085b1a3bd208fcd49bungeman            FcValue familyNameValue;
7806837b38a62a1621ff43c7e1085b1a3bd208fcd49bungeman            familyNameValue.type = FcTypeString;
7816837b38a62a1621ff43c7e1085b1a3bd208fcd49bungeman            familyNameValue.u.s = reinterpret_cast<const FcChar8*>(familyName);
7826837b38a62a1621ff43c7e1085b1a3bd208fcd49bungeman            FcPatternAddWeak(pattern, FC_FAMILY, familyNameValue, FcFalse);
7836837b38a62a1621ff43c7e1085b1a3bd208fcd49bungeman        }
7846bc2c94de334efb40e1a09e31112262dec77532bbungeman        fcpattern_from_skfontstyle(style, pattern);
7856bc2c94de334efb40e1a09e31112262dec77532bbungeman
7866bc2c94de334efb40e1a09e31112262dec77532bbungeman        SkAutoFcCharSet charSet;
7876bc2c94de334efb40e1a09e31112262dec77532bbungeman        FcCharSetAddChar(charSet, character);
7886bc2c94de334efb40e1a09e31112262dec77532bbungeman        FcPatternAddCharSet(pattern, FC_CHARSET, charSet);
7896bc2c94de334efb40e1a09e31112262dec77532bbungeman
790c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman        if (bcp47Count > 0) {
791c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman            SkASSERT(bcp47);
7926bc2c94de334efb40e1a09e31112262dec77532bbungeman            SkAutoFcLangSet langSet;
793c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman            for (int i = bcp47Count; i --> 0;) {
794c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman                FcLangSetAdd(langSet, (const FcChar8*)bcp47[i]);
795c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman            }
7966bc2c94de334efb40e1a09e31112262dec77532bbungeman            FcPatternAddLangSet(pattern, FC_LANG, langSet);
7976bc2c94de334efb40e1a09e31112262dec77532bbungeman        }
7986bc2c94de334efb40e1a09e31112262dec77532bbungeman
7996bc2c94de334efb40e1a09e31112262dec77532bbungeman        FcConfigSubstitute(fFC, pattern, FcMatchPattern);
8006bc2c94de334efb40e1a09e31112262dec77532bbungeman        FcDefaultSubstitute(pattern);
8016bc2c94de334efb40e1a09e31112262dec77532bbungeman
8026bc2c94de334efb40e1a09e31112262dec77532bbungeman        FcResult result;
8036bc2c94de334efb40e1a09e31112262dec77532bbungeman        SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
80496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == font || !FontAccessible(font) || !FontContainsCharacter(font, character)) {
80596fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
806a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
807a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
8086bc2c94de334efb40e1a09e31112262dec77532bbungeman        return createTypefaceFromFcPattern(font);
809a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
810a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
811a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
81236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                                         const SkFontStyle& style) const override
813a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    {
814a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        //TODO: should the SkTypeface_fontconfig know its family?
815b14e4a0db5cb1b96cef5236585ee4572c5d95b97bungeman        const SkTypeface_fontconfig* fcTypeface =
8169db509272a6fa2badbbdd2f5afce827370960a5fbungeman                static_cast<const SkTypeface_fontconfig*>(typeface);
817b14e4a0db5cb1b96cef5236585ee4572c5d95b97bungeman        return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY), style);
818a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
819a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
82036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
8215f213d9627d2eefa7da81cd97f36754f75eb4ae9bungeman        SkAutoTDelete<SkStreamAsset> stream(bareStream);
822a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        const size_t length = stream->getLength();
823a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        if (length <= 0 || (1u << 30) < length) {
82496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
825a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
826a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
827a4c4a2d8cd65abb1e5ac20813831cdb9ace6c7eebungeman        SkFontStyle style;
828a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        bool isFixedWidth = false;
82996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (!fScanner.scanFont(stream, ttcIndex, nullptr, &style, &isFixedWidth, nullptr)) {
83096fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
831a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
832a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
83396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return new SkTypeface_stream(new SkFontData(stream.detach(), ttcIndex, nullptr, 0), style,
834385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                     isFixedWidth);
835a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
836a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
837f6c7107d0385cc2b556802354b93b7dcff61570dbungeman    SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override {
838f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        using Scanner = SkTypeface_FreeType::Scanner;
839f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        SkAutoTDelete<SkStreamAsset> stream(s);
840f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        bool isFixedPitch;
841f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        SkFontStyle style;
842f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        SkString name;
843f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        Scanner::AxisDefinitions axisDefinitions;
844f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        if (!fScanner.scanFont(stream, params.getCollectionIndex(), &name, &style, &isFixedPitch,
845f6c7107d0385cc2b556802354b93b7dcff61570dbungeman                               &axisDefinitions))
846f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        {
847f6c7107d0385cc2b556802354b93b7dcff61570dbungeman            return nullptr;
848f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        }
849f6c7107d0385cc2b556802354b93b7dcff61570dbungeman
850f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        int paramAxisCount;
851f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        const FontParameters::Axis* paramAxes = params.getAxes(&paramAxisCount);
852f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
853f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
854f6c7107d0385cc2b556802354b93b7dcff61570dbungeman
855f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        SkFontData* data(new SkFontData(stream.detach(), params.getCollectionIndex(),
856f6c7107d0385cc2b556802354b93b7dcff61570dbungeman                                        axisValues.get(), axisDefinitions.count()));
857f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        return new SkTypeface_stream(data, style, isFixedPitch);
858f6c7107d0385cc2b556802354b93b7dcff61570dbungeman    }
859f6c7107d0385cc2b556802354b93b7dcff61570dbungeman
86036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
861385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return this->createFromStream(new SkMemoryStream(data), ttcIndex);
862a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
863a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
86436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
865a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo        return this->createFromStream(SkStream::NewFromFile(path), ttcIndex);
866a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
867a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
86841868fe5625fc3bd70daa3f461c881b5db6a9265bungeman    SkTypeface* onCreateFromFontData(SkFontData* fontData) const override {
86941868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        SkStreamAsset* stream(fontData->getStream());
87041868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        const size_t length = stream->getLength();
87141868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        if (length <= 0 || (1u << 30) < length) {
87296fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
87341868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        }
87441868fe5625fc3bd70daa3f461c881b5db6a9265bungeman
87541868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        const int ttcIndex = fontData->getIndex();
87641868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        SkFontStyle style;
87741868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        bool isFixedWidth = false;
87896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (!fScanner.scanFont(stream, ttcIndex, nullptr, &style, &isFixedWidth, nullptr)) {
87996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
88041868fe5625fc3bd70daa3f461c881b5db6a9265bungeman        }
88141868fe5625fc3bd70daa3f461c881b5db6a9265bungeman
882385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return new SkTypeface_stream(fontData, style, isFixedWidth);
88341868fe5625fc3bd70daa3f461c881b5db6a9265bungeman    }
88441868fe5625fc3bd70daa3f461c881b5db6a9265bungeman
885a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
88636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                                               unsigned styleBits) const override {
887a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        bool bold = styleBits & SkTypeface::kBold;
888a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        bool italic = styleBits & SkTypeface::kItalic;
889a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
890a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                             : SkFontStyle::kNormal_Weight,
891a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                        SkFontStyle::kNormal_Width,
892a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                        italic ? SkFontStyle::kItalic_Slant
893a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman                                               : SkFontStyle::kUpright_Slant);
894a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        SkAutoTUnref<SkTypeface> typeface(this->matchFamilyStyle(familyName, style));
89549f085dddff10473b6ebf832a974288300224e60bsalomon        if (typeface.get()) {
896a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman            return typeface.detach();
897a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman        }
898a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
89996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return this->matchFamilyStyle(nullptr, style);
900a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman    }
901a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman};
902a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman
9030b1de2626a289ab21bd3b93277ed34d022824b3dbungemanSK_API SkFontMgr* SkFontMgr_New_FontConfig(FcConfig* fc) {
9040b1de2626a289ab21bd3b93277ed34d022824b3dbungeman    return new SkFontMgr_fontconfig(fc);
905a6785ccb540b1b752ab536cdf579a698eadbf7d2bungeman}
906