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