blob: 85230b394ed6dd374b94c888e388b45816ea4337 [file] [log] [blame]
bungemana6785cc2014-08-25 12:00:49 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
bungeman0b775822016-09-13 14:03:54 -07008#include "SkAdvancedTypefaceMetrics.h"
bungemana6785cc2014-08-25 12:00:49 -07009#include "SkDataTable.h"
bungemanf20488b2015-07-29 11:49:40 -070010#include "SkFixed.h"
bungemana6785cc2014-08-25 12:00:49 -070011#include "SkFontDescriptor.h"
12#include "SkFontHost_FreeType_common.h"
13#include "SkFontMgr.h"
14#include "SkFontStyle.h"
bungemanf93d7112016-09-16 06:24:20 -070015#include "SkMakeUnique.h"
bungemana6785cc2014-08-25 12:00:49 -070016#include "SkMath.h"
mtklein1b249332015-07-07 12:21:21 -070017#include "SkMutex.h"
bungemana6785cc2014-08-25 12:00:49 -070018#include "SkOSFile.h"
bungemanf20488b2015-07-29 11:49:40 -070019#include "SkRefCnt.h"
20#include "SkStream.h"
21#include "SkString.h"
22#include "SkTDArray.h"
23#include "SkTemplates.h"
24#include "SkTypeface.h"
25#include "SkTypefaceCache.h"
26#include "SkTypes.h"
bungemana6785cc2014-08-25 12:00:49 -070027
28#include <fontconfig/fontconfig.h>
bungemanf20488b2015-07-29 11:49:40 -070029#include <string.h>
30
31class SkData;
bungemana6785cc2014-08-25 12:00:49 -070032
33// FC_POSTSCRIPT_NAME was added with b561ff20 which ended up in 2.10.92
34// Ubuntu 12.04 is on 2.8.0, 13.10 is on 2.10.93
35// Debian 7 is on 2.9.0, 8 is on 2.11
36// OpenSUSE 12.2 is on 2.9.0, 12.3 is on 2.10.2, 13.1 2.11.0
37// Fedora 19 is on 2.10.93
38#ifndef FC_POSTSCRIPT_NAME
39# define FC_POSTSCRIPT_NAME "postscriptname"
40#endif
41
42#ifdef SK_DEBUG
43# include "SkTLS.h"
44#endif
45
46/** Since FontConfig is poorly documented, this gives a high level overview:
47 *
48 * FcConfig is a handle to a FontConfig configuration instance. Each 'configuration' is independent
49 * from any others which may exist. There exists a default global configuration which is created
50 * and destroyed by FcInit and FcFini, but this default should not normally be used.
51 * Instead, one should use FcConfigCreate and FcInit* to have a named local state.
52 *
53 * FcPatterns are {objectName -> [element]} (maps from object names to a list of elements).
54 * Each element is some internal data plus an FcValue which is a variant (a union with a type tag).
55 * Lists of elements are not typed, except by convention. Any collection of FcValues must be
56 * assumed to be heterogeneous by the code, but the code need not do anything particularly
57 * interesting if the values go against convention.
58 *
59 * Somewhat like DirectWrite, FontConfig supports synthetics through FC_EMBOLDEN and FC_MATRIX.
60 * Like all synthetic information, such information must be passed with the font data.
61 */
62
63namespace {
64
65// Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a global mutex.
halcanary6950de62015-11-07 05:29:00 -080066// See https://bug.skia.org/1497 for background.
reed086eea92016-05-04 17:12:46 -070067SK_DECLARE_STATIC_MUTEX(gFCMutex);
bungemana6785cc2014-08-25 12:00:49 -070068
69#ifdef SK_DEBUG
halcanary385fe4d2015-08-26 13:07:48 -070070void* CreateThreadFcLocked() { return new bool(false); }
71void DeleteThreadFcLocked(void* v) { delete static_cast<bool*>(v); }
bungemana6785cc2014-08-25 12:00:49 -070072# define THREAD_FC_LOCKED \
73 static_cast<bool*>(SkTLS::Get(CreateThreadFcLocked, DeleteThreadFcLocked))
74#endif
75
76struct FCLocker {
77 // Assume FcGetVersion() has always been thread safe.
78
79 FCLocker() {
80 if (FcGetVersion() < 21091) {
81 gFCMutex.acquire();
82 } else {
83 SkDEBUGCODE(bool* threadLocked = THREAD_FC_LOCKED);
84 SkASSERT(false == *threadLocked);
85 SkDEBUGCODE(*threadLocked = true);
86 }
87 }
88
89 ~FCLocker() {
90 AssertHeld();
91 if (FcGetVersion() < 21091) {
92 gFCMutex.release();
93 } else {
94 SkDEBUGCODE(*THREAD_FC_LOCKED = false);
95 }
96 }
97
98 static void AssertHeld() { SkDEBUGCODE(
99 if (FcGetVersion() < 21091) {
100 gFCMutex.assertHeld();
101 } else {
102 SkASSERT(true == *THREAD_FC_LOCKED);
103 }
104 ) }
105};
106
107} // namespace
108
bungeman6bc2c942014-09-09 12:50:36 -0700109template<typename T, void (*D)(T*)> void FcTDestroy(T* t) {
bungemana6785cc2014-08-25 12:00:49 -0700110 FCLocker::AssertHeld();
bungeman6bc2c942014-09-09 12:50:36 -0700111 D(t);
bungemana6785cc2014-08-25 12:00:49 -0700112}
bungeman6bc2c942014-09-09 12:50:36 -0700113template <typename T, T* (*C)(), void (*D)(T*)> class SkAutoFc
114 : public SkAutoTCallVProc<T, FcTDestroy<T, D> > {
bungemana6785cc2014-08-25 12:00:49 -0700115public:
bungeman6bc2c942014-09-09 12:50:36 -0700116 SkAutoFc() : SkAutoTCallVProc<T, FcTDestroy<T, D> >(C()) {
117 T* obj = this->operator T*();
djsollenf2b340f2016-01-29 08:51:04 -0800118 SkASSERT_RELEASE(nullptr != obj);
bungeman6bc2c942014-09-09 12:50:36 -0700119 }
120 explicit SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, D> >(obj) {}
bungemana6785cc2014-08-25 12:00:49 -0700121};
122
bungeman6bc2c942014-09-09 12:50:36 -0700123typedef SkAutoFc<FcCharSet, FcCharSetCreate, FcCharSetDestroy> SkAutoFcCharSet;
124typedef SkAutoFc<FcConfig, FcConfigCreate, FcConfigDestroy> SkAutoFcConfig;
125typedef SkAutoFc<FcFontSet, FcFontSetCreate, FcFontSetDestroy> SkAutoFcFontSet;
126typedef SkAutoFc<FcLangSet, FcLangSetCreate, FcLangSetDestroy> SkAutoFcLangSet;
127typedef SkAutoFc<FcObjectSet, FcObjectSetCreate, FcObjectSetDestroy> SkAutoFcObjectSet;
128typedef SkAutoFc<FcPattern, FcPatternCreate, FcPatternDestroy> SkAutoFcPattern;
bungemana6785cc2014-08-25 12:00:49 -0700129
bungemand3b63d32016-04-13 13:50:20 -0700130static bool get_bool(FcPattern* pattern, const char object[], bool missing = false) {
131 FcBool value;
132 if (FcPatternGetBool(pattern, object, 0, &value) != FcResultMatch) {
133 return missing;
134 }
135 return value;
136}
137
bungemana6785cc2014-08-25 12:00:49 -0700138static int get_int(FcPattern* pattern, const char object[], int missing) {
139 int value;
140 if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) {
141 return missing;
142 }
143 return value;
144}
145
146static const char* get_string(FcPattern* pattern, const char object[], const char* missing = "") {
147 FcChar8* value;
148 if (FcPatternGetString(pattern, object, 0, &value) != FcResultMatch) {
149 return missing;
150 }
151 return (const char*)value;
152}
153
bungemand3b63d32016-04-13 13:50:20 -0700154static const FcMatrix* get_matrix(FcPattern* pattern, const char object[]) {
155 FcMatrix* matrix;
156 if (FcPatternGetMatrix(pattern, object, 0, &matrix) != FcResultMatch) {
157 return nullptr;
158 }
159 return matrix;
160}
161
bungemana6785cc2014-08-25 12:00:49 -0700162enum SkWeakReturn {
163 kIsWeak_WeakReturn,
164 kIsStrong_WeakReturn,
165 kNoId_WeakReturn
166};
167/** Ideally there would exist a call like
168 * FcResult FcPatternIsWeak(pattern, object, id, FcBool* isWeak);
169 *
170 * However, there is no such call and as of Fc 2.11.0 even FcPatternEquals ignores the weak bit.
171 * Currently, the only reliable way of finding the weak bit is by its effect on matching.
172 * The weak bit only affects the matching of FC_FAMILY and FC_POSTSCRIPT_NAME object values.
173 * A element with the weak bit is scored after FC_LANG, without the weak bit is scored before.
174 * Note that the weak bit is stored on the element, not on the value it holds.
175 */
176static SkWeakReturn is_weak(FcPattern* pattern, const char object[], int id) {
177 FCLocker::AssertHeld();
178
179 FcResult result;
180
181 // Create a copy of the pattern with only the value 'pattern'['object'['id']] in it.
182 // Internally, FontConfig pattern objects are linked lists, so faster to remove from head.
halcanary96fcdcc2015-08-27 07:41:13 -0700183 SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, nullptr));
bungemana6785cc2014-08-25 12:00:49 -0700184 SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
185 FcBool hasId = true;
186 for (int i = 0; hasId && i < id; ++i) {
187 hasId = FcPatternRemove(minimal, object, 0);
188 }
189 if (!hasId) {
190 return kNoId_WeakReturn;
191 }
192 FcValue value;
193 result = FcPatternGet(minimal, object, 0, &value);
194 if (result != FcResultMatch) {
195 return kNoId_WeakReturn;
196 }
197 while (hasId) {
198 hasId = FcPatternRemove(minimal, object, 1);
199 }
200
201 // Create a font set with two patterns.
202 // 1. the same 'object' as minimal and a lang object with only 'nomatchlang'.
203 // 2. a different 'object' from minimal and a lang object with only 'matchlang'.
bungeman6bc2c942014-09-09 12:50:36 -0700204 SkAutoFcFontSet fontSet;
bungemana6785cc2014-08-25 12:00:49 -0700205
bungeman6bc2c942014-09-09 12:50:36 -0700206 SkAutoFcLangSet strongLangSet;
bungemana6785cc2014-08-25 12:00:49 -0700207 FcLangSetAdd(strongLangSet, (const FcChar8*)"nomatchlang");
208 SkAutoFcPattern strong(FcPatternDuplicate(minimal));
209 FcPatternAddLangSet(strong, FC_LANG, strongLangSet);
210
bungeman6bc2c942014-09-09 12:50:36 -0700211 SkAutoFcLangSet weakLangSet;
bungemana6785cc2014-08-25 12:00:49 -0700212 FcLangSetAdd(weakLangSet, (const FcChar8*)"matchlang");
bungeman6bc2c942014-09-09 12:50:36 -0700213 SkAutoFcPattern weak;
bungemana6785cc2014-08-25 12:00:49 -0700214 FcPatternAddString(weak, object, (const FcChar8*)"nomatchstring");
215 FcPatternAddLangSet(weak, FC_LANG, weakLangSet);
216
mtklein18300a32016-03-16 13:53:35 -0700217 FcFontSetAdd(fontSet, strong.release());
218 FcFontSetAdd(fontSet, weak.release());
bungemana6785cc2014-08-25 12:00:49 -0700219
220 // Add 'matchlang' to the copy of the pattern.
221 FcPatternAddLangSet(minimal, FC_LANG, weakLangSet);
222
223 // Run a match against the copy of the pattern.
224 // If the 'id' was weak, then we should match the pattern with 'matchlang'.
225 // If the 'id' was strong, then we should match the pattern with 'nomatchlang'.
226
227 // Note that this config is only used for FcFontRenderPrepare, which we don't even want.
228 // However, there appears to be no way to match/sort without it.
bungeman6bc2c942014-09-09 12:50:36 -0700229 SkAutoFcConfig config;
bungemana6785cc2014-08-25 12:00:49 -0700230 FcFontSet* fontSets[1] = { fontSet };
231 SkAutoFcPattern match(FcFontSetMatch(config, fontSets, SK_ARRAY_COUNT(fontSets),
232 minimal, &result));
233
234 FcLangSet* matchLangSet;
235 FcPatternGetLangSet(match, FC_LANG, 0, &matchLangSet);
236 return FcLangEqual == FcLangSetHasLang(matchLangSet, (const FcChar8*)"matchlang")
237 ? kIsWeak_WeakReturn : kIsStrong_WeakReturn;
238}
239
240/** Removes weak elements from either FC_FAMILY or FC_POSTSCRIPT_NAME objects in the property.
241 * This can be quite expensive, and should not be used more than once per font lookup.
242 * This removes all of the weak elements after the last strong element.
243 */
244static void remove_weak(FcPattern* pattern, const char object[]) {
245 FCLocker::AssertHeld();
246
halcanary96fcdcc2015-08-27 07:41:13 -0700247 SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, nullptr));
bungemana6785cc2014-08-25 12:00:49 -0700248 SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
249
250 int lastStrongId = -1;
251 int numIds;
252 SkWeakReturn result;
253 for (int id = 0; ; ++id) {
254 result = is_weak(minimal, object, 0);
255 if (kNoId_WeakReturn == result) {
256 numIds = id;
257 break;
258 }
259 if (kIsStrong_WeakReturn == result) {
260 lastStrongId = id;
261 }
262 SkAssertResult(FcPatternRemove(minimal, object, 0));
263 }
264
265 // If they were all weak, then leave the pattern alone.
266 if (lastStrongId < 0) {
267 return;
268 }
269
270 // Remove everything after the last strong.
271 for (int id = lastStrongId + 1; id < numIds; ++id) {
272 SkAssertResult(FcPatternRemove(pattern, object, lastStrongId + 1));
273 }
274}
275
276static int map_range(SkFixed value,
277 SkFixed old_min, SkFixed old_max,
278 SkFixed new_min, SkFixed new_max)
279{
280 SkASSERT(old_min < old_max);
281 SkASSERT(new_min <= new_max);
282 return new_min + SkMulDiv(value - old_min, new_max - new_min, old_max - old_min);
283}
284
bungemana6785cc2014-08-25 12:00:49 -0700285struct MapRanges {
286 SkFixed old_val;
287 SkFixed new_val;
288};
289
290static SkFixed map_ranges_fixed(SkFixed val, MapRanges const ranges[], int rangesCount) {
291 // -Inf to [0]
292 if (val < ranges[0].old_val) {
293 return ranges[0].new_val;
294 }
295
bungeman11a77c62016-04-12 13:45:06 -0700296 // Linear from [i] to [i+1]
bungemana6785cc2014-08-25 12:00:49 -0700297 for (int i = 0; i < rangesCount - 1; ++i) {
bungemana6785cc2014-08-25 12:00:49 -0700298 if (val < ranges[i+1].old_val) {
bungeman11a77c62016-04-12 13:45:06 -0700299 return map_range(val, ranges[i].old_val, ranges[i+1].old_val,
300 ranges[i].new_val, ranges[i+1].new_val);
bungemana6785cc2014-08-25 12:00:49 -0700301 }
302 }
303
304 // From [n] to +Inf
305 // if (fcweight < Inf)
306 return ranges[rangesCount-1].new_val;
307}
308
309static int map_ranges(int val, MapRanges const ranges[], int rangesCount) {
310 return SkFixedRoundToInt(map_ranges_fixed(SkIntToFixed(val), ranges, rangesCount));
311}
312
313template<int n> struct SkTFixed {
bungeman99fe8222015-08-20 07:57:51 -0700314 static_assert(-32768 <= n && n <= 32767, "SkTFixed_n_not_in_range");
bungemana6785cc2014-08-25 12:00:49 -0700315 static const SkFixed value = static_cast<SkFixed>(n << 16);
316};
317
318static SkFontStyle skfontstyle_from_fcpattern(FcPattern* pattern) {
319 typedef SkFontStyle SkFS;
320
321 static const MapRanges weightRanges[] = {
322 { SkTFixed<FC_WEIGHT_THIN>::value, SkTFixed<SkFS::kThin_Weight>::value },
323 { SkTFixed<FC_WEIGHT_EXTRALIGHT>::value, SkTFixed<SkFS::kExtraLight_Weight>::value },
324 { SkTFixed<FC_WEIGHT_LIGHT>::value, SkTFixed<SkFS::kLight_Weight>::value },
325 { SkTFixed<FC_WEIGHT_REGULAR>::value, SkTFixed<SkFS::kNormal_Weight>::value },
326 { SkTFixed<FC_WEIGHT_MEDIUM>::value, SkTFixed<SkFS::kMedium_Weight>::value },
327 { SkTFixed<FC_WEIGHT_DEMIBOLD>::value, SkTFixed<SkFS::kSemiBold_Weight>::value },
328 { SkTFixed<FC_WEIGHT_BOLD>::value, SkTFixed<SkFS::kBold_Weight>::value },
329 { SkTFixed<FC_WEIGHT_EXTRABOLD>::value, SkTFixed<SkFS::kExtraBold_Weight>::value },
330 { SkTFixed<FC_WEIGHT_BLACK>::value, SkTFixed<SkFS::kBlack_Weight>::value },
bungeman6e45bda2016-07-25 15:11:49 -0700331 { SkTFixed<FC_WEIGHT_EXTRABLACK>::value, SkTFixed<SkFS::kExtraBlack_Weight>::value },
bungemana6785cc2014-08-25 12:00:49 -0700332 };
333 int weight = map_ranges(get_int(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR),
334 weightRanges, SK_ARRAY_COUNT(weightRanges));
335
336 static const MapRanges widthRanges[] = {
337 { SkTFixed<FC_WIDTH_ULTRACONDENSED>::value, SkTFixed<SkFS::kUltraCondensed_Width>::value },
338 { SkTFixed<FC_WIDTH_EXTRACONDENSED>::value, SkTFixed<SkFS::kExtraCondensed_Width>::value },
339 { SkTFixed<FC_WIDTH_CONDENSED>::value, SkTFixed<SkFS::kCondensed_Width>::value },
340 { SkTFixed<FC_WIDTH_SEMICONDENSED>::value, SkTFixed<SkFS::kSemiCondensed_Width>::value },
341 { SkTFixed<FC_WIDTH_NORMAL>::value, SkTFixed<SkFS::kNormal_Width>::value },
342 { SkTFixed<FC_WIDTH_SEMIEXPANDED>::value, SkTFixed<SkFS::kSemiExpanded_Width>::value },
343 { SkTFixed<FC_WIDTH_EXPANDED>::value, SkTFixed<SkFS::kExpanded_Width>::value },
344 { SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value, SkTFixed<SkFS::kExtraExpanded_Width>::value },
bungemand783e082016-08-01 12:37:13 -0700345 { SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value, SkTFixed<SkFS::kUltraExpanded_Width>::value },
bungemana6785cc2014-08-25 12:00:49 -0700346 };
347 int width = map_ranges(get_int(pattern, FC_WIDTH, FC_WIDTH_NORMAL),
348 widthRanges, SK_ARRAY_COUNT(widthRanges));
349
bungemanb4bb7d82016-04-27 10:21:04 -0700350 SkFS::Slant slant = SkFS::kUpright_Slant;
351 switch (get_int(pattern, FC_SLANT, FC_SLANT_ROMAN)) {
352 case FC_SLANT_ROMAN: slant = SkFS::kUpright_Slant; break;
353 case FC_SLANT_ITALIC : slant = SkFS::kItalic_Slant ; break;
354 case FC_SLANT_OBLIQUE: slant = SkFS::kOblique_Slant; break;
355 default: SkASSERT(false); break;
356 }
bungemana6785cc2014-08-25 12:00:49 -0700357
358 return SkFontStyle(weight, width, slant);
359}
360
361static void fcpattern_from_skfontstyle(SkFontStyle style, FcPattern* pattern) {
362 FCLocker::AssertHeld();
363
364 typedef SkFontStyle SkFS;
365
366 static const MapRanges weightRanges[] = {
367 { SkTFixed<SkFS::kThin_Weight>::value, SkTFixed<FC_WEIGHT_THIN>::value },
368 { SkTFixed<SkFS::kExtraLight_Weight>::value, SkTFixed<FC_WEIGHT_EXTRALIGHT>::value },
369 { SkTFixed<SkFS::kLight_Weight>::value, SkTFixed<FC_WEIGHT_LIGHT>::value },
370 { SkTFixed<SkFS::kNormal_Weight>::value, SkTFixed<FC_WEIGHT_REGULAR>::value },
371 { SkTFixed<SkFS::kMedium_Weight>::value, SkTFixed<FC_WEIGHT_MEDIUM>::value },
372 { SkTFixed<SkFS::kSemiBold_Weight>::value, SkTFixed<FC_WEIGHT_DEMIBOLD>::value },
373 { SkTFixed<SkFS::kBold_Weight>::value, SkTFixed<FC_WEIGHT_BOLD>::value },
374 { SkTFixed<SkFS::kExtraBold_Weight>::value, SkTFixed<FC_WEIGHT_EXTRABOLD>::value },
375 { SkTFixed<SkFS::kBlack_Weight>::value, SkTFixed<FC_WEIGHT_BLACK>::value },
bungeman6e45bda2016-07-25 15:11:49 -0700376 { SkTFixed<SkFS::kExtraBlack_Weight>::value, SkTFixed<FC_WEIGHT_EXTRABLACK>::value },
bungemana6785cc2014-08-25 12:00:49 -0700377 };
378 int weight = map_ranges(style.weight(), weightRanges, SK_ARRAY_COUNT(weightRanges));
379
380 static const MapRanges widthRanges[] = {
381 { SkTFixed<SkFS::kUltraCondensed_Width>::value, SkTFixed<FC_WIDTH_ULTRACONDENSED>::value },
382 { SkTFixed<SkFS::kExtraCondensed_Width>::value, SkTFixed<FC_WIDTH_EXTRACONDENSED>::value },
383 { SkTFixed<SkFS::kCondensed_Width>::value, SkTFixed<FC_WIDTH_CONDENSED>::value },
384 { SkTFixed<SkFS::kSemiCondensed_Width>::value, SkTFixed<FC_WIDTH_SEMICONDENSED>::value },
385 { SkTFixed<SkFS::kNormal_Width>::value, SkTFixed<FC_WIDTH_NORMAL>::value },
386 { SkTFixed<SkFS::kSemiExpanded_Width>::value, SkTFixed<FC_WIDTH_SEMIEXPANDED>::value },
387 { SkTFixed<SkFS::kExpanded_Width>::value, SkTFixed<FC_WIDTH_EXPANDED>::value },
388 { SkTFixed<SkFS::kExtraExpanded_Width>::value, SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value },
bungemand783e082016-08-01 12:37:13 -0700389 { SkTFixed<SkFS::kUltraExpanded_Width>::value, SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value },
bungemana6785cc2014-08-25 12:00:49 -0700390 };
391 int width = map_ranges(style.width(), widthRanges, SK_ARRAY_COUNT(widthRanges));
392
bungemanb4bb7d82016-04-27 10:21:04 -0700393 int slant = FC_SLANT_ROMAN;
394 switch (style.slant()) {
395 case SkFS::kUpright_Slant: slant = FC_SLANT_ROMAN ; break;
396 case SkFS::kItalic_Slant : slant = FC_SLANT_ITALIC ; break;
397 case SkFS::kOblique_Slant: slant = FC_SLANT_OBLIQUE; break;
398 default: SkASSERT(false); break;
399 }
400
bungemana6785cc2014-08-25 12:00:49 -0700401 FcPatternAddInteger(pattern, FC_WEIGHT, weight);
bungemanb4bb7d82016-04-27 10:21:04 -0700402 FcPatternAddInteger(pattern, FC_WIDTH , width);
403 FcPatternAddInteger(pattern, FC_SLANT , slant);
bungemana6785cc2014-08-25 12:00:49 -0700404}
405
bungemana6785cc2014-08-25 12:00:49 -0700406class SkTypeface_stream : public SkTypeface_FreeType {
407public:
bungeman41868fe2015-05-20 09:21:04 -0700408 /** @param data takes ownership of the font data.*/
Ben Wagner25272302017-01-25 11:15:50 -0500409 SkTypeface_stream(std::unique_ptr<SkFontData> data,
410 SkString familyName, const SkFontStyle& style, bool fixedWidth)
bungemane3aea102016-07-13 05:16:58 -0700411 : INHERITED(style, fixedWidth)
Ben Wagner25272302017-01-25 11:15:50 -0500412 , fFamilyName(std::move(familyName))
bungemanf93d7112016-09-16 06:24:20 -0700413 , fData(std::move(data))
Mike Kleinfc6c37b2016-09-27 09:34:10 -0400414 { }
bungemana6785cc2014-08-25 12:00:49 -0700415
mtklein36352bf2015-03-25 18:17:31 -0700416 void onGetFamilyName(SkString* familyName) const override {
Ben Wagner25272302017-01-25 11:15:50 -0500417 *familyName = fFamilyName;
bungemanb374d6a2014-09-17 07:48:59 -0700418 }
419
mtklein36352bf2015-03-25 18:17:31 -0700420 void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
bungemana6785cc2014-08-25 12:00:49 -0700421 *serialize = true;
422 }
423
mtklein36352bf2015-03-25 18:17:31 -0700424 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman41868fe2015-05-20 09:21:04 -0700425 *ttcIndex = fData->getIndex();
bungemanf93d7112016-09-16 06:24:20 -0700426 return fData->getStream()->duplicate();
bungeman41868fe2015-05-20 09:21:04 -0700427 }
428
bungemanf93d7112016-09-16 06:24:20 -0700429 std::unique_ptr<SkFontData> onMakeFontData() const override {
430 return skstd::make_unique<SkFontData>(*fData);
bungemana6785cc2014-08-25 12:00:49 -0700431 }
432
433private:
Ben Wagner25272302017-01-25 11:15:50 -0500434 SkString fFamilyName;
bungemanf93d7112016-09-16 06:24:20 -0700435 const std::unique_ptr<const SkFontData> fData;
bungemana6785cc2014-08-25 12:00:49 -0700436
437 typedef SkTypeface_FreeType INHERITED;
438};
439
440class SkTypeface_fontconfig : public SkTypeface_FreeType {
441public:
442 /** @param pattern takes ownership of the reference. */
443 static SkTypeface_fontconfig* Create(FcPattern* pattern) {
halcanary385fe4d2015-08-26 13:07:48 -0700444 return new SkTypeface_fontconfig(pattern);
bungemana6785cc2014-08-25 12:00:49 -0700445 }
446 mutable SkAutoFcPattern fPattern;
447
mtklein36352bf2015-03-25 18:17:31 -0700448 void onGetFamilyName(SkString* familyName) const override {
bungemanb374d6a2014-09-17 07:48:59 -0700449 *familyName = get_string(fPattern, FC_FAMILY);
450 }
451
mtklein36352bf2015-03-25 18:17:31 -0700452 void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
bungemana6785cc2014-08-25 12:00:49 -0700453 FCLocker lock;
454 desc->setFamilyName(get_string(fPattern, FC_FAMILY));
bungemana6785cc2014-08-25 12:00:49 -0700455 desc->setFullName(get_string(fPattern, FC_FULLNAME));
456 desc->setPostscriptName(get_string(fPattern, FC_POSTSCRIPT_NAME));
bungemanb8113782016-07-25 16:54:59 -0700457 desc->setStyle(this->fontStyle());
bungemana6785cc2014-08-25 12:00:49 -0700458 *serialize = false;
459 }
460
mtklein36352bf2015-03-25 18:17:31 -0700461 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungemana6785cc2014-08-25 12:00:49 -0700462 FCLocker lock;
463 *ttcIndex = get_int(fPattern, FC_INDEX, 0);
bungemanf93d7112016-09-16 06:24:20 -0700464 return SkStream::MakeFromFile(get_string(fPattern, FC_FILE)).release();
bungemana6785cc2014-08-25 12:00:49 -0700465 }
466
bungemand3b63d32016-04-13 13:50:20 -0700467 void onFilterRec(SkScalerContextRec* rec) const override {
468 const FcMatrix* fcMatrix = get_matrix(fPattern, FC_MATRIX);
469 if (fcMatrix) {
470 // fPost2x2 is column-major, left handed (y down).
471 // FcMatrix is column-major, right handed (y up).
472 SkMatrix fm;
473 fm.setAll(fcMatrix->xx,-fcMatrix->xy, 0,
474 -fcMatrix->yx, fcMatrix->yy, 0,
475 0 , 0 , 1);
476
477 SkMatrix sm;
478 rec->getMatrixFrom2x2(&sm);
479
480 sm.preConcat(fm);
481 rec->fPost2x2[0][0] = sm.getScaleX();
482 rec->fPost2x2[0][1] = sm.getSkewX();
483 rec->fPost2x2[1][0] = sm.getSkewY();
484 rec->fPost2x2[1][1] = sm.getScaleY();
485 }
486 if (get_bool(fPattern, FC_EMBOLDEN)) {
487 rec->fFlags |= SkScalerContext::kEmbolden_Flag;
488 }
489 this->INHERITED::onFilterRec(rec);
490 }
491
bungeman0b775822016-09-13 14:03:54 -0700492 SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(PerGlyphInfo perGlyphInfo,
493 const uint32_t* glyphIDs,
494 uint32_t glyphIDsCount) const override
495 {
496 SkAdvancedTypefaceMetrics* info =
497 this->INHERITED::onGetAdvancedTypefaceMetrics(perGlyphInfo, glyphIDs, glyphIDsCount);
498
499 // Simulated fonts shouldn't be considered to be of the type of their data.
500 if (get_matrix(fPattern, FC_MATRIX) || get_bool(fPattern, FC_EMBOLDEN)) {
501 info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
502 }
503 return info;
504 }
505
bungemana6785cc2014-08-25 12:00:49 -0700506 virtual ~SkTypeface_fontconfig() {
507 // Hold the lock while unrefing the pattern.
508 FCLocker lock;
509 fPattern.reset();
510 }
511
512private:
513 /** @param pattern takes ownership of the reference. */
514 SkTypeface_fontconfig(FcPattern* pattern)
bungemana4c4a2d2014-10-20 13:33:19 -0700515 : INHERITED(skfontstyle_from_fcpattern(pattern),
bungemana6785cc2014-08-25 12:00:49 -0700516 FC_PROPORTIONAL != get_int(pattern, FC_SPACING, FC_PROPORTIONAL))
517 , fPattern(pattern)
Mike Kleinfc6c37b2016-09-27 09:34:10 -0400518 { }
bungemana6785cc2014-08-25 12:00:49 -0700519
520 typedef SkTypeface_FreeType INHERITED;
521};
522
523class SkFontMgr_fontconfig : public SkFontMgr {
524 mutable SkAutoFcConfig fFC;
bungemanfeb3c1a2016-08-05 06:51:50 -0700525 sk_sp<SkDataTable> fFamilyNames;
bungeman14df8332014-10-28 15:07:23 -0700526 SkTypeface_FreeType::Scanner fScanner;
bungemana6785cc2014-08-25 12:00:49 -0700527
528 class StyleSet : public SkFontStyleSet {
529 public:
530 /** @param parent does not take ownership of the reference.
531 * @param fontSet takes ownership of the reference.
532 */
533 StyleSet(const SkFontMgr_fontconfig* parent, FcFontSet* fontSet)
534 : fFontMgr(SkRef(parent)), fFontSet(fontSet)
535 { }
536
537 virtual ~StyleSet() {
538 // Hold the lock while unrefing the font set.
539 FCLocker lock;
540 fFontSet.reset();
541 }
542
mtklein36352bf2015-03-25 18:17:31 -0700543 int count() override { return fFontSet->nfont; }
bungemana6785cc2014-08-25 12:00:49 -0700544
mtklein36352bf2015-03-25 18:17:31 -0700545 void getStyle(int index, SkFontStyle* style, SkString* styleName) override {
bungemana6785cc2014-08-25 12:00:49 -0700546 if (index < 0 || fFontSet->nfont <= index) {
547 return;
548 }
549
550 FCLocker lock;
551 if (style) {
552 *style = skfontstyle_from_fcpattern(fFontSet->fonts[index]);
553 }
554 if (styleName) {
555 *styleName = get_string(fFontSet->fonts[index], FC_STYLE);
556 }
557 }
558
mtklein36352bf2015-03-25 18:17:31 -0700559 SkTypeface* createTypeface(int index) override {
bungemana6785cc2014-08-25 12:00:49 -0700560 FCLocker lock;
561
562 FcPattern* match = fFontSet->fonts[index];
563 return fFontMgr->createTypefaceFromFcPattern(match);
564 }
565
mtklein36352bf2015-03-25 18:17:31 -0700566 SkTypeface* matchStyle(const SkFontStyle& style) override {
bungemana6785cc2014-08-25 12:00:49 -0700567 FCLocker lock;
568
bungeman6bc2c942014-09-09 12:50:36 -0700569 SkAutoFcPattern pattern;
bungemana6785cc2014-08-25 12:00:49 -0700570 fcpattern_from_skfontstyle(style, pattern);
571 FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern);
572 FcDefaultSubstitute(pattern);
573
574 FcResult result;
575 FcFontSet* fontSets[1] = { fFontSet };
576 SkAutoFcPattern match(FcFontSetMatch(fFontMgr->fFC,
577 fontSets, SK_ARRAY_COUNT(fontSets),
578 pattern, &result));
halcanary96fcdcc2015-08-27 07:41:13 -0700579 if (nullptr == match) {
580 return nullptr;
bungemana6785cc2014-08-25 12:00:49 -0700581 }
582
583 return fFontMgr->createTypefaceFromFcPattern(match);
584 }
585
586 private:
Hal Canary67b39de2016-11-07 11:47:44 -0500587 sk_sp<const SkFontMgr_fontconfig> fFontMgr;
bungemana6785cc2014-08-25 12:00:49 -0700588 SkAutoFcFontSet fFontSet;
589 };
590
591 static bool FindName(const SkTDArray<const char*>& list, const char* str) {
592 int count = list.count();
593 for (int i = 0; i < count; ++i) {
594 if (!strcmp(list[i], str)) {
595 return true;
596 }
597 }
598 return false;
599 }
600
bungemanfeb3c1a2016-08-05 06:51:50 -0700601 static sk_sp<SkDataTable> GetFamilyNames(FcConfig* fcconfig) {
bungemana6785cc2014-08-25 12:00:49 -0700602 FCLocker lock;
603
604 SkTDArray<const char*> names;
605 SkTDArray<size_t> sizes;
606
607 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
608 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
609 // Return value of FcConfigGetFonts must not be destroyed.
610 FcFontSet* allFonts(FcConfigGetFonts(fcconfig, fcNameSet[setIndex]));
halcanary96fcdcc2015-08-27 07:41:13 -0700611 if (nullptr == allFonts) {
bungemana6785cc2014-08-25 12:00:49 -0700612 continue;
613 }
614
615 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
616 FcPattern* current = allFonts->fonts[fontIndex];
617 for (int id = 0; ; ++id) {
618 FcChar8* fcFamilyName;
619 FcResult result = FcPatternGetString(current, FC_FAMILY, id, &fcFamilyName);
620 if (FcResultNoId == result) {
621 break;
622 }
623 if (FcResultMatch != result) {
624 continue;
625 }
626 const char* familyName = reinterpret_cast<const char*>(fcFamilyName);
627 if (familyName && !FindName(names, familyName)) {
628 *names.append() = familyName;
629 *sizes.append() = strlen(familyName) + 1;
630 }
631 }
632 }
633 }
634
bungemanfeb3c1a2016-08-05 06:51:50 -0700635 return SkDataTable::MakeCopyArrays((void const *const *)names.begin(),
636 sizes.begin(), names.count());
bungemana6785cc2014-08-25 12:00:49 -0700637 }
638
bungeman82a455f2016-04-14 08:04:45 -0700639 static bool FindByFcPattern(SkTypeface* cached, void* ctx) {
bungemana6785cc2014-08-25 12:00:49 -0700640 SkTypeface_fontconfig* cshFace = static_cast<SkTypeface_fontconfig*>(cached);
641 FcPattern* ctxPattern = static_cast<FcPattern*>(ctx);
642 return FcTrue == FcPatternEqual(cshFace->fPattern, ctxPattern);
643 }
644
645 mutable SkMutex fTFCacheMutex;
646 mutable SkTypefaceCache fTFCache;
647 /** Creates a typeface using a typeface cache.
648 * @param pattern a complete pattern from FcFontRenderPrepare.
649 */
650 SkTypeface* createTypefaceFromFcPattern(FcPattern* pattern) const {
651 FCLocker::AssertHeld();
652 SkAutoMutexAcquire ama(fTFCacheMutex);
653 SkTypeface* face = fTFCache.findByProcAndRef(FindByFcPattern, pattern);
halcanary96fcdcc2015-08-27 07:41:13 -0700654 if (nullptr == face) {
bungemana6785cc2014-08-25 12:00:49 -0700655 FcPatternReference(pattern);
656 face = SkTypeface_fontconfig::Create(pattern);
657 if (face) {
bungeman82a455f2016-04-14 08:04:45 -0700658 fTFCache.add(face);
bungemana6785cc2014-08-25 12:00:49 -0700659 }
660 }
661 return face;
662 }
663
664public:
bungemana6785cc2014-08-25 12:00:49 -0700665 /** Takes control of the reference to 'config'. */
666 explicit SkFontMgr_fontconfig(FcConfig* config)
bungeman0b1de262015-06-17 07:55:59 -0700667 : fFC(config ? config : FcInitLoadConfigAndFonts())
bungemana6785cc2014-08-25 12:00:49 -0700668 , fFamilyNames(GetFamilyNames(fFC)) { }
669
670 virtual ~SkFontMgr_fontconfig() {
671 // Hold the lock while unrefing the config.
672 FCLocker lock;
673 fFC.reset();
674 }
675
676protected:
mtklein36352bf2015-03-25 18:17:31 -0700677 int onCountFamilies() const override {
bungemana6785cc2014-08-25 12:00:49 -0700678 return fFamilyNames->count();
679 }
680
mtklein36352bf2015-03-25 18:17:31 -0700681 void onGetFamilyName(int index, SkString* familyName) const override {
bungemana6785cc2014-08-25 12:00:49 -0700682 familyName->set(fFamilyNames->atStr(index));
683 }
684
mtklein36352bf2015-03-25 18:17:31 -0700685 SkFontStyleSet* onCreateStyleSet(int index) const override {
bungemana6785cc2014-08-25 12:00:49 -0700686 return this->onMatchFamily(fFamilyNames->atStr(index));
687 }
688
689 /** True if any string object value in the font is the same
690 * as a string object value in the pattern.
691 */
692 static bool AnyMatching(FcPattern* font, FcPattern* pattern, const char* object) {
693 FcChar8* fontString;
694 FcChar8* patternString;
695 FcResult result;
696 // Set an arbitrary limit on the number of pattern object values to consider.
697 // TODO: re-write this to avoid N*M
698 static const int maxId = 16;
699 for (int patternId = 0; patternId < maxId; ++patternId) {
700 result = FcPatternGetString(pattern, object, patternId, &patternString);
701 if (FcResultNoId == result) {
702 break;
703 }
704 if (FcResultMatch != result) {
705 continue;
706 }
707 for (int fontId = 0; fontId < maxId; ++fontId) {
708 result = FcPatternGetString(font, object, fontId, &fontString);
709 if (FcResultNoId == result) {
710 break;
711 }
712 if (FcResultMatch != result) {
713 continue;
714 }
715 if (0 == FcStrCmpIgnoreCase(patternString, fontString)) {
716 return true;
717 }
718 }
719 }
720 return false;
721 }
722
bungeman6bc2c942014-09-09 12:50:36 -0700723 static bool FontAccessible(FcPattern* font) {
bungemana6785cc2014-08-25 12:00:49 -0700724 // FontConfig can return fonts which are unreadable.
halcanary96fcdcc2015-08-27 07:41:13 -0700725 const char* filename = get_string(font, FC_FILE, nullptr);
726 if (nullptr == filename) {
bungemana6785cc2014-08-25 12:00:49 -0700727 return false;
728 }
729 return sk_exists(filename, kRead_SkFILE_Flag);
730 }
731
bungeman6bc2c942014-09-09 12:50:36 -0700732 static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) {
733 return AnyMatching(font, pattern, FC_FAMILY);
734 }
735
736 static bool FontContainsCharacter(FcPattern* font, uint32_t character) {
737 FcResult result;
738 FcCharSet* matchCharSet;
739 for (int charSetId = 0; ; ++charSetId) {
740 result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchCharSet);
741 if (FcResultNoId == result) {
742 break;
743 }
744 if (FcResultMatch != result) {
745 continue;
746 }
747 if (FcCharSetHasChar(matchCharSet, character)) {
748 return true;
749 }
750 }
751 return false;
bungemana6785cc2014-08-25 12:00:49 -0700752 }
753
mtklein36352bf2015-03-25 18:17:31 -0700754 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
bungemana6785cc2014-08-25 12:00:49 -0700755 FCLocker lock;
756
bungeman6bc2c942014-09-09 12:50:36 -0700757 SkAutoFcPattern pattern;
bungemana6785cc2014-08-25 12:00:49 -0700758 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
759 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
760 FcDefaultSubstitute(pattern);
761
762 FcPattern* matchPattern;
halcanary96fcdcc2015-08-27 07:41:13 -0700763 SkAutoFcPattern strongPattern(nullptr);
bungemana6785cc2014-08-25 12:00:49 -0700764 if (familyName) {
765 strongPattern.reset(FcPatternDuplicate(pattern));
766 remove_weak(strongPattern, FC_FAMILY);
767 matchPattern = strongPattern;
768 } else {
769 matchPattern = pattern;
770 }
771
bungeman6bc2c942014-09-09 12:50:36 -0700772 SkAutoFcFontSet matches;
bungemana6785cc2014-08-25 12:00:49 -0700773 // TODO: Some families have 'duplicates' due to symbolic links.
774 // The patterns are exactly the same except for the FC_FILE.
775 // It should be possible to collapse these patterns by normalizing.
776 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
777 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
778 // Return value of FcConfigGetFonts must not be destroyed.
779 FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex]));
halcanary96fcdcc2015-08-27 07:41:13 -0700780 if (nullptr == allFonts) {
bungemana6785cc2014-08-25 12:00:49 -0700781 continue;
782 }
783
784 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
bungeman6bc2c942014-09-09 12:50:36 -0700785 FcPattern* font = allFonts->fonts[fontIndex];
786 if (FontAccessible(font) && FontFamilyNameMatches(font, matchPattern)) {
787 FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font));
bungemana6785cc2014-08-25 12:00:49 -0700788 }
789 }
790 }
791
mtklein18300a32016-03-16 13:53:35 -0700792 return new StyleSet(this, matches.release());
bungemana6785cc2014-08-25 12:00:49 -0700793 }
794
795 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700796 const SkFontStyle& style) const override
bungemana6785cc2014-08-25 12:00:49 -0700797 {
798 FCLocker lock;
799
bungeman6bc2c942014-09-09 12:50:36 -0700800 SkAutoFcPattern pattern;
bungemana6785cc2014-08-25 12:00:49 -0700801 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
802 fcpattern_from_skfontstyle(style, pattern);
803 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
804 FcDefaultSubstitute(pattern);
805
806 // We really want to match strong (prefered) and same (acceptable) only here.
807 // If a family name was specified, assume that any weak matches after the last strong match
808 // are weak (default) and ignore them.
809 // The reason for is that after substitution the pattern for 'sans-serif' looks like
810 // "wwwwwwwwwwwwwwswww" where there are many weak but preferred names, followed by defaults.
811 // So it is possible to have weakly matching but preferred names.
812 // In aliases, bindings are weak by default, so this is easy and common.
813 // If no family name was specified, we'll probably only get weak matches, but that's ok.
814 FcPattern* matchPattern;
halcanary96fcdcc2015-08-27 07:41:13 -0700815 SkAutoFcPattern strongPattern(nullptr);
bungemana6785cc2014-08-25 12:00:49 -0700816 if (familyName) {
817 strongPattern.reset(FcPatternDuplicate(pattern));
818 remove_weak(strongPattern, FC_FAMILY);
819 matchPattern = strongPattern;
820 } else {
821 matchPattern = pattern;
822 }
823
824 FcResult result;
bungeman6bc2c942014-09-09 12:50:36 -0700825 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
halcanary96fcdcc2015-08-27 07:41:13 -0700826 if (nullptr == font || !FontAccessible(font) || !FontFamilyNameMatches(font, matchPattern)) {
827 return nullptr;
bungemana6785cc2014-08-25 12:00:49 -0700828 }
829
bungeman6bc2c942014-09-09 12:50:36 -0700830 return createTypefaceFromFcPattern(font);
831 }
832
833 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
834 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700835 const char* bcp47[],
836 int bcp47Count,
mtklein36352bf2015-03-25 18:17:31 -0700837 SkUnichar character) const override
bungeman6bc2c942014-09-09 12:50:36 -0700838 {
839 FCLocker lock;
840
841 SkAutoFcPattern pattern;
bungeman6837b382015-04-29 14:35:49 -0700842 if (familyName) {
843 FcValue familyNameValue;
844 familyNameValue.type = FcTypeString;
845 familyNameValue.u.s = reinterpret_cast<const FcChar8*>(familyName);
846 FcPatternAddWeak(pattern, FC_FAMILY, familyNameValue, FcFalse);
847 }
bungeman6bc2c942014-09-09 12:50:36 -0700848 fcpattern_from_skfontstyle(style, pattern);
849
850 SkAutoFcCharSet charSet;
851 FcCharSetAddChar(charSet, character);
852 FcPatternAddCharSet(pattern, FC_CHARSET, charSet);
853
bungemanc20386e2014-10-23 07:08:05 -0700854 if (bcp47Count > 0) {
855 SkASSERT(bcp47);
bungeman6bc2c942014-09-09 12:50:36 -0700856 SkAutoFcLangSet langSet;
bungemanc20386e2014-10-23 07:08:05 -0700857 for (int i = bcp47Count; i --> 0;) {
858 FcLangSetAdd(langSet, (const FcChar8*)bcp47[i]);
859 }
bungeman6bc2c942014-09-09 12:50:36 -0700860 FcPatternAddLangSet(pattern, FC_LANG, langSet);
861 }
862
863 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
864 FcDefaultSubstitute(pattern);
865
866 FcResult result;
867 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
halcanary96fcdcc2015-08-27 07:41:13 -0700868 if (nullptr == font || !FontAccessible(font) || !FontContainsCharacter(font, character)) {
869 return nullptr;
bungeman6bc2c942014-09-09 12:50:36 -0700870 }
871
872 return createTypefaceFromFcPattern(font);
bungemana6785cc2014-08-25 12:00:49 -0700873 }
874
875 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
mtklein36352bf2015-03-25 18:17:31 -0700876 const SkFontStyle& style) const override
bungemana6785cc2014-08-25 12:00:49 -0700877 {
878 //TODO: should the SkTypeface_fontconfig know its family?
bungemanb14e4a02014-09-18 13:57:20 -0700879 const SkTypeface_fontconfig* fcTypeface =
bungeman9db50922014-09-12 12:14:14 -0700880 static_cast<const SkTypeface_fontconfig*>(typeface);
bungemanb14e4a02014-09-18 13:57:20 -0700881 return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY), style);
bungemana6785cc2014-08-25 12:00:49 -0700882 }
883
mtklein36352bf2015-03-25 18:17:31 -0700884 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
bungemanf93d7112016-09-16 06:24:20 -0700885 std::unique_ptr<SkStreamAsset> stream(bareStream);
bungemana6785cc2014-08-25 12:00:49 -0700886 const size_t length = stream->getLength();
887 if (length <= 0 || (1u << 30) < length) {
halcanary96fcdcc2015-08-27 07:41:13 -0700888 return nullptr;
bungemana6785cc2014-08-25 12:00:49 -0700889 }
890
Ben Wagner25272302017-01-25 11:15:50 -0500891 SkString name;
bungemana4c4a2d2014-10-20 13:33:19 -0700892 SkFontStyle style;
bungemana6785cc2014-08-25 12:00:49 -0700893 bool isFixedWidth = false;
Ben Wagner25272302017-01-25 11:15:50 -0500894 if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedWidth, nullptr)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700895 return nullptr;
bungemana6785cc2014-08-25 12:00:49 -0700896 }
897
bungemanf93d7112016-09-16 06:24:20 -0700898 auto data = skstd::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
Ben Wagner25272302017-01-25 11:15:50 -0500899 return new SkTypeface_stream(std::move(data), std::move(name), style, isFixedWidth);
bungemana6785cc2014-08-25 12:00:49 -0700900 }
901
Ben Wagnerfc497342017-02-24 11:15:26 -0500902 SkTypeface* onCreateFromStream(SkStreamAsset* s, const SkFontArguments& args) const override {
bungemanf6c71072016-01-21 14:17:47 -0800903 using Scanner = SkTypeface_FreeType::Scanner;
bungemanf93d7112016-09-16 06:24:20 -0700904 std::unique_ptr<SkStreamAsset> stream(s);
bungemanf6c71072016-01-21 14:17:47 -0800905 bool isFixedPitch;
906 SkFontStyle style;
907 SkString name;
908 Scanner::AxisDefinitions axisDefinitions;
Ben Wagnerfc497342017-02-24 11:15:26 -0500909 if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
bungemanf93d7112016-09-16 06:24:20 -0700910 &name, &style, &isFixedPitch, &axisDefinitions))
bungemanf6c71072016-01-21 14:17:47 -0800911 {
912 return nullptr;
913 }
914
bungemanf6c71072016-01-21 14:17:47 -0800915 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
Ben Wagnerfc497342017-02-24 11:15:26 -0500916 Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(),
917 axisValues, name);
bungemanf6c71072016-01-21 14:17:47 -0800918
Ben Wagnerfc497342017-02-24 11:15:26 -0500919 auto data = skstd::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
bungemanf93d7112016-09-16 06:24:20 -0700920 axisValues.get(), axisDefinitions.count());
Ben Wagner25272302017-01-25 11:15:50 -0500921 return new SkTypeface_stream(std::move(data), std::move(name), style, isFixedPitch);
bungemanf6c71072016-01-21 14:17:47 -0800922 }
923
mtklein36352bf2015-03-25 18:17:31 -0700924 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
reed42943c82016-09-12 12:01:44 -0700925 return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex);
bungemana6785cc2014-08-25 12:00:49 -0700926 }
927
mtklein36352bf2015-03-25 18:17:31 -0700928 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
bungemanf93d7112016-09-16 06:24:20 -0700929 return this->createFromStream(SkStream::MakeFromFile(path).release(), ttcIndex);
bungemana6785cc2014-08-25 12:00:49 -0700930 }
931
bungemanf93d7112016-09-16 06:24:20 -0700932 SkTypeface* onCreateFromFontData(std::unique_ptr<SkFontData> fontData) const override {
bungeman41868fe2015-05-20 09:21:04 -0700933 SkStreamAsset* stream(fontData->getStream());
934 const size_t length = stream->getLength();
935 if (length <= 0 || (1u << 30) < length) {
halcanary96fcdcc2015-08-27 07:41:13 -0700936 return nullptr;
bungeman41868fe2015-05-20 09:21:04 -0700937 }
938
939 const int ttcIndex = fontData->getIndex();
Ben Wagner25272302017-01-25 11:15:50 -0500940 SkString name;
bungeman41868fe2015-05-20 09:21:04 -0700941 SkFontStyle style;
942 bool isFixedWidth = false;
Ben Wagner25272302017-01-25 11:15:50 -0500943 if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedWidth, nullptr)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700944 return nullptr;
bungeman41868fe2015-05-20 09:21:04 -0700945 }
946
Ben Wagner25272302017-01-25 11:15:50 -0500947 return new SkTypeface_stream(std::move(fontData), std::move(name), style, isFixedWidth);
bungeman41868fe2015-05-20 09:21:04 -0700948 }
949
bungeman11a77c62016-04-12 13:45:06 -0700950 SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override {
Hal Canary67b39de2016-11-07 11:47:44 -0500951 sk_sp<SkTypeface> typeface(this->matchFamilyStyle(familyName, style));
bsalomon49f085d2014-09-05 13:34:00 -0700952 if (typeface.get()) {
mtklein18300a32016-03-16 13:53:35 -0700953 return typeface.release();
bungemana6785cc2014-08-25 12:00:49 -0700954 }
955
halcanary96fcdcc2015-08-27 07:41:13 -0700956 return this->matchFamilyStyle(nullptr, style);
bungemana6785cc2014-08-25 12:00:49 -0700957 }
958};
959
Ben Wagner3546ff12017-01-03 13:32:36 -0500960SK_API sk_sp<SkFontMgr> SkFontMgr_New_FontConfig(FcConfig* fc) {
961 return sk_make_sp<SkFontMgr_fontconfig>(fc);
962}