diff options
Diffstat (limited to 'core/jni/android/graphics')
-rw-r--r-- | core/jni/android/graphics/Canvas.cpp | 60 | ||||
-rw-r--r-- | core/jni/android/graphics/RtlProperties.h | 2 | ||||
-rw-r--r-- | core/jni/android/graphics/TextLayout.h | 34 | ||||
-rw-r--r-- | core/jni/android/graphics/TextLayoutCache.cpp | 119 | ||||
-rw-r--r-- | core/jni/android/graphics/TextLayoutCache.h | 4 |
5 files changed, 166 insertions, 53 deletions
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index b2caa98..207c72f 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -756,26 +756,36 @@ public: env->ReleaseStringChars(text, textArray); } + static void logGlyphs(sp<TextLayoutCacheValue> value) { + LOGD("drawTextWithGlyphs -- got glyphs - count=%d", value->getGlyphsCount()); + for (size_t i = 0; i < value->getGlyphsCount(); i++) { + LOGD(" glyphs[%d]=%d", i, value->getGlyphs()[i]); + } + } + + static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray, + int start, int end, + jfloat x, jfloat y, int flags, SkPaint* paint) { + + jint count = end - start; + sp<TextLayoutCacheValue> value = gTextLayoutCache.getValue( + paint, textArray, start, count, count, flags); + if (value == NULL) { + LOGE("drawTextWithGlyphs -- cannot get Cache value"); + return ; + } +#if DEBUG_GLYPHS + logGlyphs(value); +#endif + doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), + x, y, flags, paint); + } + static void drawTextWithGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { jchar* textArray = env->GetCharArrayElements(text, NULL); -#if RTL_USE_HARFBUZZ && USE_TEXT_LAYOUT_CACHE - sp<TextLayoutCacheValue> value = gTextLayoutCache.getValue( - paint, textArray + index, 0, count, count, flags); - if (value != NULL) { -#if DEBUG_GLYPHS - LOGD("drawTextWithGlyphs -- got glyphs - count=%d", value->getGlyphsCount()); - for (size_t i = 0; i < value->getGlyphsCount(); i++) { - LOGD(" glyphs[%d]=%d", i, value->getGlyphs()[i]); - } -#endif - doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), - x, y, flags, paint); - } -#else - TextLayout::drawText(paint, textArray + index, count, flags, x, y, canvas); -#endif + drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint); env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); } @@ -785,23 +795,7 @@ public: jfloat x, jfloat y, int flags, SkPaint* paint) { const jchar* textArray = env->GetStringChars(text, NULL); -#if RTL_USE_HARFBUZZ && USE_TEXT_LAYOUT_CACHE - size_t count = end - start; - sp<TextLayoutCacheValue> value = gTextLayoutCache.getValue( - paint, textArray, start, count, count, flags); - if (value != NULL) { -#if DEBUG_GLYPHS - LOGD("drawTextWithGlyphs -- got glyphs - count=%d", value->getGlyphsCount()); - for (size_t i = 0; i < value->getGlyphsCount(); i++) { - LOGD(" glyphs[%d]=%d", i, value->getGlyphs()[i]); - } -#endif - doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), - x, y, flags, paint); - } -#else - TextLayout::drawText(paint, textArray + start, end - start, flags, x, y, canvas); -#endif + drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint); env->ReleaseStringChars(text, textArray); } diff --git a/core/jni/android/graphics/RtlProperties.h b/core/jni/android/graphics/RtlProperties.h index a41c91b..4fac89a 100644 --- a/core/jni/android/graphics/RtlProperties.h +++ b/core/jni/android/graphics/RtlProperties.h @@ -52,7 +52,7 @@ static RtlDebugLevel readRtlDebugLevel() { #define DEBUG_ADVANCES 0 // Define if we want (1) to have Glyphs debug values or not (0) -#define DEBUG_GLYPHS 0 +#define DEBUG_GLYPHS 1 } // namespace android #endif // ANDROID_RTL_PROPERTIES_H diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h index f203b75..9bb1b92 100644 --- a/core/jni/android/graphics/TextLayout.h +++ b/core/jni/android/graphics/TextLayout.h @@ -46,26 +46,26 @@ namespace android { static TextLayoutCache gTextLayoutCache; #endif -class TextLayout { -public: - - enum { - kDirection_LTR = 0, - kDirection_RTL = 1, +enum { + kBidi_LTR = 0, + kBidi_RTL = 1, + kBidi_Default_LTR = 2, + kBidi_Default_RTL = 3, + kBidi_Force_LTR = 4, + kBidi_Force_RTL = 5, + + kBidi_Mask = 0x7 +}; - kDirection_Mask = 0x1 - }; +enum { + kDirection_LTR = 0, + kDirection_RTL = 1, - enum { - kBidi_LTR = 0, - kBidi_RTL = 1, - kBidi_Default_LTR = 2, - kBidi_Default_RTL = 3, - kBidi_Force_LTR = 4, - kBidi_Force_RTL = 5, + kDirection_Mask = 0x1 +}; - kBidi_Mask = 0x7 - }; +class TextLayout { +public: /* * Draws a unidirectional run of text. diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index 8db768c..088202e 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -15,6 +15,7 @@ */ #include "TextLayoutCache.h" +#include "TextLayout.h" namespace android { @@ -381,13 +382,127 @@ void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontR } } +struct GlyphRun { + inline GlyphRun() {} + inline GlyphRun(jchar* glyphs, size_t glyphsCount, bool isRTL) : + glyphs(glyphs), glyphsCount(glyphsCount), isRTL(isRTL) { } + jchar* glyphs; + size_t glyphsCount; + int isRTL; +}; + void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance, jchar** outGlyphs, size_t* outGlyphsCount) { + + UBiDiLevel bidiReq = 0; + bool forceLTR = false; + bool forceRTL = false; + + switch (dirFlags) { + case kBidi_LTR: bidiReq = 0; break; // no ICU constant, canonical LTR level + case kBidi_RTL: bidiReq = 1; break; // no ICU constant, canonical RTL level + case kBidi_Default_LTR: bidiReq = UBIDI_DEFAULT_LTR; break; + case kBidi_Default_RTL: bidiReq = UBIDI_DEFAULT_RTL; break; + case kBidi_Force_LTR: forceLTR = true; break; // every char is LTR + case kBidi_Force_RTL: forceRTL = true; break; // every char is RTL + } + + if (forceLTR || forceRTL) { +#if DEBUG_GLYPHS + LOGD("computeValuesWithHarfbuzz -- forcing run with LTR=%d RTL=%d", + forceLTR, forceRTL); +#endif + computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, + outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); + } else { + UBiDi* bidi = ubidi_open(); + if (bidi) { + UErrorCode status = U_ZERO_ERROR; + LOGD("computeValuesWithHarfbuzz -- bidiReq=%d", bidiReq); + ubidi_setPara(bidi, chars, contextCount, bidiReq, NULL, &status); + if (U_SUCCESS(status)) { + int paraDir = ubidi_getParaLevel(bidi) & kDirection_Mask; // 0 if ltr, 1 if rtl + size_t rc = ubidi_countRuns(bidi, &status); +#if DEBUG_GLYPHS + LOGD("computeValuesWithHarfbuzz -- dirFlags=%d run-count=%d paraDir=%d", dirFlags, rc, paraDir); +#endif + + if (rc == 1 || !U_SUCCESS(status)) { + LOGD("HERE !!!"); + computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, + dirFlags, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); + ubidi_close(bidi); + return; + } + + size_t runIndex = 0; + Vector<GlyphRun> glyphRuns; + for (size_t i = 0; i < rc; ++i) { + int32_t startRun; + int32_t lengthRun; + UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun); + + int newFlags = (runDir == UBIDI_RTL) ? kDirection_RTL : kDirection_LTR; + jfloat runTotalAdvance = 0; + jchar* runGlyphs; + size_t runGlyphsCount = 0; + +#if DEBUG_GLYPHS + LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d newFlags=%d", + startRun, lengthRun, newFlags); +#endif + computeRunValuesWithHarfbuzz(paint, chars, startRun, + lengthRun, contextCount, newFlags, + outAdvances + runIndex, &runTotalAdvance, + &runGlyphs, &runGlyphsCount); + + runIndex += lengthRun; + + *outTotalAdvance += runTotalAdvance; + *outGlyphsCount += runGlyphsCount; + +#if DEBUG_GLYPHS + LOGD("computeValuesWithHarfbuzz -- run=%d run-glyphs-count=%d", + i, runGlyphsCount); + for (size_t j = 0; j < runGlyphsCount; j++) { + LOGD(" -- glyphs[%d]=%d", j, runGlyphs[j]); + } +#endif + glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, newFlags)); + } + +#if DEBUG_GLYPHS + LOGD("computeValuesWithHarfbuzz -- total-glyphs-count=%d", *outGlyphsCount); +#endif + *outGlyphs = new jchar[*outGlyphsCount]; + jchar* glyphs = *outGlyphs; + for (size_t i = 0; i < glyphRuns.size(); i++) { + const GlyphRun& glyphRun = glyphRuns.itemAt(i); + if (glyphRun.isRTL) { + for (size_t n = 0; n < glyphRun.glyphsCount; n++) { + glyphs[glyphRun.glyphsCount - n - 1] = glyphRun.glyphs[n]; + } + } else { + memcpy(glyphs, glyphRun.glyphs, glyphRun.glyphsCount * sizeof(jchar)); + } + glyphs += glyphRun.glyphsCount; + delete[] glyphRun.glyphs; + } + } + ubidi_close(bidi); + } + } +} + +void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, + size_t start, size_t count, size_t contextCount, int dirFlags, + jfloat* outAdvances, jfloat* outTotalAdvance, + jchar** outGlyphs, size_t* outGlyphsCount) { + bool isRTL = dirFlags & 0x1; - // TODO: need to run BiDi algo here to breakdown the text in several runs HB_ShaperItem shaperItem; HB_FontRec font; FontData fontData; @@ -397,7 +512,7 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar #if DEBUG_GLYPHS LOGD("HARFBUZZ -- num_glypth=%d - kerning_applied=%d", shaperItem.num_glyphs, shaperItem.kerning_applied); - LOGD(" -- string= '%s'", String8(chars, contextCount).string()); + LOGD(" -- string= '%s'", String8(chars + start, count).string()); LOGD(" -- isDevKernText=%d", paint->isDevKernText()); #endif diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h index e6ce68d..62813df 100644 --- a/core/jni/android/graphics/TextLayoutCache.h +++ b/core/jni/android/graphics/TextLayoutCache.h @@ -178,6 +178,10 @@ private: static void createGlyphArrays(HB_ShaperItem* shaperItem, int size); static void resetGlyphArrays(HB_ShaperItem* shaperItem); + static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, + size_t count, size_t contextCount, int dirFlags, + jfloat* outAdvances, jfloat* outTotalAdvance, + jchar** outGlyphs, size_t* outGlyphsCount); }; // TextLayoutCacheValue /** |