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