gfx/skia/trunk/src/ports/SkFontConfigInterface_direct.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright 2009 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */
    10 #include <string>
    11 #include <unistd.h>
    12 #include <fcntl.h>
    14 #include <fontconfig/fontconfig.h>
    16 #include "SkBuffer.h"
    17 #include "SkFontConfigInterface.h"
    18 #include "SkStream.h"
    20 size_t SkFontConfigInterface::FontIdentity::writeToMemory(void* addr) const {
    21     size_t size = sizeof(fID) + sizeof(fTTCIndex);
    22     size += sizeof(int32_t) + sizeof(int32_t) + sizeof(uint8_t); // weight, width, italic
    23     size += sizeof(int32_t) + fString.size();    // store length+data
    24     if (addr) {
    25         SkWBuffer buffer(addr, size);
    27         buffer.write32(fID);
    28         buffer.write32(fTTCIndex);
    29         buffer.write32(fString.size());
    30         buffer.write32(fStyle.weight());
    31         buffer.write32(fStyle.width());
    32         buffer.write8(fStyle.slant());
    33         buffer.write(fString.c_str(), fString.size());
    34         buffer.padToAlign4();
    36         SkASSERT(buffer.pos() == size);
    37     }
    38     return size;
    39 }
    41 size_t SkFontConfigInterface::FontIdentity::readFromMemory(const void* addr,
    42                                                            size_t size) {
    43     SkRBuffer buffer(addr, size);
    45     (void)buffer.readU32(&fID);
    46     (void)buffer.readS32(&fTTCIndex);
    47     uint32_t strLen, weight, width;
    48     (void)buffer.readU32(&strLen);
    49     (void)buffer.readU32(&weight);
    50     (void)buffer.readU32(&width);
    51     uint8_t u8;
    52     (void)buffer.readU8(&u8);
    53     SkFontStyle::Slant slant = (SkFontStyle::Slant)u8;
    54     fStyle = SkFontStyle(weight, width, slant);
    55     fString.resize(strLen);
    56     (void)buffer.read(fString.writable_str(), strLen);
    57     buffer.skipToAlign4();
    59     return buffer.pos();    // the actual number of bytes read
    60 }
    62 #ifdef SK_DEBUG
    63 static void make_iden(SkFontConfigInterface::FontIdentity* iden) {
    64     iden->fID = 10;
    65     iden->fTTCIndex = 2;
    66     iden->fString.set("Hello world");
    67     iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant);
    68 }
    70 static void test_writeToMemory(const SkFontConfigInterface::FontIdentity& iden0,
    71                                int initValue) {
    72     SkFontConfigInterface::FontIdentity iden1;
    74     size_t size0 = iden0.writeToMemory(NULL);
    76     SkAutoMalloc storage(size0);
    77     memset(storage.get(), initValue, size0);
    79     size_t size1 = iden0.writeToMemory(storage.get());
    80     SkASSERT(size0 == size1);
    82     SkASSERT(iden0 != iden1);
    83     size_t size2 = iden1.readFromMemory(storage.get(), size1);
    84     SkASSERT(size2 == size1);
    85     SkASSERT(iden0 == iden1);
    86 }
    88 static void fontconfiginterface_unittest() {
    89     SkFontConfigInterface::FontIdentity iden0, iden1;
    91     SkASSERT(iden0 == iden1);
    93     make_iden(&iden0);
    94     SkASSERT(iden0 != iden1);
    96     make_iden(&iden1);
    97     SkASSERT(iden0 == iden1);
    99     test_writeToMemory(iden0, 0);
   100     test_writeToMemory(iden0, 0);
   101 }
   102 #endif
   104 class SkFontConfigInterfaceDirect : public SkFontConfigInterface {
   105 public:
   106             SkFontConfigInterfaceDirect();
   107     virtual ~SkFontConfigInterfaceDirect();
   109     virtual bool matchFamilyName(const char familyName[],
   110                                  SkTypeface::Style requested,
   111                                  FontIdentity* outFontIdentifier,
   112                                  SkString* outFamilyName,
   113                                  SkTypeface::Style* outStyle) SK_OVERRIDE;
   114     virtual SkStream* openStream(const FontIdentity&) SK_OVERRIDE;
   116     // new APIs
   117     virtual SkDataTable* getFamilyNames() SK_OVERRIDE;
   118     virtual bool matchFamilySet(const char inFamilyName[],
   119                                 SkString* outFamilyName,
   120                                 SkTArray<FontIdentity>*) SK_OVERRIDE;
   122 private:
   123     SkMutex mutex_;
   124 };
   126 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() {
   127     static SkFontConfigInterface* gDirect;
   128     if (NULL == gDirect) {
   129         static SkMutex gMutex;
   130         SkAutoMutexAcquire ac(gMutex);
   132         if (NULL == gDirect) {
   133             gDirect = new SkFontConfigInterfaceDirect;
   134         }
   135     }
   136     return gDirect;
   137 }
   139 ///////////////////////////////////////////////////////////////////////////////
   141 // Returns the string from the pattern, or NULL
   142 static const char* get_name(FcPattern* pattern, const char field[],
   143                             int index = 0) {
   144     const char* name;
   145     if (FcPatternGetString(pattern, field, index,
   146                            (FcChar8**)&name) != FcResultMatch) {
   147         name = NULL;
   148     }
   149     return name;
   150 }
   152 ///////////////////////////////////////////////////////////////////////////////
   154 namespace {
   156 // Equivalence classes, used to match the Liberation and other fonts
   157 // with their metric-compatible replacements.  See the discussion in
   158 // GetFontEquivClass().
   159 enum FontEquivClass
   160 {
   161     OTHER,
   162     SANS,
   163     SERIF,
   164     MONO,
   165     SYMBOL,
   166     PGOTHIC,
   167     GOTHIC,
   168     PMINCHO,
   169     MINCHO,
   170     SIMSUN,
   171     NSIMSUN,
   172     SIMHEI,
   173     PMINGLIU,
   174     MINGLIU,
   175     PMINGLIUHK,
   176     MINGLIUHK,
   177     CAMBRIA,
   178     CALIBRI,
   179 };
   181 // Match the font name against a whilelist of fonts, returning the equivalence
   182 // class.
   183 FontEquivClass GetFontEquivClass(const char* fontname)
   184 {
   185     // It would be nice for fontconfig to tell us whether a given suggested
   186     // replacement is a "strong" match (that is, an equivalent font) or
   187     // a "weak" match (that is, fontconfig's next-best attempt at finding a
   188     // substitute).  However, I played around with the fontconfig API for
   189     // a good few hours and could not make it reveal this information.
   190     //
   191     // So instead, we hardcode.  Initially this function emulated
   192     //   /etc/fonts/conf.d/30-metric-aliases.conf
   193     // from my Ubuntu system, but we're better off being very conservative.
   195     // Arimo, Tinos and Cousine are a set of fonts metric-compatible with
   196     // Arial, Times New Roman and Courier New  with a character repertoire
   197     // much larger than Liberation. Note that Cousine is metrically
   198     // compatible with Courier New, but the former is sans-serif while
   199     // the latter is serif.
   202     struct FontEquivMap {
   203         FontEquivClass clazz;
   204         const char name[40];
   205     };
   207     static const FontEquivMap kFontEquivMap[] = {
   208         { SANS, "Arial" },
   209         { SANS, "Arimo" },
   210         { SANS, "Liberation Sans" },
   212         { SERIF, "Times New Roman" },
   213         { SERIF, "Tinos" },
   214         { SERIF, "Liberation Serif" },
   216         { MONO, "Courier New" },
   217         { MONO, "Cousine" },
   218         { MONO, "Liberation Mono" },
   220         { SYMBOL, "Symbol" },
   221         { SYMBOL, "Symbol Neu" },
   223         // MS Pゴシック
   224         { PGOTHIC, "MS PGothic" },
   225         { PGOTHIC, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0"
   226                    "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" },
   227         { PGOTHIC, "IPAPGothic" },
   228         { PGOTHIC, "MotoyaG04Gothic" },
   230         // MS ゴシック
   231         { GOTHIC, "MS Gothic" },
   232         { GOTHIC, "\xef\xbc\xad\xef\xbc\xb3 "
   233                   "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" },
   234         { GOTHIC, "IPAGothic" },
   235         { GOTHIC, "MotoyaG04GothicMono" },
   237         // MS P明朝
   238         { PMINCHO, "MS PMincho" },
   239         { PMINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0"
   240                    "\xe6\x98\x8e\xe6\x9c\x9d"},
   241         { PMINCHO, "IPAPMincho" },
   242         { PMINCHO, "MotoyaG04Mincho" },
   244         // MS 明朝
   245         { MINCHO, "MS Mincho" },
   246         { MINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xe6\x98\x8e\xe6\x9c\x9d" },
   247         { MINCHO, "IPAMincho" },
   248         { MINCHO, "MotoyaG04MinchoMono" },
   250         // 宋体
   251         { SIMSUN, "Simsun" },
   252         { SIMSUN, "\xe5\xae\x8b\xe4\xbd\x93" },
   253         { SIMSUN, "MSung GB18030" },
   254         { SIMSUN, "Song ASC" },
   256         // 新宋体
   257         { NSIMSUN, "NSimsun" },
   258         { NSIMSUN, "\xe6\x96\xb0\xe5\xae\x8b\xe4\xbd\x93" },
   259         { NSIMSUN, "MSung GB18030" },
   260         { NSIMSUN, "N Song ASC" },
   262         // 黑体
   263         { SIMHEI, "Simhei" },
   264         { SIMHEI, "\xe9\xbb\x91\xe4\xbd\x93" },
   265         { SIMHEI, "MYingHeiGB18030" },
   266         { SIMHEI, "MYingHeiB5HK" },
   268         // 新細明體
   269         { PMINGLIU, "PMingLiU"},
   270         { PMINGLIU, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" },
   271         { PMINGLIU, "MSung B5HK"},
   273         // 細明體
   274         { MINGLIU, "MingLiU"},
   275         { MINGLIU, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" },
   276         { MINGLIU, "MSung B5HK"},
   278         // 新細明體
   279         { PMINGLIUHK, "PMingLiU_HKSCS"},
   280         { PMINGLIUHK, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" },
   281         { PMINGLIUHK, "MSung B5HK"},
   283         // 細明體
   284         { MINGLIUHK, "MingLiU_HKSCS"},
   285         { MINGLIUHK, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" },
   286         { MINGLIUHK, "MSung B5HK"},
   288         // Cambria
   289         { CAMBRIA, "Cambria" },
   290         { CAMBRIA, "Caladea" },
   292         // Calibri
   293         { CALIBRI, "Calibri" },
   294         { CALIBRI, "Carlito" },
   295     };
   297     static const size_t kFontCount =
   298         sizeof(kFontEquivMap)/sizeof(kFontEquivMap[0]);
   300     // TODO(jungshik): If this loop turns out to be hot, turn
   301     // the array to a static (hash)map to speed it up.
   302     for (size_t i = 0; i < kFontCount; ++i) {
   303         if (strcasecmp(kFontEquivMap[i].name, fontname) == 0)
   304             return kFontEquivMap[i].clazz;
   305     }
   306     return OTHER;
   307 }
   310 // Return true if |font_a| and |font_b| are visually and at the metrics
   311 // level interchangeable.
   312 bool IsMetricCompatibleReplacement(const char* font_a, const char* font_b)
   313 {
   314     FontEquivClass class_a = GetFontEquivClass(font_a);
   315     FontEquivClass class_b = GetFontEquivClass(font_b);
   317     return class_a != OTHER && class_a == class_b;
   318 }
   320 // Normally we only return exactly the font asked for. In last-resort
   321 // cases, the request either doesn't specify a font or is one of the
   322 // basic font names like "Sans", "Serif" or "Monospace". This function
   323 // tells you whether a given request is for such a fallback.
   324 bool IsFallbackFontAllowed(const std::string& family) {
   325   const char* family_cstr = family.c_str();
   326   return family.empty() ||
   327          strcasecmp(family_cstr, "sans") == 0 ||
   328          strcasecmp(family_cstr, "serif") == 0 ||
   329          strcasecmp(family_cstr, "monospace") == 0;
   330 }
   332 static bool valid_pattern(FcPattern* pattern) {
   333 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS
   334     FcBool is_scalable;
   335     if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch
   336         || !is_scalable) {
   337         return false;
   338     }
   339 #endif
   341     // fontconfig can also return fonts which are unreadable
   342     const char* c_filename = get_name(pattern, FC_FILE);
   343     if (!c_filename) {
   344         return false;
   345     }
   346     if (access(c_filename, R_OK) != 0) {
   347         return false;
   348     }
   349     return true;
   350 }
   352 // Find matching font from |font_set| for the given font family.
   353 FcPattern* MatchFont(FcFontSet* font_set,
   354                      const char* post_config_family,
   355                      const std::string& family) {
   356   // Older versions of fontconfig have a bug where they cannot select
   357   // only scalable fonts so we have to manually filter the results.
   358   FcPattern* match = NULL;
   359   for (int i = 0; i < font_set->nfont; ++i) {
   360     FcPattern* current = font_set->fonts[i];
   361     if (valid_pattern(current)) {
   362       match = current;
   363       break;
   364     }
   365   }
   367   if (match && !IsFallbackFontAllowed(family)) {
   368     bool acceptable_substitute = false;
   369     for (int id = 0; id < 255; ++id) {
   370       const char* post_match_family = get_name(match, FC_FAMILY, id);
   371       if (!post_match_family)
   372         break;
   373       acceptable_substitute =
   374           (strcasecmp(post_config_family, post_match_family) == 0 ||
   375            // Workaround for Issue 12530:
   376            //   requested family: "Bitstream Vera Sans"
   377            //   post_config_family: "Arial"
   378            //   post_match_family: "Bitstream Vera Sans"
   379            // -> We should treat this case as a good match.
   380            strcasecmp(family.c_str(), post_match_family) == 0) ||
   381            IsMetricCompatibleReplacement(family.c_str(), post_match_family);
   382       if (acceptable_substitute)
   383         break;
   384     }
   385     if (!acceptable_substitute)
   386       return NULL;
   387   }
   389   return match;
   390 }
   392 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|.
   393 SkTypeface::Style GetFontStyle(FcPattern* font) {
   394     int resulting_bold;
   395     if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold))
   396         resulting_bold = FC_WEIGHT_NORMAL;
   398     int resulting_italic;
   399     if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic))
   400         resulting_italic = FC_SLANT_ROMAN;
   402     // If we ask for an italic font, fontconfig might take a roman font and set
   403     // the undocumented property FC_MATRIX to a skew matrix. It'll then say
   404     // that the font is italic or oblique. So, if we see a matrix, we don't
   405     // believe that it's italic.
   406     FcValue matrix;
   407     const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0;
   409     // If we ask for an italic font, fontconfig might take a roman font and set
   410     // FC_EMBOLDEN.
   411     FcValue embolden;
   412     const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) == 0;
   414     int styleBits = 0;
   415     if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) {
   416         styleBits |= SkTypeface::kBold;
   417     }
   418     if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) {
   419         styleBits |= SkTypeface::kItalic;
   420     }
   422     return (SkTypeface::Style)styleBits;
   423 }
   425 }  // anonymous namespace
   427 ///////////////////////////////////////////////////////////////////////////////
   429 #define kMaxFontFamilyLength    2048
   431 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() {
   432     SkAutoMutexAcquire ac(mutex_);
   434     FcInit();
   436     SkDEBUGCODE(fontconfiginterface_unittest();)
   437 }
   439 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
   440 }
   442 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[],
   443                                                   SkTypeface::Style style,
   444                                                   FontIdentity* outIdentity,
   445                                                   SkString* outFamilyName,
   446                                                   SkTypeface::Style* outStyle) {
   447     std::string familyStr(familyName ? familyName : "");
   448     if (familyStr.length() > kMaxFontFamilyLength) {
   449         return false;
   450     }
   452     SkAutoMutexAcquire ac(mutex_);
   454     FcPattern* pattern = FcPatternCreate();
   456     if (familyName) {
   457         FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
   458     }
   459     FcPatternAddInteger(pattern, FC_WEIGHT,
   460                         (style & SkTypeface::kBold) ? FC_WEIGHT_BOLD
   461                                                     : FC_WEIGHT_NORMAL);
   462     FcPatternAddInteger(pattern, FC_SLANT,
   463                         (style & SkTypeface::kItalic) ? FC_SLANT_ITALIC
   464                                                       : FC_SLANT_ROMAN);
   465     FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
   467     FcConfigSubstitute(NULL, pattern, FcMatchPattern);
   468     FcDefaultSubstitute(pattern);
   470     // Font matching:
   471     // CSS often specifies a fallback list of families:
   472     //    font-family: a, b, c, serif;
   473     // However, fontconfig will always do its best to find *a* font when asked
   474     // for something so we need a way to tell if the match which it has found is
   475     // "good enough" for us. Otherwise, we can return NULL which gets piped up
   476     // and lets WebKit know to try the next CSS family name. However, fontconfig
   477     // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
   478     // wish to support that.
   479     //
   480     // Thus, if a specific family is requested we set @family_requested. Then we
   481     // record two strings: the family name after config processing and the
   482     // family name after resolving. If the two are equal, it's a good match.
   483     //
   484     // So consider the case where a user has mapped Arial to Helvetica in their
   485     // config.
   486     //    requested family: "Arial"
   487     //    post_config_family: "Helvetica"
   488     //    post_match_family: "Helvetica"
   489     //      -> good match
   490     //
   491     // and for a missing font:
   492     //    requested family: "Monaco"
   493     //    post_config_family: "Monaco"
   494     //    post_match_family: "Times New Roman"
   495     //      -> BAD match
   496     //
   497     // However, we special-case fallback fonts; see IsFallbackFontAllowed().
   499     const char* post_config_family = get_name(pattern, FC_FAMILY);
   500     if (!post_config_family) {
   501         // we can just continue with an empty name, e.g. default font
   502         post_config_family = "";
   503     }
   505     FcResult result;
   506     FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
   507     if (!font_set) {
   508         FcPatternDestroy(pattern);
   509         return false;
   510     }
   512     FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
   513     if (!match) {
   514         FcPatternDestroy(pattern);
   515         FcFontSetDestroy(font_set);
   516         return false;
   517     }
   519     FcPatternDestroy(pattern);
   521     // From here out we just extract our results from 'match'
   523     post_config_family = get_name(match, FC_FAMILY);
   524     if (!post_config_family) {
   525         FcFontSetDestroy(font_set);
   526         return false;
   527     }
   529     const char* c_filename = get_name(match, FC_FILE);
   530     if (!c_filename) {
   531         FcFontSetDestroy(font_set);
   532         return false;
   533     }
   535     int face_index;
   536     if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
   537         FcFontSetDestroy(font_set);
   538         return false;
   539     }
   541     FcFontSetDestroy(font_set);
   543     if (outIdentity) {
   544         outIdentity->fTTCIndex = face_index;
   545         outIdentity->fString.set(c_filename);
   546     }
   547     if (outFamilyName) {
   548         outFamilyName->set(post_config_family);
   549     }
   550     if (outStyle) {
   551         *outStyle = GetFontStyle(match);
   552     }
   553     return true;
   554 }
   556 SkStream* SkFontConfigInterfaceDirect::openStream(const FontIdentity& identity) {
   557     return SkStream::NewFromFile(identity.fString.c_str());
   558 }
   560 ///////////////////////////////////////////////////////////////////////////////
   562 static bool find_name(const SkTDArray<const char*>& list, const char* str) {
   563     int count = list.count();
   564     for (int i = 0; i < count; ++i) {
   565         if (!strcmp(list[i], str)) {
   566             return true;
   567         }
   568     }
   569     return false;
   570 }
   572 SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() {
   573     SkAutoMutexAcquire ac(mutex_);
   575     FcPattern* pat = FcPatternCreate();
   576     SkAutoTCallVProc<FcPattern, FcPatternDestroy> autoDestroyPat(pat);
   577     if (NULL == pat) {
   578         return NULL;
   579     }
   581     FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, (char *)0);
   582     SkAutoTCallVProc<FcObjectSet, FcObjectSetDestroy> autoDestroyOs(os);
   583     if (NULL == os) {
   584         return NULL;
   585     }
   587     FcFontSet* fs = FcFontList(NULL, pat, os);
   588     SkAutoTCallVProc<FcFontSet, FcFontSetDestroy> autoDestroyFs(fs);
   589     if (NULL == fs) {
   590         return NULL;
   591     }
   593     SkTDArray<const char*> names;
   594     SkTDArray<size_t> sizes;
   595     for (int i = 0; i < fs->nfont; ++i) {
   596         FcPattern* match = fs->fonts[i];
   597         const char* famName = get_name(match, FC_FAMILY);
   598         if (famName && !find_name(names, famName)) {
   599             *names.append() = famName;
   600             *sizes.append() = strlen(famName) + 1;
   601         }
   602     }
   604     return SkDataTable::NewCopyArrays((const void*const*)names.begin(),
   605                                       sizes.begin(), names.count());
   606 }
   608 bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[],
   609                                                  SkString* outFamilyName,
   610                                                  SkTArray<FontIdentity>* ids) {
   611     SkAutoMutexAcquire ac(mutex_);
   613 #if 0
   614     std::string familyStr(familyName ? familyName : "");
   615     if (familyStr.length() > kMaxFontFamilyLength) {
   616         return false;
   617     }
   619     SkAutoMutexAcquire ac(mutex_);
   621     FcPattern* pattern = FcPatternCreate();
   623     if (familyName) {
   624         FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
   625     }
   626     FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
   628     FcConfigSubstitute(NULL, pattern, FcMatchPattern);
   629     FcDefaultSubstitute(pattern);
   631     // Font matching:
   632     // CSS often specifies a fallback list of families:
   633     //    font-family: a, b, c, serif;
   634     // However, fontconfig will always do its best to find *a* font when asked
   635     // for something so we need a way to tell if the match which it has found is
   636     // "good enough" for us. Otherwise, we can return NULL which gets piped up
   637     // and lets WebKit know to try the next CSS family name. However, fontconfig
   638     // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
   639     // wish to support that.
   640     //
   641     // Thus, if a specific family is requested we set @family_requested. Then we
   642     // record two strings: the family name after config processing and the
   643     // family name after resolving. If the two are equal, it's a good match.
   644     //
   645     // So consider the case where a user has mapped Arial to Helvetica in their
   646     // config.
   647     //    requested family: "Arial"
   648     //    post_config_family: "Helvetica"
   649     //    post_match_family: "Helvetica"
   650     //      -> good match
   651     //
   652     // and for a missing font:
   653     //    requested family: "Monaco"
   654     //    post_config_family: "Monaco"
   655     //    post_match_family: "Times New Roman"
   656     //      -> BAD match
   657     //
   658     // However, we special-case fallback fonts; see IsFallbackFontAllowed().
   660     const char* post_config_family = get_name(pattern, FC_FAMILY);
   662     FcResult result;
   663     FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
   664     if (!font_set) {
   665         FcPatternDestroy(pattern);
   666         return false;
   667     }
   669     FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
   670     if (!match) {
   671         FcPatternDestroy(pattern);
   672         FcFontSetDestroy(font_set);
   673         return false;
   674     }
   676     FcPatternDestroy(pattern);
   678     // From here out we just extract our results from 'match'
   680     if (FcPatternGetString(match, FC_FAMILY, 0, &post_config_family) != FcResultMatch) {
   681         FcFontSetDestroy(font_set);
   682         return false;
   683     }
   685     FcChar8* c_filename;
   686     if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) {
   687         FcFontSetDestroy(font_set);
   688         return false;
   689     }
   691     int face_index;
   692     if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
   693         FcFontSetDestroy(font_set);
   694         return false;
   695     }
   697     FcFontSetDestroy(font_set);
   699     if (outIdentity) {
   700         outIdentity->fTTCIndex = face_index;
   701         outIdentity->fString.set((const char*)c_filename);
   702     }
   703     if (outFamilyName) {
   704         outFamilyName->set((const char*)post_config_family);
   705     }
   706     if (outStyle) {
   707         *outStyle = GetFontStyle(match);
   708     }
   709     return true;
   711 ////////////////////
   713         int count;
   714         FcPattern** match = MatchFont(font_set, post_config_family, &count);
   715         if (!match) {
   716             FcPatternDestroy(pattern);
   717             FcFontSetDestroy(font_set);
   718             return NULL;
   719         }
   721         FcPatternDestroy(pattern);
   723         SkTDArray<FcPattern*> trimmedMatches;
   724         for (int i = 0; i < count; ++i) {
   725             const char* justName = find_just_name(get_name(match[i], FC_FILE));
   726             if (!is_lower(*justName)) {
   727                 *trimmedMatches.append() = match[i];
   728             }
   729         }
   731         SkFontStyleSet_FC* sset = SkNEW_ARGS(SkFontStyleSet_FC,
   732                                              (trimmedMatches.begin(),
   733                                               trimmedMatches.count()));
   734 #endif
   735     return false;
   736 }

mercurial