From: Ben Wagner Date: Wed, 8 Feb 2017 22:29:33 +0000 (-0500) Subject: Split custom font managers. X-Git-Tag: submit/tizen/20180928.044319~55^2~425 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8ab590f17fed097758b209c3b82fc1e4d802768e;p=platform%2Fupstream%2FlibSkiaSharp.git Split custom font managers. Some users would like to use the empty font manager, but the directory gont manager brings in extra dependencies to work which would otherwise be unneeded. Allow these users to build just the bits of code they actually need. Change-Id: Ib029ef2682883509bad5a2aa39f1ef55631f4d8a Reviewed-on: https://skia-review.googlesource.com/8200 Reviewed-by: Mike Reed Commit-Queue: Ben Wagner --- diff --git a/BUILD.gn b/BUILD.gn index e389cd2d7d..d0f415d056 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -344,7 +344,11 @@ optional("fontmgr_custom") { ] sources = [ "src/ports/SkFontMgr_custom.cpp", + "src/ports/SkFontMgr_custom.h", + "src/ports/SkFontMgr_custom_directory.cpp", "src/ports/SkFontMgr_custom_directory_factory.cpp", + "src/ports/SkFontMgr_custom_embedded.cpp", + "src/ports/SkFontMgr_custom_empty.cpp", ] } @@ -373,6 +377,7 @@ optional("fontmgr_fuchsia") { ] sources = [ "src/ports/SkFontMgr_custom.cpp", + "src/ports/SkFontMgr_custom_empty.cpp", "src/ports/SkFontMgr_custom_empty_factory.cpp", ] } diff --git a/include/ports/SkFontMgr_custom.h b/include/ports/SkFontMgr_custom.h deleted file mode 100644 index d918763493..0000000000 --- a/include/ports/SkFontMgr_custom.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * 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 "SkTypes.h" - -class SkFontMgr; - -/** Create a custom font manager which scans a given directory for font files. */ -SK_API sk_sp SkFontMgr_New_Custom_Directory(const char* dir); - -/** Create a custom font manager that contains no built-in fonts. */ -SK_API sk_sp SkFontMgr_New_Custom_Empty(); - -#endif // SkFontMgr_custom_DEFINED diff --git a/include/ports/SkFontMgr_directory.h b/include/ports/SkFontMgr_directory.h new file mode 100644 index 0000000000..8f79a7f560 --- /dev/null +++ b/include/ports/SkFontMgr_directory.h @@ -0,0 +1,21 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkFontMgr_directory_DEFINED +#define SkFontMgr_directory_DEFINED + +#include "SkRefCnt.h" +#include "SkTypes.h" + +class SkFontMgr; + +/** Create a custom font manager which scans a given directory for font files. + * This font manager uses FreeType for rendering. + */ +SK_API sk_sp SkFontMgr_New_Custom_Directory(const char* dir); + +#endif // SkFontMgr_directory_DEFINED diff --git a/include/ports/SkFontMgr_empty.h b/include/ports/SkFontMgr_empty.h new file mode 100644 index 0000000000..dbeef586cb --- /dev/null +++ b/include/ports/SkFontMgr_empty.h @@ -0,0 +1,21 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkFontMgr_empty_DEFINED +#define SkFontMgr_empty_DEFINED + +#include "SkRefCnt.h" +#include "SkTypes.h" + +class SkFontMgr; + +/** Create a custom font manager that contains no built-in fonts. + * This font manager uses FreeType for rendering. + */ +SK_API sk_sp SkFontMgr_New_Custom_Empty(); + +#endif // SkFontMgr_empty_DEFINED diff --git a/public.bzl b/public.bzl index a808bb13eb..15709bf2f2 100644 --- a/public.bzl +++ b/public.bzl @@ -280,6 +280,9 @@ BASE_SRCS_IOS = struct( "src/ports/*nacl*", "src/ports/*win*", "src/ports/SkFontMgr_custom.cpp", + "src/ports/SkFontMgr_custom_directory.cpp", + "src/ports/SkFontMgr_custom_embedded.cpp", + "src/ports/SkFontMgr_custom_empty.cpp", "src/ports/SkFontMgr_custom_directory_factory.cpp", "src/ports/SkFontMgr_custom_embedded_factory.cpp", "src/ports/SkFontMgr_custom_empty_factory.cpp", 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 @@ -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 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 onMakeFontData() const override { - return skstd::make_unique(*fData); - } - -private: - const std::unique_ptr 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 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> 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> 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 set(this->onMatchFamily(defaultNames[i])); - if (nullptr == set) { - continue; - } +SkTypeface_Stream::SkTypeface_Stream(std::unique_ptr fontData, + const SkFontStyle& style, bool isFixedPitch, bool sysFont, + const SkString familyName) + : INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex()) + , fData(std::move(fontData)) +{ } - sk_sp 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 SkTypeface_Stream::onMakeFontData() const { + return skstd::make_unique(*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 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 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 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(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 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 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 set(this->onMatchFamily(defaultNames[i])); + if (nullptr == set) { + continue; } + sk_sp 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()); - } - } +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 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 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(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_New_Custom_Directory(const char* dir) { - return sk_make_sp(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* 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 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(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(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(std::move(stream), faceIndex, nullptr, 0); - addTo->appendTypeface(sk_make_sp(std::move(data), - style, isFixedPitch, - true, realname)); - } +SkTypeface* SkFontMgr_Custom::onCreateFromFontData(std::unique_ptr 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_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) { - return sk_make_sp(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 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()); + if (familyName) { + tf = this->onMatchFamilyStyle(familyName, style); } -}; + if (nullptr == tf) { + tf = fDefaultFamily->matchStyle(style); + } -SK_API sk_sp SkFontMgr_New_Custom_Empty() { - return sk_make_sp(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 fontData, + const SkFontStyle& style, bool isFixedPitch, bool sysFont, + const SkString familyName); + +protected: + SkStreamAsset* onOpenStream(int* ttcIndex) const override; + std::unique_ptr onMakeFontData() const override; + +private: + const std::unique_ptr 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 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> 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> 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 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()); + } + } + +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 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(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_New_Custom_Directory(const char* dir) { + return sk_make_sp(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()); + } + } + +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(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(std::move(stream), faceIndex, nullptr, 0); + addTo->appendTypeface(sk_make_sp(std::move(data), + style, isFixedPitch, + true, realname)); + } + } + + const SkEmbeddedResourceHeader* fHeader; +}; + +sk_sp SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) { + return sk_make_sp(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()); + } + +}; + +SK_API sk_sp SkFontMgr_New_Custom_Empty() { + return sk_make_sp(EmptyFontLoader()); +}