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 <reed@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
Ben Wagner 2017-02-08 17:29:33 -05:00 committed by Skia Commit-Bot
parent 6f22328366
commit 8ab590f17f
10 changed files with 586 additions and 446 deletions

View File

@ -344,7 +344,11 @@ optional("fontmgr_custom") {
] ]
sources = [ sources = [
"src/ports/SkFontMgr_custom.cpp", "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_directory_factory.cpp",
"src/ports/SkFontMgr_custom_embedded.cpp",
"src/ports/SkFontMgr_custom_empty.cpp",
] ]
} }
@ -373,6 +377,7 @@ optional("fontmgr_fuchsia") {
] ]
sources = [ sources = [
"src/ports/SkFontMgr_custom.cpp", "src/ports/SkFontMgr_custom.cpp",
"src/ports/SkFontMgr_custom_empty.cpp",
"src/ports/SkFontMgr_custom_empty_factory.cpp", "src/ports/SkFontMgr_custom_empty_factory.cpp",
] ]
} }

View File

@ -5,17 +5,17 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef SkFontMgr_custom_DEFINED #ifndef SkFontMgr_directory_DEFINED
#define SkFontMgr_custom_DEFINED #define SkFontMgr_directory_DEFINED
#include "SkRefCnt.h"
#include "SkTypes.h" #include "SkTypes.h"
class SkFontMgr; class SkFontMgr;
/** Create a custom font manager which scans a given directory for font files. */ /** 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> SkFontMgr_New_Custom_Directory(const char* dir); SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir);
/** Create a custom font manager that contains no built-in fonts. */ #endif // SkFontMgr_directory_DEFINED
SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Empty();
#endif // SkFontMgr_custom_DEFINED

View File

@ -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> SkFontMgr_New_Custom_Empty();
#endif // SkFontMgr_empty_DEFINED

View File

