Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2017 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  */
      7 
      8 #include "SkFontMgr_custom.h"
      9 #include "SkFontMgr_directory.h"
     10 #include "SkOSFile.h"
     11 #include "SkOSPath.h"
     12 #include "SkStream.h"
     13 
     14 class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
     15 public:
     16     DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { }
     17 
     18     void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
     19                          SkFontMgr_Custom::Families* families) const override
     20     {
     21         load_directory_fonts(scanner, fBaseDirectory, ".ttf", families);
     22         load_directory_fonts(scanner, fBaseDirectory, ".ttc", families);
     23         load_directory_fonts(scanner, fBaseDirectory, ".otf", families);
     24         load_directory_fonts(scanner, fBaseDirectory, ".pfb", families);
     25 
     26         if (families->empty()) {
     27             SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
     28             families->push_back().reset(family);
     29             family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
     30         }
     31     }
     32 
     33 private:
     34     static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
     35                                               const char familyName[])
     36     {
     37        for (int i = 0; i < families.count(); ++i) {
     38             if (families[i]->getFamilyName().equals(familyName)) {
     39                 return families[i].get();
     40             }
     41         }
     42         return nullptr;
     43     }
     44 
     45     static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner,
     46                                      const SkString& directory, const char* suffix,
     47                                      SkFontMgr_Custom::Families* families)
     48     {
     49         SkOSFile::Iter iter(directory.c_str(), suffix);
     50         SkString name;
     51 
     52         while (iter.next(&name, false)) {
     53             SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
     54             std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(filename.c_str());
     55             if (!stream) {
     56                 SkDebugf("---- failed to open <%s>\n", filename.c_str());
     57                 continue;
     58             }
     59 
     60             int numFaces;
     61             if (!scanner.recognizedFont(stream.get(), &numFaces)) {
     62                 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
     63                 continue;
     64             }
     65 
     66             for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
     67                 bool isFixedPitch;
     68                 SkString realname;
     69                 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
     70                 if (!scanner.scanFont(stream.get(), faceIndex,
     71                                       &realname, &style, &isFixedPitch, nullptr))
     72                 {
     73                     SkDebugf("---- failed to open <%s> <%d> as a font\n",
     74                              filename.c_str(), faceIndex);
     75                     continue;
     76                 }
     77 
     78                 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
     79                 if (nullptr == addTo) {
     80                     addTo = new SkFontStyleSet_Custom(realname);
     81                     families->push_back().reset(addTo);
     82                 }
     83                 addTo->appendTypeface(sk_make_sp<SkTypeface_File>(style, isFixedPitch, true,
     84                                                                   realname, filename.c_str(),
     85                                                                   faceIndex));
     86             }
     87         }
     88 
     89         SkOSFile::Iter dirIter(directory.c_str());
     90         while (dirIter.next(&name, true)) {
     91             if (name.startsWith(".")) {
     92                 continue;
     93             }
     94             SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
     95             load_directory_fonts(scanner, dirname, suffix, families);
     96         }
     97     }
     98 
     99     SkString fBaseDirectory;
    100 };
    101 
    102 SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir) {
    103     return sk_make_sp<SkFontMgr_Custom>(DirectorySystemFontLoader(dir));
    104 }
    105