2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkDataTable.h"
9 #include "SkFontDescriptor.h"
10 #include "SkFontHost_FreeType_common.h"
11 #include "SkFontMgr.h"
12 #include "SkFontStyle.h"
16 #include "SkTDArray.h"
18 #include "SkTypefaceCache.h"
21 #include <fontconfig/fontconfig.h>
23 // FC_POSTSCRIPT_NAME was added with b561ff20 which ended up in 2.10.92
24 // Ubuntu 12.04 is on 2.8.0, 13.10 is on 2.10.93
25 // Debian 7 is on 2.9.0, 8 is on 2.11
26 // OpenSUSE 12.2 is on 2.9.0, 12.3 is on 2.10.2, 13.1 2.11.0
27 // Fedora 19 is on 2.10.93
28 #ifndef FC_POSTSCRIPT_NAME
29 # define FC_POSTSCRIPT_NAME "postscriptname"
36 /** Since FontConfig is poorly documented, this gives a high level overview:
38 * FcConfig is a handle to a FontConfig configuration instance. Each 'configuration' is independent
39 * from any others which may exist. There exists a default global configuration which is created
40 * and destroyed by FcInit and FcFini, but this default should not normally be used.
41 * Instead, one should use FcConfigCreate and FcInit* to have a named local state.
43 * FcPatterns are {objectName -> [element]} (maps from object names to a list of elements).
44 * Each element is some internal data plus an FcValue which is a variant (a union with a type tag).
45 * Lists of elements are not typed, except by convention. Any collection of FcValues must be
46 * assumed to be heterogeneous by the code, but the code need not do anything particularly
47 * interesting if the values go against convention.
49 * Somewhat like DirectWrite, FontConfig supports synthetics through FC_EMBOLDEN and FC_MATRIX.
50 * Like all synthetic information, such information must be passed with the font data.
55 // Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a global mutex.
56 // See http://skbug.com/1497 for background.
57 SK_DECLARE_STATIC_MUTEX(gFCMutex);
60 void *CreateThreadFcLocked() { return SkNEW_ARGS(bool, (false)); }
61 void DeleteThreadFcLocked(void* v) { SkDELETE(static_cast<bool*>(v)); }
62 # define THREAD_FC_LOCKED \
63 static_cast<bool*>(SkTLS::Get(CreateThreadFcLocked, DeleteThreadFcLocked))
67 // Assume FcGetVersion() has always been thread safe.
70 if (FcGetVersion() < 21091) {
73 SkDEBUGCODE(bool* threadLocked = THREAD_FC_LOCKED);
74 SkASSERT(false == *threadLocked);
75 SkDEBUGCODE(*threadLocked = true);
81 if (FcGetVersion() < 21091) {
84 SkDEBUGCODE(*THREAD_FC_LOCKED = false);
88 static void AssertHeld() { SkDEBUGCODE(
89 if (FcGetVersion() < 21091) {
90 gFCMutex.assertHeld();
92 SkASSERT(true == *THREAD_FC_LOCKED);
99 template<typename T, void (*D)(T*)> void FcTDestroy(T* t) {
100 FCLocker::AssertHeld();
103 template <typename T, T* (*C)(), void (*D)(T*)> class SkAutoFc
104 : public SkAutoTCallVProc<T, FcTDestroy<T, D> > {
106 SkAutoFc() : SkAutoTCallVProc<T, FcTDestroy<T, D> >(C()) {
107 T* obj = this->operator T*();
108 SK_ALWAYSBREAK(NULL != obj);
110 explicit SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, D> >(obj) {}
113 typedef SkAutoFc<FcCharSet, FcCharSetCreate, FcCharSetDestroy> SkAutoFcCharSet;
114 typedef SkAutoFc<FcConfig, FcConfigCreate, FcConfigDestroy> SkAutoFcConfig;
115 typedef SkAutoFc<FcFontSet, FcFontSetCreate, FcFontSetDestroy> SkAutoFcFontSet;
116 typedef SkAutoFc<FcLangSet, FcLangSetCreate, FcLangSetDestroy> SkAutoFcLangSet;
117 typedef SkAutoFc<FcObjectSet, FcObjectSetCreate, FcObjectSetDestroy> SkAutoFcObjectSet;
118 typedef SkAutoFc<FcPattern, FcPatternCreate, FcPatternDestroy> SkAutoFcPattern;
120 static int get_int(FcPattern* pattern, const char object[], int missing) {
122 if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) {
128 static const char* get_string(FcPattern* pattern, const char object[], const char* missing = "") {
130 if (FcPatternGetString(pattern, object, 0, &value) != FcResultMatch) {
133 return (const char*)value;
138 kIsStrong_WeakReturn,
141 /** Ideally there would exist a call like
142 * FcResult FcPatternIsWeak(pattern, object, id, FcBool* isWeak);
144 * However, there is no such call and as of Fc 2.11.0 even FcPatternEquals ignores the weak bit.
145 * Currently, the only reliable way of finding the weak bit is by its effect on matching.
146 * The weak bit only affects the matching of FC_FAMILY and FC_POSTSCRIPT_NAME object values.
147 * A element with the weak bit is scored after FC_LANG, without the weak bit is scored before.
148 * Note that the weak bit is stored on the element, not on the value it holds.
150 static SkWeakReturn is_weak(FcPattern* pattern, const char object[], int id) {
151 FCLocker::AssertHeld();
155 // Create a copy of the pattern with only the value 'pattern'['object'['id']] in it.
156 // Internally, FontConfig pattern objects are linked lists, so faster to remove from head.
157 SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, NULL));
158 SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
160 for (int i = 0; hasId && i < id; ++i) {
161 hasId = FcPatternRemove(minimal, object, 0);
164 return kNoId_WeakReturn;
167 result = FcPatternGet(minimal, object, 0, &value);
168 if (result != FcResultMatch) {
169 return kNoId_WeakReturn;
172 hasId = FcPatternRemove(minimal, object, 1);
175 // Create a font set with two patterns.
176 // 1. the same 'object' as minimal and a lang object with only 'nomatchlang'.
177 // 2. a different 'object' from minimal and a lang object with only 'matchlang'.
178 SkAutoFcFontSet fontSet;
180 SkAutoFcLangSet strongLangSet;
181 FcLangSetAdd(strongLangSet, (const FcChar8*)"nomatchlang");
182 SkAutoFcPattern strong(FcPatternDuplicate(minimal));
183 FcPatternAddLangSet(strong, FC_LANG, strongLangSet);
185 SkAutoFcLangSet weakLangSet;
186 FcLangSetAdd(weakLangSet, (const FcChar8*)"matchlang");
187 SkAutoFcPattern weak;
188 FcPatternAddString(weak, object, (const FcChar8*)"nomatchstring");
189 FcPatternAddLangSet(weak, FC_LANG, weakLangSet);
191 FcFontSetAdd(fontSet, strong.detach());
192 FcFontSetAdd(fontSet, weak.detach());
194 // Add 'matchlang' to the copy of the pattern.
195 FcPatternAddLangSet(minimal, FC_LANG, weakLangSet);
197 // Run a match against the copy of the pattern.
198 // If the 'id' was weak, then we should match the pattern with 'matchlang'.
199 // If the 'id' was strong, then we should match the pattern with 'nomatchlang'.
201 // Note that this config is only used for FcFontRenderPrepare, which we don't even want.
202 // However, there appears to be no way to match/sort without it.
203 SkAutoFcConfig config;
204 FcFontSet* fontSets[1] = { fontSet };
205 SkAutoFcPattern match(FcFontSetMatch(config, fontSets, SK_ARRAY_COUNT(fontSets),
208 FcLangSet* matchLangSet;
209 FcPatternGetLangSet(match, FC_LANG, 0, &matchLangSet);
210 return FcLangEqual == FcLangSetHasLang(matchLangSet, (const FcChar8*)"matchlang")
211 ? kIsWeak_WeakReturn : kIsStrong_WeakReturn;
214 /** Removes weak elements from either FC_FAMILY or FC_POSTSCRIPT_NAME objects in the property.
215 * This can be quite expensive, and should not be used more than once per font lookup.
216 * This removes all of the weak elements after the last strong element.
218 static void remove_weak(FcPattern* pattern, const char object[]) {
219 FCLocker::AssertHeld();
221 SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, NULL));
222 SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
224 int lastStrongId = -1;
227 for (int id = 0; ; ++id) {
228 result = is_weak(minimal, object, 0);
229 if (kNoId_WeakReturn == result) {
233 if (kIsStrong_WeakReturn == result) {
236 SkAssertResult(FcPatternRemove(minimal, object, 0));
239 // If they were all weak, then leave the pattern alone.
240 if (lastStrongId < 0) {
244 // Remove everything after the last strong.
245 for (int id = lastStrongId + 1; id < numIds; ++id) {
246 SkAssertResult(FcPatternRemove(pattern, object, lastStrongId + 1));
250 static int map_range(SkFixed value,
251 SkFixed old_min, SkFixed old_max,
252 SkFixed new_min, SkFixed new_max)
254 SkASSERT(old_min < old_max);
255 SkASSERT(new_min <= new_max);
256 return new_min + SkMulDiv(value - old_min, new_max - new_min, old_max - old_min);
259 static int ave(SkFixed a, SkFixed b) {
260 return SkFixedAve(a, b);
268 static SkFixed map_ranges_fixed(SkFixed val, MapRanges const ranges[], int rangesCount) {
270 if (val < ranges[0].old_val) {
271 return ranges[0].new_val;
274 // Linear from [i] to ave([i], [i+1]), then from ave([i], [i+1]) to [i+1]
275 for (int i = 0; i < rangesCount - 1; ++i) {
276 if (val < ave(ranges[i].old_val, ranges[i+1].old_val)) {
277 return map_range(val, ranges[i].old_val, ave(ranges[i].old_val, ranges[i+1].old_val),
278 ranges[i].new_val, ave(ranges[i].new_val, ranges[i+1].new_val));
280 if (val < ranges[i+1].old_val) {
281 return map_range(val, ave(ranges[i].old_val, ranges[i+1].old_val), ranges[i+1].old_val,
282 ave(ranges[i].new_val, ranges[i+1].new_val), ranges[i+1].new_val);
287 // if (fcweight < Inf)
288 return ranges[rangesCount-1].new_val;
291 static int map_ranges(int val, MapRanges const ranges[], int rangesCount) {
292 return SkFixedRoundToInt(map_ranges_fixed(SkIntToFixed(val), ranges, rangesCount));
295 template<int n> struct SkTFixed {
296 SK_COMPILE_ASSERT(-32768 <= n && n <= 32767, SkTFixed_n_not_in_range);
297 static const SkFixed value = static_cast<SkFixed>(n << 16);
300 static SkFontStyle skfontstyle_from_fcpattern(FcPattern* pattern) {
301 typedef SkFontStyle SkFS;
303 static const MapRanges weightRanges[] = {
304 { SkTFixed<FC_WEIGHT_THIN>::value, SkTFixed<SkFS::kThin_Weight>::value },
305 { SkTFixed<FC_WEIGHT_EXTRALIGHT>::value, SkTFixed<SkFS::kExtraLight_Weight>::value },
306 { SkTFixed<FC_WEIGHT_LIGHT>::value, SkTFixed<SkFS::kLight_Weight>::value },
307 { SkTFixed<FC_WEIGHT_REGULAR>::value, SkTFixed<SkFS::kNormal_Weight>::value },
308 { SkTFixed<FC_WEIGHT_MEDIUM>::value, SkTFixed<SkFS::kMedium_Weight>::value },
309 { SkTFixed<FC_WEIGHT_DEMIBOLD>::value, SkTFixed<SkFS::kSemiBold_Weight>::value },
310 { SkTFixed<FC_WEIGHT_BOLD>::value, SkTFixed<SkFS::kBold_Weight>::value },
311 { SkTFixed<FC_WEIGHT_EXTRABOLD>::value, SkTFixed<SkFS::kExtraBold_Weight>::value },
312 { SkTFixed<FC_WEIGHT_BLACK>::value, SkTFixed<SkFS::kBlack_Weight>::value },
313 { SkTFixed<FC_WEIGHT_EXTRABLACK>::value, SkTFixed<1000>::value },
315 int weight = map_ranges(get_int(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR),
316 weightRanges, SK_ARRAY_COUNT(weightRanges));
318 static const MapRanges widthRanges[] = {
319 { SkTFixed<FC_WIDTH_ULTRACONDENSED>::value, SkTFixed<SkFS::kUltraCondensed_Width>::value },
320 { SkTFixed<FC_WIDTH_EXTRACONDENSED>::value, SkTFixed<SkFS::kExtraCondensed_Width>::value },
321 { SkTFixed<FC_WIDTH_CONDENSED>::value, SkTFixed<SkFS::kCondensed_Width>::value },
322 { SkTFixed<FC_WIDTH_SEMICONDENSED>::value, SkTFixed<SkFS::kSemiCondensed_Width>::value },
323 { SkTFixed<FC_WIDTH_NORMAL>::value, SkTFixed<SkFS::kNormal_Width>::value },
324 { SkTFixed<FC_WIDTH_SEMIEXPANDED>::value, SkTFixed<SkFS::kSemiExpanded_Width>::value },
325 { SkTFixed<FC_WIDTH_EXPANDED>::value, SkTFixed<SkFS::kExpanded_Width>::value },
326 { SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value, SkTFixed<SkFS::kExtraExpanded_Width>::value },
327 { SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value, SkTFixed<SkFS::kUltaExpanded_Width>::value },
329 int width = map_ranges(get_int(pattern, FC_WIDTH, FC_WIDTH_NORMAL),
330 widthRanges, SK_ARRAY_COUNT(widthRanges));
332 SkFS::Slant slant = get_int(pattern, FC_SLANT, FC_SLANT_ROMAN) > 0
333 ? SkFS::kItalic_Slant
334 : SkFS::kUpright_Slant;
336 return SkFontStyle(weight, width, slant);
339 static void fcpattern_from_skfontstyle(SkFontStyle style, FcPattern* pattern) {
340 FCLocker::AssertHeld();
342 typedef SkFontStyle SkFS;
344 static const MapRanges weightRanges[] = {
345 { SkTFixed<SkFS::kThin_Weight>::value, SkTFixed<FC_WEIGHT_THIN>::value },
346 { SkTFixed<SkFS::kExtraLight_Weight>::value, SkTFixed<FC_WEIGHT_EXTRALIGHT>::value },
347 { SkTFixed<SkFS::kLight_Weight>::value, SkTFixed<FC_WEIGHT_LIGHT>::value },
348 { SkTFixed<SkFS::kNormal_Weight>::value, SkTFixed<FC_WEIGHT_REGULAR>::value },
349 { SkTFixed<SkFS::kMedium_Weight>::value, SkTFixed<FC_WEIGHT_MEDIUM>::value },
350 { SkTFixed<SkFS::kSemiBold_Weight>::value, SkTFixed<FC_WEIGHT_DEMIBOLD>::value },
351 { SkTFixed<SkFS::kBold_Weight>::value, SkTFixed<FC_WEIGHT_BOLD>::value },
352 { SkTFixed<SkFS::kExtraBold_Weight>::value, SkTFixed<FC_WEIGHT_EXTRABOLD>::value },
353 { SkTFixed<SkFS::kBlack_Weight>::value, SkTFixed<FC_WEIGHT_BLACK>::value },
354 { SkTFixed<1000>::value, SkTFixed<FC_WEIGHT_EXTRABLACK>::value },
356 int weight = map_ranges(style.weight(), weightRanges, SK_ARRAY_COUNT(weightRanges));
358 static const MapRanges widthRanges[] = {
359 { SkTFixed<SkFS::kUltraCondensed_Width>::value, SkTFixed<FC_WIDTH_ULTRACONDENSED>::value },
360 { SkTFixed<SkFS::kExtraCondensed_Width>::value, SkTFixed<FC_WIDTH_EXTRACONDENSED>::value },
361 { SkTFixed<SkFS::kCondensed_Width>::value, SkTFixed<FC_WIDTH_CONDENSED>::value },
362 { SkTFixed<SkFS::kSemiCondensed_Width>::value, SkTFixed<FC_WIDTH_SEMICONDENSED>::value },
363 { SkTFixed<SkFS::kNormal_Width>::value, SkTFixed<FC_WIDTH_NORMAL>::value },
364 { SkTFixed<SkFS::kSemiExpanded_Width>::value, SkTFixed<FC_WIDTH_SEMIEXPANDED>::value },
365 { SkTFixed<SkFS::kExpanded_Width>::value, SkTFixed<FC_WIDTH_EXPANDED>::value },
366 { SkTFixed<SkFS::kExtraExpanded_Width>::value, SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value },
367 { SkTFixed<SkFS::kUltaExpanded_Width>::value, SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value },
369 int width = map_ranges(style.width(), widthRanges, SK_ARRAY_COUNT(widthRanges));
371 FcPatternAddInteger(pattern, FC_WEIGHT, weight);
372 FcPatternAddInteger(pattern, FC_WIDTH, width);
373 FcPatternAddInteger(pattern, FC_SLANT, style.isItalic() ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
376 static SkTypeface::Style sktypefacestyle_from_fcpattern(FcPattern* pattern) {
377 int fcweight = get_int(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR);
378 int fcslant = get_int(pattern, FC_SLANT, FC_SLANT_ROMAN);
379 return (SkTypeface::Style)((fcweight >= FC_WEIGHT_BOLD ? SkTypeface::kBold : 0) |
380 (fcslant > FC_SLANT_ROMAN ? SkTypeface::kItalic : 0));
383 class SkTypeface_stream : public SkTypeface_FreeType {
385 /** @param stream does not take ownership of the reference, does take ownership of the stream.*/
386 SkTypeface_stream(SkTypeface::Style style, bool fixedWidth, int ttcIndex, SkStreamAsset* stream)
387 : INHERITED(style, SkTypefaceCache::NewFontID(), fixedWidth)
388 , fStream(SkRef(stream))
392 virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
396 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const SK_OVERRIDE {
397 desc->setFontIndex(fIndex);
401 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
403 return fStream->duplicate();
407 SkAutoTUnref<SkStreamAsset> fStream;
410 typedef SkTypeface_FreeType INHERITED;
413 class SkTypeface_fontconfig : public SkTypeface_FreeType {
415 /** @param pattern takes ownership of the reference. */
416 static SkTypeface_fontconfig* Create(FcPattern* pattern) {
417 return SkNEW_ARGS(SkTypeface_fontconfig, (pattern));
419 mutable SkAutoFcPattern fPattern;
421 virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
422 *familyName = get_string(fPattern, FC_FAMILY);
425 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const SK_OVERRIDE {
427 desc->setFamilyName(get_string(fPattern, FC_FAMILY));
428 desc->setFullName(get_string(fPattern, FC_FULLNAME));
429 desc->setPostscriptName(get_string(fPattern, FC_POSTSCRIPT_NAME));
430 desc->setFontFileName(get_string(fPattern, FC_FILE));
431 desc->setFontIndex(get_int(fPattern, FC_INDEX, 0));
435 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
437 *ttcIndex = get_int(fPattern, FC_INDEX, 0);
438 return SkStream::NewFromFile(get_string(fPattern, FC_FILE));
441 virtual ~SkTypeface_fontconfig() {
442 // Hold the lock while unrefing the pattern.
448 /** @param pattern takes ownership of the reference. */
449 SkTypeface_fontconfig(FcPattern* pattern)
450 : INHERITED(sktypefacestyle_from_fcpattern(pattern),
451 SkTypefaceCache::NewFontID(),
452 FC_PROPORTIONAL != get_int(pattern, FC_SPACING, FC_PROPORTIONAL))
456 typedef SkTypeface_FreeType INHERITED;
459 class SkFontMgr_fontconfig : public SkFontMgr {
460 mutable SkAutoFcConfig fFC;
461 SkAutoTUnref<SkDataTable> fFamilyNames;
463 class StyleSet : public SkFontStyleSet {
465 /** @param parent does not take ownership of the reference.
466 * @param fontSet takes ownership of the reference.
468 StyleSet(const SkFontMgr_fontconfig* parent, FcFontSet* fontSet)
469 : fFontMgr(SkRef(parent)), fFontSet(fontSet)
472 virtual ~StyleSet() {
473 // Hold the lock while unrefing the font set.
478 virtual int count() SK_OVERRIDE { return fFontSet->nfont; }
480 virtual void getStyle(int index, SkFontStyle* style, SkString* styleName) SK_OVERRIDE {
481 if (index < 0 || fFontSet->nfont <= index) {
487 *style = skfontstyle_from_fcpattern(fFontSet->fonts[index]);
490 *styleName = get_string(fFontSet->fonts[index], FC_STYLE);
494 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
497 FcPattern* match = fFontSet->fonts[index];
498 return fFontMgr->createTypefaceFromFcPattern(match);
501 virtual SkTypeface* matchStyle(const SkFontStyle& style) SK_OVERRIDE {
504 SkAutoFcPattern pattern;
505 fcpattern_from_skfontstyle(style, pattern);
506 FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern);
507 FcDefaultSubstitute(pattern);
510 FcFontSet* fontSets[1] = { fFontSet };
511 SkAutoFcPattern match(FcFontSetMatch(fFontMgr->fFC,
512 fontSets, SK_ARRAY_COUNT(fontSets),
518 return fFontMgr->createTypefaceFromFcPattern(match);
522 SkAutoTUnref<const SkFontMgr_fontconfig> fFontMgr;
523 SkAutoFcFontSet fFontSet;
526 static bool FindName(const SkTDArray<const char*>& list, const char* str) {
527 int count = list.count();
528 for (int i = 0; i < count; ++i) {
529 if (!strcmp(list[i], str)) {
536 static SkDataTable* GetFamilyNames(FcConfig* fcconfig) {
539 SkTDArray<const char*> names;
540 SkTDArray<size_t> sizes;
542 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
543 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
544 // Return value of FcConfigGetFonts must not be destroyed.
545 FcFontSet* allFonts(FcConfigGetFonts(fcconfig, fcNameSet[setIndex]));
546 if (NULL == allFonts) {
550 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
551 FcPattern* current = allFonts->fonts[fontIndex];
552 for (int id = 0; ; ++id) {
553 FcChar8* fcFamilyName;
554 FcResult result = FcPatternGetString(current, FC_FAMILY, id, &fcFamilyName);
555 if (FcResultNoId == result) {
558 if (FcResultMatch != result) {
561 const char* familyName = reinterpret_cast<const char*>(fcFamilyName);
562 if (familyName && !FindName(names, familyName)) {
563 *names.append() = familyName;
564 *sizes.append() = strlen(familyName) + 1;
570 return SkDataTable::NewCopyArrays((void const *const *)names.begin(),
571 sizes.begin(), names.count());
574 static bool FindByFcPattern(SkTypeface* cached, SkTypeface::Style, void* ctx) {
575 SkTypeface_fontconfig* cshFace = static_cast<SkTypeface_fontconfig*>(cached);
576 FcPattern* ctxPattern = static_cast<FcPattern*>(ctx);
577 return FcTrue == FcPatternEqual(cshFace->fPattern, ctxPattern);
580 mutable SkMutex fTFCacheMutex;
581 mutable SkTypefaceCache fTFCache;
582 /** Creates a typeface using a typeface cache.
583 * @param pattern a complete pattern from FcFontRenderPrepare.
585 SkTypeface* createTypefaceFromFcPattern(FcPattern* pattern) const {
586 FCLocker::AssertHeld();
587 SkAutoMutexAcquire ama(fTFCacheMutex);
588 SkTypeface* face = fTFCache.findByProcAndRef(FindByFcPattern, pattern);
590 FcPatternReference(pattern);
591 face = SkTypeface_fontconfig::Create(pattern);
593 fTFCache.add(face, SkTypeface::kNormal, true);
600 SkFontMgr_fontconfig()
601 : fFC(FcInitLoadConfigAndFonts())
602 , fFamilyNames(GetFamilyNames(fFC)) { }
604 /** Takes control of the reference to 'config'. */
605 explicit SkFontMgr_fontconfig(FcConfig* config)
607 , fFamilyNames(GetFamilyNames(fFC)) { }
609 virtual ~SkFontMgr_fontconfig() {
610 // Hold the lock while unrefing the config.
616 virtual int onCountFamilies() const SK_OVERRIDE {
617 return fFamilyNames->count();
620 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
621 familyName->set(fFamilyNames->atStr(index));
624 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
625 return this->onMatchFamily(fFamilyNames->atStr(index));
628 /** True if any string object value in the font is the same
629 * as a string object value in the pattern.
631 static bool AnyMatching(FcPattern* font, FcPattern* pattern, const char* object) {
633 FcChar8* patternString;
635 // Set an arbitrary limit on the number of pattern object values to consider.
636 // TODO: re-write this to avoid N*M
637 static const int maxId = 16;
638 for (int patternId = 0; patternId < maxId; ++patternId) {
639 result = FcPatternGetString(pattern, object, patternId, &patternString);
640 if (FcResultNoId == result) {
643 if (FcResultMatch != result) {
646 for (int fontId = 0; fontId < maxId; ++fontId) {
647 result = FcPatternGetString(font, object, fontId, &fontString);
648 if (FcResultNoId == result) {
651 if (FcResultMatch != result) {
654 if (0 == FcStrCmpIgnoreCase(patternString, fontString)) {
662 static bool FontAccessible(FcPattern* font) {
663 // FontConfig can return fonts which are unreadable.
664 const char* filename = get_string(font, FC_FILE, NULL);
665 if (NULL == filename) {
668 return sk_exists(filename, kRead_SkFILE_Flag);
671 static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) {
672 return AnyMatching(font, pattern, FC_FAMILY);
675 static bool FontContainsCharacter(FcPattern* font, uint32_t character) {
677 FcCharSet* matchCharSet;
678 for (int charSetId = 0; ; ++charSetId) {
679 result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchCharSet);
680 if (FcResultNoId == result) {
683 if (FcResultMatch != result) {
686 if (FcCharSetHasChar(matchCharSet, character)) {
693 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
696 SkAutoFcPattern pattern;
697 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
698 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
699 FcDefaultSubstitute(pattern);
701 FcPattern* matchPattern;
702 SkAutoFcPattern strongPattern(NULL);
704 strongPattern.reset(FcPatternDuplicate(pattern));
705 remove_weak(strongPattern, FC_FAMILY);
706 matchPattern = strongPattern;
708 matchPattern = pattern;
711 SkAutoFcFontSet matches;
712 // TODO: Some families have 'duplicates' due to symbolic links.
713 // The patterns are exactly the same except for the FC_FILE.
714 // It should be possible to collapse these patterns by normalizing.
715 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
716 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
717 // Return value of FcConfigGetFonts must not be destroyed.
718 FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex]));
719 if (NULL == allFonts) {
723 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
724 FcPattern* font = allFonts->fonts[fontIndex];
725 if (FontAccessible(font) && FontFamilyNameMatches(font, matchPattern)) {
726 FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font));
731 return SkNEW_ARGS(StyleSet, (this, matches.detach()));
734 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
735 const SkFontStyle& style) const SK_OVERRIDE
739 SkAutoFcPattern pattern;
740 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
741 fcpattern_from_skfontstyle(style, pattern);
742 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
743 FcDefaultSubstitute(pattern);
745 // We really want to match strong (prefered) and same (acceptable) only here.
746 // If a family name was specified, assume that any weak matches after the last strong match
747 // are weak (default) and ignore them.
748 // The reason for is that after substitution the pattern for 'sans-serif' looks like
749 // "wwwwwwwwwwwwwwswww" where there are many weak but preferred names, followed by defaults.
750 // So it is possible to have weakly matching but preferred names.
751 // In aliases, bindings are weak by default, so this is easy and common.
752 // If no family name was specified, we'll probably only get weak matches, but that's ok.
753 FcPattern* matchPattern;
754 SkAutoFcPattern strongPattern(NULL);
756 strongPattern.reset(FcPatternDuplicate(pattern));
757 remove_weak(strongPattern, FC_FAMILY);
758 matchPattern = strongPattern;
760 matchPattern = pattern;
764 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
765 if (NULL == font || !FontAccessible(font) || !FontFamilyNameMatches(font, matchPattern)) {
769 return createTypefaceFromFcPattern(font);
772 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
773 const SkFontStyle& style,
775 uint32_t character) const SK_OVERRIDE
779 SkAutoFcPattern pattern;
780 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
781 fcpattern_from_skfontstyle(style, pattern);
783 SkAutoFcCharSet charSet;
784 FcCharSetAddChar(charSet, character);
785 FcPatternAddCharSet(pattern, FC_CHARSET, charSet);
788 SkAutoFcLangSet langSet;
789 FcLangSetAdd(langSet, (const FcChar8*)bpc47);
790 FcPatternAddLangSet(pattern, FC_LANG, langSet);
793 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
794 FcDefaultSubstitute(pattern);
797 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
798 if (NULL == font || !FontAccessible(font) || !FontContainsCharacter(font, character)) {
802 return createTypefaceFromFcPattern(font);
805 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
806 const SkFontStyle& style) const SK_OVERRIDE
808 //TODO: should the SkTypeface_fontconfig know its family?
809 const SkTypeface_fontconfig* fcTypeface =
810 static_cast<const SkTypeface_fontconfig*>(typeface);
811 return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY), style);
814 /** @param stream does not take ownership of the reference. */
815 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
816 const size_t length = stream->getLength();
817 if (length <= 0 || (1u << 30) < length) {
821 SkTypeface::Style style = SkTypeface::kNormal;
822 bool isFixedWidth = false;
823 if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, NULL, &style, &isFixedWidth)) {
827 return SkNEW_ARGS(SkTypeface_stream, (style, isFixedWidth, ttcIndex,
828 static_cast<SkStreamAsset*>(stream)));
831 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
832 SkAutoTUnref<SkStreamAsset> stream(SkNEW_ARGS(SkMemoryStream, (data)));
833 return this->createFromStream(stream, ttcIndex);
836 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
837 SkAutoTUnref<SkStreamAsset> stream(SkStream::NewFromFile(path));
838 return this->createFromStream(stream, ttcIndex);
841 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
842 unsigned styleBits) const SK_OVERRIDE {
843 bool bold = styleBits & SkTypeface::kBold;
844 bool italic = styleBits & SkTypeface::kItalic;
845 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
846 : SkFontStyle::kNormal_Weight,
847 SkFontStyle::kNormal_Width,
848 italic ? SkFontStyle::kItalic_Slant
849 : SkFontStyle::kUpright_Slant);
850 SkAutoTUnref<SkTypeface> typeface(this->matchFamilyStyle(familyName, style));
851 if (typeface.get()) {
852 return typeface.detach();
855 return this->matchFamilyStyle(NULL, style);
859 SkFontMgr* SkFontMgr::Factory() {
860 return SkNEW(SkFontMgr_fontconfig);