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