blob: 610a3001fb2c66e5df68e2fe08f0c34d7c0644f0 [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
8#include "SkDataTable.h"
bungemanf20488b2015-07-29 11:49:40 -07009#include "SkFixed.h"
bungemana6785cc2014-08-25 12:00:49 -070010#include "SkFontDescriptor.h"
11#include "SkFontHost_FreeType_common.h"
12#include "SkFontMgr.h"
13#include "SkFontStyle.h"
14#include "SkMath.h"
mtklein1b249332015-07-07 12:21:21 -070015#include "SkMutex.h"
bungemana6785cc2014-08-25 12:00:49 -070016#include "SkOSFile.h"
bungemanf20488b2015-07-29 11:49:40 -070017#include "SkRefCnt.h"
18#include "SkStream.h"
19#include "SkString.h"
20#include "SkTDArray.h"
21#include "SkTemplates.h"
22#include "SkTypeface.h"
23#include "SkTypefaceCache.h"
24#include "SkTypes.h"
bungemana6785cc2014-08-25 12:00:49 -070025
26#include <fontconfig/fontconfig.h>
bungemanf20488b2015-07-29 11:49:40 -070027#include <string.h>
28
29class SkData;
bungemana6785cc2014-08-25 12:00:49 -070030
31// FC_POSTSCRIPT_NAME was added with b561ff20 which ended up in 2.10.92
32// Ubuntu 12.04 is on 2.8.0, 13.10 is on 2.10.93
33// Debian 7 is on 2.9.0, 8 is on 2.11
34// OpenSUSE 12.2 is on 2.9.0, 12.3 is on 2.10.2, 13.1 2.11.0
35// Fedora 19 is on 2.10.93
36#ifndef FC_POSTSCRIPT_NAME
37# define FC_POSTSCRIPT_NAME "postscriptname"
38#endif
39
40#ifdef SK_DEBUG
41# include "SkTLS.h"
42#endif
43
44/** Since FontConfig is poorly documented, this gives a high level overview:
45 *
46 * FcConfig is a handle to a FontConfig configuration instance. Each 'configuration' is independent
47 * from any others which may exist. There exists a default global configuration which is created
48 * and destroyed by FcInit and FcFini, but this default should not normally be used.
49 * Instead, one should use FcConfigCreate and FcInit* to have a named local state.
50 *
51 * FcPatterns are {objectName -> [element]} (maps from object names to a list of elements).
52 * Each element is some internal data plus an FcValue which is a variant (a union with a type tag).
53 * Lists of elements are not typed, except by convention. Any collection of FcValues must be
54 * assumed to be heterogeneous by the code, but the code need not do anything particularly
55 * interesting if the values go against convention.
56 *
57 * Somewhat like DirectWrite, FontConfig supports synthetics through FC_EMBOLDEN and FC_MATRIX.
58 * Like all synthetic information, such information must be passed with the font data.
59 */
60
61namespace {
62
63// Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a global mutex.
halcanary6950de62015-11-07 05:29:00 -080064// See https://bug.skia.org/1497 for background.
reed086eea92016-05-04 17:12:46 -070065SK_DECLARE_STATIC_MUTEX(gFCMutex);
bungemana6785cc2014-08-25 12:00:49 -070066
67#ifdef SK_DEBUG
halcanary385fe4d2015-08-26 13:07:48 -070068void* CreateThreadFcLocked() { return new bool(false); }
69void DeleteThreadFcLocked(void* v) { delete static_cast<bool*>(v); }
bungemana6785cc2014-08-25 12:00:49 -070070# define THREAD_FC_LOCKED \
71 static_cast<bool*>(SkTLS::Get(CreateThreadFcLocked, DeleteThreadFcLocked))
72#endif
73
74struct FCLocker {
75 // Assume FcGetVersion() has always been thread safe.
76
77 FCLocker() {
78 if (FcGetVersion() < 21091) {
79 gFCMutex.acquire();
80 } else {
81 SkDEBUGCODE(bool* threadLocked = THREAD_FC_LOCKED);
82 SkASSERT(false == *threadLocked);
83 SkDEBUGCODE(*threadLocked = true);
84 }
85 }
86
87 ~FCLocker() {
88 AssertHeld();
89 if (FcGetVersion() < 21091) {
90 gFCMutex.release();
91 } else {
92 SkDEBUGCODE(*THREAD_FC_LOCKED = false);
93 }
94 }
95
96 static void AssertHeld() { SkDEBUGCODE(
97 if (FcGetVersion() < 21091) {
98 gFCMutex.assertHeld();
99 } else {
100 SkASSERT(true == *THREAD_FC_LOCKED);
101 }
102 ) }
103};
104
105} // namespace
106
bungeman6bc2c942014-09-09 12:50:36 -0700107template<typename T, void (*D)(T*)> void FcTDestroy(T* t) {
bungemana6785cc2014-08-25 12:00:49 -0700108 FCLocker::AssertHeld();
bungeman6bc2c942014-09-09 12:50:36 -0700109 D(t);
bungemana6785cc2014-08-25 12:00:49 -0700110}
bungeman6bc2c942014-09-09 12:50:36 -0700111template <typename T, T* (*C)(), void (*D)(T*)> class SkAutoFc
112 : public SkAutoTCallVProc<T, FcTDestroy<T, D> > {
bungemana6785cc2014-08-25 12:00:49 -0700113public:
bungeman6bc2c942014-09-09 12:50:36 -0700114 SkAutoFc() : SkAutoTCallVProc<T, FcTDestroy<T, D> >(C()) {
115 T* obj = this->operator T*();
djsollenf2b340f2016-01-29 08:51:04 -0800116 SkASSERT_RELEASE(nullptr != obj);
bungeman6bc2c942014-09-09 12:50:36 -0700117 }
118 explicit SkAutoFc(T* obj) : SkAutoTCallVProc<T, FcTDestroy<T, D> >(obj) {}
bungemana6785cc2014-08-25 12:00:49 -0700119};
120
bungeman6bc2c942014-09-09 12:50:36 -0700121typedef SkAutoFc<FcCharSet, FcCharSetCreate, FcCharSetDestroy> SkAutoFcCharSet;
122typedef SkAutoFc<FcConfig, FcConfigCreate, FcConfigDestroy> SkAutoFcConfig;
123typedef SkAutoFc<FcFontSet, FcFontSetCreate, FcFontSetDestroy> SkAutoFcFontSet;
124typedef SkAutoFc<FcLangSet, FcLangSetCreate, FcLangSetDestroy> SkAutoFcLangSet;
125typedef SkAutoFc<FcObjectSet, FcObjectSetCreate, FcObjectSetDestroy> SkAutoFcObjectSet;
126typedef SkAutoFc<FcPattern, FcPatternCreate, FcPatternDestroy> SkAutoFcPattern;
bungemana6785cc2014-08-25 12:00:49 -0700127
bungemand3b63d32016-04-13 13:50:20 -0700128static bool get_bool(FcPattern* pattern, const char object[], bool missing = false) {
129 FcBool value;
130 if (FcPatternGetBool(pattern, object, 0, &value) != FcResultMatch) {
131 return missing;
132 }
133 return value;
134}
135
bungemana6785cc2014-08-25 12:00:49 -0700136static int get_int(FcPattern* pattern, const char object[], int missing) {
137 int value;
138 if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) {
139 return missing;
140 }
141 return value;
142}
143
144static const char* get_string(FcPattern* pattern, const char object[], const char* missing = "") {
145 FcChar8* value;
146 if (FcPatternGetString(pattern, object, 0, &value) != FcResultMatch) {
147 return missing;
148 }
149 return (const char*)value;
150}
151
bungemand3b63d32016-04-13 13:50:20 -0700152static const FcMatrix* get_matrix(FcPattern* pattern, const char object[]) {
153 FcMatrix* matrix;
154 if (FcPatternGetMatrix(pattern, object, 0, &matrix) != FcResultMatch) {
155 return nullptr;
156 }
157 return matrix;
158}
159
bungemana6785cc2014-08-25 12:00:49 -0700160enum SkWeakReturn {
161 kIsWeak_WeakReturn,
162 kIsStrong_WeakReturn,
163 kNoId_WeakReturn
164};
165/** Ideally there would exist a call like
166 * FcResult FcPatternIsWeak(pattern, object, id, FcBool* isWeak);
167 *
168 * However, there is no such call and as of Fc 2.11.0 even FcPatternEquals ignores the weak bit.
169 * Currently, the only reliable way of finding the weak bit is by its effect on matching.
170 * The weak bit only affects the matching of FC_FAMILY and FC_POSTSCRIPT_NAME object values.
171 * A element with the weak bit is scored after FC_LANG, without the weak bit is scored before.
172 * Note that the weak bit is stored on the element, not on the value it holds.
173 */
174static SkWeakReturn is_weak(FcPattern* pattern, const char object[], int id) {
175 FCLocker::AssertHeld();
176
177 FcResult result;
178
179 // Create a copy of the pattern with only the value 'pattern'['object'['id']] in it.
180 // Internally, FontConfig pattern objects are linked lists, so faster to remove from head.
halcanary96fcdcc2015-08-27 07:41:13 -0700181 SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, nullptr));
bungemana6785cc2014-08-25 12:00:49 -0700182 SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
183 FcBool hasId = true;
184 for (int i = 0; hasId && i < id; ++i) {
185 hasId = FcPatternRemove(minimal, object, 0);
186 }
187 if (!hasId) {
188 return kNoId_WeakReturn;
189 }
190 FcValue value;
191 result = FcPatternGet(minimal, object, 0, &value);
192 if (result != FcResultMatch) {
193 return kNoId_WeakReturn;
194 }
195 while (hasId) {
196 hasId = FcPatternRemove(minimal, object, 1);
197 }
198
199 // Create a font set with two patterns.
200 // 1. the same 'object' as minimal and a lang object with only 'nomatchlang'.
201 // 2. a different 'object' from minimal and a lang object with only 'matchlang'.
bungeman6bc2c942014-09-09 12:50:36 -0700202 SkAutoFcFontSet fontSet;
bungemana6785cc2014-08-25 12:00:49 -0700203
bungeman6bc2c942014-09-09 12:50:36 -0700204 SkAutoFcLangSet strongLangSet;
bungemana6785cc2014-08-25 12:00:49 -0700205 FcLangSetAdd(strongLangSet, (const FcChar8*)"nomatchlang");
206 SkAutoFcPattern strong(FcPatternDuplicate(minimal));
207 FcPatternAddLangSet(strong, FC_LANG, strongLangSet);
208
bungeman6bc2c942014-09-09 12:50:36 -0700209 SkAutoFcLangSet weakLangSet;
bungemana6785cc2014-08-25 12:00:49 -0700210 FcLangSetAdd(weakLangSet, (const FcChar8*)"matchlang");
bungeman6bc2c942014-09-09 12:50:36 -0700211 SkAutoFcPattern weak;
bungemana6785cc2014-08-25 12:00:49 -0700212 FcPatternAddString(weak, object, (const FcChar8*)"nomatchstring");
213 FcPatternAddLangSet(weak, FC_LANG, weakLangSet);
214
mtklein18300a32016-03-16 13:53:35 -0700215 FcFontSetAdd(fontSet, strong.release());
216 FcFontSetAdd(fontSet, weak.release());
bungemana6785cc2014-08-25 12:00:49 -0700217
218 // Add 'matchlang' to the copy of the pattern.
219 FcPatternAddLangSet(minimal, FC_LANG, weakLangSet);
220
221 // Run a match against the copy of the pattern.
222 // If the 'id' was weak, then we should match the pattern with 'matchlang'.
223 // If the 'id' was strong, then we should match the pattern with 'nomatchlang'.
224
225 // Note that this config is only used for FcFontRenderPrepare, which we don't even want.
226 // However, there appears to be no way to match/sort without it.
bungeman6bc2c942014-09-09 12:50:36 -0700227 SkAutoFcConfig config;
bungemana6785cc2014-08-25 12:00:49 -0700228 FcFontSet* fontSets[1] = { fontSet };
229 SkAutoFcPattern match(FcFontSetMatch(config, fontSets, SK_ARRAY_COUNT(fontSets),
230 minimal, &result));
231
232 FcLangSet* matchLangSet;
233 FcPatternGetLangSet(match, FC_LANG, 0, &matchLangSet);
234 return FcLangEqual == FcLangSetHasLang(matchLangSet, (const FcChar8*)"matchlang")
235 ? kIsWeak_WeakReturn : kIsStrong_WeakReturn;
236}
237
238/** Removes weak elements from either FC_FAMILY or FC_POSTSCRIPT_NAME objects in the property.
239 * This can be quite expensive, and should not be used more than once per font lookup.
240 * This removes all of the weak elements after the last strong element.
241 */
242static void remove_weak(FcPattern* pattern, const char object[]) {
243 FCLocker::AssertHeld();
244
halcanary96fcdcc2015-08-27 07:41:13 -0700245 SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, nullptr));
bungemana6785cc2014-08-25 12:00:49 -0700246 SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
247
248 int lastStrongId = -1;
249 int numIds;
250 SkWeakReturn result;
251 for (int id = 0; ; ++id) {
252 result = is_weak(minimal, object, 0);
253 if (kNoId_WeakReturn == result) {
254 numIds = id;
255 break;
256 }
257 if (kIsStrong_WeakReturn == result) {
258 lastStrongId = id;
259 }
260 SkAssertResult(FcPatternRemove(minimal, object, 0));
261 }
262
263 // If they were all weak, then leave the pattern alone.
264 if (lastStrongId < 0) {
265 return;
266 }
267
268 // Remove everything after the last strong.
269 for (int id = lastStrongId + 1; id < numIds; ++id) {
270 SkAssertResult(FcPatternRemove(pattern, object, lastStrongId + 1));
271 }
272}
273
274static int map_range(SkFixed value,
275 SkFixed old_min, SkFixed old_max,
276 SkFixed new_min, SkFixed new_max)
277{
278 SkASSERT(old_min < old_max);
279 SkASSERT(new_min <= new_max);
280 return new_min + SkMulDiv(value - old_min, new_max - new_min, old_max - old_min);
281}
282
bungemana6785cc2014-08-25 12:00:49 -0700283struct MapRanges {
284 SkFixed old_val;
285 SkFixed new_val;
286};
287
288static SkFixed map_ranges_fixed(SkFixed val, MapRanges const ranges[], int rangesCount) {
289 // -Inf to [0]
290 if (val < ranges[0].old_val) {
291 return ranges[0].new_val;
292 }
293
bungeman11a77c62016-04-12 13:45:06 -0700294 // Linear from [i] to [i+1]
bungemana6785cc2014-08-25 12:00:49 -0700295 for (int i = 0; i < rangesCount - 1; ++i) {
bungemana6785cc2014-08-25 12:00:49 -0700296 if (val < ranges[i+1].old_val) {
bungeman11a77c62016-04-12 13:45:06 -0700297 return map_range(val, ranges[i].old_val, ranges[i+1].old_val,
298 ranges[i].new_val, ranges[i+1].new_val);
bungemana6785cc2014-08-25 12:00:49 -0700299 }
300 }
301
302 // From [n] to +Inf
303 // if (fcweight < Inf)
304 return ranges[rangesCount-1].new_val;
305}
306
307static int map_ranges(int val, MapRanges const ranges[], int rangesCount) {
308 return SkFixedRoundToInt(map_ranges_fixed(SkIntToFixed(val), ranges, rangesCount));
309}
310
311template<int n> struct SkTFixed {
bungeman99fe8222015-08-20 07:57:51 -0700312 static_assert(-32768 <= n && n <= 32767, "SkTFixed_n_not_in_range");
bungemana6785cc2014-08-25 12:00:49 -0700313 static const SkFixed value = static_cast<SkFixed>(n << 16);
314};
315
316static SkFontStyle skfontstyle_from_fcpattern(FcPattern* pattern) {
317 typedef SkFontStyle SkFS;
318
319 static const MapRanges weightRanges[] = {
320 { SkTFixed<FC_WEIGHT_THIN>::value, SkTFixed<SkFS::kThin_Weight>::value },
321 { SkTFixed<FC_WEIGHT_EXTRALIGHT>::value, SkTFixed<SkFS::kExtraLight_Weight>::value },
322 { SkTFixed<FC_WEIGHT_LIGHT>::value, SkTFixed<SkFS::kLight_Weight>::value },
323 { SkTFixed<FC_WEIGHT_REGULAR>::value, SkTFixed<SkFS::kNormal_Weight>::value },
324 { SkTFixed<FC_WEIGHT_MEDIUM>::value, SkTFixed<SkFS::kMedium_Weight>::value },
325 { SkTFixed<FC_WEIGHT_DEMIBOLD>::value, SkTFixed<SkFS::kSemiBold_Weight>::value },
326 { SkTFixed<FC_WEIGHT_BOLD>::value, SkTFixed<SkFS::kBold_Weight>::value },
327 { SkTFixed<FC_WEIGHT_EXTRABOLD>::value, SkTFixed<SkFS::kExtraBold_Weight>::value },
328 { SkTFixed<FC_WEIGHT_BLACK>::value, SkTFixed<SkFS::kBlack_Weight>::value },
329 { SkTFixed<FC_WEIGHT_EXTRABLACK>::value, SkTFixed<1000>::value },
330 };
331 int weight = map_ranges(get_int(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR),
332 weightRanges, SK_ARRAY_COUNT(weightRanges));
333
334 static const MapRanges widthRanges[] = {
335 { SkTFixed<FC_WIDTH_ULTRACONDENSED>::value, SkTFixed<SkFS::kUltraCondensed_Width>::value },
336 { SkTFixed<FC_WIDTH_EXTRACONDENSED>::value, SkTFixed<SkFS::kExtraCondensed_Width>::value },
337 { SkTFixed<FC_WIDTH_CONDENSED>::value, SkTFixed<SkFS::kCondensed_Width>::value },
338 { SkTFixed<FC_WIDTH_SEMICONDENSED>::value, SkTFixed<SkFS::kSemiCondensed_Width>::value },
339 { SkTFixed<FC_WIDTH_NORMAL>::value, SkTFixed<SkFS::kNormal_Width>::value },
340 { SkTFixed<FC_WIDTH_SEMIEXPANDED>::value, SkTFixed<SkFS::kSemiExpanded_Width>::value },
341 { SkTFixed<FC_WIDTH_EXPANDED>::value, SkTFixed<SkFS::kExpanded_Width>::value },
342 { SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value, SkTFixed<SkFS::kExtraExpanded_Width>::value },
343 { SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value, SkTFixed<SkFS::kUltaExpanded_Width>::value },
344 };
345 int width = map_ranges(get_int(pattern, FC_WIDTH, FC_WIDTH_NORMAL),
346 widthRanges, SK_ARRAY_COUNT(widthRanges));
347
bungemanb4bb7d82016-04-27 10:21:04 -0700348 SkFS::Slant slant = SkFS::kUpright_Slant;
349 switch (get_int(pattern, FC_SLANT, FC_SLANT_ROMAN)) {
350 case FC_SLANT_ROMAN: slant = SkFS::kUpright_Slant; break;
351 case FC_SLANT_ITALIC : slant = SkFS::kItalic_Slant ; break;
352 case FC_SLANT_OBLIQUE: slant = SkFS::kOblique_Slant; break;
353 default: SkASSERT(false); break;
354 }
bungemana6785cc2014-08-25 12:00:49 -0700355
356 return SkFontStyle(weight, width, slant);
357}
358
359static void fcpattern_from_skfontstyle(SkFontStyle style, FcPattern* pattern) {
360 FCLocker::AssertHeld();
361
362 typedef SkFontStyle SkFS;
363
364 static const MapRanges weightRanges[] = {
365 { SkTFixed<SkFS::kThin_Weight>::value, SkTFixed<FC_WEIGHT_THIN>::value },
366 { SkTFixed<SkFS::kExtraLight_Weight>::value, SkTFixed<FC_WEIGHT_EXTRALIGHT>::value },
367 { SkTFixed<SkFS::kLight_Weight>::value, SkTFixed<FC_WEIGHT_LIGHT>::value },
368 { SkTFixed<SkFS::kNormal_Weight>::value, SkTFixed<FC_WEIGHT_REGULAR>::value },
369 { SkTFixed<SkFS::kMedium_Weight>::value, SkTFixed<FC_WEIGHT_MEDIUM>::value },
370 { SkTFixed<SkFS::kSemiBold_Weight>::value, SkTFixed<FC_WEIGHT_DEMIBOLD>::value },
371 { SkTFixed<SkFS::kBold_Weight>::value, SkTFixed<FC_WEIGHT_BOLD>::value },
372 { SkTFixed<SkFS::kExtraBold_Weight>::value, SkTFixed<FC_WEIGHT_EXTRABOLD>::value },
373 { SkTFixed<SkFS::kBlack_Weight>::value, SkTFixed<FC_WEIGHT_BLACK>::value },
374 { SkTFixed<1000>::value, SkTFixed<FC_WEIGHT_EXTRABLACK>::value },
375 };
376 int weight = map_ranges(style.weight(), weightRanges, SK_ARRAY_COUNT(weightRanges));
377
378 static const MapRanges widthRanges[] = {
379 { SkTFixed<SkFS::kUltraCondensed_Width>::value, SkTFixed<FC_WIDTH_ULTRACONDENSED>::value },
380 { SkTFixed<SkFS::kExtraCondensed_Width>::value, SkTFixed<FC_WIDTH_EXTRACONDENSED>::value },
381 { SkTFixed<SkFS::kCondensed_Width>::value, SkTFixed<FC_WIDTH_CONDENSED>::value },
382 { SkTFixed<SkFS::kSemiCondensed_Width>::value, SkTFixed<FC_WIDTH_SEMICONDENSED>::value },
383 { SkTFixed<SkFS::kNormal_Width>::value, SkTFixed<FC_WIDTH_NORMAL>::value },
384 { SkTFixed<SkFS::kSemiExpanded_Width>::value, SkTFixed<FC_WIDTH_SEMIEXPANDED>::value },
385 { SkTFixed<SkFS::kExpanded_Width>::value, SkTFixed<FC_WIDTH_EXPANDED>::value },
386 { SkTFixed<SkFS::kExtraExpanded_Width>::value, SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value },
387 { SkTFixed<SkFS::kUltaExpanded_Width>::value, SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value },
388 };
389 int width = map_ranges(style.width(), widthRanges, SK_ARRAY_COUNT(widthRanges));
390
bungemanb4bb7d82016-04-27 10:21:04 -0700391 int slant = FC_SLANT_ROMAN;
392 switch (style.slant()) {
393 case SkFS::kUpright_Slant: slant = FC_SLANT_ROMAN ; break;
394 case SkFS::kItalic_Slant : slant = FC_SLANT_ITALIC ; break;
395 case SkFS::kOblique_Slant: slant = FC_SLANT_OBLIQUE; break;
396 default: SkASSERT(false); break;
397 }
398
bungemana6785cc2014-08-25 12:00:49 -0700399 FcPatternAddInteger(pattern, FC_WEIGHT, weight);
bungemanb4bb7d82016-04-27 10:21:04 -0700400 FcPatternAddInteger(pattern, FC_WIDTH , width);
401 FcPatternAddInteger(pattern, FC_SLANT , slant);
bungemana6785cc2014-08-25 12:00:49 -0700402}
403
bungemana6785cc2014-08-25 12:00:49 -0700404class SkTypeface_stream : public SkTypeface_FreeType {
405public:
bungeman41868fe2015-05-20 09:21:04 -0700406 /** @param data takes ownership of the font data.*/
407 SkTypeface_stream(SkFontData* data, const SkFontStyle& style, bool fixedWidth)
bungemana6785cc2014-08-25 12:00:49 -0700408 : INHERITED(style, SkTypefaceCache::NewFontID(), fixedWidth)
bungeman41868fe2015-05-20 09:21:04 -0700409 , fData(data)
bungemana6785cc2014-08-25 12:00:49 -0700410 { };
411
mtklein36352bf2015-03-25 18:17:31 -0700412 void onGetFamilyName(SkString* familyName) const override {
bungemanb374d6a2014-09-17 07:48:59 -0700413 familyName->reset();
414 }
415
mtklein36352bf2015-03-25 18:17:31 -0700416 void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
bungemana6785cc2014-08-25 12:00:49 -0700417 *serialize = true;
418 }
419
mtklein36352bf2015-03-25 18:17:31 -0700420 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungeman41868fe2015-05-20 09:21:04 -0700421 *ttcIndex = fData->getIndex();
422 return fData->duplicateStream();
423 }
424
425 SkFontData* onCreateFontData() const override {
426 return new SkFontData(*fData.get());
bungemana6785cc2014-08-25 12:00:49 -0700427 }
428
429private:
bungeman41868fe2015-05-20 09:21:04 -0700430 const SkAutoTDelete<const SkFontData> fData;
bungemana6785cc2014-08-25 12:00:49 -0700431
432 typedef SkTypeface_FreeType INHERITED;
433};
434
435class SkTypeface_fontconfig : public SkTypeface_FreeType {
436public:
437 /** @param pattern takes ownership of the reference. */
438 static SkTypeface_fontconfig* Create(FcPattern* pattern) {
halcanary385fe4d2015-08-26 13:07:48 -0700439 return new SkTypeface_fontconfig(pattern);
bungemana6785cc2014-08-25 12:00:49 -0700440 }
441 mutable SkAutoFcPattern fPattern;
442
mtklein36352bf2015-03-25 18:17:31 -0700443 void onGetFamilyName(SkString* familyName) const override {
bungemanb374d6a2014-09-17 07:48:59 -0700444 *familyName = get_string(fPattern, FC_FAMILY);
445 }
446
mtklein36352bf2015-03-25 18:17:31 -0700447 void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
bungemana6785cc2014-08-25 12:00:49 -0700448 FCLocker lock;
449 desc->setFamilyName(get_string(fPattern, FC_FAMILY));
bungemana6785cc2014-08-25 12:00:49 -0700450 desc->setFullName(get_string(fPattern, FC_FULLNAME));
451 desc->setPostscriptName(get_string(fPattern, FC_POSTSCRIPT_NAME));
bungemana6785cc2014-08-25 12:00:49 -0700452 *serialize = false;
453 }
454
mtklein36352bf2015-03-25 18:17:31 -0700455 SkStreamAsset* onOpenStream(int* ttcIndex) const override {
bungemana6785cc2014-08-25 12:00:49 -0700456 FCLocker lock;
457 *ttcIndex = get_int(fPattern, FC_INDEX, 0);
458 return SkStream::NewFromFile(get_string(fPattern, FC_FILE));
459 }
460
bungemand3b63d32016-04-13 13:50:20 -0700461 void onFilterRec(SkScalerContextRec* rec) const override {
462 const FcMatrix* fcMatrix = get_matrix(fPattern, FC_MATRIX);
463 if (fcMatrix) {
464 // fPost2x2 is column-major, left handed (y down).
465 // FcMatrix is column-major, right handed (y up).
466 SkMatrix fm;
467 fm.setAll(fcMatrix->xx,-fcMatrix->xy, 0,
468 -fcMatrix->yx, fcMatrix->yy, 0,
469 0 , 0 , 1);
470
471 SkMatrix sm;
472 rec->getMatrixFrom2x2(&sm);
473
474 sm.preConcat(fm);
475 rec->fPost2x2[0][0] = sm.getScaleX();
476 rec->fPost2x2[0][1] = sm.getSkewX();
477 rec->fPost2x2[1][0] = sm.getSkewY();
478 rec->fPost2x2[1][1] = sm.getScaleY();
479 }
480 if (get_bool(fPattern, FC_EMBOLDEN)) {
481 rec->fFlags |= SkScalerContext::kEmbolden_Flag;
482 }
483 this->INHERITED::onFilterRec(rec);
484 }
485
bungemana6785cc2014-08-25 12:00:49 -0700486 virtual ~SkTypeface_fontconfig() {
487 // Hold the lock while unrefing the pattern.
488 FCLocker lock;
489 fPattern.reset();
490 }
491
492private:
493 /** @param pattern takes ownership of the reference. */
494 SkTypeface_fontconfig(FcPattern* pattern)
bungemana4c4a2d2014-10-20 13:33:19 -0700495 : INHERITED(skfontstyle_from_fcpattern(pattern),
bungemana6785cc2014-08-25 12:00:49 -0700496 SkTypefaceCache::NewFontID(),
497 FC_PROPORTIONAL != get_int(pattern, FC_SPACING, FC_PROPORTIONAL))
498 , fPattern(pattern)
499 { };
500
501 typedef SkTypeface_FreeType INHERITED;
502};
503
504class SkFontMgr_fontconfig : public SkFontMgr {
505 mutable SkAutoFcConfig fFC;
506 SkAutoTUnref<SkDataTable> fFamilyNames;
bungeman14df8332014-10-28 15:07:23 -0700507 SkTypeface_FreeType::Scanner fScanner;
bungemana6785cc2014-08-25 12:00:49 -0700508
509 class StyleSet : public SkFontStyleSet {
510 public:
511 /** @param parent does not take ownership of the reference.
512 * @param fontSet takes ownership of the reference.
513 */
514 StyleSet(const SkFontMgr_fontconfig* parent, FcFontSet* fontSet)
515 : fFontMgr(SkRef(parent)), fFontSet(fontSet)
516 { }
517
518 virtual ~StyleSet() {
519 // Hold the lock while unrefing the font set.
520 FCLocker lock;
521 fFontSet.reset();
522 }
523
mtklein36352bf2015-03-25 18:17:31 -0700524 int count() override { return fFontSet->nfont; }
bungemana6785cc2014-08-25 12:00:49 -0700525
mtklein36352bf2015-03-25 18:17:31 -0700526 void getStyle(int index, SkFontStyle* style, SkString* styleName) override {
bungemana6785cc2014-08-25 12:00:49 -0700527 if (index < 0 || fFontSet->nfont <= index) {
528 return;
529 }
530
531 FCLocker lock;
532 if (style) {
533 *style = skfontstyle_from_fcpattern(fFontSet->fonts[index]);
534 }
535 if (styleName) {
536 *styleName = get_string(fFontSet->fonts[index], FC_STYLE);
537 }
538 }
539
mtklein36352bf2015-03-25 18:17:31 -0700540 SkTypeface* createTypeface(int index) override {
bungemana6785cc2014-08-25 12:00:49 -0700541 FCLocker lock;
542
543 FcPattern* match = fFontSet->fonts[index];
544 return fFontMgr->createTypefaceFromFcPattern(match);
545 }
546
mtklein36352bf2015-03-25 18:17:31 -0700547 SkTypeface* matchStyle(const SkFontStyle& style) override {
bungemana6785cc2014-08-25 12:00:49 -0700548 FCLocker lock;
549
bungeman6bc2c942014-09-09 12:50:36 -0700550 SkAutoFcPattern pattern;
bungemana6785cc2014-08-25 12:00:49 -0700551 fcpattern_from_skfontstyle(style, pattern);
552 FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern);
553 FcDefaultSubstitute(pattern);
554
555 FcResult result;
556 FcFontSet* fontSets[1] = { fFontSet };
557 SkAutoFcPattern match(FcFontSetMatch(fFontMgr->fFC,
558 fontSets, SK_ARRAY_COUNT(fontSets),
559 pattern, &result));
halcanary96fcdcc2015-08-27 07:41:13 -0700560 if (nullptr == match) {
561 return nullptr;
bungemana6785cc2014-08-25 12:00:49 -0700562 }
563
564 return fFontMgr->createTypefaceFromFcPattern(match);
565 }
566
567 private:
568 SkAutoTUnref<const SkFontMgr_fontconfig> fFontMgr;
569 SkAutoFcFontSet fFontSet;
570 };
571
572 static bool FindName(const SkTDArray<const char*>& list, const char* str) {
573 int count = list.count();
574 for (int i = 0; i < count; ++i) {
575 if (!strcmp(list[i], str)) {
576 return true;
577 }
578 }
579 return false;
580 }
581
582 static SkDataTable* GetFamilyNames(FcConfig* fcconfig) {
583 FCLocker lock;
584
585 SkTDArray<const char*> names;
586 SkTDArray<size_t> sizes;
587
588 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
589 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
590 // Return value of FcConfigGetFonts must not be destroyed.
591 FcFontSet* allFonts(FcConfigGetFonts(fcconfig, fcNameSet[setIndex]));
halcanary96fcdcc2015-08-27 07:41:13 -0700592 if (nullptr == allFonts) {
bungemana6785cc2014-08-25 12:00:49 -0700593 continue;
594 }
595
596 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
597 FcPattern* current = allFonts->fonts[fontIndex];
598 for (int id = 0; ; ++id) {
599 FcChar8* fcFamilyName;
600 FcResult result = FcPatternGetString(current, FC_FAMILY, id, &fcFamilyName);
601 if (FcResultNoId == result) {
602 break;
603 }
604 if (FcResultMatch != result) {
605 continue;
606 }
607 const char* familyName = reinterpret_cast<const char*>(fcFamilyName);
608 if (familyName && !FindName(names, familyName)) {
609 *names.append() = familyName;
610 *sizes.append() = strlen(familyName) + 1;
611 }
612 }
613 }
614 }
615
616 return SkDataTable::NewCopyArrays((void const *const *)names.begin(),
617 sizes.begin(), names.count());
618 }
619
bungeman82a455f2016-04-14 08:04:45 -0700620 static bool FindByFcPattern(SkTypeface* cached, void* ctx) {
bungemana6785cc2014-08-25 12:00:49 -0700621 SkTypeface_fontconfig* cshFace = static_cast<SkTypeface_fontconfig*>(cached);
622 FcPattern* ctxPattern = static_cast<FcPattern*>(ctx);
623 return FcTrue == FcPatternEqual(cshFace->fPattern, ctxPattern);
624 }
625
626 mutable SkMutex fTFCacheMutex;
627 mutable SkTypefaceCache fTFCache;
628 /** Creates a typeface using a typeface cache.
629 * @param pattern a complete pattern from FcFontRenderPrepare.
630 */
631 SkTypeface* createTypefaceFromFcPattern(FcPattern* pattern) const {
632 FCLocker::AssertHeld();
633 SkAutoMutexAcquire ama(fTFCacheMutex);
634 SkTypeface* face = fTFCache.findByProcAndRef(FindByFcPattern, pattern);
halcanary96fcdcc2015-08-27 07:41:13 -0700635 if (nullptr == face) {
bungemana6785cc2014-08-25 12:00:49 -0700636 FcPatternReference(pattern);
637 face = SkTypeface_fontconfig::Create(pattern);
638 if (face) {
bungeman82a455f2016-04-14 08:04:45 -0700639 fTFCache.add(face);
bungemana6785cc2014-08-25 12:00:49 -0700640 }
641 }
642 return face;
643 }
644
645public:
bungemana6785cc2014-08-25 12:00:49 -0700646 /** Takes control of the reference to 'config'. */
647 explicit SkFontMgr_fontconfig(FcConfig* config)
bungeman0b1de262015-06-17 07:55:59 -0700648 : fFC(config ? config : FcInitLoadConfigAndFonts())
bungemana6785cc2014-08-25 12:00:49 -0700649 , fFamilyNames(GetFamilyNames(fFC)) { }
650
651 virtual ~SkFontMgr_fontconfig() {
652 // Hold the lock while unrefing the config.
653 FCLocker lock;
654 fFC.reset();
655 }
656
657protected:
mtklein36352bf2015-03-25 18:17:31 -0700658 int onCountFamilies() const override {
bungemana6785cc2014-08-25 12:00:49 -0700659 return fFamilyNames->count();
660 }
661
mtklein36352bf2015-03-25 18:17:31 -0700662 void onGetFamilyName(int index, SkString* familyName) const override {
bungemana6785cc2014-08-25 12:00:49 -0700663 familyName->set(fFamilyNames->atStr(index));
664 }
665
mtklein36352bf2015-03-25 18:17:31 -0700666 SkFontStyleSet* onCreateStyleSet(int index) const override {
bungemana6785cc2014-08-25 12:00:49 -0700667 return this->onMatchFamily(fFamilyNames->atStr(index));
668 }
669
670 /** True if any string object value in the font is the same
671 * as a string object value in the pattern.
672 */
673 static bool AnyMatching(FcPattern* font, FcPattern* pattern, const char* object) {
674 FcChar8* fontString;
675 FcChar8* patternString;
676 FcResult result;
677 // Set an arbitrary limit on the number of pattern object values to consider.
678 // TODO: re-write this to avoid N*M
679 static const int maxId = 16;
680 for (int patternId = 0; patternId < maxId; ++patternId) {
681 result = FcPatternGetString(pattern, object, patternId, &patternString);
682 if (FcResultNoId == result) {
683 break;
684 }
685 if (FcResultMatch != result) {
686 continue;
687 }
688 for (int fontId = 0; fontId < maxId; ++fontId) {
689 result = FcPatternGetString(font, object, fontId, &fontString);
690 if (FcResultNoId == result) {
691 break;
692 }
693 if (FcResultMatch != result) {
694 continue;
695 }
696 if (0 == FcStrCmpIgnoreCase(patternString, fontString)) {
697 return true;
698 }
699 }
700 }
701 return false;
702 }
703
bungeman6bc2c942014-09-09 12:50:36 -0700704 static bool FontAccessible(FcPattern* font) {
bungemana6785cc2014-08-25 12:00:49 -0700705 // FontConfig can return fonts which are unreadable.
halcanary96fcdcc2015-08-27 07:41:13 -0700706 const char* filename = get_string(font, FC_FILE, nullptr);
707 if (nullptr == filename) {
bungemana6785cc2014-08-25 12:00:49 -0700708 return false;
709 }
710 return sk_exists(filename, kRead_SkFILE_Flag);
711 }
712
bungeman6bc2c942014-09-09 12:50:36 -0700713 static bool FontFamilyNameMatches(FcPattern* font, FcPattern* pattern) {
714 return AnyMatching(font, pattern, FC_FAMILY);
715 }
716
717 static bool FontContainsCharacter(FcPattern* font, uint32_t character) {
718 FcResult result;
719 FcCharSet* matchCharSet;
720 for (int charSetId = 0; ; ++charSetId) {
721 result = FcPatternGetCharSet(font, FC_CHARSET, charSetId, &matchCharSet);
722 if (FcResultNoId == result) {
723 break;
724 }
725 if (FcResultMatch != result) {
726 continue;
727 }
728 if (FcCharSetHasChar(matchCharSet, character)) {
729 return true;
730 }
731 }
732 return false;
bungemana6785cc2014-08-25 12:00:49 -0700733 }
734
mtklein36352bf2015-03-25 18:17:31 -0700735 SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
bungemana6785cc2014-08-25 12:00:49 -0700736 FCLocker lock;
737
bungeman6bc2c942014-09-09 12:50:36 -0700738 SkAutoFcPattern pattern;
bungemana6785cc2014-08-25 12:00:49 -0700739 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
740 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
741 FcDefaultSubstitute(pattern);
742
743 FcPattern* matchPattern;
halcanary96fcdcc2015-08-27 07:41:13 -0700744 SkAutoFcPattern strongPattern(nullptr);
bungemana6785cc2014-08-25 12:00:49 -0700745 if (familyName) {
746 strongPattern.reset(FcPatternDuplicate(pattern));
747 remove_weak(strongPattern, FC_FAMILY);
748 matchPattern = strongPattern;
749 } else {
750 matchPattern = pattern;
751 }
752
bungeman6bc2c942014-09-09 12:50:36 -0700753 SkAutoFcFontSet matches;
bungemana6785cc2014-08-25 12:00:49 -0700754 // TODO: Some families have 'duplicates' due to symbolic links.
755 // The patterns are exactly the same except for the FC_FILE.
756 // It should be possible to collapse these patterns by normalizing.
757 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
758 for (int setIndex = 0; setIndex < (int)SK_ARRAY_COUNT(fcNameSet); ++setIndex) {
759 // Return value of FcConfigGetFonts must not be destroyed.
760 FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex]));
halcanary96fcdcc2015-08-27 07:41:13 -0700761 if (nullptr == allFonts) {
bungemana6785cc2014-08-25 12:00:49 -0700762 continue;
763 }
764
765 for (int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
bungeman6bc2c942014-09-09 12:50:36 -0700766 FcPattern* font = allFonts->fonts[fontIndex];
767 if (FontAccessible(font) && FontFamilyNameMatches(font, matchPattern)) {
768 FcFontSetAdd(matches, FcFontRenderPrepare(fFC, pattern, font));
bungemana6785cc2014-08-25 12:00:49 -0700769 }
770 }
771 }
772
mtklein18300a32016-03-16 13:53:35 -0700773 return new StyleSet(this, matches.release());
bungemana6785cc2014-08-25 12:00:49 -0700774 }
775
776 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
mtklein36352bf2015-03-25 18:17:31 -0700777 const SkFontStyle& style) const override
bungemana6785cc2014-08-25 12:00:49 -0700778 {
779 FCLocker lock;
780
bungeman6bc2c942014-09-09 12:50:36 -0700781 SkAutoFcPattern pattern;
bungemana6785cc2014-08-25 12:00:49 -0700782 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
783 fcpattern_from_skfontstyle(style, pattern);
784 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
785 FcDefaultSubstitute(pattern);
786
787 // We really want to match strong (prefered) and same (acceptable) only here.
788 // If a family name was specified, assume that any weak matches after the last strong match
789 // are weak (default) and ignore them.
790 // The reason for is that after substitution the pattern for 'sans-serif' looks like
791 // "wwwwwwwwwwwwwwswww" where there are many weak but preferred names, followed by defaults.
792 // So it is possible to have weakly matching but preferred names.
793 // In aliases, bindings are weak by default, so this is easy and common.
794 // If no family name was specified, we'll probably only get weak matches, but that's ok.
795 FcPattern* matchPattern;
halcanary96fcdcc2015-08-27 07:41:13 -0700796 SkAutoFcPattern strongPattern(nullptr);
bungemana6785cc2014-08-25 12:00:49 -0700797 if (familyName) {
798 strongPattern.reset(FcPatternDuplicate(pattern));
799 remove_weak(strongPattern, FC_FAMILY);
800 matchPattern = strongPattern;
801 } else {
802 matchPattern = pattern;
803 }
804
805 FcResult result;
bungeman6bc2c942014-09-09 12:50:36 -0700806 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
halcanary96fcdcc2015-08-27 07:41:13 -0700807 if (nullptr == font || !FontAccessible(font) || !FontFamilyNameMatches(font, matchPattern)) {
808 return nullptr;
bungemana6785cc2014-08-25 12:00:49 -0700809 }
810
bungeman6bc2c942014-09-09 12:50:36 -0700811 return createTypefaceFromFcPattern(font);
812 }
813
814 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
815 const SkFontStyle& style,
bungemanc20386e2014-10-23 07:08:05 -0700816 const char* bcp47[],
817 int bcp47Count,
mtklein36352bf2015-03-25 18:17:31 -0700818 SkUnichar character) const override
bungeman6bc2c942014-09-09 12:50:36 -0700819 {
820 FCLocker lock;
821
822 SkAutoFcPattern pattern;
bungeman6837b382015-04-29 14:35:49 -0700823 if (familyName) {
824 FcValue familyNameValue;
825 familyNameValue.type = FcTypeString;
826 familyNameValue.u.s = reinterpret_cast<const FcChar8*>(familyName);
827 FcPatternAddWeak(pattern, FC_FAMILY, familyNameValue, FcFalse);
828 }
bungeman6bc2c942014-09-09 12:50:36 -0700829 fcpattern_from_skfontstyle(style, pattern);
830
831 SkAutoFcCharSet charSet;
832 FcCharSetAddChar(charSet, character);
833 FcPatternAddCharSet(pattern, FC_CHARSET, charSet);
834
bungemanc20386e2014-10-23 07:08:05 -0700835 if (bcp47Count > 0) {
836 SkASSERT(bcp47);
bungeman6bc2c942014-09-09 12:50:36 -0700837 SkAutoFcLangSet langSet;
bungemanc20386e2014-10-23 07:08:05 -0700838 for (int i = bcp47Count; i --> 0;) {
839 FcLangSetAdd(langSet, (const FcChar8*)bcp47[i]);
840 }
bungeman6bc2c942014-09-09 12:50:36 -0700841 FcPatternAddLangSet(pattern, FC_LANG, langSet);
842 }
843
844 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
845 FcDefaultSubstitute(pattern);
846
847 FcResult result;
848 SkAutoFcPattern font(FcFontMatch(fFC, pattern, &result));
halcanary96fcdcc2015-08-27 07:41:13 -0700849 if (nullptr == font || !FontAccessible(font) || !FontContainsCharacter(font, character)) {
850 return nullptr;
bungeman6bc2c942014-09-09 12:50:36 -0700851 }
852
853 return createTypefaceFromFcPattern(font);
bungemana6785cc2014-08-25 12:00:49 -0700854 }
855
856 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
mtklein36352bf2015-03-25 18:17:31 -0700857 const SkFontStyle& style) const override
bungemana6785cc2014-08-25 12:00:49 -0700858 {
859 //TODO: should the SkTypeface_fontconfig know its family?
bungemanb14e4a02014-09-18 13:57:20 -0700860 const SkTypeface_fontconfig* fcTypeface =
bungeman9db50922014-09-12 12:14:14 -0700861 static_cast<const SkTypeface_fontconfig*>(typeface);
bungemanb14e4a02014-09-18 13:57:20 -0700862 return this->matchFamilyStyle(get_string(fcTypeface->fPattern, FC_FAMILY), style);
bungemana6785cc2014-08-25 12:00:49 -0700863 }
864
mtklein36352bf2015-03-25 18:17:31 -0700865 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
bungeman5f213d92015-01-27 05:39:10 -0800866 SkAutoTDelete<SkStreamAsset> stream(bareStream);
bungemana6785cc2014-08-25 12:00:49 -0700867 const size_t length = stream->getLength();
868 if (length <= 0 || (1u << 30) < length) {
halcanary96fcdcc2015-08-27 07:41:13 -0700869 return nullptr;
bungemana6785cc2014-08-25 12:00:49 -0700870 }
871
bungemana4c4a2d2014-10-20 13:33:19 -0700872 SkFontStyle style;
bungemana6785cc2014-08-25 12:00:49 -0700873 bool isFixedWidth = false;
halcanary96fcdcc2015-08-27 07:41:13 -0700874 if (!fScanner.scanFont(stream, ttcIndex, nullptr, &style, &isFixedWidth, nullptr)) {
875 return nullptr;
bungemana6785cc2014-08-25 12:00:49 -0700876 }
877
mtklein18300a32016-03-16 13:53:35 -0700878 return new SkTypeface_stream(new SkFontData(stream.release(), ttcIndex, nullptr, 0), style,
halcanary385fe4d2015-08-26 13:07:48 -0700879 isFixedWidth);
bungemana6785cc2014-08-25 12:00:49 -0700880 }
881
bungemanf6c71072016-01-21 14:17:47 -0800882 SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override {
883 using Scanner = SkTypeface_FreeType::Scanner;
884 SkAutoTDelete<SkStreamAsset> stream(s);
885 bool isFixedPitch;
886 SkFontStyle style;
887 SkString name;
888 Scanner::AxisDefinitions axisDefinitions;
889 if (!fScanner.scanFont(stream, params.getCollectionIndex(), &name, &style, &isFixedPitch,
890 &axisDefinitions))
891 {
892 return nullptr;
893 }
894
895 int paramAxisCount;
896 const FontParameters::Axis* paramAxes = params.getAxes(&paramAxisCount);
897 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
898 Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
899
mtklein18300a32016-03-16 13:53:35 -0700900 SkFontData* data(new SkFontData(stream.release(), params.getCollectionIndex(),
bungemanf6c71072016-01-21 14:17:47 -0800901 axisValues.get(), axisDefinitions.count()));
902 return new SkTypeface_stream(data, style, isFixedPitch);
903 }
904
mtklein36352bf2015-03-25 18:17:31 -0700905 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
halcanary385fe4d2015-08-26 13:07:48 -0700906 return this->createFromStream(new SkMemoryStream(data), ttcIndex);
bungemana6785cc2014-08-25 12:00:49 -0700907 }
908
mtklein36352bf2015-03-25 18:17:31 -0700909 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
scroggoa1193e42015-01-21 12:09:53 -0800910 return this->createFromStream(SkStream::NewFromFile(path), ttcIndex);
bungemana6785cc2014-08-25 12:00:49 -0700911 }
912
bungeman41868fe2015-05-20 09:21:04 -0700913 SkTypeface* onCreateFromFontData(SkFontData* fontData) const override {
914 SkStreamAsset* stream(fontData->getStream());
915 const size_t length = stream->getLength();
916 if (length <= 0 || (1u << 30) < length) {
halcanary96fcdcc2015-08-27 07:41:13 -0700917 return nullptr;
bungeman41868fe2015-05-20 09:21:04 -0700918 }
919
920 const int ttcIndex = fontData->getIndex();
921 SkFontStyle style;
922 bool isFixedWidth = false;
halcanary96fcdcc2015-08-27 07:41:13 -0700923 if (!fScanner.scanFont(stream, ttcIndex, nullptr, &style, &isFixedWidth, nullptr)) {
924 return nullptr;
bungeman41868fe2015-05-20 09:21:04 -0700925 }
926
halcanary385fe4d2015-08-26 13:07:48 -0700927 return new SkTypeface_stream(fontData, style, isFixedWidth);
bungeman41868fe2015-05-20 09:21:04 -0700928 }
929
bungeman11a77c62016-04-12 13:45:06 -0700930 SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override {
bungemana6785cc2014-08-25 12:00:49 -0700931 SkAutoTUnref<SkTypeface> typeface(this->matchFamilyStyle(familyName, style));
bsalomon49f085d2014-09-05 13:34:00 -0700932 if (typeface.get()) {
mtklein18300a32016-03-16 13:53:35 -0700933 return typeface.release();
bungemana6785cc2014-08-25 12:00:49 -0700934 }
935
halcanary96fcdcc2015-08-27 07:41:13 -0700936 return this->matchFamilyStyle(nullptr, style);
bungemana6785cc2014-08-25 12:00:49 -0700937 }
938};
939
bungeman0b1de262015-06-17 07:55:59 -0700940SK_API SkFontMgr* SkFontMgr_New_FontConfig(FcConfig* fc) {
941 return new SkFontMgr_fontconfig(fc);
bungemana6785cc2014-08-25 12:00:49 -0700942}