@ -280,6 +280,9 @@ BASE_SRCS_IOS = struct(
"src/ports/*nacl*", "src/ports/*nacl*",
"src/ports/*win*", "src/ports/*win*",
"src/ports/SkFontMgr_custom.cpp", "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_directory_factory.cpp",
"src/ports/SkFontMgr_custom_embedded_factory.cpp", "src/ports/SkFontMgr_custom_embedded_factory.cpp",
"src/ports/SkFontMgr_custom_empty_factory.cpp", "src/ports/SkFontMgr_custom_empty_factory.cpp",

View File

@ -11,15 +11,12 @@
#include "SkFontMgr_custom.h" #include "SkFontMgr_custom.h"
#include "SkFontStyle.h" #include "SkFontStyle.h"
#include "SkMakeUnique.h" #include "SkMakeUnique.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
#include "SkRefCnt.h" #include "SkRefCnt.h"
#include "SkStream.h" #include "SkStream.h"
#include "SkString.h" #include "SkString.h"
#include "SkTArray.h" #include "SkTArray.h"
#include "SkTemplates.h" #include "SkTemplates.h"
#include "SkTypeface.h" #include "SkTypeface.h"
#include "SkTypefaceCache.h"
#include "SkTypes.h" #include "SkTypes.h"
#include <limits> #include <limits>
@ -27,497 +24,235 @@
class SkData; class SkData;
/** The base SkTypeface implementation for the custom font manager. */ SkTypeface_Custom::SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
class SkTypeface_Custom : public SkTypeface_FreeType { bool sysFont, const SkString familyName, int index)
public: : INHERITED(style, isFixedPitch)
SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch, , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
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 SkTypeface_Custom::onGetFamilyName(SkString* familyName) const {
void onGetFamilyName(SkString* familyName) const override { *familyName = fFamilyName;
*familyName = fFamilyName; }
}
void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override { void SkTypeface_Custom::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
desc->setFamilyName(fFamilyName.c_str()); desc->setFamilyName(fFamilyName.c_str());
desc->setStyle(this->fontStyle()); desc->setStyle(this->fontStyle());
*isLocal = !this->isSysFont(); *isLocal = !this->isSysFont();
} }
int getIndex() const { return fIndex; } int SkTypeface_Custom::getIndex() const { return fIndex; }
private:
const bool fIsSysFont;
const SkString fFamilyName;
const int fIndex;
typedef SkTypeface_FreeType INHERITED; SkTypeface_Empty::SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
};
/** The empty SkTypeface implementation for the custom font manager. SkStreamAsset* SkTypeface_Empty::onOpenStream(int*) const { return nullptr; }
* 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: SkTypeface_Stream::SkTypeface_Stream(std::unique_ptr<SkFontData> fontData,
typedef SkTypeface_Custom INHERITED; const SkFontStyle& style, bool isFixedPitch, bool sysFont,
}; const SkString familyName)
: INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex())
, fData(std::move(fontData))
{ }
/** The stream SkTypeface implementation for the custom font manager. */ SkStreamAsset* SkTypeface_Stream::onOpenStream(int* ttcIndex) const {
class SkTypeface_Stream : public SkTypeface_Custom { *ttcIndex = fData->getIndex();
public: return fData->getStream()->duplicate();
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: std::unique_ptr<SkFontData> SkTypeface_Stream::onMakeFontData() const {
SkStreamAsset* onOpenStream(int* ttcIndex) const override { return skstd::make_unique<SkFontData>(*fData);
*ttcIndex = fData->getIndex(); }
return fData->getStream()->duplicate();
}
std::unique_ptr<SkFontData> onMakeFontData() const override {
return skstd::make_unique<SkFontData>(*fData);
}
private: SkTypeface_File::SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
const std::unique_ptr<const SkFontData> fData; const SkString familyName, const char path[], int index)
: INHERITED(style, isFixedPitch, sysFont, familyName, index)
, fPath(path)
{ }
typedef SkTypeface_Custom INHERITED; SkStreamAsset* SkTypeface_File::onOpenStream(int* ttcIndex) const {
}; *ttcIndex = this->getIndex();
return SkStream::MakeFromFile(fPath.c_str()).release();
/** 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::SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) {}
* 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 SkFontStyleSet_Custom::appendTypeface(sk_sp<SkTypeface_Custom> typeface) {
void appendTypeface(sk_sp<SkTypeface_Custom> typeface) { fStyles.emplace_back(std::move(typeface));
fStyles.emplace_back(std::move(typeface)); }
int SkFontStyleSet_Custom::count() {
return fStyles.count();
}
void SkFontStyleSet_Custom::getStyle(int index, SkFontStyle* style, SkString* name) {
SkASSERT(index < fStyles.count());
if (style) {
*style = fStyles[index]->fontStyle();
} }
if (name) {
int count() override { name->reset();
return fStyles.count();
} }
}
void getStyle(int index, SkFontStyle* style, SkString* name) override { SkTypeface* SkFontStyleSet_Custom::createTypeface(int index) {
SkASSERT(index < fStyles.count()); SkASSERT(index < fStyles.count());
if (style) { return SkRef(fStyles[index].get());
*style = fStyles[index]->fontStyle(); }
}
if (name) {
name->reset();
}
}
SkTypeface* createTypeface(int index) override { SkTypeface* SkFontStyleSet_Custom::matchStyle(const SkFontStyle& pattern) {
SkASSERT(index < fStyles.count()); return this->matchStyleCSS3(pattern);
return SkRef(fStyles[index].get()); }
}
SkTypeface* matchStyle(const SkFontStyle& pattern) override { SkString SkFontStyleSet_Custom::getFamilyName() { return fFamilyName; }
return this->matchStyleCSS3(pattern);
}
SkString getFamilyName() { return fFamilyName; }
private: SkFontMgr_Custom::SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) {
SkTArray<sk_sp<SkTypeface_Custom>> fStyles; loader.loadSystemFonts(fScanner, &fFamilies);
SkString fFamilyName;
friend class SkFontMgr_Custom; // Try to pick a default font.
}; static const char* defaultNames[] = {
"Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr
/**
* 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) { for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) {
loader.loadSystemFonts(fScanner, &fFamilies); sk_sp<SkFontStyleSet_Custom> set(this->onMatchFamily(defaultNames[i]));
if (nullptr == set) {
// Try to pick a default font. continue;
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) {
continue;
}
fDefaultFamily = set.get();
break;
}
if (nullptr == fDefaultFamily) {
fDefaultFamily = fFamilies[0].get();
}
}
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());
}
SkFontStyleSet_Custom* onCreateStyleSet(int index) const override {
SkASSERT(index < fFamilies.count());
return SkRef(fFamilies[index].get());
}
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);
}
SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
const char* bcp47[], int bcp47Count,
SkUnichar character) const override
{
return nullptr;
}
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;
}
SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex);
}
SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex));
}
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(&paramAxisCount);
SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
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* 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);
}
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;
if (familyName) {
tf = this->onMatchFamilyStyle(familyName, style);
} }
sk_sp<SkTypeface> tf(set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
SkFontStyle::kNormal_Width,
SkFontStyle::kUpright_Slant)));
if (nullptr == tf) { if (nullptr == tf) {
tf = fDefaultFamily->matchStyle(style); continue;
} }
return tf; fDefaultFamily = set.get();
break;
} }
if (nullptr == fDefaultFamily) {
fDefaultFamily = fFamilies[0].get();
}
}
private: int SkFontMgr_Custom::onCountFamilies() const {
Families fFamilies; return fFamilies.count();
SkFontStyleSet_Custom* fDefaultFamily; }
SkTypeface_FreeType::Scanner fScanner;
};
/////////////////////////////////////////////////////////////////////////////// void SkFontMgr_Custom::onGetFamilyName(int index, SkString* familyName) const {
SkASSERT(index < fFamilies.count());
familyName->set(fFamilies[index]->getFamilyName());
}
class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { SkFontStyleSet_Custom* SkFontMgr_Custom::onCreateStyleSet(int index) const {
public: SkASSERT(index < fFamilies.count());
DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { } return SkRef(fFamilies[index].get());
}
void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, SkFontStyleSet_Custom* SkFontMgr_Custom::onMatchFamily(const char familyName[]) const {
SkFontMgr_Custom::Families* families) const override for (int i = 0; i < fFamilies.count(); ++i) {
{ if (fFamilies[i]->getFamilyName().equals(familyName)) {
load_directory_fonts(scanner, fBaseDirectory, ".ttf", families); return SkRef(fFamilies[i].get());
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>());
} }
} }
return nullptr;
}
private: SkTypeface* SkFontMgr_Custom::onMatchFamilyStyle(const char familyName[],
static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families, const SkFontStyle& fontStyle) const
const char familyName[]) {
{ sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
for (int i = 0; i < families.count(); ++i) { return sset->matchStyle(fontStyle);
if (families[i]->getFamilyName().equals(familyName)) { }
return families[i].get();
SkTypeface* SkFontMgr_Custom::onMatchFamilyStyleCharacter(const char familyName[],
const SkFontStyle&,
const char* bcp47[], int bcp47Count,
SkUnichar character) const
{
return nullptr;
}
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);
} }
} }
}
return nullptr;
}
SkTypeface* SkFontMgr_Custom::onCreateFromData(SkData* data, int ttcIndex) const {
return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex);
}
SkTypeface* SkFontMgr_Custom::onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const {
return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex));
}
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))
{
return nullptr; return nullptr;
} }
static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner, int paramAxisCount;
const SkString& directory, const char* suffix, const FontParameters::Axis* paramAxes = params.getAxes(&paramAxisCount);
SkFontMgr_Custom::Families* families) SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
{ Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
SkOSFile::Iter iter(directory.c_str(), suffix);
SkString name;
while (iter.next(&name, false)) { auto data = skstd::make_unique<SkFontData>(std::move(stream), params.getCollectionIndex(),
SkString filename(SkOSPath::Join(directory.c_str(), name.c_str())); axisValues.get(), axisDefinitions.count());
std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(filename.c_str()); return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
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));
} }
/////////////////////////////////////////////////////////////////////////////// SkTypeface* SkFontMgr_Custom::onCreateFromFontData(std::unique_ptr<SkFontData> data) const {
bool isFixedPitch;
struct SkEmbeddedResource { const uint8_t* data; size_t size; }; SkFontStyle style;
struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; }; SkString name;
if (!fScanner.scanFont(data->getStream(), data->getIndex(),
class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { &name, &style, &isFixedPitch, nullptr))
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; return nullptr;
} }
return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
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));
} }
/////////////////////////////////////////////////////////////////////////////// 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 { SkTypeface* SkFontMgr_Custom::onLegacyCreateTypeface(const char familyName[],
public: SkFontStyle style) const
EmptyFontLoader() { } {
SkTypeface* tf = nullptr;
void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, if (familyName) {
SkFontMgr_Custom::Families* families) const override tf = this->onMatchFamilyStyle(familyName, style);
{
SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
families->push_back().reset(family);
family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
} }
}; if (nullptr == tf) {
tf = fDefaultFamily->matchStyle(style);
}
SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Empty() { return tf;
return sk_make_sp<SkFontMgr_Custom>(EmptyFontLoader());
} }

View File

@ -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

View File

@ -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));
}

View File

@ -6,7 +6,7 @@
*/ */
#include "SkFontMgr.h" #include "SkFontMgr.h"
#include "SkFontMgr_custom.h" #include "SkFontMgr_directory.h"
#ifndef SK_FONT_FILE_PREFIX #ifndef SK_FONT_FILE_PREFIX
# define SK_FONT_FILE_PREFIX "/usr/share/fonts/" # define SK_FONT_FILE_PREFIX "/usr/share/fonts/"

View File

@ -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));
}

View File

@ -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());
}