class SkFontMgr_fontconfig : public SkFontMgr {
SkAutoTUnref<SkFontConfigInterface> fFCI;
SkDataTable* fFamilyNames;
-
+ SkTypeface_FreeType::Scanner fScanner;
public:
SkFontMgr_fontconfig(SkFontConfigInterface* fci)
// TODO should the caller give us the style or should we get it from freetype?
SkFontStyle style;
bool isFixedWidth = false;
- if (!SkTypeface_FreeType::ScanFont(stream, 0, NULL, &style, &isFixedWidth)) {
+ if (!fScanner.scanFont(stream, 0, NULL, &style, &isFixedWidth)) {
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-#include "SkTSearch.h"
-/*static*/ bool SkTypeface_FreeType::ScanFont(
- SkStream* stream, int ttcIndex, SkString* name, SkFontStyle* style, bool* isFixedPitch)
+
+SkTypeface_FreeType::Scanner::Scanner() {
+ if (FT_Init_FreeType(&fLibrary)) {
+ fLibrary = NULL;
+ }
+}
+SkTypeface_FreeType::Scanner::~Scanner() {
+ FT_Done_FreeType(fLibrary);
+}
+
+FT_Face SkTypeface_FreeType::Scanner::openFace(SkStream* stream, int ttcIndex,
+ FT_Stream ftStream) const
{
- FT_Library library;
- if (FT_Init_FreeType(&library)) {
- return false;
+ if (fLibrary == NULL) {
+ return NULL;
}
- FT_Open_Args args;
+ FT_Open_Args args;
memset(&args, 0, sizeof(args));
const void* memoryBase = stream->getMemoryBase();
- FT_StreamRec streamRec;
if (memoryBase) {
args.flags = FT_OPEN_MEMORY;
args.memory_base = (const FT_Byte*)memoryBase;
args.memory_size = stream->getLength();
} else {
- memset(&streamRec, 0, sizeof(streamRec));
- streamRec.size = stream->getLength();
- streamRec.descriptor.pointer = stream;
- streamRec.read = sk_stream_read;
- streamRec.close = sk_stream_close;
+ memset(ftStream, 0, sizeof(*ftStream));
+ ftStream->size = stream->getLength();
+ ftStream->descriptor.pointer = stream;
+ ftStream->read = sk_stream_read;
+ ftStream->close = sk_stream_close;
args.flags = FT_OPEN_STREAM;
- args.stream = &streamRec;
+ args.stream = ftStream;
}
FT_Face face;
- if (FT_Open_Face(library, &args, ttcIndex, &face)) {
- FT_Done_FreeType(library);
+ if (FT_Open_Face(fLibrary, &args, ttcIndex, &face)) {
+ return NULL;
+ }
+ return face;
+}
+
+bool SkTypeface_FreeType::Scanner::recognizedFont(SkStream* stream, int* numFaces) const {
+ SkAutoMutexAcquire libraryLock(fLibraryMutex);
+
+ FT_StreamRec streamRec;
+ FT_Face face = this->openFace(stream, -1, &streamRec);
+ if (NULL == face) {
+ return false;
+ }
+
+ *numFaces = face->num_faces;
+
+ FT_Done_Face(face);
+ return true;
+}
+
+#include "SkTSearch.h"
+bool SkTypeface_FreeType::Scanner::scanFont(
+ SkStream* stream, int ttcIndex, SkString* name, SkFontStyle* style, bool* isFixedPitch) const
+{
+ SkAutoMutexAcquire libraryLock(fLibraryMutex);
+
+ FT_StreamRec streamRec;
+ FT_Face face = this->openFace(stream, ttcIndex, &streamRec);
+ if (NULL == face) {
return false;
}
{ "book", (SkFontStyle::kNormal_Weight + SkFontStyle::kLight_Weight)/2 },
{ "demi", SkFontStyle::kSemiBold_Weight },
{ "demibold", SkFontStyle::kSemiBold_Weight },
+ { "extra", SkFontStyle::kExtraBold_Weight },
{ "extrabold", SkFontStyle::kExtraBold_Weight },
{ "extralight", SkFontStyle::kExtraLight_Weight },
+ { "hairline", SkFontStyle::kThin_Weight },
{ "heavy", SkFontStyle::kBlack_Weight },
{ "light", SkFontStyle::kLight_Weight },
{ "medium", SkFontStyle::kMedium_Weight },
{ "normal", SkFontStyle::kNormal_Weight },
+ { "plain", SkFontStyle::kNormal_Weight },
{ "regular", SkFontStyle::kNormal_Weight },
+ { "roman", SkFontStyle::kNormal_Weight },
{ "semibold", SkFontStyle::kSemiBold_Weight },
+ { "standard", SkFontStyle::kNormal_Weight },
{ "thin", SkFontStyle::kThin_Weight },
{ "ultra", SkFontStyle::kExtraBold_Weight },
{ "ultrablack", 1000 },
if (index >= 0) {
weight = commonWeights[index].weight;
} else {
- SkDEBUGF(("Do not know weight for: %s\n", psFontInfo.weight));
+ SkDEBUGF(("Do not know weight for: %s (%s) \n", face->family_name, psFontInfo.weight));
}
}
}
FT_Done_Face(face);
- FT_Done_FreeType(library);
return true;
}
#include "SkGlyph.h"
#include "SkScalerContext.h"
#include "SkTypeface.h"
+#include "SkTypes.h"
#include <ft2build.h>
#include FT_FREETYPE_H
/** For SkFontMgrs to make use of our ability to extract
* name and style from a stream, using FreeType's API.
*/
- static bool ScanFont(SkStream* stream, int ttcIndex,
- SkString* name, SkFontStyle* style, bool* isFixedPitch);
+ class Scanner : ::SkNoncopyable {
+ public:
+ Scanner();
+ ~Scanner();
+ bool recognizedFont(SkStream* stream, int* numFonts) const;
+ bool scanFont(SkStream* stream, int ttcIndex,
+ SkString* name, SkFontStyle* style, bool* isFixedPitch) const;
+ private:
+ FT_Face openFace(SkStream* stream, int ttcIndex, FT_Stream ftStream) const;
+ FT_Library fLibrary;
+ mutable SkMutex fLibraryMutex;
+ };
protected:
SkTypeface_FreeType(const SkFontStyle& style, SkFontID uniqueID, bool isFixedPitch)
#include <limits>
#ifndef SK_FONT_FILE_PREFIX
-# define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/"
+# define SK_FONT_FILE_PREFIX "/usr/share/fonts/"
#endif
///////////////////////////////////////////////////////////////////////////////
bool isFixedPitch;
SkFontStyle style;
SkString name;
- if (SkTypeface_FreeType::ScanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
+ if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
return SkNEW_ARGS(SkTypeface_Stream, (style, isFixedPitch, false, name,
stream, ttcIndex));
} else {
private:
- static bool get_name_and_style(const char path[], SkString* name,
- SkFontStyle* style, bool* isFixedPitch) {
- SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
- if (stream.get()) {
- return SkTypeface_FreeType::ScanFont(stream, 0, name, style, isFixedPitch);
- } else {
- SkDebugf("---- failed to open <%s> as a font\n", path);
- return false;
- }
- }
-
- void load_directory_fonts(const SkString& directory) {
- SkOSFile::Iter iter(directory.c_str(), ".ttf");
+ void load_directory_fonts(const SkString& directory, const char* suffix) {
+ SkOSFile::Iter iter(directory.c_str(), suffix);
SkString name;
while (iter.next(&name, false)) {
- SkString filename(
- SkOSPath::Join(directory.c_str(), name.c_str()));
-
- bool isFixedPitch;
- SkString realname;
- SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
- if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPitch)) {
- SkDebugf("------ can't load <%s> as a font\n", filename.c_str());
+ SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
+ SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
+ if (!stream.get()) {
+ SkDebugf("---- failed to open <%s>\n", filename.c_str());
continue;
}
- SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
- style,
- isFixedPitch,
- true, // system-font (cannot delete)
- realname,
- filename.c_str(), 0));
-
- SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str());
- if (NULL == addTo) {
- addTo = new SkFontStyleSet_Custom(realname);
- fFamilies.push_back().reset(addTo);
+ int numFaces;
+ if (!fScanner.recognizedFont(stream, &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 (!fScanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) {
+ SkDebugf("---- failed to open <%s> <%d> as a font\n",
+ filename.c_str(), faceIndex);
+ continue;
+ }
+
+ SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
+ style,
+ isFixedPitch,
+ true, // system-font (cannot delete)
+ realname,
+ filename.c_str(), 0));
+
+ SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str());
+ if (NULL == addTo) {
+ addTo = new SkFontStyleSet_Custom(realname);
+ fFamilies.push_back().reset(addTo);
+ }
+ addTo->appendTypeface(tf);
}
- addTo->appendTypeface(tf);
}
SkOSFile::Iter dirIter(directory.c_str());
continue;
}
SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
- load_directory_fonts(dirname);
+ load_directory_fonts(dirname, suffix);
}
}
void load_system_fonts(const char* dir) {
SkString baseDirectory(dir);
- load_directory_fonts(baseDirectory);
+ load_directory_fonts(baseDirectory, ".ttf");
+ load_directory_fonts(baseDirectory, ".ttc");
+ load_directory_fonts(baseDirectory, ".otf");
+ load_directory_fonts(baseDirectory, ".pfb");
if (fFamilies.empty()) {
SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies;
SkFontStyleSet_Custom* gDefaultFamily;
SkTypeface* gDefaultNormal;
+ SkTypeface_FreeType::Scanner fScanner;
};
SkFontMgr* SkFontMgr::Factory() {
class SkFontStyleSet_Android : public SkFontStyleSet {
public:
- explicit SkFontStyleSet_Android(const FontFamily& family, const char* basePath) {
+ explicit SkFontStyleSet_Android(const FontFamily& family, const char* basePath,
+ const SkTypeface_FreeType::Scanner& scanner)
+ {
const SkString* cannonicalFamilyName = NULL;
if (family.fNames.count() > 0) {
cannonicalFamilyName = &family.fNames[0];
SkString familyName;
SkFontStyle style;
bool isFixedWidth;
- if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex,
- &familyName, &style, &isFixedWidth)) {
+ if (!scanner.scanFont(stream.get(), ttcIndex, &familyName, &style, &isFixedWidth)) {
DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathName.c_str()));
continue;
}
bool isFixedPitch;
SkFontStyle style;
SkString name;
- if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
+ if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
return NULL;
}
return SkNEW_ARGS(SkTypeface_AndroidStream, (stream, ttcIndex,
private:
+ SkTypeface_FreeType::Scanner fScanner;
+
SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
SkFontStyleSet* fDefaultFamily;
SkTypeface* fDefaultTypeface;
}
}
- SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family, basePath));
+ SkFontStyleSet_Android* newSet =
+ SkNEW_ARGS(SkFontStyleSet_Android, (family, basePath, fScanner));
if (0 == newSet->count()) {
SkDELETE(newSet);
continue;
class SkFontMgr_fontconfig : public SkFontMgr {
mutable SkAutoFcConfig fFC;
SkAutoTUnref<SkDataTable> fFamilyNames;
+ SkTypeface_FreeType::Scanner fScanner;
class StyleSet : public SkFontStyleSet {
public:
SkFontStyle style;
bool isFixedWidth = false;
- if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, NULL, &style, &isFixedWidth)) {
+ if (!fScanner.scanFont(stream, ttcIndex, NULL, &style, &isFixedWidth)) {
return NULL;
}