gfx/skia/trunk/src/fonts/SkFontMgr_fontconfig.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 2013 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 #include "SkFontMgr.h"
     9 #include "SkFontStyle.h"
    10 #include "SkFontConfigInterface.h"
    11 #include "SkFontConfigTypeface.h"
    12 #include "SkMath.h"
    13 #include "SkString.h"
    14 #include "SkTDArray.h"
    16 // for now we pull these in directly. eventually we will solely rely on the
    17 // SkFontConfigInterface instance.
    18 #include <fontconfig/fontconfig.h>
    19 #include <unistd.h>
    21 // Defined in SkFontHost_FreeType.cpp
    22 bool find_name_and_attributes(SkStream* stream, SkString* name,
    23                               SkTypeface::Style* style, bool* isFixedWidth);
    25 // borrow this global from SkFontHost_fontconfig. eventually that file should
    26 // go away, and be replaced with this one.
    27 extern SkFontConfigInterface* SkFontHost_fontconfig_ref_global();
    28 static SkFontConfigInterface* RefFCI() {
    29     return SkFontHost_fontconfig_ref_global();
    30 }
    32 // look for the last substring after a '/' and return that, or return null.
    33 static const char* find_just_name(const char* str) {
    34     const char* last = strrchr(str, '/');
    35     return last ? last + 1 : NULL;
    36 }
    38 static bool is_lower(char c) {
    39     return c >= 'a' && c <= 'z';
    40 }
    42 static int get_int(FcPattern* pattern, const char field[]) {
    43     int value;
    44     if (FcPatternGetInteger(pattern, field, 0, &value) != FcResultMatch) {
    45         value = SK_MinS32;
    46     }
    47     return value;
    48 }
    50 static const char* get_name(FcPattern* pattern, const char field[]) {
    51     const char* name;
    52     if (FcPatternGetString(pattern, field, 0, (FcChar8**)&name) != FcResultMatch) {
    53         name = "";
    54     }
    55     return name;
    56 }
    58 static bool valid_pattern(FcPattern* pattern) {
    59     FcBool is_scalable;
    60     if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch || !is_scalable) {
    61         return false;
    62     }
    64     // fontconfig can also return fonts which are unreadable
    65     const char* c_filename = get_name(pattern, FC_FILE);
    66     if (0 == *c_filename) {
    67         return false;
    68     }
    69     if (access(c_filename, R_OK) != 0) {
    70         return false;
    71     }
    72     return true;
    73 }
    75 static bool match_name(FcPattern* pattern, const char family_name[]) {
    76     return !strcasecmp(family_name, get_name(pattern, FC_FAMILY));
    77 }
    79 static FcPattern** MatchFont(FcFontSet* font_set,
    80                              const char post_config_family[],
    81                              int* count) {
    82   // Older versions of fontconfig have a bug where they cannot select
    83   // only scalable fonts so we have to manually filter the results.
    85     FcPattern** iter = font_set->fonts;
    86     FcPattern** stop = iter + font_set->nfont;
    87     // find the first good match
    88     for (; iter < stop; ++iter) {
    89         if (valid_pattern(*iter)) {
    90             break;
    91         }
    92     }
    94     if (iter == stop || !match_name(*iter, post_config_family)) {
    95         return NULL;
    96     }
    98     FcPattern** firstIter = iter++;
    99     for (; iter < stop; ++iter) {
   100         if (!valid_pattern(*iter) || !match_name(*iter, post_config_family)) {
   101             break;
   102         }
   103     }
   105     *count = iter - firstIter;
   106     return firstIter;
   107 }
   109 class SkFontStyleSet_FC : public SkFontStyleSet {
   110 public:
   111     SkFontStyleSet_FC(FcPattern** matches, int count);
   112     virtual ~SkFontStyleSet_FC();
   114     virtual int count() SK_OVERRIDE { return fRecCount; }
   115     virtual void getStyle(int index, SkFontStyle*, SkString* style) SK_OVERRIDE;
   116     virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
   117     virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
   119 private:
   120     struct Rec {
   121         SkString    fStyleName;
   122         SkString    fFileName;
   123         SkFontStyle fStyle;
   124     };
   125     Rec* fRecs;
   126     int  fRecCount;
   127 };
   129 static int map_range(int value,
   130                      int old_min, int old_max, int new_min, int new_max) {
   131     SkASSERT(old_min < old_max);
   132     SkASSERT(new_min < new_max);
   133     return new_min + SkMulDiv(value - old_min,
   134                               new_max - new_min, old_max - old_min);
   135 }
   137 static SkFontStyle make_fontconfig_style(FcPattern* match) {
   138     int weight = get_int(match, FC_WEIGHT);
   139     int width = get_int(match, FC_WIDTH);
   140     int slant = get_int(match, FC_SLANT);
   141 //    SkDebugf("old weight %d new weight %d\n", weight, map_range(weight, 0, 80, 0, 400));
   143     // fontconfig weight seems to be 0..200 or so, so we remap it here
   144     weight = map_range(weight, 0, 80, 0, 400);
   145     width = map_range(width, 0, 200, 0, 9);
   146     return SkFontStyle(weight, width, slant > 0 ? SkFontStyle::kItalic_Slant
   147                                                 : SkFontStyle::kUpright_Slant);
   148 }
   150 SkFontStyleSet_FC::SkFontStyleSet_FC(FcPattern** matches, int count) {
   151     fRecCount = count;
   152     fRecs = SkNEW_ARRAY(Rec, count);
   153     for (int i = 0; i < count; ++i) {
   154         fRecs[i].fStyleName.set(get_name(matches[i], FC_STYLE));
   155         fRecs[i].fFileName.set(get_name(matches[i], FC_FILE));
   156         fRecs[i].fStyle = make_fontconfig_style(matches[i]);
   157     }
   158 }
   160 SkFontStyleSet_FC::~SkFontStyleSet_FC() {
   161     SkDELETE_ARRAY(fRecs);
   162 }
   164 void SkFontStyleSet_FC::getStyle(int index, SkFontStyle* style,
   165                                  SkString* styleName) {
   166     SkASSERT((unsigned)index < (unsigned)fRecCount);
   167     if (style) {
   168         *style = fRecs[index].fStyle;
   169     }
   170     if (styleName) {
   171         *styleName = fRecs[index].fStyleName;
   172     }
   173 }
   175 SkTypeface* SkFontStyleSet_FC::createTypeface(int index) {
   176     return NULL;
   177 }
   179 SkTypeface* SkFontStyleSet_FC::matchStyle(const SkFontStyle& pattern) {
   180     return NULL;
   181 }
   183 class SkFontMgr_fontconfig : public SkFontMgr {
   184     SkAutoTUnref<SkFontConfigInterface> fFCI;
   185     SkDataTable* fFamilyNames;
   188 public:
   189     SkFontMgr_fontconfig(SkFontConfigInterface* fci)
   190         : fFCI(fci)
   191         , fFamilyNames(fFCI->getFamilyNames()) {}
   193     virtual ~SkFontMgr_fontconfig() {
   194         SkSafeUnref(fFamilyNames);
   195     }
   197 protected:
   198     virtual int onCountFamilies() const SK_OVERRIDE {
   199         return fFamilyNames->count();
   200     }
   202     virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
   203         familyName->set(fFamilyNames->atStr(index));
   204     }
   206     virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
   207         return this->onMatchFamily(fFamilyNames->atStr(index));
   208     }
   210     virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
   211         FcPattern* pattern = FcPatternCreate();
   213         FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
   214 #if 0
   215         FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
   216 #endif
   217         FcConfigSubstitute(NULL, pattern, FcMatchPattern);
   218         FcDefaultSubstitute(pattern);
   220         const char* post_config_family = get_name(pattern, FC_FAMILY);
   222         FcResult result;
   223         FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
   224         if (!font_set) {
   225             FcPatternDestroy(pattern);
   226             return NULL;
   227         }
   229         int count;
   230         FcPattern** match = MatchFont(font_set, post_config_family, &count);
   231         if (!match) {
   232             FcPatternDestroy(pattern);
   233             FcFontSetDestroy(font_set);
   234             return NULL;
   235         }
   237         FcPatternDestroy(pattern);
   239         SkTDArray<FcPattern*> trimmedMatches;
   240         for (int i = 0; i < count; ++i) {
   241             const char* justName = find_just_name(get_name(match[i], FC_FILE));
   242             if (!is_lower(*justName)) {
   243                 *trimmedMatches.append() = match[i];
   244             }
   245         }
   247         SkFontStyleSet_FC* sset = SkNEW_ARGS(SkFontStyleSet_FC,
   248                                              (trimmedMatches.begin(),
   249                                               trimmedMatches.count()));
   250         return sset;
   251     }
   253     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
   254                                            const SkFontStyle&) const SK_OVERRIDE { return NULL; }
   255     virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,
   256                                          const SkFontStyle&) const SK_OVERRIDE { return NULL; }
   258     virtual SkTypeface* onCreateFromData(SkData*, int ttcIndex) const SK_OVERRIDE { return NULL; }
   260     virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
   261         const size_t length = stream->getLength();
   262         if (!length) {
   263             return NULL;
   264         }
   265         if (length >= 1024 * 1024 * 1024) {
   266             return NULL;  // don't accept too large fonts (>= 1GB) for safety.
   267         }
   269         // TODO should the caller give us the style or should we get it from freetype?
   270         SkTypeface::Style style = SkTypeface::kNormal;
   271         bool isFixedWidth = false;
   272         if (!find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) {
   273             return NULL;
   274         }
   276         SkTypeface* face = SkNEW_ARGS(FontConfigTypeface, (style, isFixedWidth, stream));
   277         return face;
   278     }
   280     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
   281         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
   282         return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
   283     }
   285     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
   286                                                unsigned styleBits) const SK_OVERRIDE {
   287         return FontConfigTypeface::LegacyCreateTypeface(NULL, familyName,
   288                                                   (SkTypeface::Style)styleBits);
   289     }
   290 };
   292 SkFontMgr* SkFontMgr::Factory() {
   293     SkFontConfigInterface* fci = RefFCI();
   294     return fci ? SkNEW_ARGS(SkFontMgr_fontconfig, (fci)) : NULL;
   295 }

mercurial