1096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger/* 2096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * Copyright 2009 Google Inc. 3096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * 4096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 5096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * found in the LICENSE file. 6096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger */ 7096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 8096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger/* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */ 9096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 10096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include <string> 11096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include <unistd.h> 12096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include <fcntl.h> 13096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 14096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include <fontconfig/fontconfig.h> 15096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkBuffer.h" 17096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkFontConfigInterface.h" 18096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkStream.h" 19096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergersize_t SkFontConfigInterface::FontIdentity::writeToMemory(void* addr) const { 217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger size_t size = sizeof(fID) + sizeof(fTTCIndex); 227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger size += sizeof(int32_t) + sizeof(int32_t) + sizeof(uint8_t); // weight, width, italic 237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger size += sizeof(int32_t) + fString.size(); // store length+data 247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (addr) { 257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkWBuffer buffer(addr, size); 267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.write32(fID); 287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.write32(fTTCIndex); 297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.write32(fString.size()); 307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.write32(fStyle.weight()); 317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.write32(fStyle.width()); 327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.write8(fStyle.slant()); 337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.write(fString.c_str(), fString.size()); 347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.padToAlign4(); 357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(buffer.pos() == size); 377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return size; 397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergersize_t SkFontConfigInterface::FontIdentity::readFromMemory(const void* addr, 427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger size_t size) { 437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkRBuffer buffer(addr, size); 447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fID = buffer.readU32(); 467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fTTCIndex = buffer.readU32(); 477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger size_t strLen = buffer.readU32(); 487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger int weight = buffer.readU32(); 497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger int width = buffer.readU32(); 507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkFontStyle::Slant slant = (SkFontStyle::Slant)buffer.readU8(); 517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fStyle = SkFontStyle(weight, width, slant); 527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fString.resize(strLen); 537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.read(fString.writable_str(), strLen); 547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger buffer.skipToAlign4(); 557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return buffer.pos(); // the actual number of bytes read 577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#ifdef SK_DEBUG 607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void make_iden(SkFontConfigInterface::FontIdentity* iden) { 617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger iden->fID = 10; 627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger iden->fTTCIndex = 2; 637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger iden->fString.set("Hello world"); 647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant); 657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void test_writeToMemory(const SkFontConfigInterface::FontIdentity& iden0, 687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger int initValue) { 697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkFontConfigInterface::FontIdentity iden1; 707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger size_t size0 = iden0.writeToMemory(NULL); 727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkAutoMalloc storage(size0); 747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger memset(storage.get(), initValue, size0); 757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger size_t size1 = iden0.writeToMemory(storage.get()); 777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(size0 == size1); 787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(iden0 != iden1); 807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger size_t size2 = iden1.readFromMemory(storage.get(), size1); 817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(size2 == size1); 827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(iden0 == iden1); 837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void fontconfiginterface_unittest() { 867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkFontConfigInterface::FontIdentity iden0, iden1; 877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(iden0 == iden1); 897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger make_iden(&iden0); 917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(iden0 != iden1); 927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger make_iden(&iden1); 947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(iden0 == iden1); 957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger test_writeToMemory(iden0, 0); 977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger test_writeToMemory(iden0, 0); 987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif 1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 101096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerclass SkFontConfigInterfaceDirect : public SkFontConfigInterface { 102096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerpublic: 103096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkFontConfigInterfaceDirect(); 104096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger virtual ~SkFontConfigInterfaceDirect(); 105096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 106096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger virtual bool matchFamilyName(const char familyName[], 107096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkTypeface::Style requested, 108096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FontIdentity* outFontIdentifier, 109096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkString* outFamilyName, 110096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkTypeface::Style* outStyle) SK_OVERRIDE; 111096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger virtual SkStream* openStream(const FontIdentity&) SK_OVERRIDE; 112096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // new APIs 1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual SkDataTable* getFamilyNames() SK_OVERRIDE; 1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual bool matchFamilySet(const char inFamilyName[], 1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkString* outFamilyName, 1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkTArray<FontIdentity>*) SK_OVERRIDE; 1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 119096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerprivate: 120096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkMutex mutex_; 121096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}; 122096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 123096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() { 124096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger static SkFontConfigInterface* gDirect; 125096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (NULL == gDirect) { 1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static SkMutex gMutex; 1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkAutoMutexAcquire ac(gMutex); 1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (NULL == gDirect) { 1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger gDirect = new SkFontConfigInterfaceDirect; 1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 132096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 133096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return gDirect; 134096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 135096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// Returns the string from the pattern, or NULL 1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic const char* get_name(FcPattern* pattern, const char field[], 1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger int index = 0) { 1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* name; 1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (FcPatternGetString(pattern, field, index, 1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger (FcChar8**)&name) != FcResultMatch) { 1447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger name = NULL; 1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return name; 1477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 151096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergernamespace { 152096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 153096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// Equivalence classes, used to match the Liberation and other fonts 154096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// with their metric-compatible replacements. See the discussion in 155096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// GetFontEquivClass(). 156096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerenum FontEquivClass 157096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger{ 158096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger OTHER, 159096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SANS, 160096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SERIF, 161096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger MONO, 162096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SYMBOL, 163096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger PGOTHIC, 164096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger GOTHIC, 165096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger PMINCHO, 166096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger MINCHO, 167096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SIMSUN, 168096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger NSIMSUN, 169096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SIMHEI, 170096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger PMINGLIU, 171096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger MINGLIU, 172096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger PMINGLIUHK, 173096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger MINGLIUHK, 174096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger CAMBRIA, 175096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}; 176096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 177096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// Match the font name against a whilelist of fonts, returning the equivalence 178096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// class. 179096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerFontEquivClass GetFontEquivClass(const char* fontname) 180096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger{ 181096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // It would be nice for fontconfig to tell us whether a given suggested 182096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // replacement is a "strong" match (that is, an equivalent font) or 183096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // a "weak" match (that is, fontconfig's next-best attempt at finding a 184096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // substitute). However, I played around with the fontconfig API for 185096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // a good few hours and could not make it reveal this information. 186096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 187096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // So instead, we hardcode. Initially this function emulated 188096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // /etc/fonts/conf.d/30-metric-aliases.conf 189096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // from my Ubuntu system, but we're better off being very conservative. 190096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 191096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Arimo, Tinos and Cousine are a set of fonts metric-compatible with 192096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Arial, Times New Roman and Courier New with a character repertoire 193096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // much larger than Liberation. Note that Cousine is metrically 194096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // compatible with Courier New, but the former is sans-serif while 195096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // the latter is serif. 196096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 197096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 198096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger struct FontEquivMap { 199096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FontEquivClass clazz; 200096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const char name[40]; 201096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger }; 202096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 203096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger static const FontEquivMap kFontEquivMap[] = { 204096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SANS, "Arial" }, 205096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SANS, "Arimo" }, 206096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SANS, "Liberation Sans" }, 207096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 208096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SERIF, "Times New Roman" }, 209096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SERIF, "Tinos" }, 210096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SERIF, "Liberation Serif" }, 211096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 212096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MONO, "Courier New" }, 213096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MONO, "Cousine" }, 214096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MONO, "Liberation Mono" }, 215096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 216096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SYMBOL, "Symbol" }, 217096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SYMBOL, "Symbol Neu" }, 218096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 219096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // MS Pゴシック 220096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PGOTHIC, "MS PGothic" }, 221096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PGOTHIC, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0" 222096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" }, 223096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PGOTHIC, "IPAPGothic" }, 224096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PGOTHIC, "MotoyaG04Gothic" }, 225096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 226096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // MS ゴシック 227096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { GOTHIC, "MS Gothic" }, 228096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { GOTHIC, "\xef\xbc\xad\xef\xbc\xb3 " 229096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" }, 230096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { GOTHIC, "IPAGothic" }, 231096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { GOTHIC, "MotoyaG04GothicMono" }, 232096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 233096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // MS P明朝 234096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINCHO, "MS PMincho" }, 235096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0" 236096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger "\xe6\x98\x8e\xe6\x9c\x9d"}, 237096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINCHO, "IPAPMincho" }, 238096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINCHO, "MotoyaG04Mincho" }, 239096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 240096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // MS 明朝 241096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINCHO, "MS Mincho" }, 242096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xe6\x98\x8e\xe6\x9c\x9d" }, 243096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINCHO, "IPAMincho" }, 244096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINCHO, "MotoyaG04MinchoMono" }, 245096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 246096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 宋体 247096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SIMSUN, "Simsun" }, 248096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SIMSUN, "\xe5\xae\x8b\xe4\xbd\x93" }, 249096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SIMSUN, "MSung GB18030" }, 250096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SIMSUN, "Song ASC" }, 251096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 252096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 新宋体 253096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { NSIMSUN, "NSimsun" }, 254096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { NSIMSUN, "\xe6\x96\xb0\xe5\xae\x8b\xe4\xbd\x93" }, 255096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { NSIMSUN, "MSung GB18030" }, 256096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { NSIMSUN, "N Song ASC" }, 257096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 258096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 黑体 259096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SIMHEI, "Simhei" }, 260096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SIMHEI, "\xe9\xbb\x91\xe4\xbd\x93" }, 261096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SIMHEI, "MYingHeiGB18030" }, 262096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { SIMHEI, "MYingHeiB5HK" }, 263096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 264096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 新細明體 265096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINGLIU, "PMingLiU"}, 266096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINGLIU, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" }, 267096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINGLIU, "MSung B5HK"}, 268096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 269096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 細明體 270096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINGLIU, "MingLiU"}, 271096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINGLIU, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" }, 272096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINGLIU, "MSung B5HK"}, 273096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 274096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 新細明體 275096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINGLIUHK, "PMingLiU_HKSCS"}, 276096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINGLIUHK, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" }, 277096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { PMINGLIUHK, "MSung B5HK"}, 278096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 279096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 細明體 280096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINGLIUHK, "MingLiU_HKSCS"}, 281096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINGLIUHK, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" }, 282096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { MINGLIUHK, "MSung B5HK"}, 283096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 284096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Cambria 285096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { CAMBRIA, "Cambria" }, 286096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger { CAMBRIA, "Caladea" }, 287096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger }; 288096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 289096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger static const size_t kFontCount = 290096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger sizeof(kFontEquivMap)/sizeof(kFontEquivMap[0]); 291096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 292096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // TODO(jungshik): If this loop turns out to be hot, turn 293096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // the array to a static (hash)map to speed it up. 294096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger for (size_t i = 0; i < kFontCount; ++i) { 295096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (strcasecmp(kFontEquivMap[i].name, fontname) == 0) 296096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return kFontEquivMap[i].clazz; 297096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 298096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return OTHER; 299096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 300096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 301096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 302096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// Return true if |font_a| and |font_b| are visually and at the metrics 303096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// level interchangeable. 304096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerbool IsMetricCompatibleReplacement(const char* font_a, const char* font_b) 305096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger{ 306096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FontEquivClass class_a = GetFontEquivClass(font_a); 307096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FontEquivClass class_b = GetFontEquivClass(font_b); 308096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 309096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return class_a != OTHER && class_a == class_b; 310096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 311096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 312096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// Normally we only return exactly the font asked for. In last-resort 313096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// cases, the request either doesn't specify a font or is one of the 314096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// basic font names like "Sans", "Serif" or "Monospace". This function 315096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// tells you whether a given request is for such a fallback. 316096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerbool IsFallbackFontAllowed(const std::string& family) { 317096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const char* family_cstr = family.c_str(); 318096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return family.empty() || 319096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger strcasecmp(family_cstr, "sans") == 0 || 320096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger strcasecmp(family_cstr, "serif") == 0 || 321096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger strcasecmp(family_cstr, "monospace") == 0; 322096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 323096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 3247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic bool valid_pattern(FcPattern* pattern) { 3257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcBool is_scalable; 3267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch 3277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger || !is_scalable) { 3287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 3297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 3307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 3317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // fontconfig can also return fonts which are unreadable 3327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* c_filename = get_name(pattern, FC_FILE); 3337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!c_filename) { 3347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 3357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 3367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (access(c_filename, R_OK) != 0) { 3377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 3387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 3397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return true; 3407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 3417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 342096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// Find matching font from |font_set| for the given font family. 343096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerFcPattern* MatchFont(FcFontSet* font_set, 3447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* post_config_family, 345096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const std::string& family) { 346096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Older versions of fontconfig have a bug where they cannot select 347096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // only scalable fonts so we have to manually filter the results. 348096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPattern* match = NULL; 349096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger for (int i = 0; i < font_set->nfont; ++i) { 350096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPattern* current = font_set->fonts[i]; 3517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (valid_pattern(current)) { 3527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger match = current; 3537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger break; 354096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 355096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 356096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 357096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (match && !IsFallbackFontAllowed(family)) { 358096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger bool acceptable_substitute = false; 359096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger for (int id = 0; id < 255; ++id) { 3607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* post_match_family = get_name(match, FC_FAMILY, id); 3617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!post_match_family) 362096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 363096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger acceptable_substitute = 3647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger (strcasecmp(post_config_family, post_match_family) == 0 || 365096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Workaround for Issue 12530: 366096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // requested family: "Bitstream Vera Sans" 367096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // post_config_family: "Arial" 368096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // post_match_family: "Bitstream Vera Sans" 369096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // -> We should treat this case as a good match. 3707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger strcasecmp(family.c_str(), post_match_family) == 0) || 3717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger IsMetricCompatibleReplacement(family.c_str(), post_match_family); 372096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (acceptable_substitute) 373096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger break; 374096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 375096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (!acceptable_substitute) 376096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return NULL; 377096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 378096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 379096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return match; 380096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 381096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 382096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|. 383096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSkTypeface::Style GetFontStyle(FcPattern* font) { 384096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger int resulting_bold; 385096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold)) 386096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger resulting_bold = FC_WEIGHT_NORMAL; 387096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 388096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger int resulting_italic; 389096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic)) 390096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger resulting_italic = FC_SLANT_ROMAN; 391096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 392096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // If we ask for an italic font, fontconfig might take a roman font and set 393096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // the undocumented property FC_MATRIX to a skew matrix. It'll then say 394096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // that the font is italic or oblique. So, if we see a matrix, we don't 395096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // believe that it's italic. 396096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcValue matrix; 397096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0; 398096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 399096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // If we ask for an italic font, fontconfig might take a roman font and set 400096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // FC_EMBOLDEN. 401096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcValue embolden; 402096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) == 0; 403096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 404096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger int styleBits = 0; 405096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) { 406096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger styleBits |= SkTypeface::kBold; 407096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 408096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) { 409096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger styleBits |= SkTypeface::kItalic; 410096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 411096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 412096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return (SkTypeface::Style)styleBits; 413096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 414096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 415096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} // anonymous namespace 416096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 417096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 418096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 419096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#define kMaxFontFamilyLength 2048 420096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 421096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() { 4227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkAutoMutexAcquire ac(mutex_); 4237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 424096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcInit(); 4257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkDEBUGCODE(fontconfiginterface_unittest();) 427096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 428096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 429096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() { 430096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 431096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 432096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerbool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], 433096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkTypeface::Style style, 434096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FontIdentity* outIdentity, 435096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkString* outFamilyName, 436096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkTypeface::Style* outStyle) { 437096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger std::string familyStr(familyName ? familyName : ""); 438096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (familyStr.length() > kMaxFontFamilyLength) { 439096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return false; 440096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 441096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 442096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkAutoMutexAcquire ac(mutex_); 443096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 444096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPattern* pattern = FcPatternCreate(); 445096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 446096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (familyName) { 447096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); 448096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 449096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPatternAddInteger(pattern, FC_WEIGHT, 450096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger (style & SkTypeface::kBold) ? FC_WEIGHT_BOLD 451096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger : FC_WEIGHT_NORMAL); 452096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPatternAddInteger(pattern, FC_SLANT, 453096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger (style & SkTypeface::kItalic) ? FC_SLANT_ITALIC 454096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger : FC_SLANT_ROMAN); 455096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); 456096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 457096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcConfigSubstitute(NULL, pattern, FcMatchPattern); 458096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcDefaultSubstitute(pattern); 459096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 460096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Font matching: 461096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // CSS often specifies a fallback list of families: 462096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // font-family: a, b, c, serif; 463096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // However, fontconfig will always do its best to find *a* font when asked 464096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // for something so we need a way to tell if the match which it has found is 465096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // "good enough" for us. Otherwise, we can return NULL which gets piped up 466096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // and lets WebKit know to try the next CSS family name. However, fontconfig 467096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we 468096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // wish to support that. 469096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 470096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Thus, if a specific family is requested we set @family_requested. Then we 471096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // record two strings: the family name after config processing and the 472096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // family name after resolving. If the two are equal, it's a good match. 473096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 474096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // So consider the case where a user has mapped Arial to Helvetica in their 475096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // config. 476096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // requested family: "Arial" 477096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // post_config_family: "Helvetica" 478096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // post_match_family: "Helvetica" 479096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // -> good match 480096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 481096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // and for a missing font: 482096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // requested family: "Monaco" 483096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // post_config_family: "Monaco" 484096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // post_match_family: "Times New Roman" 485096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // -> BAD match 486096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // 487096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // However, we special-case fallback fonts; see IsFallbackFontAllowed(). 4887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* post_config_family = get_name(pattern, FC_FAMILY); 4907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!post_config_family) { 4917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // we can just continue with an empty name, e.g. default font 4927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger post_config_family = ""; 4937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 4947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcResult result; 4967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); 4977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!font_set) { 4987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPatternDestroy(pattern); 4997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 5007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPattern* match = MatchFont(font_set, post_config_family, familyStr); 5037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!match) { 5047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPatternDestroy(pattern); 5057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcFontSetDestroy(font_set); 5067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 5077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPatternDestroy(pattern); 5107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // From here out we just extract our results from 'match' 5127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger post_config_family = get_name(match, FC_FAMILY); 5147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!post_config_family) { 5157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcFontSetDestroy(font_set); 5167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 5177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* c_filename = get_name(match, FC_FILE); 5207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!c_filename) { 5217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcFontSetDestroy(font_set); 5227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 5237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger int face_index; 5267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) { 5277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcFontSetDestroy(font_set); 5287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 5297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcFontSetDestroy(font_set); 5327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (outIdentity) { 5347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger outIdentity->fTTCIndex = face_index; 5357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger outIdentity->fString.set(c_filename); 5367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (outFamilyName) { 5387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger outFamilyName->set(post_config_family); 5397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (outStyle) { 5417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *outStyle = GetFontStyle(match); 5427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return true; 5447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 5457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkStream* SkFontConfigInterfaceDirect::openStream(const FontIdentity& identity) { 5477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return SkStream::NewFromFile(identity.fString.c_str()); 5487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 5497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 5517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic bool find_name(const SkTDArray<const char*>& list, const char* str) { 5537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger int count = list.count(); 5547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger for (int i = 0; i < count; ++i) { 5557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!strcmp(list[i], str)) { 5567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return true; 5577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 5607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 5617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() { 5637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkAutoMutexAcquire ac(mutex_); 5647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPattern* pat = FcPatternCreate(); 56658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkAutoTCallVProc<FcPattern, FcPatternDestroy> autoDestroyPat(pat); 56758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (NULL == pat) { 56858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return NULL; 56958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 57058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 57158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, (char *)0); 57258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkAutoTCallVProc<FcObjectSet, FcObjectSetDestroy> autoDestroyOs(os); 5737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (NULL == os) { 5747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return NULL; 5757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 57658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 5777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcFontSet* fs = FcFontList(NULL, pat, os); 57858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkAutoTCallVProc<FcFontSet, FcFontSetDestroy> autoDestroyFs(fs); 5797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (NULL == fs) { 5807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return NULL; 5817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkTDArray<const char*> names; 5847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkTDArray<size_t> sizes; 5857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger for (int i = 0; i < fs->nfont; ++i) { 5867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPattern* match = fs->fonts[i]; 5877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* famName = get_name(match, FC_FAMILY); 5887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (famName && !find_name(names, famName)) { 5897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *names.append() = famName; 5907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *sizes.append() = strlen(famName) + 1; 5917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 5937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return SkDataTable::NewCopyArrays((const void*const*)names.begin(), 5957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger sizes.begin(), names.count()); 5967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 5977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[], 5997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkString* outFamilyName, 6007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkTArray<FontIdentity>* ids) { 6017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkAutoMutexAcquire ac(mutex_); 6027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if 0 6047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger std::string familyStr(familyName ? familyName : ""); 6057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (familyStr.length() > kMaxFontFamilyLength) { 6067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 6077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkAutoMutexAcquire ac(mutex_); 6107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPattern* pattern = FcPatternCreate(); 6127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (familyName) { 6147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); 6157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); 6177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcConfigSubstitute(NULL, pattern, FcMatchPattern); 6197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcDefaultSubstitute(pattern); 6207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // Font matching: 6227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // CSS often specifies a fallback list of families: 6237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // font-family: a, b, c, serif; 6247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // However, fontconfig will always do its best to find *a* font when asked 6257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // for something so we need a way to tell if the match which it has found is 6267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // "good enough" for us. Otherwise, we can return NULL which gets piped up 6277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // and lets WebKit know to try the next CSS family name. However, fontconfig 6287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we 6297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // wish to support that. 6307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // 6317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // Thus, if a specific family is requested we set @family_requested. Then we 6327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // record two strings: the family name after config processing and the 6337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // family name after resolving. If the two are equal, it's a good match. 6347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // 6357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // So consider the case where a user has mapped Arial to Helvetica in their 6367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // config. 6377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // requested family: "Arial" 6387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // post_config_family: "Helvetica" 6397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // post_match_family: "Helvetica" 6407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // -> good match 6417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // 6427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // and for a missing font: 6437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // requested family: "Monaco" 6447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // post_config_family: "Monaco" 6457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // post_match_family: "Times New Roman" 6467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // -> BAD match 6477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // 6487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // However, we special-case fallback fonts; see IsFallbackFontAllowed(). 6497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* post_config_family = get_name(pattern, FC_FAMILY); 651096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 652096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcResult result; 653096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); 654096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (!font_set) { 655096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPatternDestroy(pattern); 656096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return false; 657096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 658096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 659096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPattern* match = MatchFont(font_set, post_config_family, familyStr); 660096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (!match) { 661096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPatternDestroy(pattern); 662096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcFontSetDestroy(font_set); 663096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return false; 664096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 665096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 666096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcPatternDestroy(pattern); 667096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 668096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // From here out we just extract our results from 'match' 669096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 670096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (FcPatternGetString(match, FC_FAMILY, 0, &post_config_family) != FcResultMatch) { 671096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcFontSetDestroy(font_set); 672096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return false; 673096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 674096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 675096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcChar8* c_filename; 676096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) { 677096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcFontSetDestroy(font_set); 678096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return false; 679096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 680096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 681096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger int face_index; 682096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) { 683096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcFontSetDestroy(font_set); 684096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return false; 685096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 686096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 687096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger FcFontSetDestroy(font_set); 688096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 689096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (outIdentity) { 690096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger outIdentity->fTTCIndex = face_index; 691096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger outIdentity->fString.set((const char*)c_filename); 692096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 693096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (outFamilyName) { 694096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger outFamilyName->set((const char*)post_config_family); 695096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 696096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (outStyle) { 697096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *outStyle = GetFontStyle(match); 698096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 699096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return true; 700096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 7017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger//////////////////// 7027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger int count; 7047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPattern** match = MatchFont(font_set, post_config_family, &count); 7057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!match) { 7067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPatternDestroy(pattern); 7077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcFontSetDestroy(font_set); 7087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return NULL; 7097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger FcPatternDestroy(pattern); 7127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkTDArray<FcPattern*> trimmedMatches; 7147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger for (int i = 0; i < count; ++i) { 7157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* justName = find_just_name(get_name(match[i], FC_FILE)); 7167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!is_lower(*justName)) { 7177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *trimmedMatches.append() = match[i]; 7187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkFontStyleSet_FC* sset = SkNEW_ARGS(SkFontStyleSet_FC, 7227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger (trimmedMatches.begin(), 7237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger trimmedMatches.count())); 7247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif 7257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 726096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 727