From 1637dcd16cd314574a58602337a2c7222130b1b9 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Wed, 2 May 2012 10:41:14 -0700 Subject: Use paint typeface for shaping when it supports the requested script. This is a hackish but workable fix for bug 6415796. Change-Id: Iaba91e1e53e688a3ee05a1fdb68fd05102e369f2 --- core/jni/android/graphics/TextLayoutCache.cpp | 68 +++++++++++++++++---------- core/jni/android/graphics/TextLayoutCache.h | 3 ++ 2 files changed, 46 insertions(+), 25 deletions(-) (limited to 'core/jni') diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index 0d36edf..2bd36c3 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -739,18 +739,18 @@ void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars #endif } - -size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) { - // Reset kerning - mShaperItem.kerning_applied = false; - - // Update Harfbuzz Shaper - mShaperItem.item.bidiLevel = isRTL; - - SkTypeface* typeface = paint->getTypeface(); - +/** + * Return the first typeface in the logical change, starting with this typeface, + * that contains the specified unichar, or NULL if none is found. + * + * Note that this function does _not_ increment the reference count on the typeface, as the + * 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 (mShaperItem.item.script) { + switch (script) { case HB_Script_Arabic: typeface = getCachedTypeface(&mArabicTypeface, TYPEFACE_ARABIC); #if DEBUG_GLYPHS @@ -815,32 +815,31 @@ size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) { break; default: - if (!typeface) { - typeface = mDefaultTypeface; -#if DEBUG_GLYPHS - ALOGD("Using Default Typeface"); -#endif - } else { #if DEBUG_GLYPHS + if (typeface) { ALOGD("Using Paint Typeface"); -#endif } +#endif break; } + return typeface; +} - mShapingPaint.setTypeface(typeface); - mShaperItem.face = getCachedHBFace(typeface); +size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) { + // Reset kerning + mShaperItem.kerning_applied = false; -#if DEBUG_GLYPHS - ALOGD("Run typeface = %p, uniqueID = %d, hb_face = %p", - typeface, typeface->uniqueID(), mShaperItem.face); -#endif + // Update Harfbuzz Shaper + mShaperItem.item.bidiLevel = isRTL; + + SkTypeface* typeface = paint->getTypeface(); // Get the glyphs base count for offsetting the glyphIDs returned by Harfbuzz // This is needed as the Typeface used for shaping can be not the default one // when we are shaping any script that needs to use a fallback Font. // 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: @@ -850,7 +849,7 @@ size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) { case HB_Script_Thai:{ const uint16_t* text16 = (const uint16_t*)(mShaperItem.string + mShaperItem.item.pos); const uint16_t* text16End = text16 + mShaperItem.item.length; - SkUnichar firstUnichar = SkUTF16_NextUnichar(&text16); + firstUnichar = SkUTF16_NextUnichar(&text16); while (firstUnichar == ' ' && text16 < text16End) { firstUnichar = SkUTF16_NextUnichar(&text16); } @@ -861,6 +860,25 @@ size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) { 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); + } + + if (!typeface) { + typeface = mDefaultTypeface; +#if DEBUG_GLYPHS + ALOGD("Using Default Typeface"); +#endif + } + mShapingPaint.setTypeface(typeface); + mShaperItem.face = getCachedHBFace(typeface); + +#if DEBUG_GLYPHS + ALOGD("Run typeface = %p, uniqueID = %d, hb_face = %p", + typeface, typeface->uniqueID(), mShaperItem.face); +#endif + // Shape assert(mShaperItem.item.length > 0); // Harfbuzz will overwrite other memory if length is 0. ensureShaperItemGlyphArrays(mShaperItem.item.length * 3 / 2); diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h index 3c834a4..7d7caac 100644 --- a/core/jni/android/graphics/TextLayoutCache.h +++ b/core/jni/android/graphics/TextLayoutCache.h @@ -217,6 +217,9 @@ private: */ UnicodeString mBuffer; + SkTypeface* typefaceForUnichar(const SkPaint* paint, SkTypeface* typeface, + SkUnichar unichar, HB_Script script); + size_t shapeFontRun(const SkPaint* paint, bool isRTL); void computeValues(const SkPaint* paint, const UChar* chars, -- cgit v1.1