From d6deccb346e913d906f484d279b19e0f6ea18d94 Mon Sep 17 00:00:00 2001 From: Billy Hewlett Date: Fri, 22 Jun 2012 10:30:55 -0700 Subject: [PATCH] Remove hardcoded typeface pointers There were a number of extraneous typeface pointers, one per language, in TextLayoutCache. Removing these makes adding additional supported fonts easier. This checkin now properly unrefs typefaces returned by SkCreateTypefaceForScript. Additionally, all harfbuzz shaped fonts (with exceptions Greek, Cyrillic, Hangul) should call SkCreateTypefaceForScript. Change-Id: I7dcf603a89e5ff52c6dab8fb87ae1807a79c351c --- core/jni/android/graphics/TextLayoutCache.cpp | 201 ++++-------------- core/jni/android/graphics/TextLayoutCache.h | 15 +- 2 files changed, 45 insertions(+), 171 deletions(-) diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index 5466be45d79ae..2bdba87473dbd 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -345,26 +345,10 @@ TextLayoutShaper::TextLayoutShaper() : mShaperItemGlyphArraySize(0) { void TextLayoutShaper::init() { mDefaultTypeface = SkFontHost::CreateTypeface(NULL, NULL, NULL, 0, SkTypeface::kNormal); - mArabicTypeface = NULL; - mHebrewRegularTypeface = NULL; - mHebrewBoldTypeface = NULL; - mBengaliTypeface = NULL; - mThaiTypeface = NULL; - mDevanagariRegularTypeface = NULL; - mTamilRegularTypeface = NULL; - mTamilBoldTypeface = NULL; } void TextLayoutShaper::unrefTypefaces() { SkSafeUnref(mDefaultTypeface); - SkSafeUnref(mArabicTypeface); - SkSafeUnref(mHebrewRegularTypeface); - SkSafeUnref(mHebrewBoldTypeface); - SkSafeUnref(mBengaliTypeface); - SkSafeUnref(mThaiTypeface); - SkSafeUnref(mDevanagariRegularTypeface); - SkSafeUnref(mTamilRegularTypeface); - SkSafeUnref(mTamilBoldTypeface); } TextLayoutShaper::~TextLayoutShaper() { @@ -750,115 +734,32 @@ void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars * assumption is that its lifetime is managed elsewhere - in particular, the fallback typefaces * for the default font live in a global cache. */ -SkTypeface* TextLayoutShaper::typefaceForUnichar(const SkPaint* paint, SkTypeface* typeface, - SkUnichar unichar, HB_Script script) { - // Set the correct Typeface depending on the script - switch (script) { - case HB_Script_Arabic: - typeface = getCachedTypeface(&mArabicTypeface, HB_Script_Arabic, - SkTypeface::kNormal); -#if DEBUG_GLYPHS - ALOGD("Using Arabic Typeface"); -#endif - break; - - case HB_Script_Hebrew: - if (typeface) { - switch (typeface->style()) { - case SkTypeface::kBold: - case SkTypeface::kBoldItalic: - typeface = getCachedTypeface(&mHebrewBoldTypeface, HB_Script_Hebrew, - SkTypeface::kBold); -#if DEBUG_GLYPHS - ALOGD("Using Hebrew Bold/BoldItalic Typeface"); -#endif - break; - - case SkTypeface::kNormal: - case SkTypeface::kItalic: - default: - typeface = getCachedTypeface(&mHebrewRegularTypeface, HB_Script_Hebrew, - SkTypeface::kNormal); -#if DEBUG_GLYPHS - ALOGD("Using Hebrew Regular/Italic Typeface"); -#endif - break; - } - } else { - typeface = getCachedTypeface(&mHebrewRegularTypeface, HB_Script_Hebrew, - SkTypeface::kNormal); -#if DEBUG_GLYPHS - ALOGD("Using Hebrew Regular Typeface"); -#endif - } - break; - - case HB_Script_Bengali: - typeface = getCachedTypeface(&mBengaliTypeface, HB_Script_Bengali, - SkTypeface::kNormal); -#if DEBUG_GLYPHS - ALOGD("Using Bengali Typeface"); -#endif - break; - - case HB_Script_Thai: - typeface = getCachedTypeface(&mThaiTypeface, HB_Script_Thai, - SkTypeface::kNormal); -#if DEBUG_GLYPHS - ALOGD("Using Thai Typeface"); -#endif - break; - - case HB_Script_Devanagari: - typeface = getCachedTypeface(&mDevanagariRegularTypeface, HB_Script_Devanagari, - SkTypeface::kNormal); -#if DEBUG_GLYPHS - ALOGD("Using Devanagari Regular Typeface"); -#endif - break; - - case HB_Script_Tamil: - if (typeface) { - switch (typeface->style()) { - case SkTypeface::kBold: - case SkTypeface::kBoldItalic: - typeface = getCachedTypeface(&mTamilBoldTypeface, HB_Script_Tamil, - SkTypeface::kBold); -#if DEBUG_GLYPHS - ALOGD("Using Tamil Bold Typeface"); -#endif - break; - - case SkTypeface::kNormal: - case SkTypeface::kItalic: - default: - typeface = getCachedTypeface(&mTamilRegularTypeface, HB_Script_Tamil, - SkTypeface::kNormal); -#if DEBUG_GLYPHS - ALOGD("Using Tamil Regular Typeface"); -#endif - break; - } - } else { - typeface = getCachedTypeface(&mTamilRegularTypeface, HB_Script_Tamil, - SkTypeface::kNormal); -#if DEBUG_GLYPHS - ALOGD("Using Tamil Regular Typeface"); -#endif - } - break; - - default: -#if DEBUG_GLYPHS - if (typeface) { - ALOGD("Using Paint Typeface"); - } -#endif - break; +SkTypeface* TextLayoutShaper::typefaceForScript(const SkPaint* paint, SkTypeface* typeface, + HB_Script script) { + SkTypeface::Style currentStyle = SkTypeface::kNormal; + if (typeface) { + currentStyle = typeface->style(); } + typeface = SkCreateTypefaceForScript(script, currentStyle); +#if DEBUG_GLYPHS + ALOGD("Using Harfbuzz Script %d, Style %d", script, currentStyle); +#endif return typeface; } +bool TextLayoutShaper::isComplexScript(HB_Script script) { + switch (script) { + case HB_Script_Common: + case HB_Script_Greek: + case HB_Script_Cyrillic: + case HB_Script_Hangul: + case HB_Script_Inherited: + return false; + default: + return true; + } +} + size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) { // Reset kerning mShaperItem.kerning_applied = false; @@ -874,37 +775,35 @@ size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) { // If we are a "common" script we dont need to shift size_t baseGlyphCount = 0; SkUnichar firstUnichar = 0; - switch (mShaperItem.item.script) { - case HB_Script_Arabic: - case HB_Script_Hebrew: - case HB_Script_Bengali: - case HB_Script_Devanagari: - case HB_Script_Tamil: - case HB_Script_Thai:{ - const uint16_t* text16 = (const uint16_t*)(mShaperItem.string + mShaperItem.item.pos); + if (isComplexScript(mShaperItem.item.script)) { + const uint16_t* text16 = (const uint16_t*) (mShaperItem.string + mShaperItem.item.pos); const uint16_t* text16End = text16 + mShaperItem.item.length; firstUnichar = SkUTF16_NextUnichar(&text16); while (firstUnichar == ' ' && text16 < text16End) { firstUnichar = SkUTF16_NextUnichar(&text16); } baseGlyphCount = paint->getBaseGlyphCount(firstUnichar); - break; - } - default: - break; } - // We test the baseGlyphCount to see if the typeface supports the requested script if (baseGlyphCount != 0) { - typeface = typefaceForUnichar(paint, typeface, firstUnichar, mShaperItem.item.script); + typeface = typefaceForScript(paint, typeface, mShaperItem.item.script); + if (!typeface) { + typeface = mDefaultTypeface; + SkSafeRef(typeface); +#if DEBUG_GLYPHS + ALOGD("Using Default Typeface"); +#endif + } + } else { + if (!typeface) { + typeface = mDefaultTypeface; +#if DEBUG_GLYPHS + ALOGD("Using Default Typeface"); +#endif + } + SkSafeRef(typeface); } - if (!typeface) { - typeface = mDefaultTypeface; -#if DEBUG_GLYPHS - ALOGD("Using Default Typeface"); -#endif - } mShapingPaint.setTypeface(typeface); mShaperItem.face = getCachedHBFace(typeface); @@ -912,6 +811,7 @@ size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) { ALOGD("Run typeface = %p, uniqueID = %d, hb_face = %p", typeface, typeface->uniqueID(), mShaperItem.face); #endif + SkSafeUnref(typeface); // Shape assert(mShaperItem.item.length > 0); // Harfbuzz will overwrite other memory if length is 0. @@ -960,25 +860,6 @@ void TextLayoutShaper::deleteShaperItemGlyphArrays() { delete[] mShaperItem.log_clusters; } -SkTypeface* TextLayoutShaper::getCachedTypeface(SkTypeface** typeface, HB_Script script, - SkTypeface::Style style) { - if (!*typeface) { - *typeface = SkCreateTypefaceForScript(script, style); - // CreateFromFile(path) can return NULL if the path is non existing - if (!*typeface) { -#if DEBUG_GLYPHS - ALOGD("No font for Harfbuzz script %d, will use default font", script); -#endif - return mDefaultTypeface; - } - (*typeface)->ref(); -#if DEBUG_GLYPHS - ALOGD("Created SkTypeface for Harfbuzz script %d with uniqueID = %d", script, (*typeface)->uniqueID()); -#endif - } - return *typeface; -} - HB_Face TextLayoutShaper::getCachedHBFace(SkTypeface* typeface) { SkFontID fontId = typeface->uniqueID(); ssize_t index = mCachedHBFaces.indexOfKey(fontId); diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h index 62d17964290cb..0b25e936fcd00 100644 --- a/core/jni/android/graphics/TextLayoutCache.h +++ b/core/jni/android/graphics/TextLayoutCache.h @@ -189,17 +189,9 @@ private: SkPaint mShapingPaint; /** - * Skia typefaces cached for shaping + * Skia default typeface to be returned if we cannot resolve script */ SkTypeface* mDefaultTypeface; - SkTypeface* mArabicTypeface; - SkTypeface* mHebrewRegularTypeface; - SkTypeface* mHebrewBoldTypeface; - SkTypeface* mBengaliTypeface; - SkTypeface* mThaiTypeface; - SkTypeface* mDevanagariRegularTypeface; - SkTypeface* mTamilRegularTypeface; - SkTypeface* mTamilBoldTypeface; /** * Cache of Harfbuzz faces @@ -224,8 +216,8 @@ private: void init(); void unrefTypefaces(); - SkTypeface* typefaceForUnichar(const SkPaint* paint, SkTypeface* typeface, - SkUnichar unichar, HB_Script script); + SkTypeface* typefaceForScript(const SkPaint* paint, SkTypeface* typeface, + HB_Script script); size_t shapeFontRun(const SkPaint* paint, bool isRTL); @@ -245,6 +237,7 @@ private: bool doShaping(size_t size); void createShaperItemGlyphArrays(size_t size); void deleteShaperItemGlyphArrays(); + bool isComplexScript(HB_Script script); }; // TextLayoutShaper