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