diff options
Diffstat (limited to 'src/ports')
-rw-r--r-- | src/ports/SkFontMgr_custom.cpp | 601 | ||||
-rw-r--r-- | src/ports/SkFontMgr_custom.h | 158 | ||||
-rw-r--r-- | src/ports/SkFontMgr_custom_directory.cpp | 104 | ||||
-rw-r--r-- | src/ports/SkFontMgr_custom_directory_factory.cpp | 2 | ||||
-rw-r--r-- | src/ports/SkFontMgr_custom_embedded.cpp | 87 | ||||
-rw-r--r-- | src/ports/SkFontMgr_custom_empty.cpp | 27 |
6 files changed, 545 insertions, 434 deletions
diff --git a/src/ports/SkFontMgr_custom.cpp b/src/ports/SkFontMgr_custom.cpp index 1b6baa19a4..4e4887d27d 100644 --- a/src/ports/SkFontMgr_custom.cpp +++ b/src/ports/SkFontMgr_custom.cpp @@ -11,15 +11,12 @@ #include "SkFontMgr_custom.h" #include "SkFontStyle.h" #include "SkMakeUnique.h" -#include "SkOSFile.h" -#include "SkOSPath.h" #include "SkRefCnt.h" #include "SkStream.h" #include "SkString.h" #include "SkTArray.h" #include "SkTemplates.h" #include "SkTypeface.h" -#include "SkTypefaceCache.h" #include "SkTypes.h" #include <limits> @@ -27,497 +24,235 @@ class SkData; -/** The base SkTypeface implementation for the custom font manager. */ -class SkTypeface_Custom : public SkTypeface_FreeType { -public: - SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch, - bool sysFont, const SkString familyName, int index) - : INHERITED(style, isFixedPitch) - , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index) - { } +SkTypeface_Custom::SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch, + bool sysFont, const SkString familyName, int index) + : INHERITED(style, isFixedPitch) + , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index) +{ } - bool isSysFont() const { return fIsSysFont; } +bool SkTypeface_Custom::isSysFont() const { return fIsSysFont; } -protected: - void onGetFamilyName(SkString* familyName) const override { - *familyName = fFamilyName; - } - - void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override { - desc->setFamilyName(fFamilyName.c_str()); - desc->setStyle(this->fontStyle()); - *isLocal = !this->isSysFont(); - } - - int getIndex() const { return fIndex; } - -private: - const bool fIsSysFont; - const SkString fFamilyName; - const int fIndex; - - typedef SkTypeface_FreeType INHERITED; -}; - -/** The empty SkTypeface implementation for the custom font manager. - * Used as the last resort fallback typeface. - */ -class SkTypeface_Empty : public SkTypeface_Custom { -public: - SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {} - -protected: - SkStreamAsset* onOpenStream(int*) const override { return nullptr; } - -private: - typedef SkTypeface_Custom INHERITED; -}; - -/** The stream SkTypeface implementation for the custom font manager. */ -class SkTypeface_Stream : public SkTypeface_Custom { -public: - SkTypeface_Stream(std::unique_ptr<SkFontData> fontData, - const SkFontStyle& style, bool isFixedPitch, bool sysFont, - const SkString familyName) - : INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex()) - , fData(std::move(fontData)) - { } - -protected: - SkStreamAsset* onOpenStream(int* ttcIndex) const override { - *ttcIndex = fData->getIndex(); - return fData->getStream()->duplicate(); - } - - std::unique_ptr<SkFontData> onMakeFontData() const override { - return skstd::make_unique<SkFontData>(*fData); - } - -private: - const std::unique_ptr<const SkFontData> fData; - - typedef SkTypeface_Custom INHERITED; -}; - -/** The file SkTypeface implementation for the custom font manager. */ -class SkTypeface_File : public SkTypeface_Custom { -public: - SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont, - const SkString familyName, const char path[], int index) - : INHERITED(style, isFixedPitch, sysFont, familyName, index) - , fPath(path) - { } - -protected: - SkStreamAsset* onOpenStream(int* ttcIndex) const override { - *ttcIndex = this->getIndex(); - return SkStream::MakeFromFile(fPath.c_str()).release(); - } - -private: - SkString fPath; - - typedef SkTypeface_Custom INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// - -/** - * SkFontStyleSet_Custom - * - * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families. - */ -class SkFontStyleSet_Custom : public SkFontStyleSet { -public: - explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { } - - /** Should only be called during the inital build phase. */ - void appendTypeface(sk_sp<SkTypeface_Custom> typeface) { - fStyles.emplace_back(std::move(typeface)); - } - - int count() override { - return fStyles.count(); - } +void SkTypeface_Custom::onGetFamilyName(SkString* familyName) const { + *familyName = fFamilyName; +} - void getStyle(int index, SkFontStyle* style, SkString* name) override { - SkASSERT(index < fStyles.count()); - if (style) { - *style = fStyles[index]->fontStyle(); - } - if (name) { - name->reset(); - } - } +void SkTypeface_Custom::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const { + desc->setFamilyName(fFamilyName.c_str()); + desc->setStyle(this->fontStyle()); + *isLocal = !this->isSysFont(); +} - SkTypeface* createTypeface(int index) override { - SkASSERT(index < fStyles.count()); - return SkRef(fStyles[index].get()); - } +int SkTypeface_Custom::getIndex() const { return fIndex; } - SkTypeface* matchStyle(const SkFontStyle& pattern) override { - return this->matchStyleCSS3(pattern); - } - SkString getFamilyName() { return fFamilyName; } +SkTypeface_Empty::SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {} -private: - SkTArray<sk_sp<SkTypeface_Custom>> fStyles; - SkString fFamilyName; +SkStreamAsset* SkTypeface_Empty::onOpenStream(int*) const { return nullptr; } - friend class SkFontMgr_Custom; -}; -/** - * SkFontMgr_Custom - * - * This class is essentially a collection of SkFontStyleSet_Custom, - * one SkFontStyleSet_Custom for each family. This class may be modified - * to load fonts from any source by changing the initialization. - */ -class SkFontMgr_Custom : public SkFontMgr { -public: - typedef SkTArray<sk_sp<SkFontStyleSet_Custom>> Families; - class SystemFontLoader { - public: - virtual ~SystemFontLoader() { } - virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Families*) const = 0; - }; - explicit SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) { - loader.loadSystemFonts(fScanner, &fFamilies); - - // Try to pick a default font. - static const char* defaultNames[] = { - "Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr - }; - for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) { - sk_sp<SkFontStyleSet_Custom> set(this->onMatchFamily(defaultNames[i])); - if (nullptr == set) { - continue; - } +SkTypeface_Stream::SkTypeface_Stream(std::unique_ptr<SkFontData> fontData, + const SkFontStyle& style, bool isFixedPitch, bool sysFont, + const SkString familyName) + : INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex()) + , fData(std::move(fontData)) +{ } - sk_sp<SkTypeface> tf(set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight, - SkFontStyle::kNormal_Width, - SkFontStyle::kUpright_Slant))); - if (nullptr == tf) { - continue; - } +SkStreamAsset* SkTypeface_Stream::onOpenStream(int* ttcIndex) const { + *ttcIndex = fData->getIndex(); + return fData->getStream()->duplicate(); +} - fDefaultFamily = set.get(); - break; - } - if (nullptr == fDefaultFamily) { - fDefaultFamily = fFamilies[0].get(); - } - } +std::unique_ptr<SkFontData> SkTypeface_Stream::onMakeFontData() const { + return skstd::make_unique<SkFontData>(*fData); +} -protected: - int onCountFamilies() const override { - return fFamilies.count(); - } - void onGetFamilyName(int index, SkString* familyName) const override { - SkASSERT(index < fFamilies.count()); - familyName->set(fFamilies[index]->getFamilyName()); - } +SkTypeface_File::SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont, + const SkString familyName, const char path[], int index) + : INHERITED(style, isFixedPitch, sysFont, familyName, index) + , fPath(path) +{ } - SkFontStyleSet_Custom* onCreateStyleSet(int index) const override { - SkASSERT(index < fFamilies.count()); - return SkRef(fFamilies[index].get()); - } +SkStreamAsset* SkTypeface_File::onOpenStream(int* ttcIndex) const { + *ttcIndex = this->getIndex(); + return SkStream::MakeFromFile(fPath.c_str()).release(); +} - SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override { - for (int i = 0; i < fFamilies.count(); ++i) { - if (fFamilies[i]->getFamilyName().equals(familyName)) { - return SkRef(fFamilies[i].get()); - } - } - return nullptr; - } +/////////////////////////////////////////////////////////////////////////////// - SkTypeface* onMatchFamilyStyle(const char familyName[], - const SkFontStyle& fontStyle) const override - { - sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName)); - return sset->matchStyle(fontStyle); - } +SkFontStyleSet_Custom::SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) {} - SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&, - const char* bcp47[], int bcp47Count, - SkUnichar character) const override - { - return nullptr; - } +void SkFontStyleSet_Custom::appendTypeface(sk_sp<SkTypeface_Custom> typeface) { + fStyles.emplace_back(std::move(typeface)); +} - SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, - const SkFontStyle& fontStyle) const override - { - for (int i = 0; i < fFamilies.count(); ++i) { - for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) { - if (fFamilies[i]->fStyles[j].get() == familyMember) { - return fFamilies[i]->matchStyle(fontStyle); - } - } - } - return nullptr; - } +int SkFontStyleSet_Custom::count() { + return fStyles.count(); +} - SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { - return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex); +void SkFontStyleSet_Custom::getStyle(int index, SkFontStyle* style, SkString* name) { + SkASSERT(index < fStyles.count()); + if (style) { + *style = fStyles[index]->fontStyle(); } - - SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override { - return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex)); + if (name) { + name->reset(); } +} - SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override { - using Scanner = SkTypeface_FreeType::Scanner; - std::unique_ptr<SkStreamAsset> stream(s); - bool isFixedPitch; - SkFontStyle style; - SkString name; - Scanner::AxisDefinitions axisDefinitions; - if (!fScanner.scanFont(stream.get(), params.getCollectionIndex(), - &name, &style, &isFixedPitch, &axisDefinitions)) - { - return nullptr; - } - - int paramAxisCount; - const FontParameters::Axis* paramAxes = params.getAxes(¶mAxisCount); - SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count()); - Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name); +SkTypeface* SkFontStyleSet_Custom::createTypeface(int index) { + SkASSERT(index < fStyles.count()); + return SkRef(fStyles[index].get()); +} - auto data = skstd::make_unique<SkFontData>(std::move(stream), params.getCollectionIndex(), - axisValues.get(), axisDefinitions.count()); - return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name); - } +SkTypeface* SkFontStyleSet_Custom::matchStyle(const SkFontStyle& pattern) { + return this->matchStyleCSS3(pattern); +} - SkTypeface* onCreateFromFontData(std::unique_ptr<SkFontData> data) const override { - bool isFixedPitch; - SkFontStyle style; - SkString name; - if (!fScanner.scanFont(data->getStream(), data->getIndex(), - &name, &style, &isFixedPitch, nullptr)) - { - return nullptr; - } - return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name); - } +SkString SkFontStyleSet_Custom::getFamilyName() { return fFamilyName; } - SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { - std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path); - return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr; - } - SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override { - SkTypeface* tf = nullptr; +SkFontMgr_Custom::SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) { + loader.loadSystemFonts(fScanner, &fFamilies); - if (familyName) { - tf = this->onMatchFamilyStyle(familyName, style); + // Try to pick a default font. + static const char* defaultNames[] = { + "Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr + }; + for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) { + sk_sp<SkFontStyleSet_Custom> set(this->onMatchFamily(defaultNames[i])); + if (nullptr == set) { + continue; } + sk_sp<SkTypeface> tf(set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight, + SkFontStyle::kNormal_Width, + SkFontStyle::kUpright_Slant))); if (nullptr == tf) { - tf = fDefaultFamily->matchStyle(style); + continue; } - return tf; + fDefaultFamily = set.get(); + break; } + if (nullptr == fDefaultFamily) { + fDefaultFamily = fFamilies[0].get(); + } +} -private: - Families fFamilies; - SkFontStyleSet_Custom* fDefaultFamily; - SkTypeface_FreeType::Scanner fScanner; -}; - -/////////////////////////////////////////////////////////////////////////////// +int SkFontMgr_Custom::onCountFamilies() const { + return fFamilies.count(); +} -class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { -public: - DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { } +void SkFontMgr_Custom::onGetFamilyName(int index, SkString* familyName) const { + SkASSERT(index < fFamilies.count()); + familyName->set(fFamilies[index]->getFamilyName()); +} - void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, - SkFontMgr_Custom::Families* families) const override - { - load_directory_fonts(scanner, fBaseDirectory, ".ttf", families); - load_directory_fonts(scanner, fBaseDirectory, ".ttc", families); - load_directory_fonts(scanner, fBaseDirectory, ".otf", families); - load_directory_fonts(scanner, fBaseDirectory, ".pfb", families); - - if (families->empty()) { - SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); - families->push_back().reset(family); - family->appendTypeface(sk_make_sp<SkTypeface_Empty>()); - } - } +SkFontStyleSet_Custom* SkFontMgr_Custom::onCreateStyleSet(int index) const { + SkASSERT(index < fFamilies.count()); + return SkRef(fFamilies[index].get()); +} -private: - static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families, - const char familyName[]) - { - for (int i = 0; i < families.count(); ++i) { - if (families[i]->getFamilyName().equals(familyName)) { - return families[i].get(); - } +SkFontStyleSet_Custom* SkFontMgr_Custom::onMatchFamily(const char familyName[]) const { + for (int i = 0; i < fFamilies.count(); ++i) { + if (fFamilies[i]->getFamilyName().equals(familyName)) { + return SkRef(fFamilies[i].get()); } - return nullptr; } + return nullptr; +} - static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner, - const SkString& directory, const char* suffix, - SkFontMgr_Custom::Families* families) - { - SkOSFile::Iter iter(directory.c_str(), suffix); - SkString name; - - while (iter.next(&name, false)) { - SkString filename(SkOSPath::Join(directory.c_str(), name.c_str())); - std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(filename.c_str()); - if (!stream) { - SkDebugf("---- failed to open <%s>\n", filename.c_str()); - continue; - } - - int numFaces; - if (!scanner.recognizedFont(stream.get(), &numFaces)) { - SkDebugf("---- failed to open <%s> as a font\n", filename.c_str()); - continue; - } +SkTypeface* SkFontMgr_Custom::onMatchFamilyStyle(const char familyName[], + const SkFontStyle& fontStyle) const +{ + sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName)); + return sset->matchStyle(fontStyle); +} - for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { - bool isFixedPitch; - SkString realname; - SkFontStyle style = SkFontStyle(); // avoid uninitialized warning - if (!scanner.scanFont(stream.get(), faceIndex, - &realname, &style, &isFixedPitch, nullptr)) - { - SkDebugf("---- failed to open <%s> <%d> as a font\n", - filename.c_str(), faceIndex); - continue; - } - - SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); - if (nullptr == addTo) { - addTo = new SkFontStyleSet_Custom(realname); - families->push_back().reset(addTo); - } - addTo->appendTypeface(sk_make_sp<SkTypeface_File>(style, isFixedPitch, true, - realname, filename.c_str(), - faceIndex)); - } - } +SkTypeface* SkFontMgr_Custom::onMatchFamilyStyleCharacter(const char familyName[], + const SkFontStyle&, + const char* bcp47[], int bcp47Count, + SkUnichar character) const +{ + return nullptr; +} - SkOSFile::Iter dirIter(directory.c_str()); - while (dirIter.next(&name, true)) { - if (name.startsWith(".")) { - continue; +SkTypeface* SkFontMgr_Custom::onMatchFaceStyle(const SkTypeface* familyMember, + const SkFontStyle& fontStyle) const +{ + for (int i = 0; i < fFamilies.count(); ++i) { + for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) { + if (fFamilies[i]->fStyles[j].get() == familyMember) { + return fFamilies[i]->matchStyle(fontStyle); } - SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str())); - load_directory_fonts(scanner, dirname, suffix, families); } } - - SkString fBaseDirectory; -}; - -SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir) { - return sk_make_sp<SkFontMgr_Custom>(DirectorySystemFontLoader(dir)); + return nullptr; } -/////////////////////////////////////////////////////////////////////////////// - -struct SkEmbeddedResource { const uint8_t* data; size_t size; }; -struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; }; - -class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { -public: - EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { } - - void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, - SkFontMgr_Custom::Families* families) const override - { - for (int i = 0; i < fHeader->count; ++i) { - const SkEmbeddedResource& fontEntry = fHeader->entries[i]; - load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, families); - } +SkTypeface* SkFontMgr_Custom::onCreateFromData(SkData* data, int ttcIndex) const { + return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex); +} - if (families->empty()) { - SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); - families->push_back().reset(family); - family->appendTypeface(sk_make_sp<SkTypeface_Empty>()); - } - } +SkTypeface* SkFontMgr_Custom::onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const { + return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex)); +} -private: - static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families, - const char familyName[]) +SkTypeface* SkFontMgr_Custom::onCreateFromStream(SkStreamAsset* s, + const FontParameters& params) const +{ + using Scanner = SkTypeface_FreeType::Scanner; + std::unique_ptr<SkStreamAsset> stream(s); + bool isFixedPitch; + SkFontStyle style; + SkString name; + Scanner::AxisDefinitions axisDefinitions; + if (!fScanner.scanFont(stream.get(), params.getCollectionIndex(), + &name, &style, &isFixedPitch, &axisDefinitions)) { - for (int i = 0; i < families.count(); ++i) { - if (families[i]->getFamilyName().equals(familyName)) { - return families[i].get(); - } - } return nullptr; } - static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner, - const uint8_t* data, size_t size, int index, - SkFontMgr_Custom::Families* families) - { - auto stream = skstd::make_unique<SkMemoryStream>(data, size, false); - - int numFaces; - if (!scanner.recognizedFont(stream.get(), &numFaces)) { - SkDebugf("---- failed to open <%d> as a font\n", index); - return; - } + int paramAxisCount; + const FontParameters::Axis* paramAxes = params.getAxes(¶mAxisCount); + SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count()); + Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name); - for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { - bool isFixedPitch; - SkString realname; - SkFontStyle style = SkFontStyle(); // avoid uninitialized warning - if (!scanner.scanFont(stream.get(), faceIndex, - &realname, &style, &isFixedPitch, nullptr)) - { - SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex); - return; - } + auto data = skstd::make_unique<SkFontData>(std::move(stream), params.getCollectionIndex(), + axisValues.get(), axisDefinitions.count()); + return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name); +} - SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); - if (nullptr == addTo) { - addTo = new SkFontStyleSet_Custom(realname); - families->push_back().reset(addTo); - } - auto data = skstd::make_unique<SkFontData>(std::move(stream), faceIndex, nullptr, 0); - addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data), - style, isFixedPitch, - true, realname)); - } +SkTypeface* SkFontMgr_Custom::onCreateFromFontData(std::unique_ptr<SkFontData> data) const { + bool isFixedPitch; + SkFontStyle style; + SkString name; + if (!fScanner.scanFont(data->getStream(), data->getIndex(), + &name, &style, &isFixedPitch, nullptr)) + { + return nullptr; } - - const SkEmbeddedResourceHeader* fHeader; -}; - -sk_sp<SkFontMgr> SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) { - return sk_make_sp<SkFontMgr_Custom>(EmbeddedSystemFontLoader(header)); + return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name); } -/////////////////////////////////////////////////////////////////////////////// +SkTypeface* SkFontMgr_Custom::onCreateFromFile(const char path[], int ttcIndex) const { + std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path); + return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr; +} -class EmptyFontLoader : public SkFontMgr_Custom::SystemFontLoader { -public: - EmptyFontLoader() { } +SkTypeface* SkFontMgr_Custom::onLegacyCreateTypeface(const char familyName[], + SkFontStyle style) const +{ + SkTypeface* tf = nullptr; - void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, - SkFontMgr_Custom::Families* families) const override - { - SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); - families->push_back().reset(family); - family->appendTypeface(sk_make_sp<SkTypeface_Empty>()); + if (familyName) { + tf = this->onMatchFamilyStyle(familyName, style); } -}; + if (nullptr == tf) { + tf = fDefaultFamily->matchStyle(style); + } -SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Empty() { - return sk_make_sp<SkFontMgr_Custom>(EmptyFontLoader()); + return tf; } diff --git a/src/ports/SkFontMgr_custom.h b/src/ports/SkFontMgr_custom.h new file mode 100644 index 0000000000..9149378a50 --- /dev/null +++ b/src/ports/SkFontMgr_custom.h @@ -0,0 +1,158 @@ +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkFontMgr_custom_DEFINED +#define SkFontMgr_custom_DEFINED + +#include "SkFontHost_FreeType_common.h" +#include "SkFontMgr.h" +#include "SkFontStyle.h" +#include "SkRefCnt.h" +#include "SkString.h" +#include "SkTArray.h" +#include "SkTypes.h" + +class SkData; +class SkFontDescriptor; +class SkStreamAsset; +class SkTypeface; + +/** The base SkTypeface implementation for the custom font manager. */ +class SkTypeface_Custom : public SkTypeface_FreeType { +public: + SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch, + bool sysFont, const SkString familyName, int index); + bool isSysFont() const; + +protected: + void onGetFamilyName(SkString* familyName) const override; + void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override; + int getIndex() const; + +private: + const bool fIsSysFont; + const SkString fFamilyName; + const int fIndex; + + typedef SkTypeface_FreeType INHERITED; +}; + +/** The empty SkTypeface implementation for the custom font manager. + * Used as the last resort fallback typeface. + */ +class SkTypeface_Empty : public SkTypeface_Custom { +public: + SkTypeface_Empty() ; + +protected: + SkStreamAsset* onOpenStream(int*) const override; + +private: + typedef SkTypeface_Custom INHERITED; +}; + +/** The stream SkTypeface implementation for the custom font manager. */ +class SkTypeface_Stream : public SkTypeface_Custom { +public: + SkTypeface_Stream(std::unique_ptr<SkFontData> fontData, + const SkFontStyle& style, bool isFixedPitch, bool sysFont, + const SkString familyName); + +protected: + SkStreamAsset* onOpenStream(int* ttcIndex) const override; + std::unique_ptr<SkFontData> onMakeFontData() const override; + +private: + const std::unique_ptr<const SkFontData> fData; + + typedef SkTypeface_Custom INHERITED; +}; + +/** The file SkTypeface implementation for the custom font manager. */ +class SkTypeface_File : public SkTypeface_Custom { +public: + SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont, + const SkString familyName, const char path[], int index); + +protected: + SkStreamAsset* onOpenStream(int* ttcIndex) const override; + +private: + SkString fPath; + + typedef SkTypeface_Custom INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +/** + * SkFontStyleSet_Custom + * + * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families. + */ +class SkFontStyleSet_Custom : public SkFontStyleSet { +public: + explicit SkFontStyleSet_Custom(const SkString familyName); + + /** Should only be called during the inital build phase. */ + void appendTypeface(sk_sp<SkTypeface_Custom> typeface); + int count() override; + void getStyle(int index, SkFontStyle* style, SkString* name) override; + SkTypeface* createTypeface(int index) override; + SkTypeface* matchStyle(const SkFontStyle& pattern) override; + SkString getFamilyName(); + +private: + SkTArray<sk_sp<SkTypeface_Custom>> fStyles; + SkString fFamilyName; + + friend class SkFontMgr_Custom; +}; + +/** + * SkFontMgr_Custom + * + * This class is essentially a collection of SkFontStyleSet_Custom, + * one SkFontStyleSet_Custom for each family. This class may be modified + * to load fonts from any source by changing the initialization. + */ +class SkFontMgr_Custom : public SkFontMgr { +public: + typedef SkTArray<sk_sp<SkFontStyleSet_Custom>> Families; + class SystemFontLoader { + public: + virtual ~SystemFontLoader() { } + virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Families*) const = 0; + }; + explicit SkFontMgr_Custom(const SystemFontLoader& loader); + +protected: + int onCountFamilies() const override; + void onGetFamilyName(int index, SkString* familyName) const override; + SkFontStyleSet_Custom* onCreateStyleSet(int index) const override; + SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override; + SkTypeface* onMatchFamilyStyle(const char familyName[], + const SkFontStyle& fontStyle) const override; + SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&, + const char* bcp47[], int bcp47Count, + SkUnichar character) const override; + SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, + const SkFontStyle& fontStyle) const override; + SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override; + SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override; + SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override; + SkTypeface* onCreateFromFontData(std::unique_ptr<SkFontData> data) const override; + SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override; + SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override; + +private: + Families fFamilies; + SkFontStyleSet_Custom* fDefaultFamily; + SkTypeface_FreeType::Scanner fScanner; +}; + +#endif diff --git a/src/ports/SkFontMgr_custom_directory.cpp b/src/ports/SkFontMgr_custom_directory.cpp new file mode 100644 index 0000000000..af322875f3 --- /dev/null +++ b/src/ports/SkFontMgr_custom_directory.cpp @@ -0,0 +1,104 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkFontMgr_custom.h" +#include "SkFontMgr_directory.h" +#include "SkOSFile.h" +#include "SkOSPath.h" +#include "SkStream.h" + +class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { +public: + DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { } + + void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, + SkFontMgr_Custom::Families* families) const override + { + load_directory_fonts(scanner, fBaseDirectory, ".ttf", families); + load_directory_fonts(scanner, fBaseDirectory, ".ttc", families); + load_directory_fonts(scanner, fBaseDirectory, ".otf", families); + load_directory_fonts(scanner, fBaseDirectory, ".pfb", families); + + if (families->empty()) { + SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); + families->push_back().reset(family); + family->appendTypeface(sk_make_sp<SkTypeface_Empty>()); + } + } + +private: + static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families, + const char familyName[]) + { + for (int i = 0; i < families.count(); ++i) { + if (families[i]->getFamilyName().equals(familyName)) { + return families[i].get(); + } + } + return nullptr; + } + + static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner, + const SkString& directory, const char* suffix, + SkFontMgr_Custom::Families* families) + { + SkOSFile::Iter iter(directory.c_str(), suffix); + SkString name; + + while (iter.next(&name, false)) { + SkString filename(SkOSPath::Join(directory.c_str(), name.c_str())); + std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(filename.c_str()); + if (!stream) { + SkDebugf("---- failed to open <%s>\n", filename.c_str()); + continue; + } + + int numFaces; + if (!scanner.recognizedFont(stream.get(), &numFaces)) { + SkDebugf("---- failed to open <%s> as a font\n", filename.c_str()); + continue; + } + + for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { + bool isFixedPitch; + SkString realname; + SkFontStyle style = SkFontStyle(); // avoid uninitialized warning + if (!scanner.scanFont(stream.get(), faceIndex, + &realname, &style, &isFixedPitch, nullptr)) + { + SkDebugf("---- failed to open <%s> <%d> as a font\n", + filename.c_str(), faceIndex); + continue; + } + + SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); + if (nullptr == addTo) { + addTo = new SkFontStyleSet_Custom(realname); + families->push_back().reset(addTo); + } + addTo->appendTypeface(sk_make_sp<SkTypeface_File>(style, isFixedPitch, true, + realname, filename.c_str(), + faceIndex)); + } + } + + SkOSFile::Iter dirIter(directory.c_str()); + while (dirIter.next(&name, true)) { + if (name.startsWith(".")) { + continue; + } + SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str())); + load_directory_fonts(scanner, dirname, suffix, families); + } + } + + SkString fBaseDirectory; +}; + +SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir) { + return sk_make_sp<SkFontMgr_Custom>(DirectorySystemFontLoader(dir)); +} diff --git a/src/ports/SkFontMgr_custom_directory_factory.cpp b/src/ports/SkFontMgr_custom_directory_factory.cpp index 7ed47118e4..e8d4bb3f3e 100644 --- a/src/ports/SkFontMgr_custom_directory_factory.cpp +++ b/src/ports/SkFontMgr_custom_directory_factory.cpp @@ -6,7 +6,7 @@ */ #include "SkFontMgr.h" -#include "SkFontMgr_custom.h" +#include "SkFontMgr_directory.h" #ifndef SK_FONT_FILE_PREFIX # define SK_FONT_FILE_PREFIX "/usr/share/fonts/" diff --git a/src/ports/SkFontMgr_custom_embedded.cpp b/src/ports/SkFontMgr_custom_embedded.cpp new file mode 100644 index 0000000000..bb8d9f20b7 --- /dev/null +++ b/src/ports/SkFontMgr_custom_embedded.cpp @@ -0,0 +1,87 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkFontDescriptor.h" +#include "SkFontMgr_custom.h" +#include "SkMakeUnique.h" +#include "SkStream.h" + +struct SkEmbeddedResource { const uint8_t* data; size_t size; }; +struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; }; + +class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { +public: + EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { } + + void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, + SkFontMgr_Custom::Families* families) const override + { + for (int i = 0; i < fHeader->count; ++i) { + const SkEmbeddedResource& fontEntry = fHeader->entries[i]; + load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, families); + } + + if (families->empty()) { + SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); + families->push_back().reset(family); + family->appendTypeface(sk_make_sp<SkTypeface_Empty>()); + } + } + +private: + static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families, + const char familyName[]) + { + for (int i = 0; i < families.count(); ++i) { + if (families[i]->getFamilyName().equals(familyName)) { + return families[i].get(); + } + } + return nullptr; + } + + static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner, + const uint8_t* data, size_t size, int index, + SkFontMgr_Custom::Families* families) + { + auto stream = skstd::make_unique<SkMemoryStream>(data, size, false); + + int numFaces; + if (!scanner.recognizedFont(stream.get(), &numFaces)) { + SkDebugf("---- failed to open <%d> as a font\n", index); + return; + } + + for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { + bool isFixedPitch; + SkString realname; + SkFontStyle style = SkFontStyle(); // avoid uninitialized warning + if (!scanner.scanFont(stream.get(), faceIndex, + &realname, &style, &isFixedPitch, nullptr)) + { + SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex); + return; + } + + SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); + if (nullptr == addTo) { + addTo = new SkFontStyleSet_Custom(realname); + families->push_back().reset(addTo); + } + auto data = skstd::make_unique<SkFontData>(std::move(stream), faceIndex, nullptr, 0); + addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data), + style, isFixedPitch, + true, realname)); + } + } + + const SkEmbeddedResourceHeader* fHeader; +}; + +sk_sp<SkFontMgr> SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) { + return sk_make_sp<SkFontMgr_Custom>(EmbeddedSystemFontLoader(header)); +} diff --git a/src/ports/SkFontMgr_custom_empty.cpp b/src/ports/SkFontMgr_custom_empty.cpp new file mode 100644 index 0000000000..8732bc32b4 --- /dev/null +++ b/src/ports/SkFontMgr_custom_empty.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkFontMgr_custom.h" +#include "SkFontMgr_empty.h" + +class EmptyFontLoader : public SkFontMgr_Custom::SystemFontLoader { +public: + EmptyFontLoader() { } + + void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, + SkFontMgr_Custom::Families* families) const override + { + SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); + families->push_back().reset(family); + family->appendTypeface(sk_make_sp<SkTypeface_Empty>()); + } + +}; + +SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Empty() { + return sk_make_sp<SkFontMgr_Custom>(EmptyFontLoader()); +} |