1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2009-2015 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 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontStyle.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkFixed.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMutex.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTDArray.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkAutoMalloc.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkBuffer.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/ports/SkFontConfigInterface_direct.h"
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker #include <fontconfig/fontconfig.h>
24*c8dee2aaSAndroid Build Coastguard Worker #include <unistd.h>
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker namespace {
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Worker // FontConfig was thread antagonistic until 2.10.91 with known thread safety issues until 2.13.93.
29*c8dee2aaSAndroid Build Coastguard Worker // Before that, lock with a global mutex.
30*c8dee2aaSAndroid Build Coastguard Worker // See https://bug.skia.org/1497 and cl/339089311 for background.
f_c_mutex()31*c8dee2aaSAndroid Build Coastguard Worker static SkMutex& f_c_mutex() {
32*c8dee2aaSAndroid Build Coastguard Worker static SkMutex& mutex = *(new SkMutex);
33*c8dee2aaSAndroid Build Coastguard Worker return mutex;
34*c8dee2aaSAndroid Build Coastguard Worker }
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker struct FCLocker {
37*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int FontConfigThreadSafeVersion = 21393;
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker // Assume FcGetVersion() has always been thread safe.
FCLocker__anon669f15a30111::FCLocker40*c8dee2aaSAndroid Build Coastguard Worker FCLocker() {
41*c8dee2aaSAndroid Build Coastguard Worker if (FcGetVersion() < FontConfigThreadSafeVersion) {
42*c8dee2aaSAndroid Build Coastguard Worker f_c_mutex().acquire();
43*c8dee2aaSAndroid Build Coastguard Worker }
44*c8dee2aaSAndroid Build Coastguard Worker }
45*c8dee2aaSAndroid Build Coastguard Worker
~FCLocker__anon669f15a30111::FCLocker46*c8dee2aaSAndroid Build Coastguard Worker ~FCLocker() {
47*c8dee2aaSAndroid Build Coastguard Worker AssertHeld();
48*c8dee2aaSAndroid Build Coastguard Worker if (FcGetVersion() < FontConfigThreadSafeVersion) {
49*c8dee2aaSAndroid Build Coastguard Worker f_c_mutex().release();
50*c8dee2aaSAndroid Build Coastguard Worker }
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker
AssertHeld__anon669f15a30111::FCLocker53*c8dee2aaSAndroid Build Coastguard Worker static void AssertHeld() { SkDEBUGCODE(
54*c8dee2aaSAndroid Build Coastguard Worker if (FcGetVersion() < FontConfigThreadSafeVersion) {
55*c8dee2aaSAndroid Build Coastguard Worker f_c_mutex().assertHeld();
56*c8dee2aaSAndroid Build Coastguard Worker }
57*c8dee2aaSAndroid Build Coastguard Worker ) }
58*c8dee2aaSAndroid Build Coastguard Worker };
59*c8dee2aaSAndroid Build Coastguard Worker
60*c8dee2aaSAndroid Build Coastguard Worker using UniqueFCConfig = std::unique_ptr<FcConfig, SkFunctionObject<FcConfigDestroy>>;
61*c8dee2aaSAndroid Build Coastguard Worker
62*c8dee2aaSAndroid Build Coastguard Worker } // namespace
63*c8dee2aaSAndroid Build Coastguard Worker
writeToMemory(void * addr) const64*c8dee2aaSAndroid Build Coastguard Worker size_t SkFontConfigInterface::FontIdentity::writeToMemory(void* addr) const {
65*c8dee2aaSAndroid Build Coastguard Worker size_t size = sizeof(fID) + sizeof(fTTCIndex);
66*c8dee2aaSAndroid Build Coastguard Worker size += sizeof(int32_t) + sizeof(int32_t) + sizeof(uint8_t); // weight, width, italic
67*c8dee2aaSAndroid Build Coastguard Worker size += sizeof(int32_t) + fString.size(); // store length+data
68*c8dee2aaSAndroid Build Coastguard Worker if (addr) {
69*c8dee2aaSAndroid Build Coastguard Worker SkWBuffer buffer(addr, size);
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker buffer.write32(fID);
72*c8dee2aaSAndroid Build Coastguard Worker buffer.write32(fTTCIndex);
73*c8dee2aaSAndroid Build Coastguard Worker buffer.write32(fString.size());
74*c8dee2aaSAndroid Build Coastguard Worker buffer.write32(fStyle.weight());
75*c8dee2aaSAndroid Build Coastguard Worker buffer.write32(fStyle.width());
76*c8dee2aaSAndroid Build Coastguard Worker buffer.write8(fStyle.slant());
77*c8dee2aaSAndroid Build Coastguard Worker buffer.write(fString.c_str(), fString.size());
78*c8dee2aaSAndroid Build Coastguard Worker buffer.padToAlign4();
79*c8dee2aaSAndroid Build Coastguard Worker
80*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(buffer.pos() == size);
81*c8dee2aaSAndroid Build Coastguard Worker }
82*c8dee2aaSAndroid Build Coastguard Worker return size;
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker
readFromMemory(const void * addr,size_t size)85*c8dee2aaSAndroid Build Coastguard Worker size_t SkFontConfigInterface::FontIdentity::readFromMemory(const void* addr,
86*c8dee2aaSAndroid Build Coastguard Worker size_t size) {
87*c8dee2aaSAndroid Build Coastguard Worker SkRBuffer buffer(addr, size);
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker (void)buffer.readU32(&fID);
90*c8dee2aaSAndroid Build Coastguard Worker (void)buffer.readS32(&fTTCIndex);
91*c8dee2aaSAndroid Build Coastguard Worker uint32_t strLen, weight, width;
92*c8dee2aaSAndroid Build Coastguard Worker (void)buffer.readU32(&strLen);
93*c8dee2aaSAndroid Build Coastguard Worker (void)buffer.readU32(&weight);
94*c8dee2aaSAndroid Build Coastguard Worker (void)buffer.readU32(&width);
95*c8dee2aaSAndroid Build Coastguard Worker uint8_t u8;
96*c8dee2aaSAndroid Build Coastguard Worker (void)buffer.readU8(&u8);
97*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle::Slant slant = (SkFontStyle::Slant)u8;
98*c8dee2aaSAndroid Build Coastguard Worker fStyle = SkFontStyle(weight, width, slant);
99*c8dee2aaSAndroid Build Coastguard Worker fString.resize(strLen);
100*c8dee2aaSAndroid Build Coastguard Worker (void)buffer.read(fString.data(), strLen);
101*c8dee2aaSAndroid Build Coastguard Worker buffer.skipToAlign4();
102*c8dee2aaSAndroid Build Coastguard Worker
103*c8dee2aaSAndroid Build Coastguard Worker return buffer.pos(); // the actual number of bytes read
104*c8dee2aaSAndroid Build Coastguard Worker }
105*c8dee2aaSAndroid Build Coastguard Worker
106*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
make_iden(SkFontConfigInterface::FontIdentity * iden)107*c8dee2aaSAndroid Build Coastguard Worker static void make_iden(SkFontConfigInterface::FontIdentity* iden) {
108*c8dee2aaSAndroid Build Coastguard Worker iden->fID = 10;
109*c8dee2aaSAndroid Build Coastguard Worker iden->fTTCIndex = 2;
110*c8dee2aaSAndroid Build Coastguard Worker iden->fString.set("Hello world");
111*c8dee2aaSAndroid Build Coastguard Worker iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant);
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker
test_writeToMemory(const SkFontConfigInterface::FontIdentity & iden0,int initValue)114*c8dee2aaSAndroid Build Coastguard Worker static void test_writeToMemory(const SkFontConfigInterface::FontIdentity& iden0,
115*c8dee2aaSAndroid Build Coastguard Worker int initValue) {
116*c8dee2aaSAndroid Build Coastguard Worker SkFontConfigInterface::FontIdentity iden1;
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker size_t size0 = iden0.writeToMemory(nullptr);
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker SkAutoMalloc storage(size0);
121*c8dee2aaSAndroid Build Coastguard Worker memset(storage.get(), initValue, size0);
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker size_t size1 = iden0.writeToMemory(storage.get());
124*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(size0 == size1);
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(iden0 != iden1);
127*c8dee2aaSAndroid Build Coastguard Worker size_t size2 = iden1.readFromMemory(storage.get(), size1);
128*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(size2 == size1);
129*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(iden0 == iden1);
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker
fontconfiginterface_unittest()132*c8dee2aaSAndroid Build Coastguard Worker static void fontconfiginterface_unittest() {
133*c8dee2aaSAndroid Build Coastguard Worker SkFontConfigInterface::FontIdentity iden0, iden1;
134*c8dee2aaSAndroid Build Coastguard Worker
135*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(iden0 == iden1);
136*c8dee2aaSAndroid Build Coastguard Worker
137*c8dee2aaSAndroid Build Coastguard Worker make_iden(&iden0);
138*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(iden0 != iden1);
139*c8dee2aaSAndroid Build Coastguard Worker
140*c8dee2aaSAndroid Build Coastguard Worker make_iden(&iden1);
141*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(iden0 == iden1);
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker test_writeToMemory(iden0, 0);
144*c8dee2aaSAndroid Build Coastguard Worker test_writeToMemory(iden0, 0);
145*c8dee2aaSAndroid Build Coastguard Worker }
146*c8dee2aaSAndroid Build Coastguard Worker #endif
147*c8dee2aaSAndroid Build Coastguard Worker
148*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
149*c8dee2aaSAndroid Build Coastguard Worker
150*c8dee2aaSAndroid Build Coastguard Worker // Returns the string from the pattern, or nullptr
get_string(FcPattern * pattern,const char field[],int index=0)151*c8dee2aaSAndroid Build Coastguard Worker static const char* get_string(FcPattern* pattern, const char field[], int index = 0) {
152*c8dee2aaSAndroid Build Coastguard Worker char* name;
153*c8dee2aaSAndroid Build Coastguard Worker if (FcPatternGetString(pattern, field, index, (FcChar8**)&name) != FcResultMatch) {
154*c8dee2aaSAndroid Build Coastguard Worker name = nullptr;
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker return name;
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker
159*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
160*c8dee2aaSAndroid Build Coastguard Worker
161*c8dee2aaSAndroid Build Coastguard Worker namespace {
162*c8dee2aaSAndroid Build Coastguard Worker
163*c8dee2aaSAndroid Build Coastguard Worker // Equivalence classes, used to match the Liberation and other fonts
164*c8dee2aaSAndroid Build Coastguard Worker // with their metric-compatible replacements. See the discussion in
165*c8dee2aaSAndroid Build Coastguard Worker // GetFontEquivClass().
166*c8dee2aaSAndroid Build Coastguard Worker enum FontEquivClass
167*c8dee2aaSAndroid Build Coastguard Worker {
168*c8dee2aaSAndroid Build Coastguard Worker OTHER,
169*c8dee2aaSAndroid Build Coastguard Worker SANS,
170*c8dee2aaSAndroid Build Coastguard Worker SERIF,
171*c8dee2aaSAndroid Build Coastguard Worker MONO,
172*c8dee2aaSAndroid Build Coastguard Worker SYMBOL,
173*c8dee2aaSAndroid Build Coastguard Worker PGOTHIC,
174*c8dee2aaSAndroid Build Coastguard Worker GOTHIC,
175*c8dee2aaSAndroid Build Coastguard Worker PMINCHO,
176*c8dee2aaSAndroid Build Coastguard Worker MINCHO,
177*c8dee2aaSAndroid Build Coastguard Worker SIMSUN,
178*c8dee2aaSAndroid Build Coastguard Worker NSIMSUN,
179*c8dee2aaSAndroid Build Coastguard Worker SIMHEI,
180*c8dee2aaSAndroid Build Coastguard Worker PMINGLIU,
181*c8dee2aaSAndroid Build Coastguard Worker MINGLIU,
182*c8dee2aaSAndroid Build Coastguard Worker PMINGLIUHK,
183*c8dee2aaSAndroid Build Coastguard Worker MINGLIUHK,
184*c8dee2aaSAndroid Build Coastguard Worker CAMBRIA,
185*c8dee2aaSAndroid Build Coastguard Worker CALIBRI,
186*c8dee2aaSAndroid Build Coastguard Worker };
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker // Match the font name against a whilelist of fonts, returning the equivalence
189*c8dee2aaSAndroid Build Coastguard Worker // class.
GetFontEquivClass(const char * fontname)190*c8dee2aaSAndroid Build Coastguard Worker FontEquivClass GetFontEquivClass(const char* fontname)
191*c8dee2aaSAndroid Build Coastguard Worker {
192*c8dee2aaSAndroid Build Coastguard Worker // It would be nice for fontconfig to tell us whether a given suggested
193*c8dee2aaSAndroid Build Coastguard Worker // replacement is a "strong" match (that is, an equivalent font) or
194*c8dee2aaSAndroid Build Coastguard Worker // a "weak" match (that is, fontconfig's next-best attempt at finding a
195*c8dee2aaSAndroid Build Coastguard Worker // substitute). However, I played around with the fontconfig API for
196*c8dee2aaSAndroid Build Coastguard Worker // a good few hours and could not make it reveal this information.
197*c8dee2aaSAndroid Build Coastguard Worker //
198*c8dee2aaSAndroid Build Coastguard Worker // So instead, we hardcode. Initially this function emulated
199*c8dee2aaSAndroid Build Coastguard Worker // /etc/fonts/conf.d/30-metric-aliases.conf
200*c8dee2aaSAndroid Build Coastguard Worker // from my Ubuntu system, but we're better off being very conservative.
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard Worker // Arimo, Tinos and Cousine are a set of fonts metric-compatible with
203*c8dee2aaSAndroid Build Coastguard Worker // Arial, Times New Roman and Courier New with a character repertoire
204*c8dee2aaSAndroid Build Coastguard Worker // much larger than Liberation. Note that Cousine is metrically
205*c8dee2aaSAndroid Build Coastguard Worker // compatible with Courier New, but the former is sans-serif while
206*c8dee2aaSAndroid Build Coastguard Worker // the latter is serif.
207*c8dee2aaSAndroid Build Coastguard Worker
208*c8dee2aaSAndroid Build Coastguard Worker
209*c8dee2aaSAndroid Build Coastguard Worker struct FontEquivMap {
210*c8dee2aaSAndroid Build Coastguard Worker FontEquivClass clazz;
211*c8dee2aaSAndroid Build Coastguard Worker const char name[40];
212*c8dee2aaSAndroid Build Coastguard Worker };
213*c8dee2aaSAndroid Build Coastguard Worker
214*c8dee2aaSAndroid Build Coastguard Worker static const FontEquivMap kFontEquivMap[] = {
215*c8dee2aaSAndroid Build Coastguard Worker { SANS, "Arial" },
216*c8dee2aaSAndroid Build Coastguard Worker { SANS, "Arimo" },
217*c8dee2aaSAndroid Build Coastguard Worker { SANS, "Liberation Sans" },
218*c8dee2aaSAndroid Build Coastguard Worker
219*c8dee2aaSAndroid Build Coastguard Worker { SERIF, "Times New Roman" },
220*c8dee2aaSAndroid Build Coastguard Worker { SERIF, "Tinos" },
221*c8dee2aaSAndroid Build Coastguard Worker { SERIF, "Liberation Serif" },
222*c8dee2aaSAndroid Build Coastguard Worker
223*c8dee2aaSAndroid Build Coastguard Worker { MONO, "Courier New" },
224*c8dee2aaSAndroid Build Coastguard Worker { MONO, "Cousine" },
225*c8dee2aaSAndroid Build Coastguard Worker { MONO, "Liberation Mono" },
226*c8dee2aaSAndroid Build Coastguard Worker
227*c8dee2aaSAndroid Build Coastguard Worker { SYMBOL, "Symbol" },
228*c8dee2aaSAndroid Build Coastguard Worker { SYMBOL, "Symbol Neu" },
229*c8dee2aaSAndroid Build Coastguard Worker
230*c8dee2aaSAndroid Build Coastguard Worker // MS Pゴシック
231*c8dee2aaSAndroid Build Coastguard Worker { PGOTHIC, "MS PGothic" },
232*c8dee2aaSAndroid Build Coastguard Worker { PGOTHIC, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0"
233*c8dee2aaSAndroid Build Coastguard Worker "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" },
234*c8dee2aaSAndroid Build Coastguard Worker { PGOTHIC, "Noto Sans CJK JP" },
235*c8dee2aaSAndroid Build Coastguard Worker { PGOTHIC, "IPAPGothic" },
236*c8dee2aaSAndroid Build Coastguard Worker { PGOTHIC, "MotoyaG04Gothic" },
237*c8dee2aaSAndroid Build Coastguard Worker
238*c8dee2aaSAndroid Build Coastguard Worker // MS ゴシック
239*c8dee2aaSAndroid Build Coastguard Worker { GOTHIC, "MS Gothic" },
240*c8dee2aaSAndroid Build Coastguard Worker { GOTHIC, "\xef\xbc\xad\xef\xbc\xb3 "
241*c8dee2aaSAndroid Build Coastguard Worker "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" },
242*c8dee2aaSAndroid Build Coastguard Worker { GOTHIC, "Noto Sans Mono CJK JP" },
243*c8dee2aaSAndroid Build Coastguard Worker { GOTHIC, "IPAGothic" },
244*c8dee2aaSAndroid Build Coastguard Worker { GOTHIC, "MotoyaG04GothicMono" },
245*c8dee2aaSAndroid Build Coastguard Worker
246*c8dee2aaSAndroid Build Coastguard Worker // MS P明朝
247*c8dee2aaSAndroid Build Coastguard Worker { PMINCHO, "MS PMincho" },
248*c8dee2aaSAndroid Build Coastguard Worker { PMINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0"
249*c8dee2aaSAndroid Build Coastguard Worker "\xe6\x98\x8e\xe6\x9c\x9d"},
250*c8dee2aaSAndroid Build Coastguard Worker { PMINCHO, "Noto Serif CJK JP" },
251*c8dee2aaSAndroid Build Coastguard Worker { PMINCHO, "IPAPMincho" },
252*c8dee2aaSAndroid Build Coastguard Worker { PMINCHO, "MotoyaG04Mincho" },
253*c8dee2aaSAndroid Build Coastguard Worker
254*c8dee2aaSAndroid Build Coastguard Worker // MS 明朝
255*c8dee2aaSAndroid Build Coastguard Worker { MINCHO, "MS Mincho" },
256*c8dee2aaSAndroid Build Coastguard Worker { MINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xe6\x98\x8e\xe6\x9c\x9d" },
257*c8dee2aaSAndroid Build Coastguard Worker { MINCHO, "Noto Serif CJK JP" },
258*c8dee2aaSAndroid Build Coastguard Worker { MINCHO, "IPAMincho" },
259*c8dee2aaSAndroid Build Coastguard Worker { MINCHO, "MotoyaG04MinchoMono" },
260*c8dee2aaSAndroid Build Coastguard Worker
261*c8dee2aaSAndroid Build Coastguard Worker // 宋体
262*c8dee2aaSAndroid Build Coastguard Worker { SIMSUN, "Simsun" },
263*c8dee2aaSAndroid Build Coastguard Worker { SIMSUN, "\xe5\xae\x8b\xe4\xbd\x93" },
264*c8dee2aaSAndroid Build Coastguard Worker { SIMSUN, "Noto Serif CJK SC" },
265*c8dee2aaSAndroid Build Coastguard Worker { SIMSUN, "MSung GB18030" },
266*c8dee2aaSAndroid Build Coastguard Worker { SIMSUN, "Song ASC" },
267*c8dee2aaSAndroid Build Coastguard Worker
268*c8dee2aaSAndroid Build Coastguard Worker // 新宋体
269*c8dee2aaSAndroid Build Coastguard Worker { NSIMSUN, "NSimsun" },
270*c8dee2aaSAndroid Build Coastguard Worker { NSIMSUN, "\xe6\x96\xb0\xe5\xae\x8b\xe4\xbd\x93" },
271*c8dee2aaSAndroid Build Coastguard Worker { NSIMSUN, "Noto Serif CJK SC" },
272*c8dee2aaSAndroid Build Coastguard Worker { NSIMSUN, "MSung GB18030" },
273*c8dee2aaSAndroid Build Coastguard Worker { NSIMSUN, "N Song ASC" },
274*c8dee2aaSAndroid Build Coastguard Worker
275*c8dee2aaSAndroid Build Coastguard Worker // 黑体
276*c8dee2aaSAndroid Build Coastguard Worker { SIMHEI, "Simhei" },
277*c8dee2aaSAndroid Build Coastguard Worker { SIMHEI, "\xe9\xbb\x91\xe4\xbd\x93" },
278*c8dee2aaSAndroid Build Coastguard Worker { SIMHEI, "Noto Sans CJK SC" },
279*c8dee2aaSAndroid Build Coastguard Worker { SIMHEI, "MYingHeiGB18030" },
280*c8dee2aaSAndroid Build Coastguard Worker { SIMHEI, "MYingHeiB5HK" },
281*c8dee2aaSAndroid Build Coastguard Worker
282*c8dee2aaSAndroid Build Coastguard Worker // 新細明體
283*c8dee2aaSAndroid Build Coastguard Worker { PMINGLIU, "PMingLiU"},
284*c8dee2aaSAndroid Build Coastguard Worker { PMINGLIU, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" },
285*c8dee2aaSAndroid Build Coastguard Worker { PMINGLIU, "Noto Serif CJK TC"},
286*c8dee2aaSAndroid Build Coastguard Worker { PMINGLIU, "MSung B5HK"},
287*c8dee2aaSAndroid Build Coastguard Worker
288*c8dee2aaSAndroid Build Coastguard Worker // 細明體
289*c8dee2aaSAndroid Build Coastguard Worker { MINGLIU, "MingLiU"},
290*c8dee2aaSAndroid Build Coastguard Worker { MINGLIU, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" },
291*c8dee2aaSAndroid Build Coastguard Worker { MINGLIU, "Noto Serif CJK TC"},
292*c8dee2aaSAndroid Build Coastguard Worker { MINGLIU, "MSung B5HK"},
293*c8dee2aaSAndroid Build Coastguard Worker
294*c8dee2aaSAndroid Build Coastguard Worker // 新細明體
295*c8dee2aaSAndroid Build Coastguard Worker { PMINGLIUHK, "PMingLiU_HKSCS"},
296*c8dee2aaSAndroid Build Coastguard Worker { PMINGLIUHK, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" },
297*c8dee2aaSAndroid Build Coastguard Worker { PMINGLIUHK, "Noto Serif CJK TC"},
298*c8dee2aaSAndroid Build Coastguard Worker { PMINGLIUHK, "MSung B5HK"},
299*c8dee2aaSAndroid Build Coastguard Worker
300*c8dee2aaSAndroid Build Coastguard Worker // 細明體
301*c8dee2aaSAndroid Build Coastguard Worker { MINGLIUHK, "MingLiU_HKSCS"},
302*c8dee2aaSAndroid Build Coastguard Worker { MINGLIUHK, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" },
303*c8dee2aaSAndroid Build Coastguard Worker { MINGLIUHK, "Noto Serif CJK TC"},
304*c8dee2aaSAndroid Build Coastguard Worker { MINGLIUHK, "MSung B5HK"},
305*c8dee2aaSAndroid Build Coastguard Worker
306*c8dee2aaSAndroid Build Coastguard Worker // Cambria
307*c8dee2aaSAndroid Build Coastguard Worker { CAMBRIA, "Cambria" },
308*c8dee2aaSAndroid Build Coastguard Worker { CAMBRIA, "Caladea" },
309*c8dee2aaSAndroid Build Coastguard Worker
310*c8dee2aaSAndroid Build Coastguard Worker // Calibri
311*c8dee2aaSAndroid Build Coastguard Worker { CALIBRI, "Calibri" },
312*c8dee2aaSAndroid Build Coastguard Worker { CALIBRI, "Carlito" },
313*c8dee2aaSAndroid Build Coastguard Worker };
314*c8dee2aaSAndroid Build Coastguard Worker
315*c8dee2aaSAndroid Build Coastguard Worker static const size_t kFontCount =
316*c8dee2aaSAndroid Build Coastguard Worker sizeof(kFontEquivMap)/sizeof(kFontEquivMap[0]);
317*c8dee2aaSAndroid Build Coastguard Worker
318*c8dee2aaSAndroid Build Coastguard Worker // TODO(jungshik): If this loop turns out to be hot, turn
319*c8dee2aaSAndroid Build Coastguard Worker // the array to a static (hash)map to speed it up.
320*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < kFontCount; ++i) {
321*c8dee2aaSAndroid Build Coastguard Worker if (strcasecmp(kFontEquivMap[i].name, fontname) == 0)
322*c8dee2aaSAndroid Build Coastguard Worker return kFontEquivMap[i].clazz;
323*c8dee2aaSAndroid Build Coastguard Worker }
324*c8dee2aaSAndroid Build Coastguard Worker return OTHER;
325*c8dee2aaSAndroid Build Coastguard Worker }
326*c8dee2aaSAndroid Build Coastguard Worker
327*c8dee2aaSAndroid Build Coastguard Worker
328*c8dee2aaSAndroid Build Coastguard Worker // Return true if |font_a| and |font_b| are visually and at the metrics
329*c8dee2aaSAndroid Build Coastguard Worker // level interchangeable.
IsMetricCompatibleReplacement(const char * font_a,const char * font_b)330*c8dee2aaSAndroid Build Coastguard Worker bool IsMetricCompatibleReplacement(const char* font_a, const char* font_b)
331*c8dee2aaSAndroid Build Coastguard Worker {
332*c8dee2aaSAndroid Build Coastguard Worker FontEquivClass class_a = GetFontEquivClass(font_a);
333*c8dee2aaSAndroid Build Coastguard Worker FontEquivClass class_b = GetFontEquivClass(font_b);
334*c8dee2aaSAndroid Build Coastguard Worker
335*c8dee2aaSAndroid Build Coastguard Worker return class_a != OTHER && class_a == class_b;
336*c8dee2aaSAndroid Build Coastguard Worker }
337*c8dee2aaSAndroid Build Coastguard Worker
338*c8dee2aaSAndroid Build Coastguard Worker // Normally we only return exactly the font asked for. In last-resort
339*c8dee2aaSAndroid Build Coastguard Worker // cases, the request either doesn't specify a font or is one of the
340*c8dee2aaSAndroid Build Coastguard Worker // basic font names like "Sans", "Serif" or "Monospace". This function
341*c8dee2aaSAndroid Build Coastguard Worker // tells you whether a given request is for such a fallback.
IsFallbackFontAllowed(const SkString & family)342*c8dee2aaSAndroid Build Coastguard Worker bool IsFallbackFontAllowed(const SkString& family) {
343*c8dee2aaSAndroid Build Coastguard Worker const char* family_cstr = family.c_str();
344*c8dee2aaSAndroid Build Coastguard Worker return family.isEmpty() ||
345*c8dee2aaSAndroid Build Coastguard Worker strcasecmp(family_cstr, "sans") == 0 ||
346*c8dee2aaSAndroid Build Coastguard Worker strcasecmp(family_cstr, "serif") == 0 ||
347*c8dee2aaSAndroid Build Coastguard Worker strcasecmp(family_cstr, "monospace") == 0;
348*c8dee2aaSAndroid Build Coastguard Worker }
349*c8dee2aaSAndroid Build Coastguard Worker
350*c8dee2aaSAndroid Build Coastguard Worker // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|.
get_int(FcPattern * pattern,const char object[],int missing)351*c8dee2aaSAndroid Build Coastguard Worker static int get_int(FcPattern* pattern, const char object[], int missing) {
352*c8dee2aaSAndroid Build Coastguard Worker int value;
353*c8dee2aaSAndroid Build Coastguard Worker if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) {
354*c8dee2aaSAndroid Build Coastguard Worker return missing;
355*c8dee2aaSAndroid Build Coastguard Worker }
356*c8dee2aaSAndroid Build Coastguard Worker return value;
357*c8dee2aaSAndroid Build Coastguard Worker }
358*c8dee2aaSAndroid Build Coastguard Worker
map_range(SkScalar value,SkScalar old_min,SkScalar old_max,SkScalar new_min,SkScalar new_max)359*c8dee2aaSAndroid Build Coastguard Worker static int map_range(SkScalar value,
360*c8dee2aaSAndroid Build Coastguard Worker SkScalar old_min, SkScalar old_max,
361*c8dee2aaSAndroid Build Coastguard Worker SkScalar new_min, SkScalar new_max)
362*c8dee2aaSAndroid Build Coastguard Worker {
363*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(old_min < old_max);
364*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(new_min <= new_max);
365*c8dee2aaSAndroid Build Coastguard Worker return new_min + ((value - old_min) * (new_max - new_min) / (old_max - old_min));
366*c8dee2aaSAndroid Build Coastguard Worker }
367*c8dee2aaSAndroid Build Coastguard Worker
368*c8dee2aaSAndroid Build Coastguard Worker struct MapRanges {
369*c8dee2aaSAndroid Build Coastguard Worker SkScalar old_val;
370*c8dee2aaSAndroid Build Coastguard Worker SkScalar new_val;
371*c8dee2aaSAndroid Build Coastguard Worker };
372*c8dee2aaSAndroid Build Coastguard Worker
map_ranges(SkScalar val,MapRanges const ranges[],int rangesCount)373*c8dee2aaSAndroid Build Coastguard Worker static SkScalar map_ranges(SkScalar val, MapRanges const ranges[], int rangesCount) {
374*c8dee2aaSAndroid Build Coastguard Worker // -Inf to [0]
375*c8dee2aaSAndroid Build Coastguard Worker if (val < ranges[0].old_val) {
376*c8dee2aaSAndroid Build Coastguard Worker return ranges[0].new_val;
377*c8dee2aaSAndroid Build Coastguard Worker }
378*c8dee2aaSAndroid Build Coastguard Worker
379*c8dee2aaSAndroid Build Coastguard Worker // Linear from [i] to [i+1]
380*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < rangesCount - 1; ++i) {
381*c8dee2aaSAndroid Build Coastguard Worker if (val < ranges[i+1].old_val) {
382*c8dee2aaSAndroid Build Coastguard Worker return map_range(val, ranges[i].old_val, ranges[i+1].old_val,
383*c8dee2aaSAndroid Build Coastguard Worker ranges[i].new_val, ranges[i+1].new_val);
384*c8dee2aaSAndroid Build Coastguard Worker }
385*c8dee2aaSAndroid Build Coastguard Worker }
386*c8dee2aaSAndroid Build Coastguard Worker
387*c8dee2aaSAndroid Build Coastguard Worker // From [n] to +Inf
388*c8dee2aaSAndroid Build Coastguard Worker // if (fcweight < Inf)
389*c8dee2aaSAndroid Build Coastguard Worker return ranges[rangesCount-1].new_val;
390*c8dee2aaSAndroid Build Coastguard Worker }
391*c8dee2aaSAndroid Build Coastguard Worker
392*c8dee2aaSAndroid Build Coastguard Worker #ifndef FC_WEIGHT_DEMILIGHT
393*c8dee2aaSAndroid Build Coastguard Worker #define FC_WEIGHT_DEMILIGHT 65
394*c8dee2aaSAndroid Build Coastguard Worker #endif
395*c8dee2aaSAndroid Build Coastguard Worker
skfontstyle_from_fcpattern(FcPattern * pattern)396*c8dee2aaSAndroid Build Coastguard Worker static SkFontStyle skfontstyle_from_fcpattern(FcPattern* pattern) {
397*c8dee2aaSAndroid Build Coastguard Worker typedef SkFontStyle SkFS;
398*c8dee2aaSAndroid Build Coastguard Worker
399*c8dee2aaSAndroid Build Coastguard Worker static constexpr MapRanges weightRanges[] = {
400*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_THIN, SkFS::kThin_Weight },
401*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_EXTRALIGHT, SkFS::kExtraLight_Weight },
402*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_LIGHT, SkFS::kLight_Weight },
403*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_DEMILIGHT, 350 },
404*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_BOOK, 380 },
405*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_REGULAR, SkFS::kNormal_Weight },
406*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_MEDIUM, SkFS::kMedium_Weight },
407*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_DEMIBOLD, SkFS::kSemiBold_Weight },
408*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_BOLD, SkFS::kBold_Weight },
409*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_EXTRABOLD, SkFS::kExtraBold_Weight },
410*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_BLACK, SkFS::kBlack_Weight },
411*c8dee2aaSAndroid Build Coastguard Worker { FC_WEIGHT_EXTRABLACK, SkFS::kExtraBlack_Weight },
412*c8dee2aaSAndroid Build Coastguard Worker };
413*c8dee2aaSAndroid Build Coastguard Worker SkScalar weight = map_ranges(get_int(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR),
414*c8dee2aaSAndroid Build Coastguard Worker weightRanges, std::size(weightRanges));
415*c8dee2aaSAndroid Build Coastguard Worker
416*c8dee2aaSAndroid Build Coastguard Worker static constexpr MapRanges widthRanges[] = {
417*c8dee2aaSAndroid Build Coastguard Worker { FC_WIDTH_ULTRACONDENSED, SkFS::kUltraCondensed_Width },
418*c8dee2aaSAndroid Build Coastguard Worker { FC_WIDTH_EXTRACONDENSED, SkFS::kExtraCondensed_Width },
419*c8dee2aaSAndroid Build Coastguard Worker { FC_WIDTH_CONDENSED, SkFS::kCondensed_Width },
420*c8dee2aaSAndroid Build Coastguard Worker { FC_WIDTH_SEMICONDENSED, SkFS::kSemiCondensed_Width },
421*c8dee2aaSAndroid Build Coastguard Worker { FC_WIDTH_NORMAL, SkFS::kNormal_Width },
422*c8dee2aaSAndroid Build Coastguard Worker { FC_WIDTH_SEMIEXPANDED, SkFS::kSemiExpanded_Width },
423*c8dee2aaSAndroid Build Coastguard Worker { FC_WIDTH_EXPANDED, SkFS::kExpanded_Width },
424*c8dee2aaSAndroid Build Coastguard Worker { FC_WIDTH_EXTRAEXPANDED, SkFS::kExtraExpanded_Width },
425*c8dee2aaSAndroid Build Coastguard Worker { FC_WIDTH_ULTRAEXPANDED, SkFS::kUltraExpanded_Width },
426*c8dee2aaSAndroid Build Coastguard Worker };
427*c8dee2aaSAndroid Build Coastguard Worker SkScalar width = map_ranges(get_int(pattern, FC_WIDTH, FC_WIDTH_NORMAL),
428*c8dee2aaSAndroid Build Coastguard Worker widthRanges, std::size(widthRanges));
429*c8dee2aaSAndroid Build Coastguard Worker
430*c8dee2aaSAndroid Build Coastguard Worker SkFS::Slant slant = SkFS::kUpright_Slant;
431*c8dee2aaSAndroid Build Coastguard Worker switch (get_int(pattern, FC_SLANT, FC_SLANT_ROMAN)) {
432*c8dee2aaSAndroid Build Coastguard Worker case FC_SLANT_ROMAN: slant = SkFS::kUpright_Slant; break;
433*c8dee2aaSAndroid Build Coastguard Worker case FC_SLANT_ITALIC : slant = SkFS::kItalic_Slant ; break;
434*c8dee2aaSAndroid Build Coastguard Worker case FC_SLANT_OBLIQUE: slant = SkFS::kOblique_Slant; break;
435*c8dee2aaSAndroid Build Coastguard Worker default: SkASSERT(false); break;
436*c8dee2aaSAndroid Build Coastguard Worker }
437*c8dee2aaSAndroid Build Coastguard Worker
438*c8dee2aaSAndroid Build Coastguard Worker return SkFontStyle(SkScalarRoundToInt(weight), SkScalarRoundToInt(width), slant);
439*c8dee2aaSAndroid Build Coastguard Worker }
440*c8dee2aaSAndroid Build Coastguard Worker
fcpattern_from_skfontstyle(SkFontStyle style,FcPattern * pattern)441*c8dee2aaSAndroid Build Coastguard Worker static void fcpattern_from_skfontstyle(SkFontStyle style, FcPattern* pattern) {
442*c8dee2aaSAndroid Build Coastguard Worker typedef SkFontStyle SkFS;
443*c8dee2aaSAndroid Build Coastguard Worker
444*c8dee2aaSAndroid Build Coastguard Worker static constexpr MapRanges weightRanges[] = {
445*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kThin_Weight, FC_WEIGHT_THIN },
446*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kExtraLight_Weight, FC_WEIGHT_EXTRALIGHT },
447*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kLight_Weight, FC_WEIGHT_LIGHT },
448*c8dee2aaSAndroid Build Coastguard Worker { 350, FC_WEIGHT_DEMILIGHT },
449*c8dee2aaSAndroid Build Coastguard Worker { 380, FC_WEIGHT_BOOK },
450*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kNormal_Weight, FC_WEIGHT_REGULAR },
451*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kMedium_Weight, FC_WEIGHT_MEDIUM },
452*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kSemiBold_Weight, FC_WEIGHT_DEMIBOLD },
453*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kBold_Weight, FC_WEIGHT_BOLD },
454*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kExtraBold_Weight, FC_WEIGHT_EXTRABOLD },
455*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kBlack_Weight, FC_WEIGHT_BLACK },
456*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kExtraBlack_Weight, FC_WEIGHT_EXTRABLACK },
457*c8dee2aaSAndroid Build Coastguard Worker };
458*c8dee2aaSAndroid Build Coastguard Worker int weight = map_ranges(style.weight(), weightRanges, std::size(weightRanges));
459*c8dee2aaSAndroid Build Coastguard Worker
460*c8dee2aaSAndroid Build Coastguard Worker static constexpr MapRanges widthRanges[] = {
461*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kUltraCondensed_Width, FC_WIDTH_ULTRACONDENSED },
462*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kExtraCondensed_Width, FC_WIDTH_EXTRACONDENSED },
463*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kCondensed_Width, FC_WIDTH_CONDENSED },
464*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kSemiCondensed_Width, FC_WIDTH_SEMICONDENSED },
465*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kNormal_Width, FC_WIDTH_NORMAL },
466*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kSemiExpanded_Width, FC_WIDTH_SEMIEXPANDED },
467*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kExpanded_Width, FC_WIDTH_EXPANDED },
468*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kExtraExpanded_Width, FC_WIDTH_EXTRAEXPANDED },
469*c8dee2aaSAndroid Build Coastguard Worker { SkFS::kUltraExpanded_Width, FC_WIDTH_ULTRAEXPANDED },
470*c8dee2aaSAndroid Build Coastguard Worker };
471*c8dee2aaSAndroid Build Coastguard Worker int width = map_ranges(style.width(), widthRanges, std::size(widthRanges));
472*c8dee2aaSAndroid Build Coastguard Worker
473*c8dee2aaSAndroid Build Coastguard Worker int slant = FC_SLANT_ROMAN;
474*c8dee2aaSAndroid Build Coastguard Worker switch (style.slant()) {
475*c8dee2aaSAndroid Build Coastguard Worker case SkFS::kUpright_Slant: slant = FC_SLANT_ROMAN ; break;
476*c8dee2aaSAndroid Build Coastguard Worker case SkFS::kItalic_Slant : slant = FC_SLANT_ITALIC ; break;
477*c8dee2aaSAndroid Build Coastguard Worker case SkFS::kOblique_Slant: slant = FC_SLANT_OBLIQUE; break;
478*c8dee2aaSAndroid Build Coastguard Worker default: SkASSERT(false); break;
479*c8dee2aaSAndroid Build Coastguard Worker }
480*c8dee2aaSAndroid Build Coastguard Worker
481*c8dee2aaSAndroid Build Coastguard Worker FcPatternAddInteger(pattern, FC_WEIGHT, weight);
482*c8dee2aaSAndroid Build Coastguard Worker FcPatternAddInteger(pattern, FC_WIDTH , width);
483*c8dee2aaSAndroid Build Coastguard Worker FcPatternAddInteger(pattern, FC_SLANT , slant);
484*c8dee2aaSAndroid Build Coastguard Worker }
485*c8dee2aaSAndroid Build Coastguard Worker
486*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
487*c8dee2aaSAndroid Build Coastguard Worker
488*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
489*c8dee2aaSAndroid Build Coastguard Worker
490*c8dee2aaSAndroid Build Coastguard Worker #define kMaxFontFamilyLength 2048
491*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_FONT_CONFIG_INTERFACE_ONLY_ALLOW_SFNT_FONTS
492*c8dee2aaSAndroid Build Coastguard Worker const char* kFontFormatTrueType = "TrueType";
493*c8dee2aaSAndroid Build Coastguard Worker const char* kFontFormatCFF = "CFF";
494*c8dee2aaSAndroid Build Coastguard Worker #endif
495*c8dee2aaSAndroid Build Coastguard Worker
SkFontConfigInterfaceDirect(FcConfig * fc)496*c8dee2aaSAndroid Build Coastguard Worker SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect(FcConfig* fc) : fFC(fc)
497*c8dee2aaSAndroid Build Coastguard Worker {
498*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fontconfiginterface_unittest();)
499*c8dee2aaSAndroid Build Coastguard Worker }
500*c8dee2aaSAndroid Build Coastguard Worker
~SkFontConfigInterfaceDirect()501*c8dee2aaSAndroid Build Coastguard Worker SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
502*c8dee2aaSAndroid Build Coastguard Worker if (fFC) {
503*c8dee2aaSAndroid Build Coastguard Worker FcConfigDestroy(fFC);
504*c8dee2aaSAndroid Build Coastguard Worker }
505*c8dee2aaSAndroid Build Coastguard Worker }
506*c8dee2aaSAndroid Build Coastguard Worker
isAccessible(const char * filename)507*c8dee2aaSAndroid Build Coastguard Worker bool SkFontConfigInterfaceDirect::isAccessible(const char* filename) {
508*c8dee2aaSAndroid Build Coastguard Worker if (access(filename, R_OK) != 0) {
509*c8dee2aaSAndroid Build Coastguard Worker return false;
510*c8dee2aaSAndroid Build Coastguard Worker }
511*c8dee2aaSAndroid Build Coastguard Worker return true;
512*c8dee2aaSAndroid Build Coastguard Worker }
513*c8dee2aaSAndroid Build Coastguard Worker
isValidPattern(FcPattern * pattern)514*c8dee2aaSAndroid Build Coastguard Worker bool SkFontConfigInterfaceDirect::isValidPattern(FcPattern* pattern) {
515*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_FONT_CONFIG_INTERFACE_ONLY_ALLOW_SFNT_FONTS
516*c8dee2aaSAndroid Build Coastguard Worker const char* font_format = get_string(pattern, FC_FONTFORMAT);
517*c8dee2aaSAndroid Build Coastguard Worker if (font_format
518*c8dee2aaSAndroid Build Coastguard Worker && 0 != strcmp(font_format, kFontFormatTrueType)
519*c8dee2aaSAndroid Build Coastguard Worker && 0 != strcmp(font_format, kFontFormatCFF))
520*c8dee2aaSAndroid Build Coastguard Worker {
521*c8dee2aaSAndroid Build Coastguard Worker return false;
522*c8dee2aaSAndroid Build Coastguard Worker }
523*c8dee2aaSAndroid Build Coastguard Worker #endif
524*c8dee2aaSAndroid Build Coastguard Worker
525*c8dee2aaSAndroid Build Coastguard Worker // fontconfig can also return fonts which are unreadable
526*c8dee2aaSAndroid Build Coastguard Worker const char* c_filename = get_string(pattern, FC_FILE);
527*c8dee2aaSAndroid Build Coastguard Worker if (!c_filename) {
528*c8dee2aaSAndroid Build Coastguard Worker return false;
529*c8dee2aaSAndroid Build Coastguard Worker }
530*c8dee2aaSAndroid Build Coastguard Worker
531*c8dee2aaSAndroid Build Coastguard Worker FcConfig* fc = fFC;
532*c8dee2aaSAndroid Build Coastguard Worker UniqueFCConfig fcStorage;
533*c8dee2aaSAndroid Build Coastguard Worker if (!fc) {
534*c8dee2aaSAndroid Build Coastguard Worker fcStorage.reset(FcConfigReference(nullptr));
535*c8dee2aaSAndroid Build Coastguard Worker fc = fcStorage.get();
536*c8dee2aaSAndroid Build Coastguard Worker }
537*c8dee2aaSAndroid Build Coastguard Worker
538*c8dee2aaSAndroid Build Coastguard Worker const char* sysroot = (const char*)FcConfigGetSysRoot(fc);
539*c8dee2aaSAndroid Build Coastguard Worker SkString resolvedFilename;
540*c8dee2aaSAndroid Build Coastguard Worker if (sysroot) {
541*c8dee2aaSAndroid Build Coastguard Worker resolvedFilename = sysroot;
542*c8dee2aaSAndroid Build Coastguard Worker resolvedFilename += c_filename;
543*c8dee2aaSAndroid Build Coastguard Worker c_filename = resolvedFilename.c_str();
544*c8dee2aaSAndroid Build Coastguard Worker }
545*c8dee2aaSAndroid Build Coastguard Worker return this->isAccessible(c_filename);
546*c8dee2aaSAndroid Build Coastguard Worker }
547*c8dee2aaSAndroid Build Coastguard Worker
548*c8dee2aaSAndroid Build Coastguard Worker // Find matching font from |font_set| for the given font family.
MatchFont(FcFontSet * font_set,const char * post_config_family,const SkString & family)549*c8dee2aaSAndroid Build Coastguard Worker FcPattern* SkFontConfigInterfaceDirect::MatchFont(FcFontSet* font_set,
550*c8dee2aaSAndroid Build Coastguard Worker const char* post_config_family,
551*c8dee2aaSAndroid Build Coastguard Worker const SkString& family) {
552*c8dee2aaSAndroid Build Coastguard Worker // Older versions of fontconfig have a bug where they cannot select
553*c8dee2aaSAndroid Build Coastguard Worker // only scalable fonts so we have to manually filter the results.
554*c8dee2aaSAndroid Build Coastguard Worker FcPattern* match = nullptr;
555*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < font_set->nfont; ++i) {
556*c8dee2aaSAndroid Build Coastguard Worker FcPattern* current = font_set->fonts[i];
557*c8dee2aaSAndroid Build Coastguard Worker if (this->isValidPattern(current)) {
558*c8dee2aaSAndroid Build Coastguard Worker match = current;
559*c8dee2aaSAndroid Build Coastguard Worker break;
560*c8dee2aaSAndroid Build Coastguard Worker }
561*c8dee2aaSAndroid Build Coastguard Worker }
562*c8dee2aaSAndroid Build Coastguard Worker
563*c8dee2aaSAndroid Build Coastguard Worker if (match && !IsFallbackFontAllowed(family)) {
564*c8dee2aaSAndroid Build Coastguard Worker bool acceptable_substitute = false;
565*c8dee2aaSAndroid Build Coastguard Worker for (int id = 0; id < 255; ++id) {
566*c8dee2aaSAndroid Build Coastguard Worker const char* post_match_family = get_string(match, FC_FAMILY, id);
567*c8dee2aaSAndroid Build Coastguard Worker if (!post_match_family)
568*c8dee2aaSAndroid Build Coastguard Worker break;
569*c8dee2aaSAndroid Build Coastguard Worker acceptable_substitute =
570*c8dee2aaSAndroid Build Coastguard Worker (strcasecmp(post_config_family, post_match_family) == 0 ||
571*c8dee2aaSAndroid Build Coastguard Worker // Workaround for Issue 12530:
572*c8dee2aaSAndroid Build Coastguard Worker // requested family: "Bitstream Vera Sans"
573*c8dee2aaSAndroid Build Coastguard Worker // post_config_family: "Arial"
574*c8dee2aaSAndroid Build Coastguard Worker // post_match_family: "Bitstream Vera Sans"
575*c8dee2aaSAndroid Build Coastguard Worker // -> We should treat this case as a good match.
576*c8dee2aaSAndroid Build Coastguard Worker strcasecmp(family.c_str(), post_match_family) == 0) ||
577*c8dee2aaSAndroid Build Coastguard Worker IsMetricCompatibleReplacement(family.c_str(), post_match_family);
578*c8dee2aaSAndroid Build Coastguard Worker if (acceptable_substitute)
579*c8dee2aaSAndroid Build Coastguard Worker break;
580*c8dee2aaSAndroid Build Coastguard Worker }
581*c8dee2aaSAndroid Build Coastguard Worker if (!acceptable_substitute)
582*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
583*c8dee2aaSAndroid Build Coastguard Worker }
584*c8dee2aaSAndroid Build Coastguard Worker
585*c8dee2aaSAndroid Build Coastguard Worker return match;
586*c8dee2aaSAndroid Build Coastguard Worker }
587*c8dee2aaSAndroid Build Coastguard Worker
matchFamilyName(const char familyName[],SkFontStyle style,FontIdentity * outIdentity,SkString * outFamilyName,SkFontStyle * outStyle)588*c8dee2aaSAndroid Build Coastguard Worker bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[],
589*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle style,
590*c8dee2aaSAndroid Build Coastguard Worker FontIdentity* outIdentity,
591*c8dee2aaSAndroid Build Coastguard Worker SkString* outFamilyName,
592*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle* outStyle) {
593*c8dee2aaSAndroid Build Coastguard Worker SkString familyStr(familyName ? familyName : "");
594*c8dee2aaSAndroid Build Coastguard Worker if (familyStr.size() > kMaxFontFamilyLength) {
595*c8dee2aaSAndroid Build Coastguard Worker return false;
596*c8dee2aaSAndroid Build Coastguard Worker }
597*c8dee2aaSAndroid Build Coastguard Worker
598*c8dee2aaSAndroid Build Coastguard Worker FcConfig* fc = fFC;
599*c8dee2aaSAndroid Build Coastguard Worker UniqueFCConfig fcStorage;
600*c8dee2aaSAndroid Build Coastguard Worker if (!fc) {
601*c8dee2aaSAndroid Build Coastguard Worker fcStorage.reset(FcConfigReference(nullptr));
602*c8dee2aaSAndroid Build Coastguard Worker fc = fcStorage.get();
603*c8dee2aaSAndroid Build Coastguard Worker }
604*c8dee2aaSAndroid Build Coastguard Worker
605*c8dee2aaSAndroid Build Coastguard Worker FCLocker lock;
606*c8dee2aaSAndroid Build Coastguard Worker FcPattern* pattern = FcPatternCreate();
607*c8dee2aaSAndroid Build Coastguard Worker
608*c8dee2aaSAndroid Build Coastguard Worker if (familyName) {
609*c8dee2aaSAndroid Build Coastguard Worker FcPatternAddString(pattern, FC_FAMILY, (const FcChar8*)familyName);
610*c8dee2aaSAndroid Build Coastguard Worker }
611*c8dee2aaSAndroid Build Coastguard Worker fcpattern_from_skfontstyle(style, pattern);
612*c8dee2aaSAndroid Build Coastguard Worker
613*c8dee2aaSAndroid Build Coastguard Worker FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
614*c8dee2aaSAndroid Build Coastguard Worker
615*c8dee2aaSAndroid Build Coastguard Worker FcConfigSubstitute(fc, pattern, FcMatchPattern);
616*c8dee2aaSAndroid Build Coastguard Worker FcDefaultSubstitute(pattern);
617*c8dee2aaSAndroid Build Coastguard Worker
618*c8dee2aaSAndroid Build Coastguard Worker // Font matching:
619*c8dee2aaSAndroid Build Coastguard Worker // CSS often specifies a fallback list of families:
620*c8dee2aaSAndroid Build Coastguard Worker // font-family: a, b, c, serif;
621*c8dee2aaSAndroid Build Coastguard Worker // However, fontconfig will always do its best to find *a* font when asked
622*c8dee2aaSAndroid Build Coastguard Worker // for something so we need a way to tell if the match which it has found is
623*c8dee2aaSAndroid Build Coastguard Worker // "good enough" for us. Otherwise, we can return nullptr which gets piped up
624*c8dee2aaSAndroid Build Coastguard Worker // and lets WebKit know to try the next CSS family name. However, fontconfig
625*c8dee2aaSAndroid Build Coastguard Worker // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
626*c8dee2aaSAndroid Build Coastguard Worker // wish to support that.
627*c8dee2aaSAndroid Build Coastguard Worker //
628*c8dee2aaSAndroid Build Coastguard Worker // Thus, if a specific family is requested we set @family_requested. Then we
629*c8dee2aaSAndroid Build Coastguard Worker // record two strings: the family name after config processing and the
630*c8dee2aaSAndroid Build Coastguard Worker // family name after resolving. If the two are equal, it's a good match.
631*c8dee2aaSAndroid Build Coastguard Worker //
632*c8dee2aaSAndroid Build Coastguard Worker // So consider the case where a user has mapped Arial to Helvetica in their
633*c8dee2aaSAndroid Build Coastguard Worker // config.
634*c8dee2aaSAndroid Build Coastguard Worker // requested family: "Arial"
635*c8dee2aaSAndroid Build Coastguard Worker // post_config_family: "Helvetica"
636*c8dee2aaSAndroid Build Coastguard Worker // post_match_family: "Helvetica"
637*c8dee2aaSAndroid Build Coastguard Worker // -> good match
638*c8dee2aaSAndroid Build Coastguard Worker //
639*c8dee2aaSAndroid Build Coastguard Worker // and for a missing font:
640*c8dee2aaSAndroid Build Coastguard Worker // requested family: "Monaco"
641*c8dee2aaSAndroid Build Coastguard Worker // post_config_family: "Monaco"
642*c8dee2aaSAndroid Build Coastguard Worker // post_match_family: "Times New Roman"
643*c8dee2aaSAndroid Build Coastguard Worker // -> BAD match
644*c8dee2aaSAndroid Build Coastguard Worker //
645*c8dee2aaSAndroid Build Coastguard Worker // However, we special-case fallback fonts; see IsFallbackFontAllowed().
646*c8dee2aaSAndroid Build Coastguard Worker
647*c8dee2aaSAndroid Build Coastguard Worker const char* post_config_family = get_string(pattern, FC_FAMILY);
648*c8dee2aaSAndroid Build Coastguard Worker if (!post_config_family) {
649*c8dee2aaSAndroid Build Coastguard Worker // we can just continue with an empty name, e.g. default font
650*c8dee2aaSAndroid Build Coastguard Worker post_config_family = "";
651*c8dee2aaSAndroid Build Coastguard Worker }
652*c8dee2aaSAndroid Build Coastguard Worker
653*c8dee2aaSAndroid Build Coastguard Worker FcResult result;
654*c8dee2aaSAndroid Build Coastguard Worker FcFontSet* font_set = FcFontSort(fc, pattern, 0, nullptr, &result);
655*c8dee2aaSAndroid Build Coastguard Worker if (!font_set) {
656*c8dee2aaSAndroid Build Coastguard Worker FcPatternDestroy(pattern);
657*c8dee2aaSAndroid Build Coastguard Worker return false;
658*c8dee2aaSAndroid Build Coastguard Worker }
659*c8dee2aaSAndroid Build Coastguard Worker
660*c8dee2aaSAndroid Build Coastguard Worker FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr);
661*c8dee2aaSAndroid Build Coastguard Worker if (!match) {
662*c8dee2aaSAndroid Build Coastguard Worker FcPatternDestroy(pattern);
663*c8dee2aaSAndroid Build Coastguard Worker FcFontSetDestroy(font_set);
664*c8dee2aaSAndroid Build Coastguard Worker return false;
665*c8dee2aaSAndroid Build Coastguard Worker }
666*c8dee2aaSAndroid Build Coastguard Worker
667*c8dee2aaSAndroid Build Coastguard Worker FcPatternDestroy(pattern);
668*c8dee2aaSAndroid Build Coastguard Worker
669*c8dee2aaSAndroid Build Coastguard Worker // From here out we just extract our results from 'match'
670*c8dee2aaSAndroid Build Coastguard Worker
671*c8dee2aaSAndroid Build Coastguard Worker post_config_family = get_string(match, FC_FAMILY);
672*c8dee2aaSAndroid Build Coastguard Worker if (!post_config_family) {
673*c8dee2aaSAndroid Build Coastguard Worker FcFontSetDestroy(font_set);
674*c8dee2aaSAndroid Build Coastguard Worker return false;
675*c8dee2aaSAndroid Build Coastguard Worker }
676*c8dee2aaSAndroid Build Coastguard Worker
677*c8dee2aaSAndroid Build Coastguard Worker const char* c_filename = get_string(match, FC_FILE);
678*c8dee2aaSAndroid Build Coastguard Worker if (!c_filename) {
679*c8dee2aaSAndroid Build Coastguard Worker FcFontSetDestroy(font_set);
680*c8dee2aaSAndroid Build Coastguard Worker return false;
681*c8dee2aaSAndroid Build Coastguard Worker }
682*c8dee2aaSAndroid Build Coastguard Worker const char* sysroot = (const char*)FcConfigGetSysRoot(fc);
683*c8dee2aaSAndroid Build Coastguard Worker SkString resolvedFilename;
684*c8dee2aaSAndroid Build Coastguard Worker if (sysroot) {
685*c8dee2aaSAndroid Build Coastguard Worker resolvedFilename = sysroot;
686*c8dee2aaSAndroid Build Coastguard Worker resolvedFilename += c_filename;
687*c8dee2aaSAndroid Build Coastguard Worker c_filename = resolvedFilename.c_str();
688*c8dee2aaSAndroid Build Coastguard Worker }
689*c8dee2aaSAndroid Build Coastguard Worker
690*c8dee2aaSAndroid Build Coastguard Worker int face_index = get_int(match, FC_INDEX, 0);
691*c8dee2aaSAndroid Build Coastguard Worker
692*c8dee2aaSAndroid Build Coastguard Worker FcFontSetDestroy(font_set);
693*c8dee2aaSAndroid Build Coastguard Worker
694*c8dee2aaSAndroid Build Coastguard Worker if (outIdentity) {
695*c8dee2aaSAndroid Build Coastguard Worker outIdentity->fTTCIndex = face_index;
696*c8dee2aaSAndroid Build Coastguard Worker outIdentity->fString.set(c_filename);
697*c8dee2aaSAndroid Build Coastguard Worker }
698*c8dee2aaSAndroid Build Coastguard Worker if (outFamilyName) {
699*c8dee2aaSAndroid Build Coastguard Worker outFamilyName->set(post_config_family);
700*c8dee2aaSAndroid Build Coastguard Worker }
701*c8dee2aaSAndroid Build Coastguard Worker if (outStyle) {
702*c8dee2aaSAndroid Build Coastguard Worker *outStyle = skfontstyle_from_fcpattern(match);
703*c8dee2aaSAndroid Build Coastguard Worker }
704*c8dee2aaSAndroid Build Coastguard Worker return true;
705*c8dee2aaSAndroid Build Coastguard Worker }
706*c8dee2aaSAndroid Build Coastguard Worker
openStream(const FontIdentity & identity)707*c8dee2aaSAndroid Build Coastguard Worker SkStreamAsset* SkFontConfigInterfaceDirect::openStream(const FontIdentity& identity) {
708*c8dee2aaSAndroid Build Coastguard Worker return SkStream::MakeFromFile(identity.fString.c_str()).release();
709*c8dee2aaSAndroid Build Coastguard Worker }
710