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