diff options
author | Fabrice Di Meglio <fdimeglio@google.com> | 2011-09-23 13:30:41 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-09-23 13:30:41 -0700 |
commit | 651e46679b2d5dc7809fdb2b57e15a9ba2992db4 (patch) | |
tree | f55c36d5e90675c001bc90a7a1a1a7d30da84ae3 /core | |
parent | 83a559e78f57703645066c822a1ec7257c06ba56 (diff) | |
parent | 79df5323e7ed541b854cea5684a89e8be8c2dfc9 (diff) | |
download | frameworks_base-651e46679b2d5dc7809fdb2b57e15a9ba2992db4.zip frameworks_base-651e46679b2d5dc7809fdb2b57e15a9ba2992db4.tar.gz frameworks_base-651e46679b2d5dc7809fdb2b57e15a9ba2992db4.tar.bz2 |
Merge "Fix bug #5332081 TextLayoutCache needs to be able to have more cache hits"
Diffstat (limited to 'core')
-rw-r--r-- | core/jni/android/graphics/Canvas.cpp | 29 | ||||
-rw-r--r-- | core/jni/android/graphics/Paint.cpp | 15 | ||||
-rw-r--r-- | core/jni/android/graphics/TextLayout.cpp | 13 | ||||
-rw-r--r-- | core/jni/android/graphics/TextLayout.h | 2 | ||||
-rw-r--r-- | core/jni/android/graphics/TextLayoutCache.cpp | 209 | ||||
-rw-r--r-- | core/jni/android/graphics/TextLayoutCache.h | 40 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 28 |
7 files changed, 186 insertions, 150 deletions
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index 9313d0a..02c5bb3 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -758,21 +758,7 @@ public: jfloat x, jfloat y, int flags, SkPaint* paint) { jint count = end - start; - sp<TextLayoutCacheValue> value; -#if USE_TEXT_LAYOUT_CACHE - value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count, - end, flags); - if (value == NULL) { - LOGE("Cannot get TextLayoutCache value"); - return ; - } -#else - value = new TextLayoutCacheValue(); - value->computeValues(paint, textArray, start, count, end, flags); -#endif - - doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), - x, y, flags, paint); + drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint); } static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray, @@ -781,19 +767,20 @@ public: sp<TextLayoutCacheValue> value; #if USE_TEXT_LAYOUT_CACHE - value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count, - contextCount, flags); + value = TextLayoutCache::getInstance().getValue(paint, textArray, contextCount, flags); if (value == NULL) { LOGE("Cannot get TextLayoutCache value"); return ; } #else value = new TextLayoutCacheValue(); - value->computeValues(paint, textArray, start, count, contextCount, flags); + value->computeValues(paint, textArray, contextCount, flags); #endif - - doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), - x, y, flags, paint); + size_t startIndex = 0; + size_t glyphsCount = 0; + value->getGlyphsIndexAndCount(start, count, &startIndex, &glyphsCount); + const jchar* glyphs = value->getGlyphs(startIndex, glyphsCount); + doDrawGlyphs(canvas, glyphs, 0, glyphsCount, x, y, flags, paint); } static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count, diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 7d222f6..3daf7d0 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -352,7 +352,7 @@ public: jfloat result = 0; #if RTL_USE_HARFBUZZ TextLayout::getTextRunAdvances(paint, textArray, index, count, textLength, - paint->getFlags(), NULL /* dont need all advances */, result); + paint->getFlags(), NULL /* dont need all advances */, &result); #else // we double count, since measureText wants a byteLength SkScalar width = paint->measureText(textArray + index, count << 1); @@ -382,7 +382,7 @@ public: #if RTL_USE_HARFBUZZ TextLayout::getTextRunAdvances(paint, textArray, start, count, textLength, - paint->getFlags(), NULL /* dont need all advances */, width); + paint->getFlags(), NULL /* dont need all advances */, &width); #else width = SkScalarToFloat(paint->measureText(textArray + start, count << 1)); @@ -406,7 +406,7 @@ public: #if RTL_USE_HARFBUZZ TextLayout::getTextRunAdvances(paint, textArray, 0, textLength, textLength, - paint->getFlags(), NULL /* dont need all advances */, width); + paint->getFlags(), NULL /* dont need all advances */, &width); #else width = SkScalarToFloat(paint->measureText(textArray, textLength << 1)); #endif @@ -435,10 +435,8 @@ public: jfloat* widthsArray = autoWidths.ptr(); #if RTL_USE_HARFBUZZ - jfloat totalAdvance; - TextLayout::getTextRunAdvances(paint, text, 0, count, count, - paint->getFlags(), widthsArray, totalAdvance); + paint->getFlags(), widthsArray, NULL /* dont need totalAdvance */); #else SkScalar* scalarArray = (SkScalar*)widthsArray; @@ -533,7 +531,7 @@ public: jfloat totalAdvance = 0; TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags, - advancesArray, totalAdvance); + advancesArray, &totalAdvance); if (advances != NULL) { env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray); @@ -604,10 +602,9 @@ public: jint count, jint flags, jint offset, jint opt) { #if RTL_USE_HARFBUZZ jfloat scalarArray[count]; - jfloat totalAdvance = 0; TextLayout::getTextRunAdvances(paint, text, start, count, count, flags, - scalarArray, totalAdvance); + scalarArray, NULL /* dont need totalAdvance */); #else SkScalar scalarArray[count]; jchar buffer[count]; diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp index a2d6efb..ae17aed 100644 --- a/core/jni/android/graphics/TextLayout.cpp +++ b/core/jni/android/graphics/TextLayout.cpp @@ -253,21 +253,22 @@ void TextLayout::drawTextRun(SkPaint* paint, const jchar* chars, void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start, jint count, jint contextCount, jint dirFlags, - jfloat* resultAdvances, jfloat& resultTotalAdvance) { + jfloat* resultAdvances, jfloat* resultTotalAdvance) { sp<TextLayoutCacheValue> value; #if USE_TEXT_LAYOUT_CACHE // Return advances from the cache. Compute them if needed - value = TextLayoutCache::getInstance().getValue( - paint, chars, start, count, contextCount, dirFlags); + value = TextLayoutCache::getInstance().getValue(paint, chars, contextCount, dirFlags); #else value = new TextLayoutCacheValue(); - value->computeValues(paint, chars, start, count, contextCount, dirFlags); + value->computeValues(paint, chars, contextCount, dirFlags); #endif if (value != NULL) { if (resultAdvances != NULL) { - memcpy(resultAdvances, value->getAdvances(), value->getAdvancesCount() * sizeof(jfloat)); + value->getAdvances(start, count, resultAdvances); + } + if (resultTotalAdvance) { + *resultTotalAdvance = value->getTotalAdvance(start, count); } - resultTotalAdvance = value->getTotalAdvance(); } } diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h index 9d8913c..9df3829 100644 --- a/core/jni/android/graphics/TextLayout.h +++ b/core/jni/android/graphics/TextLayout.h @@ -71,7 +71,7 @@ public: static void getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start, jint count, jint contextCount, jint dirFlags, - jfloat* resultAdvances, jfloat& resultTotalAdvance); + jfloat* resultAdvances, jfloat* resultTotalAdvance); static void getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start, jint count, jint contextCount, jint dirFlags, diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index e4eeec8..c045c07 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -106,7 +106,7 @@ void TextLayoutCache::clear() { * Caching */ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, - const jchar* text, jint start, jint count, jint contextCount, jint dirFlags) { + const jchar* text, jint count, jint dirFlags) { AutoMutex _l(mLock); nsecs_t startTime = 0; if (mDebugEnabled) { @@ -114,7 +114,7 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, } // Create the key - TextLayoutCacheKey key(paint, text, start, count, contextCount, dirFlags); + TextLayoutCacheKey key(paint, text, count, dirFlags); // Get value from cache if possible sp<TextLayoutCacheValue> value = mCache.get(key); @@ -128,7 +128,7 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, value = new TextLayoutCacheValue(); // Compute advances and store them - value->computeValues(paint, text, start, count, contextCount, dirFlags); + value->computeValues(paint, text, count, dirFlags); nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC); @@ -157,20 +157,20 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, // Update timing information for statistics value->setElapsedTime(endTime - startTime); - LOGD("CACHE MISS: Added entry with start=%d, count=%d, " - "contextCount=%d, entry size %d bytes, remaining space %d bytes" + LOGD("CACHE MISS: Added entry with " + "count=%d, entry size %d bytes, remaining space %d bytes" " - Compute time in nanos: %d - Text='%s' ", - start, count, contextCount, size, mMaxSize - mSize, value->getElapsedTime(), - String8(text, contextCount).string()); + count, size, mMaxSize - mSize, value->getElapsedTime(), + String8(text, count).string()); } } else { if (mDebugEnabled) { LOGD("CACHE MISS: Calculated but not storing entry because it is too big " - "with start=%d, count=%d, contextCount=%d, " + "with count=%d, " "entry size %d bytes, remaining space %d bytes" " - Compute time in nanos: %lld - Text='%s'", - start, count, contextCount, size, mMaxSize - mSize, endTime, - String8(text, contextCount).string()); + count, size, mMaxSize - mSize, endTime, + String8(text, count).string()); } value.clear(); } @@ -184,12 +184,12 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint, if (value->getElapsedTime() > 0) { float deltaPercent = 100 * ((value->getElapsedTime() - elapsedTimeThruCacheGet) / ((float)value->getElapsedTime())); - LOGD("CACHE HIT #%d with start=%d, count=%d, contextCount=%d " + LOGD("CACHE HIT #%d with count=%d " "- Compute time in nanos: %d - " "Cache get time in nanos: %lld - Gain in percent: %2.2f - Text='%s' ", - mCacheHitCount, start, count, contextCount, + mCacheHitCount, count, value->getElapsedTime(), elapsedTimeThruCacheGet, deltaPercent, - String8(text, contextCount).string()); + String8(text, count).string()); } if (mCacheHitCount % DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL == 0) { dumpCacheStats(); @@ -218,15 +218,14 @@ void TextLayoutCache::dumpCacheStats() { /** * TextLayoutCacheKey */ -TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), start(0), count(0), contextCount(0), +TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), count(0), dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0), hinting(SkPaint::kNo_Hinting) { } TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, - const UChar* text, size_t start, size_t count, - size_t contextCount, int dirFlags) : - text(text), start(start), count(count), contextCount(contextCount), + const UChar* text, size_t count, int dirFlags) : + text(text), count(count), dirFlags(dirFlags) { typeface = paint->getTypeface(); textSize = paint->getTextSize(); @@ -239,9 +238,7 @@ TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) : text(NULL), textCopy(other.textCopy), - start(other.start), count(other.count), - contextCount(other.contextCount), dirFlags(other.dirFlags), typeface(other.typeface), textSize(other.textSize), @@ -256,18 +253,15 @@ TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) : bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const { LTE_INT(count) { - LTE_INT(contextCount) { - LTE_INT(start) { - LTE_INT(typeface) { - LTE_FLOAT(textSize) { - LTE_FLOAT(textSkewX) { - LTE_FLOAT(textScaleX) { - LTE_INT(flags) { - LTE_INT(hinting) { - LTE_INT(dirFlags) { - return strncmp16(getText(), rhs.getText(), contextCount) < 0; - } - } + LTE_INT(typeface) { + LTE_FLOAT(textSize) { + LTE_FLOAT(textSkewX) { + LTE_FLOAT(textScaleX) { + LTE_INT(flags) { + LTE_INT(hinting) { + LTE_INT(dirFlags) { + return memcmp(getText(), rhs.getText(), + count * sizeof(UChar)) < 0; } } } @@ -280,12 +274,12 @@ bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const { } void TextLayoutCacheKey::internalTextCopy() { - textCopy.setTo(text, contextCount); + textCopy.setTo(text, count); text = NULL; } size_t TextLayoutCacheKey::getSize() { - return sizeof(TextLayoutCacheKey) + sizeof(UChar) * contextCount; + return sizeof(TextLayoutCacheKey) + sizeof(UChar) * count; } /** @@ -303,23 +297,23 @@ uint32_t TextLayoutCacheValue::getElapsedTime() { return mElapsedTime; } -void TextLayoutCacheValue::computeValues(SkPaint* paint, const UChar* chars, size_t start, - size_t count, size_t contextCount, int dirFlags) { - // Give a hint for advances and glyphs vectors size - mAdvances.setCapacity(count); - mGlyphs.setCapacity(count); - computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, - &mAdvances, &mTotalAdvance, &mGlyphs); +void TextLayoutCacheValue::computeValues(SkPaint* paint, const UChar* chars, + size_t contextCount, int dirFlags) { + // Give a hint for advances, glyphs and log clusters vectors size + mAdvances.setCapacity(contextCount); + mGlyphs.setCapacity(contextCount); + mLogClusters.setCapacity(contextCount); + + computeValuesWithHarfbuzz(paint, chars, contextCount, dirFlags, + &mAdvances, &mTotalAdvance, &mGlyphs, &mLogClusters); #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, mTotalAdvance, - mAdvances[0], mAdvances[1], mAdvances[2], mAdvances[3]); + LOGD("Advances - countextCount=%d - totalAdvance=%f", contextCount, mTotalAdvance); #endif } size_t TextLayoutCacheValue::getSize() { return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * mAdvances.capacity() + - sizeof(jchar) * mGlyphs.capacity(); + sizeof(jchar) * mGlyphs.capacity() + sizeof(unsigned short) * mLogClusters.capacity(); } void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, @@ -391,9 +385,9 @@ void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontR } void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, - size_t start, size_t count, size_t contextCount, int dirFlags, + size_t contextCount, int dirFlags, Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, - Vector<jchar>* const outGlyphs) { + Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters) { UBiDiLevel bidiReq = 0; bool forceLTR = false; @@ -413,8 +407,8 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar LOGD("computeValuesWithHarfbuzz -- forcing run with LTR=%d RTL=%d", forceLTR, forceRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, forceRTL, - outAdvances, outTotalAdvance, outGlyphs); + computeRunValuesWithHarfbuzz(paint, chars, 0, contextCount, contextCount, forceRTL, + outAdvances, outTotalAdvance, outGlyphs, outLogClusters); } else { UBiDi* bidi = ubidi_open(); if (bidi) { @@ -433,35 +427,16 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar bool isRTL = (paraDir == 1); #if DEBUG_GLYPHS LOGD("computeValuesWithHarfbuzz -- processing SINGLE run " - "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL); + "-- run-start=%d run-len=%d isRTL=%d", 0, contextCount, isRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, - isRTL, outAdvances, outTotalAdvance, outGlyphs); + computeRunValuesWithHarfbuzz(paint, chars, 0, contextCount, contextCount, + isRTL, outAdvances, outTotalAdvance, outGlyphs, outLogClusters); } else { - int32_t end = start + count; for (size_t i = 0; i < rc; ++i) { int32_t startRun; int32_t lengthRun; UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun); - if (startRun >= end) { - break; - } - - int32_t endRun = startRun + lengthRun; - if (endRun <= start) { - continue; - } - - if (startRun < start) { - startRun = start; - } - if (endRun > end) { - endRun = end; - } - - lengthRun = endRun - startRun; - bool isRTL = (runDir == UBIDI_RTL); jfloat runTotalAdvance = 0; #if DEBUG_GLYPHS @@ -471,7 +446,7 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar computeRunValuesWithHarfbuzz(paint, chars, startRun, lengthRun, contextCount, isRTL, outAdvances, &runTotalAdvance, - outGlyphs); + outGlyphs, outLogClusters); *outTotalAdvance += runTotalAdvance; } @@ -483,10 +458,10 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar bool isRTL = (bidiReq = 1) || (bidiReq = UBIDI_DEFAULT_RTL); #if DEBUG_GLYPHS LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering a SINGLE Run " - "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL); + "-- run-start=%d run-len=%d isRTL=%d", 0, contextCount, isRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, isRTL, - outAdvances, outTotalAdvance, outGlyphs); + computeRunValuesWithHarfbuzz(paint, chars, 0, contextCount, contextCount, isRTL, + outAdvances, outTotalAdvance, outGlyphs, outLogClusters); } } #if DEBUG_GLYPHS @@ -506,7 +481,7 @@ static void logGlyphs(HB_ShaperItem shaperItem) { void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, bool isRTL, Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, - Vector<jchar>* const outGlyphs) { + Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters) { HB_ShaperItem shaperItem; HB_FontRec font; @@ -557,15 +532,15 @@ void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UC #if DEBUG_ADVANCES for (size_t i = 0; i < count; i++) { LOGD("hb-adv[%d] = %f - log_clusters = %d - total = %f", i, - outAdvances[i], shaperItem.log_clusters[i], totalAdvance); + (*outAdvances)[i], shaperItem.log_clusters[i], totalAdvance); } #endif // Get Glyphs and reverse them in place if RTL if (outGlyphs) { - size_t count = shaperItem.num_glyphs; - for (size_t i = 0; i < count; i++) { - jchar glyph = (jchar) shaperItem.glyphs[(!isRTL) ? i : count - 1 - i]; + size_t countGlyphs = shaperItem.num_glyphs; + for (size_t i = 0; i < countGlyphs; i++) { + jchar glyph = (jchar) shaperItem.glyphs[(!isRTL) ? i : countGlyphs - 1 - i]; #if DEBUG_GLYPHS LOGD("HARFBUZZ -- glyph[%d]=%d", i, glyph); #endif @@ -573,6 +548,20 @@ void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UC } } + // Get LogClusters + if (outLogClusters) { + size_t countLogClusters = outLogClusters->size(); + size_t countGlyphs = shaperItem.num_glyphs; + for (size_t i = 0; i < countGlyphs; i++) { + // As there may be successive runs, we need to shift the log clusters + unsigned short logCluster = shaperItem.log_clusters[i] + countLogClusters; +#if DEBUG_GLYPHS + LOGD("HARFBUZZ -- logCluster[%d] relative=%d - absolute=%d", i, shaperItem.log_clusters[i], logCluster); +#endif + outLogClusters->add(logCluster); + } + } + // Cleaning deleteGlyphArrays(&shaperItem); HB_FreeFace(shaperItem.face); @@ -603,5 +592,67 @@ void TextLayoutCacheValue::resetGlyphArrays(HB_ShaperItem* shaperItem) { memset(shaperItem->offsets, 0, size * sizeof(shaperItem->offsets[0])); } +void TextLayoutCacheValue::getAdvances(size_t start, size_t count, jfloat* outAdvances) const { + memcpy(outAdvances, mAdvances.array() + start, count * sizeof(jfloat)); +#if DEBUG_ADVANCES + LOGD("getAdvances - start=%d count=%d", start, count); + for (size_t i = 0; i < count; i++) { + LOGD(" adv[%d] = %f", i, outAdvances[i]); + } +#endif +} + +jfloat TextLayoutCacheValue::getTotalAdvance(size_t start, size_t count) const { + jfloat outTotalAdvance = 0; + for (size_t i = start; i < start + count; i++) { + outTotalAdvance += mAdvances[i]; + } +#if DEBUG_ADVANCES + LOGD("getTotalAdvance - start=%d count=%d - total=%f", start, count, outTotalAdvance); +#endif + return outTotalAdvance; +} + +void TextLayoutCacheValue::getGlyphsIndexAndCount(size_t start, size_t count, size_t* outStartIndex, + size_t* outGlyphsCount) const { + *outStartIndex = 0; + if (count == 0) { + *outGlyphsCount = 0; + return; + } + size_t endIndex = 0; + for(size_t i = 0; i < mGlyphs.size(); i++) { + if (mLogClusters[i] <= start) { + *outStartIndex = i; + endIndex = i; + continue; + } + if (mLogClusters[i] <= start + count) { + endIndex = i; + } + } + *outGlyphsCount = endIndex - *outStartIndex + 1; +#if DEBUG_GLYPHS + LOGD("getGlyphsIndexes - start=%d count=%d - startIndex=%d count=%d", start, count, + *outStartIndex, *outGlyphsCount); + for(size_t i = 0; i < mGlyphs.size(); i++) { + LOGD("getGlyphs - all - glyph[%d] = %d", i, mGlyphs[i]); + } + for(size_t i = 0; i < mGlyphs.size(); i++) { + LOGD("getGlyphs - all - logcl[%d] = %d", i, mLogClusters[i]); + } +#endif +} + +const jchar* TextLayoutCacheValue::getGlyphs(size_t startIndex, size_t count) { + const jchar* glyphs = mGlyphs.array() + startIndex; +#if DEBUG_GLYPHS + LOGD("getGlyphs - with startIndex = %d count = %d", startIndex, count); + for (size_t i = 0; i < count; i++) { + LOGD("getGlyphs - result - glyph[%d] = %d", i, glyphs[i]); + } +#endif + return glyphs; +} } // namespace android diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h index 1f08bda..35dd6fd 100644 --- a/core/jni/android/graphics/TextLayoutCache.h +++ b/core/jni/android/graphics/TextLayoutCache.h @@ -68,9 +68,7 @@ class TextLayoutCacheKey { public: TextLayoutCacheKey(); - TextLayoutCacheKey(const SkPaint* paint, - const UChar* text, size_t start, size_t count, - size_t contextCount, int dirFlags); + TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t count, int dirFlags); TextLayoutCacheKey(const TextLayoutCacheKey& other); @@ -90,9 +88,7 @@ public: private: const UChar* text; // if text is NULL, use textCopy String16 textCopy; - size_t start; size_t count; - size_t contextCount; int dirFlags; SkTypeface* typeface; SkScalar textSize; @@ -116,14 +112,13 @@ public: void setElapsedTime(uint32_t time); uint32_t getElapsedTime(); - void computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count, - size_t contextCount, int dirFlags); + void computeValues(SkPaint* paint, const UChar* chars, size_t contextCount, int dirFlags); - inline const jfloat* getAdvances() const { return mAdvances.array(); } - inline size_t getAdvancesCount() const { return mAdvances.size(); } - inline jfloat getTotalAdvance() const { return mTotalAdvance; } - inline const jchar* getGlyphs() const { return mGlyphs.array(); } - inline size_t getGlyphsCount() const { return mGlyphs.size(); } + void getAdvances(size_t start, size_t count, jfloat* outAdvances) const; + jfloat getTotalAdvance(size_t start, size_t count) const; + void getGlyphsIndexAndCount(size_t start, size_t count, size_t* outStartIndex, + size_t* outGlyphsCount) const; + const jchar* getGlyphs(size_t startIndex, size_t count); /** * Get the size of the Cache entry @@ -138,14 +133,10 @@ public: SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, bool isRTL); - static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, - size_t count, size_t contextCount, int dirFlags, + static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, + size_t contextCount, int dirFlags, Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, - Vector<jchar>* const outGlyphs); - - static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start, - size_t count, size_t contextCount, int dirFlags, - jfloat* outAdvances, jfloat* outTotalAdvance); + Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters); private: /** @@ -164,6 +155,11 @@ private: Vector<jchar> mGlyphs; /** + * Harfbuzz Log Clusters + */ + Vector<unsigned short> mLogClusters; + + /** * Time for computing the values (in milliseconds) */ uint32_t mElapsedTime; @@ -175,7 +171,7 @@ private: static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, bool isRTL, Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance, - Vector<jchar>* const outGlyphs); + Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters); }; // TextLayoutCacheValue /** @@ -199,8 +195,8 @@ public: */ void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc); - sp<TextLayoutCacheValue> getValue(SkPaint* paint, - const jchar* text, jint start, jint count, jint contextCount, jint dirFlags); + sp<TextLayoutCacheValue> getValue(SkPaint* paint, const jchar* text, jint count, + jint dirFlags); /** * Clear the cache diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 395e417..e542a47 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -477,19 +477,21 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count, #if RTL_USE_HARFBUZZ sp<TextLayoutCacheValue> value; #if USE_TEXT_LAYOUT_CACHE - value = TextLayoutCache::getInstance().getValue(paint, text, 0, count, count, flags); + value = TextLayoutCache::getInstance().getValue(paint, text, count, flags); if (value == NULL) { LOGE("Cannot get TextLayoutCache value"); return ; } #else value = new TextLayoutCacheValue(); - value->computeValues(paint, text, 0, count, count, flags); + value->computeValues(paint, text, count, flags); #endif - const jchar* glyphArray = value->getGlyphs(); - int glyphCount = value->getGlyphsCount(); - int bytesCount = glyphCount * sizeof(jchar); - renderer->drawText((const char*) glyphArray, bytesCount, glyphCount, x, y, paint); + size_t startIndex = 0; + size_t glyphsCount = 0; + value->getGlyphsIndexAndCount(0, count, &startIndex, &glyphsCount); + const jchar* glyphs = value->getGlyphs(startIndex, glyphsCount); + int bytesCount = glyphsCount * sizeof(jchar); + renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint); #else const jchar *workText; jchar* buffer = NULL; @@ -507,19 +509,21 @@ static void renderTextRun(OpenGLRenderer* renderer, const jchar* text, #if RTL_USE_HARFBUZZ sp<TextLayoutCacheValue> value; #if USE_TEXT_LAYOUT_CACHE - value = TextLayoutCache::getInstance().getValue(paint, text, start, count, contextCount, flags); + value = TextLayoutCache::getInstance().getValue(paint, text, contextCount, flags); if (value == NULL) { LOGE("Cannot get TextLayoutCache value"); return ; } #else value = new TextLayoutCacheValue(); - value->computeValues(paint, text, start, count, contextCount, flags); + value->computeValues(paint, text, contextCount, flags); #endif - const jchar* glyphArray = value->getGlyphs(); - int glyphCount = value->getGlyphsCount(); - int bytesCount = glyphCount * sizeof(jchar); - renderer->drawText((const char*) glyphArray, bytesCount, glyphCount, x, y, paint); + size_t startIndex = 0; + size_t glyphsCount = 0; + value->getGlyphsIndexAndCount(start, count, &startIndex, &glyphsCount); + const jchar* glyphs = value->getGlyphs(startIndex, glyphsCount); + int bytesCount = glyphsCount * sizeof(jchar); + renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint); #else uint8_t rtl = flags & 0x1; if (rtl) { |