Index: src/ports/SkFontHost_FreeType.cpp |
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp |
index 06109e1e6e2aeaea8d06cbfcd5c5dc5de78fd637..d5a435d4230cce7f66a3b902cc9e52ad52b604f6 100644 |
--- a/src/ports/SkFontHost_FreeType.cpp |
+++ b/src/ports/SkFontHost_FreeType.cpp |
@@ -338,6 +338,39 @@ static void unref_ft_face(FT_Face face) { |
SkDEBUGFAIL("shouldn't get here, face not in list"); |
} |
+class AutoFTAccess { |
+public: |
+ AutoFTAccess(const SkTypeface* tf) : fRec(NULL), fFace(NULL) { |
+ gFTMutex.acquire(); |
+ if (1 == ++gFTCount) { |
+ if (!InitFreetype()) { |
+ sk_throw(); |
+ } |
+ } |
+ fRec = ref_ft_face(tf); |
+ if (fRec) { |
+ fFace = fRec->fFace; |
+ } |
+ } |
+ |
+ ~AutoFTAccess() { |
+ if (fFace) { |
+ unref_ft_face(fFace); |
+ } |
+ if (0 == --gFTCount) { |
+ FT_Done_FreeType(gFTLibrary); |
+ } |
+ gFTMutex.release(); |
+ } |
+ |
+ SkFaceRec* rec() { return fRec; } |
+ FT_Face face() { return fFace; } |
+ |
+private: |
+ SkFaceRec* fRec; |
+ FT_Face fFace; |
+}; |
+ |
/////////////////////////////////////////////////////////////////////////// |
// Work around for old versions of freetype. |
@@ -455,18 +488,11 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics( |
#if defined(SK_BUILD_FOR_MAC) |
return NULL; |
#else |
- SkAutoMutexAcquire ac(gFTMutex); |
- FT_Library libInit = NULL; |
- if (gFTCount == 0) { |
- if (!InitFreetype()) |
- sk_throw(); |
- libInit = gFTLibrary; |
- } |
- SkAutoTCallIProc<struct FT_LibraryRec_, FT_Done_FreeType> ftLib(libInit); |
- SkFaceRec* rec = ref_ft_face(this); |
- if (NULL == rec) |
+ AutoFTAccess fta(this); |
+ FT_Face face = fta.face(); |
+ if (!face) { |
return NULL; |
- FT_Face face = rec->fFace; |
+ } |
SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; |
info->fFontName.set(FT_Get_Postscript_Name(face)); |
@@ -628,7 +654,6 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics( |
if (!canEmbed(face)) |
info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; |
- unref_ft_face(face); |
return info; |
#endif |
} |
@@ -700,23 +725,9 @@ void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const { |
} |
int SkTypeface_FreeType::onGetUPEM() const { |
- SkAutoMutexAcquire ac(gFTMutex); |
- FT_Library libInit = NULL; |
- if (gFTCount == 0) { |
- if (!InitFreetype()) |
- sk_throw(); |
- libInit = gFTLibrary; |
- } |
- SkAutoTCallIProc<struct FT_LibraryRec_, FT_Done_FreeType> ftLib(libInit); |
- SkFaceRec *rec = ref_ft_face(this); |
- int unitsPerEm = 0; |
- |
- if (rec != NULL && rec->fFace != NULL) { |
- unitsPerEm = rec->fFace->units_per_EM; |
- unref_ft_face(rec->fFace); |
- } |
- |
- return unitsPerEm; |
+ AutoFTAccess fta(this); |
+ FT_Face face = fta.face(); |
+ return face ? face->units_per_EM : 0; |
} |
SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, |
@@ -1320,8 +1331,81 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, |
} |
} |
-//////////////////////////////////////////////////////////////////////// |
-//////////////////////////////////////////////////////////////////////// |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+#include "SkUtils.h" |
+ |
+static SkUnichar next_utf8(const void** chars) { |
+ return SkUTF8_NextUnichar((const char**)chars); |
+} |
+ |
+static SkUnichar next_utf16(const void** chars) { |
+ return SkUTF16_NextUnichar((const uint16_t**)chars); |
+} |
+ |
+static SkUnichar next_utf32(const void** chars) { |
+ const SkUnichar** uniChars = (const SkUnichar**)chars; |
+ SkUnichar uni = **uniChars; |
+ *uniChars += 1; |
+ return uni; |
+} |
+ |
+typedef SkUnichar (*EncodingProc)(const void**); |
+ |
+static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { |
+ static const EncodingProc gProcs[] = { |
+ next_utf8, next_utf16, next_utf32 |
+ }; |
+ SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); |
+ return gProcs[enc]; |
+} |
+ |
+int SkTypeface_FreeType::onCharsToGlyphs(const void* chars, Encoding encoding, |
+ uint16_t glyphs[], int glyphCount) const { |
+ AutoFTAccess fta(this); |
+ FT_Face face = fta.face(); |
+ if (!face) { |
+ if (glyphs) { |
+ sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); |
+ } |
+ return 0; |
+ } |
+ |
+ EncodingProc next_uni_proc = find_encoding_proc(encoding); |
+ |
+ if (NULL == glyphs) { |
+ for (int i = 0; i < glyphCount; ++i) { |
+ if (0 == FT_Get_Char_Index(face, next_uni_proc(&chars))) { |
+ return i; |
+ } |
+ } |
+ return glyphCount; |
+ } else { |
+ int first = glyphCount; |
+ for (int i = 0; i < glyphCount; ++i) { |
+ unsigned id = FT_Get_Char_Index(face, next_uni_proc(&chars)); |
+ glyphs[i] = SkToU16(id); |
+ if (0 == id && i < first) { |
+ first = i; |
+ } |
+ } |
+ return first; |
+ } |
+} |
+ |
+int SkTypeface_FreeType::onCountGlyphs() const { |
+ // we cache this value, using -1 as a sentinel for "not computed" |
+ if (fGlyphCount < 0) { |
+ AutoFTAccess fta(this); |
+ FT_Face face = fta.face(); |
+ // if the face failed, we still assign a non-negative value |
+ fGlyphCount = face ? face->num_glyphs : 0; |
+ } |
+ return fGlyphCount; |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+/////////////////////////////////////////////////////////////////////////////// |
/* Export this so that other parts of our FonttHost port can make use of our |
ability to extract the name+style from a stream, using FreeType's api. |