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