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