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