SkFontMgr_fontconfig.cpp revision 97043299cb352f50f604878b7a1dc8ad127fc1c6
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, 410 SkString familyName, const SkFontStyle& style, bool fixedWidth) 411 : INHERITED(style, fixedWidth) 412 , fFamilyName(std::move(familyName)) 413 , fData(std::move(data)) 414 { } 415 416 void onGetFamilyName(SkString* familyName) const override { 417 *familyName = fFamilyName; 418 } 419 420 void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override { 421 *serialize = true; 422 } 423 424 SkStreamAsset* onOpenStream(int* ttcIndex) const override { 425 *ttcIndex = fData->getIndex(); 426 return fData->getStream()->duplicate(); 427 } 428 429 std::unique_ptr<SkFontData> onMakeFontData() const override { 430 return skstd::make_unique<SkFontData>(*fData); 431 } 432 433private: 434 SkString fFamilyName; 435 const std::unique_ptr<const SkFontData> fData; 436 437 typedef SkTypeface_FreeType INHERITED; 438}; 439 440class SkTypeface_fontconfig : public SkTypeface_FreeType { 441public: 442 /** @param pattern takes ownership of the reference. */ 443 static SkTypeface_fontconfig* Create(FcPattern* pattern) { 444 return new SkTypeface_fontconfig(pattern); 445 } 446 mutable SkAutoFcPattern fPattern; 447 448 void onGetFamilyName(SkString* familyName) const override { 449 *familyName = get_string(fPattern, FC_FAMILY); 450 } 451 452 void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override { 453 FCLocker lock; 454 desc->setFamilyName(get_string(fPattern, FC_FAMILY)); 455 desc->setFullName(get_string(fPattern, FC_FULLNAME)); 456 desc->setPostscriptName(get_string(fPattern, FC_POSTSCRIPT_NAME)); 457 desc->setStyle(this->fontStyle()); 458 *serialize = false; 459 } 460 461 SkStreamAsset* onOpenStream(int* ttcIndex) const override { 462 FCLocker lock; 463 *ttcIndex = get_int(fPattern, FC_INDEX, 0); 464 return SkStream::MakeFromFile(get_string(fPattern, FC_FILE)).release(); 465 } 466 467 void onFilterRec(SkScalerContextRec* rec) const override { 468 const FcMatrix* fcMatrix = get_matrix(fPattern, FC_MATRIX); 469 if (fcMatrix) { 470 // fPost2x2 is column-major, left handed (y down). 471 // FcMatrix is column-major, right handed (y up). 472 SkMatrix fm; 473 fm.setAll(fcMatrix->xx,-fcMatrix->xy, 0, 474 -fcMatrix->yx, fcMatrix->yy, 0, 475 0 , 0 , 1); 476 477 SkMatrix sm; 478 rec->getMatrixFrom2x2(&sm); 479 480 sm.preConcat(fm); 481 rec->fPost2x2[0][0] = sm.getScaleX(); 482 rec->fPost2x2[0][1] = sm.getSkewX(); 483 rec->fPost2x2[1][0] = sm.getSkewY(); 484 rec->fPost2x2[1][1] = sm.getScaleY(); 485 } 486 if (get_bool(fPattern, FC_EMBOLDEN)) { 487 rec->fFlags |= SkScalerContext::kEmbolden_Flag; 488 } 489 this->INHERITED::onFilterRec(rec); 490 } 491 492 SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(PerGlyphInfo perGlyphInfo, 493 const uint32_t* glyphIDs, 494 uint32_t glyphIDsCount) const override 495 { 496 SkAdvancedTypefaceMetrics* info = 497 this->INHERITED::onGetAdvancedTypefaceMetrics(perGlyphInfo, glyphIDs, glyphIDsCount); 498 499 // Simulated fonts shouldn't be considered to be of the type of their data. 500 if (get_matrix(fPattern, FC_MATRIX) || get_bool(fPattern, FC_EMBOLDEN)) { 501 info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 502 } 503 return info; 504 } 505 506 virtual ~SkTypeface_fontconfig() { 507 // Hold the lock while unrefing the pattern. 508 FCLocker lock; 509 fPattern.reset(); 510 } 511 512private: 513 /** @param pattern takes ownership of the reference. */ 514 SkTypeface_fontconfig(FcPattern* pattern) 515 : INHERITED(skfontstyle_from_fcpattern(pattern), 516 FC_PROPORTIONAL != get_int(pattern, FC_SPACING, FC_PROPORTIONAL)) 517 , fPattern(pattern) 518 { } 519 520 typedef SkTypeface_FreeType INHERITED; 521}; 522 523class SkFontMgr_fontconfig : public SkFontMgr { 524 mutable SkAutoFcConfig fFC; 525 sk_sp<SkDataTable> fFamilyNames; 526 SkTypeface_FreeType::Scanner fScanner; 527 528 class StyleSet : public SkFontStyleSet { 529 public: 530 /** @param parent does not take ownership of the reference. 531 * @param fontSet takes ownership of the reference. 532 */ 533 StyleSet(const SkFontMgr_fontconfig* parent, FcFontSet* fontSet) 534 : fFontMgr(SkRef(parent)), fFontSet(fontSet) 535 { } 536 537 virtual ~StyleSet() { 538 // Hold the lock while unrefing the font set. 539 FCLocker lock; 540 fFontSet.reset(); 541 } 542 543 int count() override { return fFontSet->nfont; } 544 545 void getStyle(int index, SkFontStyle* style, SkString* styleName) override { 546 if (index < 0 || fFontSet->nfont <= index) { 547 return; 548 } 549 550 FCLocker lock; 551 if (style) { 552 *style = skfontstyle_from_fcpattern(fFontSet->fonts[index]); 553 } 554 if (styleName) { 555 *styleName = get_string(fFontSet->fonts[index], FC_STYLE); 556 } 557 } 558 559 SkTypeface* createTypeface(int index) override { 560 FCLocker lock; 561 562 FcPattern* match = fFontSet->fonts[index]; 563 return fFontMgr->createTypefaceFromFcPattern(match); 564 } 565 566 SkTypeface* matchStyle(const SkFontStyle& style) override { 567 FCLocker lock; 568 569 SkAutoFcPattern pattern; 570 fcpattern_from_skfontstyle(style, pattern); 571 FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern); 572 FcDefaultSubstitute(pattern); 573 574 FcResult result; 575 FcFontSet* fontSets[1] = { fFontSet }; 576 SkAutoFcPattern match(FcFontSetMatch(fFontMgr->fFC, 577 fontSets, SK_ARRAY_COUNT(fontSets), 578 pattern, &result)); 579 if (nullptr == match) { 580 return nullptr; 581 } 582 583 return fFontMgr->createTypefaceFromFcPattern(match); 584 } 585 586 private: 587 sk_sp<const SkFontMgr_fontconfig> fFontMgr; 588 SkAutoFcFontSet fFontSet; 589 }; 590 591 static bool FindName(const SkTDArray<const char*>& list, const char* str) { 592 int count = list.count(); 593 for (int i = 0; i < count; ++i) { 594 if (!strcmp(list[i], str)) { 595 return true; 596 } 597 } 598 return false; 599 } 600 601 static sk_sp<SkDataTable> GetFamilyNames(FcConfig* fcconfig) { 602 FCLocker lock; 603 604 SkTDArray<const char*> names; 605 SkTDArray<size_t> sizes; 606 607 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication }; 608 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) { 609 // Return value of FcConfigGetFonts must not be destroyed. 610 FcFontSet* allFonts(FcConfigGetFonts(fcconfig, fcNameSet[setIndex])); 611 if (nullptr == allFonts) { 612 continue; 613 } 614 615 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) { 616 FcPattern* current = allFonts->fonts[fontIndex]; 617 for (int id = 0; ; ++id) { 618 FcChar8* fcFamilyName; 619 FcResult result = FcPatternGetString(current, FC_FAMILY, id, &fcFamilyName); 620 if (FcResultNoId == result) { 621 break; 622 } 623 if (FcResultMatch != result) { 624 continue; 625 } 626 const char* familyName = reinterpret_cast<const char*>(fcFamilyName); 627 if (familyName && !FindName(names, familyName)) { 628 *names.append() = familyName; 629 *sizes.append() = strlen(familyName) + 1; 630 } 631 } 632 } 633 } 634 635 return SkDataTable::MakeCopyArrays((void const *const *)names.begin(), 636 sizes.begin(), names.count()); 637 } 638 639 static bool FindByFcPattern(SkTypeface* cached, void* ctx) { 640 SkTypeface_fontconfig* cshFace = static_cast<SkTypeface_fontconfig*>(cached); 641 FcPattern* ctxPattern = static_cast<FcPattern*>(ctx); 642 return FcTrue == FcPatternEqual(cshFace->fPattern, ctxPattern); 643 } 644 645 mutable SkMutex fTFCacheMutex; 646 mutable SkTypefaceCache fTFCache; 647 /** Creates a typeface using a typeface cache. 648 * @param pattern a complete pattern from FcFontRenderPrepare. 649 */ 650 SkTypeface* createTypefaceFromFcPattern(FcPattern* pattern) const { 651 FCLocker::AssertHeld(); 652 SkAutoMutexAcquire ama(fTFCacheMutex); 653 SkTypeface* face = fTFCache.findByProcAndRef(FindByFcPattern, pattern); 654 if (nullptr == face) { 655 FcPatternReference(pattern); 656 face = SkTypeface_fontconfig::Create(pattern); 657 if (face) { 658 fTFCache.add(face); 659 } 660 } 661 return face; 662 } 663 664public: 665 /** Takes control of the reference to 'config'. */ 666 explicit SkFontMgr_fontconfig(FcConfig* config) 667 : fFC(config ? config : FcInitLoadConfigAndFonts()) 668 , fFamilyNames(GetFamilyNames(fFC)) { } 669 670 virtual ~SkFontMgr_fontconfig() { 671 // Hold the lock while unrefing the config. 672 FCLocker lock; 673 fFC.reset(); 674 } 675 676protected: 677 int onCountFamilies() const override { 678 return fFamilyNames->count(); 679 } 680 681 void onGetFamilyName(int index, SkString* familyName) const override { 682 familyName->set(fFamilyNames->atStr(index)); 683 } 684 685 SkFontStyleSet* onCreateStyleSet(int index) const override { 686 return this->onMatchFamily(fFamilyNames->atStr(index)); 687 } 688 689 /** True if any string object value in the font is the same 690 * as a string object value in the pattern. 691 */ 692 static bool AnyMatching(FcPattern* font, FcPattern* pattern, const char* object) { 693 FcChar8* fontString; 694 FcChar8* patternString; 695 FcResult result; 696 // Set an arbitrary limit on the number of pattern object values to consider. 697 // TODO: re-write this to avoid N*M 698 static const int maxId = 16; 699 for (int patternId = 0; patternId < maxId; ++patternId) { 700 result = FcPatternGetString(pattern, object, patternId, &patternString); 701 if (FcResultNoId == result) { 702 break; 703 } 704 if (FcResultMatch != result) { 705 continue; 706 } 707 for (int fontId = 0; fontId < maxId; ++fontId) { 708 result = FcPatternGetString(font, object, fontId, &fontString); 709 if (FcResultNoId == result) { 710 break; 711 } 712 if (FcResultMatch != result) { 713 continue; 714 } 715 if (0 == FcStrCmpIgnoreCase(patternString, fontString)) { 716 return true; 717 } 718 } 719 } 720 return false; 721 } 722 723 static bool FontAccessible(FcPattern* font) { 724 // FontConfig can return fonts which are unreadable. 725 const char* filename = get_string(font, FC_FILE, nullptr); 726 if (nullptr == filename) { 727 return false; 728 } 729 return sk_exists(filename, kRead_SkFILE_Flag); 730 } 731 732 static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) { 733 return AnyMatching(font, pattern, FC_FAMILY); 734 } 735 736 static bool FontContainsCharacter(FcPattern* font, uint32_t character) { 737 FcResult result; 738 FcCharSet* matchCharSet; 739 for (int charSetId = 0; ; ++charSetId) { 740 result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchCharSet); 741 if (FcResultNoId == result) { 742 break; 743 } 744 if (FcResultMatch != result) { 745 continue; 746 } 747 if (FcCharSetHasChar(matchCharSet, character)) { 748 return true; 749 } 750 } 751 return false; 752 } 753 754 SkFontStyleSet* onMatchFamily(const char familyName[]) const override { 755 FCLocker lock; 756 757 SkAutoFcPattern pattern; 758 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); 759 FcConfigSubstitute(fFC, pattern, FcMatchPattern); 760 FcDefaultSubstitute(pattern); 761 762 FcPattern* matchPattern; 763 SkAutoFcPattern strongPattern(nullptr); 764 if (familyName) { 765 strongPattern.reset(FcPatternDuplicate(pattern)); 766 remove_weak(strongPattern, FC_FAMILY); 767 matchPattern = strongPattern; 768 } else { 769 matchPattern = pattern; 770 } 771 772 SkAutoFcFontSet matches; 773 // TODO: Some families have 'duplicates' due to symbolic links. 774 // The patterns are exactly the same except for the FC_FILE. 775 // It should be possible to collapse these patterns by normalizing. 776 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication }; 777 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) { 778 // Return value of FcConfigGetFonts must not be destroyed. 779 FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex])); 780 if (nullptr == allFonts) { 781 continue; 782 } 783 784 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) { 785 FcPattern* font = allFonts->fonts[fontIndex]; 786 if (FontAccessible(font) && FontFamilyNameMatches(font, matchPattern)) { 787 FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font)); 788 } 789 } 790 } 791 792 return new StyleSet(this, matches.release()); 793 } 794 795 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 796 const SkFontStyle& style) const override 797 { 798 FCLocker lock; 799 800 SkAutoFcPattern pattern; 801 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); 802 fcpattern_from_skfontstyle(style, pattern); 803 FcConfigSubstitute(fFC, pattern, FcMatchPattern); 804 FcDefaultSubstitute(pattern); 805 806 // We really want to match strong (prefered) and same (acceptable) only here. 807 // If a family name was specified, assume that any weak matches after the last strong match 808 // are weak (default) and ignore them. 809 // The reason for is that after substitution the pattern for 'sans-serif' looks like 810 // "wwwwwwwwwwwwwwswww" where there are many weak but preferred names, followed by defaults. 811 // So it is possible to have weakly matching but preferred names. 812 // In aliases, bindings are weak by default, so this is easy and common. 813 // If no family name was specified, we'll probably only get weak matches, but that's ok. 814 FcPattern* matchPattern; 815 SkAutoFcPattern strongPattern(nullptr); 816 if (familyName) { 817 strongPattern.reset(FcPatternDuplicate(pattern)); 818 remove_weak(strongPattern, FC_FAMILY); 819 matchPattern = strongPattern; 820 } else { 821 matchPattern = pattern; 822 } 823 824 FcResult result; 825 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result)); 826 if (nullptr == font || !FontAccessible(font) || !FontFamilyNameMatches(font, matchPattern)) { 827 return nullptr; 828 } 829 830 return createTypefaceFromFcPattern(font); 831 } 832 833 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], 834 const SkFontStyle& style, 835 const char* bcp47[], 836 int bcp47Count, 837 SkUnichar character) const override 838 { 839 FCLocker lock; 840 841 SkAutoFcPattern pattern; 842 if (familyName) { 843 FcValue familyNameValue; 844 familyNameValue.type = FcTypeString; 845 familyNameValue.u.s = reinterpret_cast<const FcChar8*>(familyName); 846 FcPatternAddWeak(pattern, FC_FAMILY, familyNameValue, FcFalse); 847 } 848 fcpattern_from_skfontstyle(style, pattern); 849 850 SkAutoFcCharSet charSet; 851 FcCharSetAddChar(charSet, character); 852 FcPatternAddCharSet(pattern, FC_CHARSET, charSet); 853 854 if (bcp47Count > 0) { 855 SkASSERT(bcp47); 856 SkAutoFcLangSet langSet; 857 for (int i = bcp47Count; i --> 0;) { 858 FcLangSetAdd(langSet, (const FcChar8*)bcp47[i]); 859 } 860 FcPatternAddLangSet(pattern, FC_LANG, langSet); 861 } 862 863 FcConfigSubstitute(fFC, pattern, FcMatchPattern); 864 FcDefaultSubstitute(pattern); 865 866 FcResult result; 867 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result)); 868 if (nullptr == font || !FontAccessible(font) || !FontContainsCharacter(font, character)) { 869 return nullptr; 870 } 871 872 return createTypefaceFromFcPattern(font); 873 } 874 875 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, 876 const SkFontStyle& style) const override 877 { 878 //TODO: should the SkTypeface_fontconfig know its family? 879 const SkTypeface_fontconfig* fcTypeface = 880 static_cast<const SkTypeface_fontconfig*>(typeface); 881 return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY), style); 882 } 883 884 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override { 885 std::unique_ptr<SkStreamAsset> stream(bareStream); 886 const size_t length = stream->getLength(); 887 if (length <= 0 || (1u << 30) < length) { 888 return nullptr; 889 } 890 891 SkString name; 892 SkFontStyle style; 893 bool isFixedWidth = false; 894 if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedWidth, nullptr)) { 895 return nullptr; 896 } 897 898 auto data = skstd::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0); 899 return new SkTypeface_stream(std::move(data), std::move(name), style, isFixedWidth); 900 } 901 902 SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override { 903 using Scanner = SkTypeface_FreeType::Scanner; 904 std::unique_ptr<SkStreamAsset> stream(s); 905 bool isFixedPitch; 906 SkFontStyle style; 907 SkString name; 908 Scanner::AxisDefinitions axisDefinitions; 909 if (!fScanner.scanFont(stream.get(), params.getCollectionIndex(), 910 &name, &style, &isFixedPitch, &axisDefinitions)) 911 { 912 return nullptr; 913 } 914 915 int paramAxisCount; 916 const FontParameters::Axis* paramAxes = params.getAxes(¶mAxisCount); 917 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count()); 918 Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name); 919 920 auto data = skstd::make_unique<SkFontData>(std::move(stream), params.getCollectionIndex(), 921 axisValues.get(), axisDefinitions.count()); 922 return new SkTypeface_stream(std::move(data), std::move(name), style, isFixedPitch); 923 } 924 925 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { 926 return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex); 927 } 928 929 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { 930 return this->createFromStream(SkStream::MakeFromFile(path).release(), ttcIndex); 931 } 932 933 SkTypeface* onCreateFromFontData(std::unique_ptr<SkFontData> fontData) const override { 934 SkStreamAsset* stream(fontData->getStream()); 935 const size_t length = stream->getLength(); 936 if (length <= 0 || (1u << 30) < length) { 937 return nullptr; 938 } 939 940 const int ttcIndex = fontData->getIndex(); 941 SkString name; 942 SkFontStyle style; 943 bool isFixedWidth = false; 944 if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedWidth, nullptr)) { 945 return nullptr; 946 } 947 948 return new SkTypeface_stream(std::move(fontData), std::move(name), style, isFixedWidth); 949 } 950 951 SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override { 952 sk_sp<SkTypeface> typeface(this->matchFamilyStyle(familyName, style)); 953 if (typeface.get()) { 954 return typeface.release(); 955 } 956 957 return this->matchFamilyStyle(nullptr, style); 958 } 959}; 960 961SK_API sk_sp<SkFontMgr> SkFontMgr_New_FontConfig(FcConfig* fc) { 962 return sk_make_sp<SkFontMgr_fontconfig>(fc); 963} 964