18ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner/*
28ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner * Copyright 2017 Google Inc.
38ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner *
48ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner * Use of this source code is governed by a BSD-style license that can be
58ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner * found in the LICENSE file.
68ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner */
78ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
88ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner#include "SkFontMgr_custom.h"
98ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner#include "SkFontMgr_directory.h"
108ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner#include "SkOSFile.h"
118ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner#include "SkOSPath.h"
128ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner#include "SkStream.h"
138ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
148ab590f17fed097758b209c3b82fc1e4d802768eBen Wagnerclass DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
158ab590f17fed097758b209c3b82fc1e4d802768eBen Wagnerpublic:
168ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { }
178ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
188ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
198ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                         SkFontMgr_Custom::Families* families) const override
208ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    {
218ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        load_directory_fonts(scanner, fBaseDirectory, ".ttf", families);
228ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        load_directory_fonts(scanner, fBaseDirectory, ".ttc", families);
238ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        load_directory_fonts(scanner, fBaseDirectory, ".otf", families);
248ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        load_directory_fonts(scanner, fBaseDirectory, ".pfb", families);
258ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
268ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        if (families->empty()) {
278ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
288ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            families->push_back().reset(family);
298ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
308ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        }
318ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    }
328ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
338ab590f17fed097758b209c3b82fc1e4d802768eBen Wagnerprivate:
348ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
358ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                                              const char familyName[])
368ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    {
378ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner       for (int i = 0; i < families.count(); ++i) {
388ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            if (families[i]->getFamilyName().equals(familyName)) {
398ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                return families[i].get();
408ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            }
418ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        }
428ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        return nullptr;
438ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    }
448ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
458ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner,
468ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                                     const SkString& directory, const char* suffix,
478ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                                     SkFontMgr_Custom::Families* families)
488ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    {
498ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        SkOSFile::Iter iter(directory.c_str(), suffix);
508ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        SkString name;
518ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
528ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        while (iter.next(&name, false)) {
538ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
548ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(filename.c_str());
558ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            if (!stream) {
568ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                SkDebugf("---- failed to open <%s>\n", filename.c_str());
578ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                continue;
588ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            }
598ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
608ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            int numFaces;
618ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            if (!scanner.recognizedFont(stream.get(), &numFaces)) {
628ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
638ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                continue;
648ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            }
658ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
668ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
678ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                bool isFixedPitch;
688ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                SkString realname;
698ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
708ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                if (!scanner.scanFont(stream.get(), faceIndex,
718ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                                      &realname, &style, &isFixedPitch, nullptr))
728ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                {
738ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                    SkDebugf("---- failed to open <%s> <%d> as a font\n",
748ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                             filename.c_str(), faceIndex);
758ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                    continue;
768ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                }
778ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
788ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
798ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                if (nullptr == addTo) {
808ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                    addTo = new SkFontStyleSet_Custom(realname);
818ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                    families->push_back().reset(addTo);
828ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                }
838ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                addTo->appendTypeface(sk_make_sp<SkTypeface_File>(style, isFixedPitch, true,
848ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                                                                  realname, filename.c_str(),
858ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                                                                  faceIndex));
868ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            }
878ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        }
888ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
898ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        SkOSFile::Iter dirIter(directory.c_str());
908ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        while (dirIter.next(&name, true)) {
918ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            if (name.startsWith(".")) {
928ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner                continue;
938ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            }
948ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
958ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner            load_directory_fonts(scanner, dirname, suffix, families);
968ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner        }
978ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    }
988ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
998ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    SkString fBaseDirectory;
1008ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner};
1018ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner
1028ab590f17fed097758b209c3b82fc1e4d802768eBen WagnerSK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir) {
1038ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner    return sk_make_sp<SkFontMgr_Custom>(DirectorySystemFontLoader(dir));
1048ab590f17fed097758b209c3b82fc1e4d802768eBen Wagner}
105