Loading core/jni/android/graphics/Canvas.cpp +27 −33 Original line number Diff line number Diff line Loading @@ -756,26 +756,36 @@ public: env->ReleaseStringChars(text, textArray); } 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 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); } #else TextLayout::drawText(paint, textArray + index, count, flags, x, y, canvas); #endif 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); drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint); env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); } Loading @@ -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); } Loading core/jni/android/graphics/RtlProperties.h +1 −1 Original line number Diff line number Diff line Loading @@ -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 core/jni/android/graphics/TextLayout.h +17 −17 Original line number Diff line number Diff line Loading @@ -46,16 +46,6 @@ namespace android { static TextLayoutCache gTextLayoutCache; #endif class TextLayout { public: enum { kDirection_LTR = 0, kDirection_RTL = 1, kDirection_Mask = 0x1 }; enum { kBidi_LTR = 0, kBidi_RTL = 1, Loading @@ -67,6 +57,16 @@ public: kBidi_Mask = 0x7 }; enum { kDirection_LTR = 0, kDirection_RTL = 1, kDirection_Mask = 0x1 }; class TextLayout { public: /* * Draws a unidirectional run of text. */ Loading core/jni/android/graphics/TextLayoutCache.cpp +117 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include "TextLayoutCache.h" #include "TextLayout.h" namespace android { Loading Loading @@ -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; Loading @@ -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 Loading core/jni/android/graphics/TextLayoutCache.h +4 −0 Original line number Diff line number Diff line Loading @@ -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 /** Loading Loading
core/jni/android/graphics/Canvas.cpp +27 −33 Original line number Diff line number Diff line Loading @@ -756,26 +756,36 @@ public: env->ReleaseStringChars(text, textArray); } 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 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); } #else TextLayout::drawText(paint, textArray + index, count, flags, x, y, canvas); #endif 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); drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint); env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); } Loading @@ -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); } Loading
core/jni/android/graphics/RtlProperties.h +1 −1 Original line number Diff line number Diff line Loading @@ -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
core/jni/android/graphics/TextLayout.h +17 −17 Original line number Diff line number Diff line Loading @@ -46,16 +46,6 @@ namespace android { static TextLayoutCache gTextLayoutCache; #endif class TextLayout { public: enum { kDirection_LTR = 0, kDirection_RTL = 1, kDirection_Mask = 0x1 }; enum { kBidi_LTR = 0, kBidi_RTL = 1, Loading @@ -67,6 +57,16 @@ public: kBidi_Mask = 0x7 }; enum { kDirection_LTR = 0, kDirection_RTL = 1, kDirection_Mask = 0x1 }; class TextLayout { public: /* * Draws a unidirectional run of text. */ Loading
core/jni/android/graphics/TextLayoutCache.cpp +117 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include "TextLayoutCache.h" #include "TextLayout.h" namespace android { Loading Loading @@ -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; Loading @@ -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 Loading
core/jni/android/graphics/TextLayoutCache.h +4 −0 Original line number Diff line number Diff line Loading @@ -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 /** Loading