diff options
author | 2013-07-02 16:32:29 +0000 | |
---|---|---|
committer | 2013-07-02 16:32:29 +0000 | |
commit | b4162b12b1e8e38c48b328f819c97199a0825d2b (patch) | |
tree | 04b4467683b318b37409ec291b1bebf9c44bbfa3 /src/ports | |
parent | 231129753cdbefbfa026d4c14b260aece973b4e9 (diff) |
impl charsToGlyphs for freetype
BUG=
R=bungeman@google.com
Review URL: https://codereview.chromium.org/18040004
git-svn-id: http://skia.googlecode.com/svn/trunk@9866 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/ports')
-rw-r--r-- | src/ports/SkFontHost_FreeType.cpp | 146 | ||||
-rw-r--r-- | src/ports/SkFontHost_FreeType_common.h | 10 |
2 files changed, 124 insertions, 32 deletions
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 06109e1e6e..d5a435d423 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. diff --git a/src/ports/SkFontHost_FreeType_common.h b/src/ports/SkFontHost_FreeType_common.h index acf9a4ab2b..6bd3532d66 100644 --- a/src/ports/SkFontHost_FreeType_common.h +++ b/src/ports/SkFontHost_FreeType_common.h @@ -48,7 +48,9 @@ private: class SkTypeface_FreeType : public SkTypeface { protected: SkTypeface_FreeType(Style style, SkFontID uniqueID, bool isFixedPitch) - : INHERITED(style, uniqueID, isFixedPitch) {} + : INHERITED(style, uniqueID, isFixedPitch) + , fGlyphCount(-1) + {} virtual SkScalerContext* onCreateScalerContext( const SkDescriptor*) const SK_OVERRIDE; @@ -58,7 +60,13 @@ protected: const uint32_t*, uint32_t) const SK_OVERRIDE; virtual int onGetUPEM() const SK_OVERRIDE; + virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], + int glyphCount) const SK_OVERRIDE; + virtual int onCountGlyphs() const SK_OVERRIDE; + private: + mutable int fGlyphCount; + typedef SkTypeface INHERITED; }; |