Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkFontHost.h"
      9 #include "SkFontHost_FreeType_common.h"
     10 #include "SkFontDescriptor.h"
     11 #include "SkFontMgr.h"
     12 #include "SkDescriptor.h"
     13 #include "SkOSFile.h"
     14 #include "SkPaint.h"
     15 #include "SkString.h"
     16 #include "SkStream.h"
     17 #include "SkThread.h"
     18 #include "SkTSearch.h"
     19 #include "SkTypefaceCache.h"
     20 #include "SkTArray.h"
     21 
     22 #include <limits>
     23 
     24 #ifndef SK_FONT_FILE_PREFIX
     25 #    define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/"
     26 #endif
     27 #ifndef SK_FONT_FILE_DIR_SEPERATOR
     28 #    define SK_FONT_FILE_DIR_SEPERATOR "/"
     29 #endif
     30 
     31 bool find_name_and_attributes(SkStream* stream, SkString* name,
     32                               SkTypeface::Style* style, bool* isFixedPitch);
     33 
     34 ///////////////////////////////////////////////////////////////////////////////
     35 
     36 /** The base SkTypeface implementation for the custom font manager. */
     37 class SkTypeface_Custom : public SkTypeface_FreeType {
     38 public:
     39     SkTypeface_Custom(Style style, bool sysFont, bool isFixedPitch, const SkString familyName)
     40         : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
     41         , fIsSysFont(sysFont), fFamilyName(familyName)
     42     { }
     43 
     44     bool isSysFont() const { return fIsSysFont; }
     45 
     46     virtual const char* getUniqueString() const = 0;
     47 
     48 protected:
     49     virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const SK_OVERRIDE {
     50         desc->setFamilyName(fFamilyName.c_str());
     51         desc->setFontFileName(this->getUniqueString());
     52         *isLocal = !this->isSysFont();
     53     }
     54 
     55 private:
     56     bool fIsSysFont;
     57     SkString fFamilyName;
     58 
     59     typedef SkTypeface_FreeType INHERITED;
     60 };
     61 
     62 /** The empty SkTypeface implementation for the custom font manager.
     63  *  Used as the last resort fallback typeface.
     64  */
     65 class SkTypeface_Empty : public SkTypeface_Custom {
     66 public:
     67     SkTypeface_Empty() : INHERITED(SkTypeface::kNormal, true, false, SkString()) {}
     68 
     69     virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
     70 
     71 protected:
     72     virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; }
     73 
     74 private:
     75     typedef SkTypeface_Custom INHERITED;
     76 };
     77 
     78 /** The stream SkTypeface implementation for the custom font manager. */
     79 class SkTypeface_Stream : public SkTypeface_Custom {
     80 public:
     81     SkTypeface_Stream(Style style, bool sysFont, SkStream* stream,
     82                       bool isFixedPitch, const SkString familyName)
     83         : INHERITED(style, sysFont, isFixedPitch, familyName)
     84         , fStream(SkRef(stream))
     85     { }
     86 
     87     virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
     88 
     89 protected:
     90     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
     91         *ttcIndex = 0;
     92         return SkRef(fStream.get());
     93     }
     94 
     95 private:
     96     SkAutoTUnref<SkStream> fStream;
     97 
     98     typedef SkTypeface_Custom INHERITED;
     99 };
    100 
    101 /** The file SkTypeface implementation for the custom font manager. */
    102 class SkTypeface_File : public SkTypeface_Custom {
    103 public:
    104     SkTypeface_File(Style style, bool sysFont, const char path[],
    105                     bool isFixedPitch, const SkString familyName)
    106         : INHERITED(style, sysFont, isFixedPitch, familyName)
    107         , fPath(path)
    108     { }
    109 
    110     virtual const char* getUniqueString() const SK_OVERRIDE {
    111         const char* str = strrchr(fPath.c_str(), '/');
    112         if (str) {
    113             str += 1;   // skip the '/'
    114         }
    115         return str;
    116     }
    117 
    118 protected:
    119     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
    120         *ttcIndex = 0;
    121         return SkStream::NewFromFile(fPath.c_str());
    122     }
    123 
    124 private:
    125     SkString fPath;
    126 
    127     typedef SkTypeface_Custom INHERITED;
    128 };
    129 
    130 ///////////////////////////////////////////////////////////////////////////////
    131 
    132 /**
    133  *  SkFontStyleSet_Custom
    134  *
    135  *  This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
    136  */
    137 class SkFontStyleSet_Custom : public SkFontStyleSet {
    138 public:
    139     explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
    140 
    141     virtual int count() SK_OVERRIDE {
    142         return fStyles.count();
    143     }
    144 
    145     virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
    146         SkASSERT(index < fStyles.count());
    147         bool bold = fStyles[index]->isBold();
    148         bool italic = fStyles[index]->isItalic();
    149         *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight,
    150                              SkFontStyle::kNormal_Width,
    151                              italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant);
    152         name->reset();
    153     }
    154 
    155     virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
    156         SkASSERT(index < fStyles.count());
    157         return SkRef(fStyles[index].get());
    158     }
    159 
    160     static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
    161         int score = 0;
    162         score += (pattern.width() - candidate.width()) * 100;
    163         score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000;
    164         score += pattern.weight() - candidate.weight();
    165         return score;
    166     }
    167 
    168     virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
    169         if (0 == fStyles.count()) {
    170             return NULL;
    171         }
    172 
    173         SkTypeface_Custom* closest = fStyles[0];
    174         int minScore = std::numeric_limits<int>::max();
    175         for (int i = 0; i < fStyles.count(); ++i) {
    176             bool bold = fStyles[i]->isBold();
    177             bool italic = fStyles[i]->isItalic();
    178             SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
    179                                                  : SkFontStyle::kNormal_Weight,
    180                                             SkFontStyle::kNormal_Width,
    181                                             italic ? SkFontStyle::kItalic_Slant
    182                                                    : SkFontStyle::kUpright_Slant);
    183 
    184             int score = match_score(pattern, style);
    185             if (score < minScore) {
    186                 closest = fStyles[i];
    187                 minScore = score;
    188             }
    189         }
    190         return SkRef(closest);
    191     }
    192 
    193 private:
    194     SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles;
    195     SkString fFamilyName;
    196 
    197     void appendTypeface(SkTypeface_Custom* typeface) {
    198         fStyles.push_back().reset(typeface);
    199     }
    200 
    201     friend class SkFontMgr_Custom;
    202 };
    203 
    204 /**
    205  *  SkFontMgr_Custom
    206  *
    207  *  This class is essentially a collection of SkFontStyleSet_Custom,
    208  *  one SkFontStyleSet_Custom for each family. This class may be modified
    209  *  to load fonts from any source by changing the initialization.
    210  */
    211 class SkFontMgr_Custom : public SkFontMgr {
    212 public:
    213     explicit SkFontMgr_Custom(const char* dir) {
    214         this->load_system_fonts(dir);
    215     }
    216 
    217 protected:
    218     virtual int onCountFamilies() SK_OVERRIDE {
    219         return fFamilies.count();
    220     }
    221 
    222     virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
    223         SkASSERT(index < fFamilies.count());
    224         familyName->set(fFamilies[index]->fFamilyName);
    225     }
    226 
    227     virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) SK_OVERRIDE {
    228         SkASSERT(index < fFamilies.count());
    229         return SkRef(fFamilies[index].get());
    230     }
    231 
    232     virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) SK_OVERRIDE {
    233         for (int i = 0; i < fFamilies.count(); ++i) {
    234             if (fFamilies[i]->fFamilyName.equals(familyName)) {
    235                 return SkRef(fFamilies[i].get());
    236             }
    237         }
    238         return NULL;
    239     }
    240 
    241     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
    242                                            const SkFontStyle& fontStyle) SK_OVERRIDE
    243     {
    244         SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
    245         return sset->matchStyle(fontStyle);
    246     }
    247 
    248     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
    249                                          const SkFontStyle& fontStyle) SK_OVERRIDE
    250     {
    251         for (int i = 0; i < fFamilies.count(); ++i) {
    252             for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
    253                 if (fFamilies[i]->fStyles[j] == familyMember) {
    254                     return fFamilies[i]->matchStyle(fontStyle);
    255                 }
    256             }
    257         }
    258         return NULL;
    259     }
    260 
    261     virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE {
    262         SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
    263         return this->createFromStream(stream, ttcIndex);
    264     }
    265 
    266     virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE {
    267         if (NULL == stream || stream->getLength() <= 0) {
    268             SkDELETE(stream);
    269             return NULL;
    270         }
    271 
    272         bool isFixedPitch;
    273         SkTypeface::Style style;
    274         SkString name;
    275         if (find_name_and_attributes(stream, &name, &style, &isFixedPitch)) {
    276             return SkNEW_ARGS(SkTypeface_Stream, (style, false, stream, isFixedPitch, name));
    277         } else {
    278             return NULL;
    279         }
    280     }
    281 
    282     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE {
    283         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
    284         return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
    285     }
    286 
    287     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
    288                                                unsigned styleBits) SK_OVERRIDE
    289     {
    290         SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
    291         SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
    292                                                  ? SkFontStyle::kBold_Weight
    293                                                  : SkFontStyle::kNormal_Weight,
    294                                         SkFontStyle::kNormal_Width,
    295                                         oldStyle & SkTypeface::kItalic
    296                                                  ? SkFontStyle::kItalic_Slant
    297                                                  : SkFontStyle::kUpright_Slant);
    298         SkTypeface* tf = NULL;
    299 
    300         if (NULL != familyName) {
    301             tf = this->onMatchFamilyStyle(familyName, style);
    302         }
    303 
    304         if (NULL == tf) {
    305             tf = gDefaultFamily->matchStyle(style);
    306         }
    307 
    308         return SkSafeRef(tf);
    309     }
    310 
    311 private:
    312 
    313     static bool get_name_and_style(const char path[], SkString* name,
    314                                    SkTypeface::Style* style, bool* isFixedPitch) {
    315         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
    316         if (stream.get()) {
    317             return find_name_and_attributes(stream, name, style, isFixedPitch);
    318         } else {
    319             SkDebugf("---- failed to open <%s> as a font\n", path);
    320             return false;
    321         }
    322     }
    323 
    324     void load_directory_fonts(const SkString& directory) {
    325         SkOSFile::Iter iter(directory.c_str(), ".ttf");
    326         SkString name;
    327 
    328         while (iter.next(&name, false)) {
    329             SkString filename(directory);
    330             filename.append(name);
    331 
    332             bool isFixedPitch;
    333             SkString realname;
    334             SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning
    335 
    336             if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPitch)) {
    337                 SkDebugf("------ can't load <%s> as a font\n", filename.c_str());
    338                 continue;
    339             }
    340 
    341             SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
    342                                                 style,
    343                                                 true,  // system-font (cannot delete)
    344                                                 filename.c_str(),
    345                                                 isFixedPitch,
    346                                                 realname));
    347 
    348             SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str());
    349             if (NULL == addTo) {
    350                 addTo = new SkFontStyleSet_Custom(realname);
    351                 fFamilies.push_back().reset(addTo);
    352             }
    353             addTo->appendTypeface(tf);
    354         }
    355 
    356         SkOSFile::Iter dirIter(directory.c_str());
    357         while (dirIter.next(&name, true)) {
    358             if (name.startsWith(".")) {
    359                 continue;
    360             }
    361             SkString dirname(directory);
    362             dirname.append(name);
    363             dirname.append(SK_FONT_FILE_DIR_SEPERATOR);
    364             load_directory_fonts(dirname);
    365         }
    366     }
    367 
    368     void load_system_fonts(const char* dir) {
    369         SkString baseDirectory(dir);
    370         load_directory_fonts(baseDirectory);
    371 
    372         if (fFamilies.empty()) {
    373             SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
    374             fFamilies.push_back().reset(family);
    375             family->appendTypeface(SkNEW(SkTypeface_Empty));
    376         }
    377 
    378         // Try to pick a default font.
    379         static const char* gDefaultNames[] = {
    380             "Arial", "Verdana", "Times New Roman", NULL
    381         };
    382         for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
    383             SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]);
    384             if (NULL == set) {
    385                 continue;
    386             }
    387 
    388             SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
    389                                                          SkFontStyle::kNormal_Width,
    390                                                          SkFontStyle::kUpright_Slant));
    391             if (NULL == tf) {
    392                 continue;
    393             }
    394 
    395             gDefaultFamily = set;
    396             gDefaultNormal = tf;
    397             break;
    398         }
    399         if (NULL == gDefaultNormal) {
    400             gDefaultFamily = fFamilies[0];
    401             gDefaultNormal = gDefaultFamily->fStyles[0];
    402         }
    403     }
    404 
    405     SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies;
    406     SkFontStyleSet_Custom* gDefaultFamily;
    407     SkTypeface* gDefaultNormal;
    408 };
    409 
    410 SkFontMgr* SkFontMgr::Factory() {
    411     return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX);
    412 }
    413