Chromium Code Reviews| 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 { |
|
bungeman-skia
2013/07/02 16:04:20
Is this intended to replace SkScalerContext::gener
reed1
2013/07/02 16:14:37
Not sure I follow : I'm extracting a cached FT_Fac
bungeman-skia
2013/07/02 16:25:31
I suppose I'm just pointing out that the entirety
|
| + // 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. |