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_FreeType_common.h"
      9 #include "SkFontDescriptor.h"
     10 #include "SkFontMgr.h"
     11 #include "SkDescriptor.h"
     12 #include "SkOSFile.h"
     13 #include "SkPaint.h"
     14 #include "SkRTConf.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 /** The base SkTypeface implementation for the custom font manager. */
     25 class SkTypeface_Custom : public SkTypeface_FreeType {
     26 public:
     27     SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
     28                       bool sysFont, const SkString familyName, int index)
     29         : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
     30         , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
     31     { }
     32 
     33     bool isSysFont() const { return fIsSysFont; }
     34 
     35 protected:
     36     void onGetFamilyName(SkString* familyName) const override {
     37         *familyName = fFamilyName;
     38     }
     39 
     40     void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override {
     41         desc->setFamilyName(fFamilyName.c_str());
     42         desc->setFontIndex(fIndex);
     43         *isLocal = !this->isSysFont();
     44     }
     45 
     46     int getIndex() const { return fIndex; }
     47 
     48 private:
     49     const bool fIsSysFont;
     50     const SkString fFamilyName;
     51     const int fIndex;
     52 
     53     typedef SkTypeface_FreeType INHERITED;
     54 };
     55 
     56 /** The empty SkTypeface implementation for the custom font manager.
     57  *  Used as the last resort fallback typeface.
     58  */
     59 class SkTypeface_Empty : public SkTypeface_Custom {
     60 public:
     61     SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
     62 
     63 protected:
     64     SkStreamAsset* onOpenStream(int*) const override { return NULL; }
     65 
     66 private:
     67     typedef SkTypeface_Custom INHERITED;
     68 };
     69 
     70 /** The stream SkTypeface implementation for the custom font manager. */
     71 class SkTypeface_Stream : public SkTypeface_Custom {
     72 public:
     73     SkTypeface_Stream(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
     74                       const SkString familyName, SkStreamAsset* stream, int index)
     75         : INHERITED(style, isFixedPitch, sysFont, familyName, index)
     76         , fStream(stream)
     77     { }
     78 
     79 protected:
     80     SkStreamAsset* onOpenStream(int* ttcIndex) const override {
     81         *ttcIndex = this->getIndex();
     82         return fStream->duplicate();
     83     }
     84 
     85 private:
     86     const SkAutoTDelete<const SkStreamAsset> fStream;
     87 
     88     typedef SkTypeface_Custom INHERITED;
     89 };
     90 
     91 // This configuration option is useful if we need to open and hold handles to
     92 // all found system font data (e.g., for skfiddle, where the application can't
     93 // access the filesystem to read fonts on demand)
     94 
     95 SK_CONF_DECLARE(bool, c_CustomTypefaceRetain, "fonts.customFont.retainAllData", false,
     96                 "Retain the open stream for each found font on the system.");
     97 
     98 /** The file SkTypeface implementation for the custom font manager. */
     99 class SkTypeface_File : public SkTypeface_Custom {
    100 public:
    101     SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
    102                     const SkString familyName, const char path[], int index)
    103         : INHERITED(style, isFixedPitch, sysFont, familyName, index)
    104         , fPath(path)
    105         , fStream(c_CustomTypefaceRetain ? SkStream::NewFromFile(fPath.c_str()) : NULL)
    106     { }
    107 
    108 protected:
    109     SkStreamAsset* onOpenStream(int* ttcIndex) const override {
    110         *ttcIndex = this->getIndex();
    111         if (fStream.get()) {
    112             return fStream->duplicate();
    113         } else {
    114             return SkStream::NewFromFile(fPath.c_str());
    115         }
    116     }
    117 
    118 private:
    119     SkString fPath;
    120     const SkAutoTDelete<SkStreamAsset> fStream;
    121 
    122     typedef SkTypeface_Custom INHERITED;
    123 };
    124 
    125 ///////////////////////////////////////////////////////////////////////////////
    126 
    127 /**
    128  *  SkFontStyleSet_Custom
    129  *
    130  *  This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
    131  */
    132 class SkFontStyleSet_Custom : public SkFontStyleSet {
    133 public:
    134     explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
    135 
    136     /** Should only be called during the inital build phase. */
    137     void appendTypeface(SkTypeface_Custom* typeface) {
    138         fStyles.push_back().reset(typeface);
    139     }
    140 
    141     int count() override {
    142         return fStyles.count();
    143     }
    144 
    145     void getStyle(int index, SkFontStyle* style, SkString* name) 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     SkTypeface* createTypeface(int index) 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     SkTypeface* matchStyle(const SkFontStyle& pattern) 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     SkString getFamilyName() { return fFamilyName; }
    194 
    195 private:
    196     SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles;
    197     SkString fFamilyName;
    198 
    199     friend class SkFontMgr_Custom;
    200 };
    201 
    202 /**
    203  *  SkFontMgr_Custom
    204  *
    205  *  This class is essentially a collection of SkFontStyleSet_Custom,
    206  *  one SkFontStyleSet_Custom for each family. This class may be modified
    207  *  to load fonts from any source by changing the initialization.
    208  */
    209 class SkFontMgr_Custom : public SkFontMgr {
    210 public:
    211     typedef SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> Families;
    212     class SystemFontLoader {
    213     public:
    214         virtual ~SystemFontLoader() { }
    215         virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Families*) const = 0;
    216     };
    217     explicit SkFontMgr_Custom(const SystemFontLoader& loader) {
    218         loader.loadSystemFonts(fScanner, &fFamilies);
    219 
    220         // Try to pick a default font.
    221         static const char* defaultNames[] = {
    222             "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL
    223         };
    224         for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) {
    225             SkFontStyleSet_Custom* set = this->onMatchFamily(defaultNames[i]);
    226             if (NULL == set) {
    227                 continue;
    228             }
    229 
    230             SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
    231                                                          SkFontStyle::kNormal_Width,
    232                                                          SkFontStyle::kUpright_Slant));
    233             if (NULL == tf) {
    234                 continue;
    235             }
    236 
    237             fDefaultFamily = set;
    238             break;
    239         }
    240         if (NULL == fDefaultFamily) {
    241             fDefaultFamily = fFamilies[0];
    242         }
    243     }
    244 
    245 protected:
    246     int onCountFamilies() const override {
    247         return fFamilies.count();
    248     }
    249 
    250     void onGetFamilyName(int index, SkString* familyName) const override {
    251         SkASSERT(index < fFamilies.count());
    252         familyName->set(fFamilies[index]->getFamilyName());
    253     }
    254 
    255     SkFontStyleSet_Custom* onCreateStyleSet(int index) const override {
    256         SkASSERT(index < fFamilies.count());
    257         return SkRef(fFamilies[index].get());
    258     }
    259 
    260     SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override {
    261         for (int i = 0; i < fFamilies.count(); ++i) {
    262             if (fFamilies[i]->getFamilyName().equals(familyName)) {
    263                 return SkRef(fFamilies[i].get());
    264             }
    265         }
    266         return NULL;
    267     }
    268 
    269     SkTypeface* onMatchFamilyStyle(const char familyName[],
    270                                    const SkFontStyle& fontStyle) const override
    271     {
    272         SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
    273         return sset->matchStyle(fontStyle);
    274     }
    275 
    276     SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
    277                                             const char* bcp47[], int bcp47Count,
    278                                             SkUnichar character) const override
    279     {
    280         return NULL;
    281     }
    282 
    283     SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
    284                                  const SkFontStyle& fontStyle) const override
    285     {
    286         for (int i = 0; i < fFamilies.count(); ++i) {
    287             for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
    288                 if (fFamilies[i]->fStyles[j] == familyMember) {
    289                     return fFamilies[i]->matchStyle(fontStyle);
    290                 }
    291             }
    292         }
    293         return NULL;
    294     }
    295 
    296     SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
    297         return this->createFromStream(new SkMemoryStream(data), ttcIndex);
    298     }
    299 
    300     SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
    301         SkAutoTDelete<SkStreamAsset> stream(bareStream);
    302         if (NULL == stream || stream->getLength() <= 0) {
    303             return NULL;
    304         }
    305 
    306         bool isFixedPitch;
    307         SkFontStyle style;
    308         SkString name;
    309         if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
    310             return SkNEW_ARGS(SkTypeface_Stream, (style, isFixedPitch, false, name,
    311                                                   stream.detach(), ttcIndex));
    312         } else {
    313             return NULL;
    314         }
    315     }
    316 
    317     SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
    318         SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path));
    319         return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : NULL;
    320     }
    321 
    322     SkTypeface* onLegacyCreateTypeface(const char familyName[], unsigned styleBits) const override {
    323         SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
    324         SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
    325                                                  ? SkFontStyle::kBold_Weight
    326                                                  : SkFontStyle::kNormal_Weight,
    327                                         SkFontStyle::kNormal_Width,
    328                                         oldStyle & SkTypeface::kItalic
    329                                                  ? SkFontStyle::kItalic_Slant
    330                                                  : SkFontStyle::kUpright_Slant);
    331         SkTypeface* tf = NULL;
    332 
    333         if (familyName) {
    334             tf = this->onMatchFamilyStyle(familyName, style);
    335         }
    336 
    337         if (NULL == tf) {
    338             tf = fDefaultFamily->matchStyle(style);
    339         }
    340 
    341         return SkSafeRef(tf);
    342     }
    343 
    344 private:
    345     Families fFamilies;
    346     SkFontStyleSet_Custom* fDefaultFamily;
    347     SkTypeface_FreeType::Scanner fScanner;
    348 };
    349 
    350 ///////////////////////////////////////////////////////////////////////////////
    351 
    352 class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
    353 public:
    354     DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { }
    355 
    356     void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
    357                          SkFontMgr_Custom::Families* families) const override
    358     {
    359         load_directory_fonts(scanner, fBaseDirectory, ".ttf", families);
    360         load_directory_fonts(scanner, fBaseDirectory, ".ttc", families);
    361         load_directory_fonts(scanner, fBaseDirectory, ".otf", families);
    362         load_directory_fonts(scanner, fBaseDirectory, ".pfb", families);
    363 
    364         if (families->empty()) {
    365             SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
    366             families->push_back().reset(family);
    367             family->appendTypeface(SkNEW(SkTypeface_Empty));
    368         }
    369     }
    370 
    371 private:
    372     static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
    373                                               const char familyName[])
    374     {
    375        for (int i = 0; i < families.count(); ++i) {
    376             if (families[i]->getFamilyName().equals(familyName)) {
    377                 return families[i].get();
    378             }
    379         }
    380         return NULL;
    381     }
    382 
    383     static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner,
    384                                      const SkString& directory, const char* suffix,
    385                                      SkFontMgr_Custom::Families* families)
    386     {
    387         SkOSFile::Iter iter(directory.c_str(), suffix);
    388         SkString name;
    389 
    390         while (iter.next(&name, false)) {
    391             SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
    392             SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
    393             if (!stream.get()) {
    394                 SkDebugf("---- failed to open <%s>\n", filename.c_str());
    395                 continue;
    396             }
    397 
    398             int numFaces;
    399             if (!scanner.recognizedFont(stream, &numFaces)) {
    400                 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
    401                 continue;
    402             }
    403 
    404             for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
    405                 bool isFixedPitch;
    406                 SkString realname;
    407                 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
    408                 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) {
    409                     SkDebugf("---- failed to open <%s> <%d> as a font\n",
    410                              filename.c_str(), faceIndex);
    411                     continue;
    412                 }
    413 
    414                 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
    415                                                     style,
    416                                                     isFixedPitch,
    417                                                     true,  // system-font (cannot delete)
    418                                                     realname,
    419                                                     filename.c_str(),
    420                                                     faceIndex));
    421 
    422                 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
    423                 if (NULL == addTo) {
    424                     addTo = new SkFontStyleSet_Custom(realname);
    425                     families->push_back().reset(addTo);
    426                 }
    427                 addTo->appendTypeface(tf);
    428             }
    429         }
    430 
    431         SkOSFile::Iter dirIter(directory.c_str());
    432         while (dirIter.next(&name, true)) {
    433             if (name.startsWith(".")) {
    434                 continue;
    435             }
    436             SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
    437             load_directory_fonts(scanner, dirname, suffix, families);
    438         }
    439     }
    440 
    441     SkString fBaseDirectory;
    442 };
    443 
    444 struct SkEmbeddedResource { const uint8_t* data; size_t size; };
    445 struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; };
    446 
    447 class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
    448 public:
    449     EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { }
    450 
    451     void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
    452                          SkFontMgr_Custom::Families* families) const override
    453     {
    454         for (int i = 0; i < fHeader->count; ++i) {
    455             const SkEmbeddedResource& fontEntry = fHeader->entries[i];
    456             load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, families);
    457         }
    458 
    459         if (families->empty()) {
    460             SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
    461             families->push_back().reset(family);
    462             family->appendTypeface(SkNEW(SkTypeface_Empty));
    463         }
    464     }
    465 
    466 private:
    467     static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
    468                                               const char familyName[])
    469     {
    470        for (int i = 0; i < families.count(); ++i) {
    471             if (families[i]->getFamilyName().equals(familyName)) {
    472                 return families[i].get();
    473             }
    474         }
    475         return NULL;
    476     }
    477 
    478     static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner,
    479                                    const uint8_t* data, size_t size, int index,
    480                                    SkFontMgr_Custom::Families* families)
    481     {
    482         SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(data, size, false));
    483 
    484         int numFaces;
    485         if (!scanner.recognizedFont(stream, &numFaces)) {
    486             SkDebugf("---- failed to open <%d> as a font\n", index);
    487             return;
    488         }
    489 
    490         for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
    491             bool isFixedPitch;
    492             SkString realname;
    493             SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
    494             if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) {
    495                 SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex);
    496                 return;
    497             }
    498 
    499             SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_Stream, (
    500                                                 style,
    501                                                 isFixedPitch,
    502                                                 true,  // system-font (cannot delete)
    503                                                 realname,
    504                                                 stream.detach(),
    505                                                 faceIndex));
    506 
    507             SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
    508             if (NULL == addTo) {
    509                 addTo = new SkFontStyleSet_Custom(realname);
    510                 families->push_back().reset(addTo);
    511             }
    512             addTo->appendTypeface(tf);
    513         }
    514     }
    515 
    516     const SkEmbeddedResourceHeader* fHeader;
    517 };
    518 
    519 #ifdef SK_EMBEDDED_FONTS
    520 
    521 extern "C" const SkEmbeddedResourceHeader SK_EMBEDDED_FONTS;
    522 SkFontMgr* SkFontMgr::Factory() {
    523     return new SkFontMgr_Custom(EmbeddedSystemFontLoader(&SK_EMBEDDED_FONTS));
    524 }
    525 
    526 #else
    527 
    528 #ifndef SK_FONT_FILE_PREFIX
    529 #    define SK_FONT_FILE_PREFIX "/usr/share/fonts/"
    530 #endif
    531 SkFontMgr* SkFontMgr::Factory() {
    532     return new SkFontMgr_Custom(DirectorySystemFontLoader(SK_FONT_FILE_PREFIX));
    533 }
    534 
    535 #endif
    536