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