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