Loading core/jni/android/graphics/Canvas.cpp +64 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include "SkTemplates.h" #include "TextLayout.h" #include "TextLayoutCache.h" #include "unicode/ubidi.h" #include "unicode/ushape.h" Loading Loading @@ -755,11 +756,57 @@ public: env->ReleaseStringChars(text, textArray); } static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jcharArray glyphs, int index, int count, static void drawTextWithGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); 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 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); } static void drawTextWithGlyphs__StringIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jstring text, int start, int end, 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 env->ReleaseStringChars(text, textArray); } static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { // TODO: need to suppress this code after the GL renderer is modified for not // copying the paint Loading @@ -768,10 +815,18 @@ public: // Define Glyph encoding paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); TextLayout::drawText(paint, glyphArray + index, count, flags, x, y, canvas); canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint); // Get back old encoding paint->setTextEncoding(oldEncoding); } static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jcharArray glyphs, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); doDrawGlyphs(canvas, glyphArray, index, count, x, y, flags, paint); env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT); } Loading Loading @@ -967,6 +1022,10 @@ static JNINativeMethod gCanvasMethods[] = { (void*) SkCanvasGlue::drawText___CIIFFIPaint}, {"native_drawText","(ILjava/lang/String;IIFFII)V", (void*) SkCanvasGlue::drawText__StringIIFFIPaint}, {"native_drawTextWithGlyphs","(I[CIIFFII)V", (void*) SkCanvasGlue::drawTextWithGlyphs___CIIFFIPaint}, {"native_drawTextWithGlyphs","(ILjava/lang/String;IIFFII)V", (void*) SkCanvasGlue::drawTextWithGlyphs__StringIIFFIPaint}, {"native_drawGlyphs","(I[CIIFFII)V", (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint}, {"native_drawTextRun","(I[CIIIIFFII)V", Loading core/jni/android/graphics/RtlProperties.h +2 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ static RtlDebugLevel readRtlDebugLevel() { // Define if we want (1) to have Advances debug values or not (0) #define DEBUG_ADVANCES 0 // Define if we want (1) to have Glyphs debug values or not (0) #define DEBUG_GLYPHS 0 } // namespace android #endif // ANDROID_RTL_PROPERTIES_H core/jni/android/graphics/TextLayout.cpp +10 −10 Original line number Diff line number Diff line Loading @@ -26,10 +26,6 @@ namespace android { #if USE_TEXT_LAYOUT_CACHE TextLayoutCache TextLayout::mCache; #endif // Returns true if we might need layout. If bidiFlags force LTR, assume no layout, if // bidiFlags indicate there probably is RTL, assume we do, otherwise scan the text // looking for a character >= the first RTL character in unicode and assume we do if Loading Loading @@ -260,12 +256,16 @@ void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint sta jfloat* resultAdvances, jfloat& resultTotalAdvance) { #if USE_TEXT_LAYOUT_CACHE // Return advances from the cache. Compute them if needed mCache.getRunAdvances(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance); sp<TextLayoutCacheValue> layout = gTextLayoutCache.getValue( paint, chars, start, count, contextCount, dirFlags); if (layout != NULL) { memcpy(resultAdvances, layout->getAdvances(), layout->getAdvancesCount() * sizeof(jfloat)); resultTotalAdvance = layout->getTotalAdvance(); } #else // Compute advances and return them TextLayoutCacheValue::computeAdvances(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance); TextLayoutCacheValue::computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance, NULL, NULL ); #endif } Loading @@ -273,8 +273,8 @@ void TextLayout::getTextRunAdvancesHB(SkPaint* paint, const jchar* chars, jint s jint count, jint contextCount, jint dirFlags, jfloat* resultAdvances, jfloat& resultTotalAdvance) { // Compute advances and return them TextLayoutCacheValue::computeAdvancesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance); TextLayoutCacheValue::computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance, NULL, NULL); } void TextLayout::getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start, Loading core/jni/android/graphics/TextLayout.h +6 −6 Original line number Diff line number Diff line Loading @@ -41,6 +41,11 @@ namespace android { */ #define USE_TEXT_LAYOUT_CACHE 1 #if USE_TEXT_LAYOUT_CACHE static TextLayoutCache gTextLayoutCache; #endif class TextLayout { public: Loading Loading @@ -106,10 +111,5 @@ private: UErrorCode &status); static void handleText(SkPaint* paint, const jchar* text, jsize len, int bidiFlags, jfloat x, jfloat y, SkCanvas* canvas, SkPath* path); #if USE_TEXT_LAYOUT_CACHE static TextLayoutCache mCache; #endif }; } } // namespace android core/jni/android/graphics/TextLayoutCache.cpp +53 −52 Original line number Diff line number Diff line Loading @@ -19,14 +19,14 @@ namespace android { TextLayoutCache::TextLayoutCache() : mCache(GenerationCache<TextLayoutCacheKey, TextLayoutCacheValue*>::kUnlimitedCapacity), mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> >::kUnlimitedCapacity), mSize(0), mMaxSize(MB(DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB)), mCacheHitCount(0), mNanosecondsSaved(0) { init(); } TextLayoutCache::TextLayoutCache(uint32_t max): mCache(GenerationCache<TextLayoutCacheKey, TextLayoutCacheValue*>::kUnlimitedCapacity), mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> >::kUnlimitedCapacity), mSize(0), mMaxSize(max), mCacheHitCount(0), mNanosecondsSaved(0) { init(); Loading Loading @@ -88,14 +88,14 @@ void TextLayoutCache::removeOldests() { /** * Callbacks */ void TextLayoutCache::operator()(TextLayoutCacheKey& text, TextLayoutCacheValue*& desc) { if (desc) { void TextLayoutCache::operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc) { if (desc != NULL) { size_t totalSizeToDelete = text.getSize() + desc->getSize(); mSize -= totalSizeToDelete; if (mDebugEnabled) { LOGD("Cache value deleted, size = %d", totalSizeToDelete); } delete desc; desc.clear(); } } Loading @@ -109,29 +109,26 @@ void TextLayoutCache::clear() { /* * Caching */ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, jint start, jint count, jint contextCount, jint dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance) { sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, const jchar* text, jint start, jint count, jint contextCount, jint dirFlags) { AutoMutex _l(mLock); nsecs_t startTime = 0; if (mDebugEnabled) { startTime = systemTime(SYSTEM_TIME_MONOTONIC); } // Create the key TextLayoutCacheKey key(paint, text, start, count, contextCount, dirFlags); // Get entry for cache if possible TextLayoutCacheValue* value = mCache.get(key); // Get value from cache if possible sp<TextLayoutCacheValue> value = mCache.get(key); // Value not found for the entry, we need to add a new value in the cache if (!value) { // Value not found for the key, we need to add a new value in the cache if (value == NULL) { value = new TextLayoutCacheValue(); // Compute advances and store them value->computeAdvances(paint, text, start, count, contextCount, dirFlags); value->copyResult(outAdvances, outTotalAdvance); value->computeValues(paint, text, start, count, contextCount, dirFlags); // Don't bother to add in the cache if the entry is too big size_t size = key.getSize() + value->getSize(); Loading @@ -156,7 +153,7 @@ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, mCache.put(key, value); if (mDebugEnabled) { // Update timing information for statistics. // Update timing information for statistics value->setElapsedTime(systemTime(SYSTEM_TIME_MONOTONIC) - startTime); LOGD("CACHE MISS: Added entry for text='%s' with start=%d, count=%d, " Loading @@ -174,11 +171,10 @@ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, String8(text, contextCount).string(), start, count, contextCount, size, mMaxSize - mSize, value->getElapsedTime()); } delete value; value.clear(); } } else { // This is a cache hit, just copy the pre-computed results value->copyResult(outAdvances, outTotalAdvance); // This is a cache hit, just log timestamp and user infos if (mDebugEnabled) { nsecs_t elapsedTimeThruCacheGet = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; mNanosecondsSaved += (value->getElapsedTime() - elapsedTimeThruCacheGet); Loading @@ -199,6 +195,7 @@ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, } } } return value; } void TextLayoutCache::dumpCacheStats() { Loading Loading @@ -273,49 +270,46 @@ size_t TextLayoutCacheKey::getSize() { /** * TextLayoutCacheValue */ TextLayoutCacheValue::TextLayoutCacheValue() { advances = NULL; totalAdvance = 0; TextLayoutCacheValue::TextLayoutCacheValue() : mAdvances(NULL), mTotalAdvance(0), mAdvancesCount(0), mGlyphs(NULL), mGlyphsCount(0), mElapsedTime(0) { } TextLayoutCacheValue::~TextLayoutCacheValue() { delete[] advances; delete[] mAdvances; delete[] mGlyphs; } void TextLayoutCacheValue::setElapsedTime(uint32_t time) { elapsedTime = time; mElapsedTime = time; } uint32_t TextLayoutCacheValue::getElapsedTime() { return elapsedTime; return mElapsedTime; } void TextLayoutCacheValue::computeAdvances(SkPaint* paint, const UChar* chars, size_t start, void TextLayoutCacheValue::computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags) { advances = new float[count]; this->count = count; mAdvancesCount = count; mAdvances = new float[count]; #if RTL_USE_HARFBUZZ computeAdvancesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, advances, &totalAdvance); computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, mAdvances, &mTotalAdvance, &mGlyphs, &mGlyphsCount); #else computeAdvancesWithICU(paint, chars, start, count, contextCount, dirFlags, advances, &totalAdvance); mAdvances, &mTotalAdvance); #endif #if DEBUG_ADVANCES LOGD("Advances - count=%d - countextCount=%d - totalAdvance=%f - " "adv[0]=%f adv[1]=%f adv[2]=%f adv[3]=%f", count, contextCount, totalAdvance, advances[0], advances[1], advances[2], advances[3]); "adv[0]=%f adv[1]=%f adv[2]=%f adv[3]=%f", count, contextCount, mTotalAdvance, mAdvances[0], mAdvances[1], mAdvances[2], mAdvances[3]); #endif } void TextLayoutCacheValue::copyResult(jfloat* outAdvances, jfloat* outTotalAdvance) { memcpy(outAdvances, advances, count * sizeof(jfloat)); *outTotalAdvance = totalAdvance; } size_t TextLayoutCacheValue::getSize() { return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * count; return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * mAdvancesCount + sizeof(jchar) * mGlyphsCount; } void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, Loading Loading @@ -387,49 +381,56 @@ void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontR } } void TextLayoutCacheValue::computeAdvancesWithHarfbuzz(SkPaint* paint, const UChar* chars, void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance) { 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; shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, chars, start, count, contextCount, dirFlags); #if DEBUG_ADVANCES #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(" -- isDevKernText=%d", paint->isDevKernText()); #endif // Get Advances and their total jfloat totalAdvance = 0; for (size_t i = 0; i < count; i++) { totalAdvance += outAdvances[i] = HBFixedToFloat(shaperItem.advances[i]); #if DEBUG_ADVANCES LOGD("hb-adv = %d - rebased = %f - total = %f", shaperItem.advances[i], outAdvances[i], totalAdvance); #endif } *outTotalAdvance = totalAdvance; // Get Glyphs if (outGlyphs) { *outGlyphsCount = shaperItem.num_glyphs; *outGlyphs = new jchar[shaperItem.num_glyphs]; for (size_t i = 0; i < shaperItem.num_glyphs; i++) { (*outGlyphs)[i] = (jchar) shaperItem.glyphs[i]; } } // Cleaning deleteGlyphArrays(&shaperItem); HB_FreeFace(shaperItem.face); *outTotalAdvance = totalAdvance; } void TextLayoutCacheValue::computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance) { SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount); jchar* buffer = tempBuffer.get(); SkScalar* scalarArray = (SkScalar*)outAdvances; // this is where we'd call harfbuzz Loading Loading
core/jni/android/graphics/Canvas.cpp +64 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include "SkTemplates.h" #include "TextLayout.h" #include "TextLayoutCache.h" #include "unicode/ubidi.h" #include "unicode/ushape.h" Loading Loading @@ -755,11 +756,57 @@ public: env->ReleaseStringChars(text, textArray); } static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jcharArray glyphs, int index, int count, static void drawTextWithGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); 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 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); } static void drawTextWithGlyphs__StringIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jstring text, int start, int end, 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 env->ReleaseStringChars(text, textArray); } static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { // TODO: need to suppress this code after the GL renderer is modified for not // copying the paint Loading @@ -768,10 +815,18 @@ public: // Define Glyph encoding paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); TextLayout::drawText(paint, glyphArray + index, count, flags, x, y, canvas); canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint); // Get back old encoding paint->setTextEncoding(oldEncoding); } static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jcharArray glyphs, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); doDrawGlyphs(canvas, glyphArray, index, count, x, y, flags, paint); env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT); } Loading Loading @@ -967,6 +1022,10 @@ static JNINativeMethod gCanvasMethods[] = { (void*) SkCanvasGlue::drawText___CIIFFIPaint}, {"native_drawText","(ILjava/lang/String;IIFFII)V", (void*) SkCanvasGlue::drawText__StringIIFFIPaint}, {"native_drawTextWithGlyphs","(I[CIIFFII)V", (void*) SkCanvasGlue::drawTextWithGlyphs___CIIFFIPaint}, {"native_drawTextWithGlyphs","(ILjava/lang/String;IIFFII)V", (void*) SkCanvasGlue::drawTextWithGlyphs__StringIIFFIPaint}, {"native_drawGlyphs","(I[CIIFFII)V", (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint}, {"native_drawTextRun","(I[CIIIIFFII)V", Loading
core/jni/android/graphics/RtlProperties.h +2 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ static RtlDebugLevel readRtlDebugLevel() { // Define if we want (1) to have Advances debug values or not (0) #define DEBUG_ADVANCES 0 // Define if we want (1) to have Glyphs debug values or not (0) #define DEBUG_GLYPHS 0 } // namespace android #endif // ANDROID_RTL_PROPERTIES_H
core/jni/android/graphics/TextLayout.cpp +10 −10 Original line number Diff line number Diff line Loading @@ -26,10 +26,6 @@ namespace android { #if USE_TEXT_LAYOUT_CACHE TextLayoutCache TextLayout::mCache; #endif // Returns true if we might need layout. If bidiFlags force LTR, assume no layout, if // bidiFlags indicate there probably is RTL, assume we do, otherwise scan the text // looking for a character >= the first RTL character in unicode and assume we do if Loading Loading @@ -260,12 +256,16 @@ void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint sta jfloat* resultAdvances, jfloat& resultTotalAdvance) { #if USE_TEXT_LAYOUT_CACHE // Return advances from the cache. Compute them if needed mCache.getRunAdvances(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance); sp<TextLayoutCacheValue> layout = gTextLayoutCache.getValue( paint, chars, start, count, contextCount, dirFlags); if (layout != NULL) { memcpy(resultAdvances, layout->getAdvances(), layout->getAdvancesCount() * sizeof(jfloat)); resultTotalAdvance = layout->getTotalAdvance(); } #else // Compute advances and return them TextLayoutCacheValue::computeAdvances(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance); TextLayoutCacheValue::computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance, NULL, NULL ); #endif } Loading @@ -273,8 +273,8 @@ void TextLayout::getTextRunAdvancesHB(SkPaint* paint, const jchar* chars, jint s jint count, jint contextCount, jint dirFlags, jfloat* resultAdvances, jfloat& resultTotalAdvance) { // Compute advances and return them TextLayoutCacheValue::computeAdvancesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance); TextLayoutCacheValue::computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance, NULL, NULL); } void TextLayout::getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start, Loading
core/jni/android/graphics/TextLayout.h +6 −6 Original line number Diff line number Diff line Loading @@ -41,6 +41,11 @@ namespace android { */ #define USE_TEXT_LAYOUT_CACHE 1 #if USE_TEXT_LAYOUT_CACHE static TextLayoutCache gTextLayoutCache; #endif class TextLayout { public: Loading Loading @@ -106,10 +111,5 @@ private: UErrorCode &status); static void handleText(SkPaint* paint, const jchar* text, jsize len, int bidiFlags, jfloat x, jfloat y, SkCanvas* canvas, SkPath* path); #if USE_TEXT_LAYOUT_CACHE static TextLayoutCache mCache; #endif }; } } // namespace android
core/jni/android/graphics/TextLayoutCache.cpp +53 −52 Original line number Diff line number Diff line Loading @@ -19,14 +19,14 @@ namespace android { TextLayoutCache::TextLayoutCache() : mCache(GenerationCache<TextLayoutCacheKey, TextLayoutCacheValue*>::kUnlimitedCapacity), mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> >::kUnlimitedCapacity), mSize(0), mMaxSize(MB(DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB)), mCacheHitCount(0), mNanosecondsSaved(0) { init(); } TextLayoutCache::TextLayoutCache(uint32_t max): mCache(GenerationCache<TextLayoutCacheKey, TextLayoutCacheValue*>::kUnlimitedCapacity), mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> >::kUnlimitedCapacity), mSize(0), mMaxSize(max), mCacheHitCount(0), mNanosecondsSaved(0) { init(); Loading Loading @@ -88,14 +88,14 @@ void TextLayoutCache::removeOldests() { /** * Callbacks */ void TextLayoutCache::operator()(TextLayoutCacheKey& text, TextLayoutCacheValue*& desc) { if (desc) { void TextLayoutCache::operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc) { if (desc != NULL) { size_t totalSizeToDelete = text.getSize() + desc->getSize(); mSize -= totalSizeToDelete; if (mDebugEnabled) { LOGD("Cache value deleted, size = %d", totalSizeToDelete); } delete desc; desc.clear(); } } Loading @@ -109,29 +109,26 @@ void TextLayoutCache::clear() { /* * Caching */ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, jint start, jint count, jint contextCount, jint dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance) { sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, const jchar* text, jint start, jint count, jint contextCount, jint dirFlags) { AutoMutex _l(mLock); nsecs_t startTime = 0; if (mDebugEnabled) { startTime = systemTime(SYSTEM_TIME_MONOTONIC); } // Create the key TextLayoutCacheKey key(paint, text, start, count, contextCount, dirFlags); // Get entry for cache if possible TextLayoutCacheValue* value = mCache.get(key); // Get value from cache if possible sp<TextLayoutCacheValue> value = mCache.get(key); // Value not found for the entry, we need to add a new value in the cache if (!value) { // Value not found for the key, we need to add a new value in the cache if (value == NULL) { value = new TextLayoutCacheValue(); // Compute advances and store them value->computeAdvances(paint, text, start, count, contextCount, dirFlags); value->copyResult(outAdvances, outTotalAdvance); value->computeValues(paint, text, start, count, contextCount, dirFlags); // Don't bother to add in the cache if the entry is too big size_t size = key.getSize() + value->getSize(); Loading @@ -156,7 +153,7 @@ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, mCache.put(key, value); if (mDebugEnabled) { // Update timing information for statistics. // Update timing information for statistics value->setElapsedTime(systemTime(SYSTEM_TIME_MONOTONIC) - startTime); LOGD("CACHE MISS: Added entry for text='%s' with start=%d, count=%d, " Loading @@ -174,11 +171,10 @@ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, String8(text, contextCount).string(), start, count, contextCount, size, mMaxSize - mSize, value->getElapsedTime()); } delete value; value.clear(); } } else { // This is a cache hit, just copy the pre-computed results value->copyResult(outAdvances, outTotalAdvance); // This is a cache hit, just log timestamp and user infos if (mDebugEnabled) { nsecs_t elapsedTimeThruCacheGet = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; mNanosecondsSaved += (value->getElapsedTime() - elapsedTimeThruCacheGet); Loading @@ -199,6 +195,7 @@ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, } } } return value; } void TextLayoutCache::dumpCacheStats() { Loading Loading @@ -273,49 +270,46 @@ size_t TextLayoutCacheKey::getSize() { /** * TextLayoutCacheValue */ TextLayoutCacheValue::TextLayoutCacheValue() { advances = NULL; totalAdvance = 0; TextLayoutCacheValue::TextLayoutCacheValue() : mAdvances(NULL), mTotalAdvance(0), mAdvancesCount(0), mGlyphs(NULL), mGlyphsCount(0), mElapsedTime(0) { } TextLayoutCacheValue::~TextLayoutCacheValue() { delete[] advances; delete[] mAdvances; delete[] mGlyphs; } void TextLayoutCacheValue::setElapsedTime(uint32_t time) { elapsedTime = time; mElapsedTime = time; } uint32_t TextLayoutCacheValue::getElapsedTime() { return elapsedTime; return mElapsedTime; } void TextLayoutCacheValue::computeAdvances(SkPaint* paint, const UChar* chars, size_t start, void TextLayoutCacheValue::computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags) { advances = new float[count]; this->count = count; mAdvancesCount = count; mAdvances = new float[count]; #if RTL_USE_HARFBUZZ computeAdvancesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, advances, &totalAdvance); computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, mAdvances, &mTotalAdvance, &mGlyphs, &mGlyphsCount); #else computeAdvancesWithICU(paint, chars, start, count, contextCount, dirFlags, advances, &totalAdvance); mAdvances, &mTotalAdvance); #endif #if DEBUG_ADVANCES LOGD("Advances - count=%d - countextCount=%d - totalAdvance=%f - " "adv[0]=%f adv[1]=%f adv[2]=%f adv[3]=%f", count, contextCount, totalAdvance, advances[0], advances[1], advances[2], advances[3]); "adv[0]=%f adv[1]=%f adv[2]=%f adv[3]=%f", count, contextCount, mTotalAdvance, mAdvances[0], mAdvances[1], mAdvances[2], mAdvances[3]); #endif } void TextLayoutCacheValue::copyResult(jfloat* outAdvances, jfloat* outTotalAdvance) { memcpy(outAdvances, advances, count * sizeof(jfloat)); *outTotalAdvance = totalAdvance; } size_t TextLayoutCacheValue::getSize() { return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * count; return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * mAdvancesCount + sizeof(jchar) * mGlyphsCount; } void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, Loading Loading @@ -387,49 +381,56 @@ void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontR } } void TextLayoutCacheValue::computeAdvancesWithHarfbuzz(SkPaint* paint, const UChar* chars, void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance) { 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; shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, chars, start, count, contextCount, dirFlags); #if DEBUG_ADVANCES #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(" -- isDevKernText=%d", paint->isDevKernText()); #endif // Get Advances and their total jfloat totalAdvance = 0; for (size_t i = 0; i < count; i++) { totalAdvance += outAdvances[i] = HBFixedToFloat(shaperItem.advances[i]); #if DEBUG_ADVANCES LOGD("hb-adv = %d - rebased = %f - total = %f", shaperItem.advances[i], outAdvances[i], totalAdvance); #endif } *outTotalAdvance = totalAdvance; // Get Glyphs if (outGlyphs) { *outGlyphsCount = shaperItem.num_glyphs; *outGlyphs = new jchar[shaperItem.num_glyphs]; for (size_t i = 0; i < shaperItem.num_glyphs; i++) { (*outGlyphs)[i] = (jchar) shaperItem.glyphs[i]; } } // Cleaning deleteGlyphArrays(&shaperItem); HB_FreeFace(shaperItem.face); *outTotalAdvance = totalAdvance; } void TextLayoutCacheValue::computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance) { SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount); jchar* buffer = tempBuffer.get(); SkScalar* scalarArray = (SkScalar*)outAdvances; // this is where we'd call harfbuzz Loading