Loading core/jni/android/graphics/Canvas.cpp +8 −21 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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, Loading core/jni/android/graphics/Paint.cpp +6 −9 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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)); Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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]; Loading core/jni/android/graphics/TextLayout.cpp +7 −6 Original line number Diff line number Diff line Loading @@ -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(); } } Loading core/jni/android/graphics/TextLayout.h +1 −1 Original line number Diff line number Diff line Loading @@ -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, Loading core/jni/android/graphics/TextLayoutCache.cpp +130 −79 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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); Loading @@ -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); Loading Loading @@ -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(); } Loading @@ -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(); Loading Loading @@ -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(); Loading @@ -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), Loading @@ -256,8 +253,6 @@ 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) { Loading @@ -265,9 +260,8 @@ bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const { LTE_INT(flags) { LTE_INT(hinting) { LTE_INT(dirFlags) { return strncmp16(getText(), rhs.getText(), contextCount) < 0; } } return memcmp(getText(), rhs.getText(), count * sizeof(UChar)) < 0; } } } Loading @@ -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; } /** Loading @@ -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, Loading Loading @@ -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; Loading @@ -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) { Loading @@ -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 Loading @@ -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; } Loading @@ -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 Loading @@ -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; Loading Loading @@ -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 Loading @@ -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); Loading Loading @@ -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 Loading
core/jni/android/graphics/Canvas.cpp +8 −21 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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, Loading
core/jni/android/graphics/Paint.cpp +6 −9 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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)); Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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]; Loading
core/jni/android/graphics/TextLayout.cpp +7 −6 Original line number Diff line number Diff line Loading @@ -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(); } } Loading
core/jni/android/graphics/TextLayout.h +1 −1 Original line number Diff line number Diff line Loading @@ -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, Loading
core/jni/android/graphics/TextLayoutCache.cpp +130 −79 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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); Loading @@ -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); Loading Loading @@ -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(); } Loading @@ -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(); Loading Loading @@ -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(); Loading @@ -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), Loading @@ -256,8 +253,6 @@ 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) { Loading @@ -265,9 +260,8 @@ bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const { LTE_INT(flags) { LTE_INT(hinting) { LTE_INT(dirFlags) { return strncmp16(getText(), rhs.getText(), contextCount) < 0; } } return memcmp(getText(), rhs.getText(), count * sizeof(UChar)) < 0; } } } Loading @@ -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; } /** Loading @@ -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, Loading Loading @@ -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; Loading @@ -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) { Loading @@ -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 Loading @@ -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; } Loading @@ -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 Loading @@ -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; Loading Loading @@ -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 Loading @@ -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); Loading Loading @@ -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