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