diff options
author | Fabrice Di Meglio <fdimeglio@google.com> | 2011-09-14 12:10:00 -0700 |
---|---|---|
committer | Fabrice Di Meglio <fdimeglio@google.com> | 2011-09-16 13:47:34 -0700 |
commit | d686d76814f18061e06995df0d5de9feb9f70a7e (patch) | |
tree | c8ab59b81d7fe718c79a23fb5744a1a32ebb74d2 /core/jni/android/graphics/TextLayout.cpp | |
parent | fd4d90b8204d9a4e2ab8ce4974019b8d81287ad8 (diff) | |
download | frameworks_base-d686d76814f18061e06995df0d5de9feb9f70a7e.zip frameworks_base-d686d76814f18061e06995df0d5de9feb9f70a7e.tar.gz frameworks_base-d686d76814f18061e06995df0d5de9feb9f70a7e.tar.bz2 |
Fix bug #5332081 TextLayoutCache needs to be able to have more cache hits
- makes TextLayoutCache not carring about start/count. Basically he will cache the result for
the full string and gives back the "chunk" corresponding to start/count
- changed the TextLayoutCacheValue API to take start/count parameters
- added the Harfbuzz LogClusters in TextLayoutCacheValue as it is needed for extracting the start/count "chunk"
- fix potential issue of cache key leaking
Change-Id: I9276f9bec744e8de36349acfba8429f7c6f83394
Diffstat (limited to 'core/jni/android/graphics/TextLayout.cpp')
-rw-r--r-- | core/jni/android/graphics/TextLayout.cpp | 90 |
1 files changed, 80 insertions, 10 deletions
diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp index fa9a7b7..97a3cde 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)); + if (resultAdvances) { + value->getAdvances(start, count, resultAdvances); + } + if (resultTotalAdvance) { + *resultTotalAdvance = value->getTotalAdvance(start, count); } - resultTotalAdvance = value->getTotalAdvance(); } } @@ -275,18 +276,87 @@ 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::computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, - dirFlags, resultAdvances, &resultTotalAdvance, NULL, NULL); + TextLayoutCacheValue::computeValuesWithHarfbuzz(paint, chars, contextCount, + dirFlags, resultAdvances, &resultTotalAdvance, NULL, NULL, NULL); } void TextLayout::getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start, jint count, jint contextCount, jint dirFlags, jfloat* resultAdvances, jfloat& resultTotalAdvance) { // Compute advances and return them - TextLayoutCacheValue::computeAdvancesWithICU(paint, chars, start, count, contextCount, dirFlags, + computeAdvancesWithICU(paint, chars, start, count, contextCount, dirFlags, resultAdvances, &resultTotalAdvance); } +void TextLayout::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 + // for now we just use ushape.c + size_t widths; + const jchar* text; + if (dirFlags & 0x1) { // rtl, call arabic shaping in case + UErrorCode status = U_ZERO_ERROR; + // Use fixed length since we need to keep start and count valid + u_shapeArabic(chars, contextCount, buffer, contextCount, + U_SHAPE_LENGTH_FIXED_SPACES_NEAR | + U_SHAPE_TEXT_DIRECTION_LOGICAL | U_SHAPE_LETTERS_SHAPE | + U_SHAPE_X_LAMALEF_SUB_ALTERNATE, &status); + // we shouldn't fail unless there's an out of memory condition, + // in which case we're hosed anyway + for (int i = start, e = i + count; i < e; ++i) { + if (buffer[i] == UNICODE_NOT_A_CHAR) { + buffer[i] = UNICODE_ZWSP; // zero-width-space for skia + } + } + text = buffer + start; + widths = paint->getTextWidths(text, count << 1, scalarArray); + } else { + text = chars + start; + widths = paint->getTextWidths(text, count << 1, scalarArray); + } + + jfloat totalAdvance = 0; + if (widths < count) { +#if DEBUG_ADVANCES + LOGD("ICU -- count=%d", widths); +#endif + // Skia operates on code points, not code units, so surrogate pairs return only + // one value. Expand the result so we have one value per UTF-16 code unit. + + // Note, skia's getTextWidth gets confused if it encounters a surrogate pair, + // leaving the remaining widths zero. Not nice. + for (size_t i = 0, p = 0; i < widths; ++i) { + totalAdvance += outAdvances[p++] = SkScalarToFloat(scalarArray[i]); + if (p < count && + text[p] >= UNICODE_FIRST_LOW_SURROGATE && + text[p] < UNICODE_FIRST_PRIVATE_USE && + text[p-1] >= UNICODE_FIRST_HIGH_SURROGATE && + text[p-1] < UNICODE_FIRST_LOW_SURROGATE) { + outAdvances[p++] = 0; + } +#if DEBUG_ADVANCES + LOGD("icu-adv = %f - total = %f", outAdvances[i], totalAdvance); +#endif + } + } else { +#if DEBUG_ADVANCES + LOGD("ICU -- count=%d", count); +#endif + for (size_t i = 0; i < count; i++) { + totalAdvance += outAdvances[i] = SkScalarToFloat(scalarArray[i]); +#if DEBUG_ADVANCES + LOGD("icu-adv = %f - total = %f", outAdvances[i], totalAdvance); +#endif + } + } + *outTotalAdvance = totalAdvance; +} + // Draws a paragraph of text on a single line, running bidi and shaping void TextLayout::drawText(SkPaint* paint, const jchar* text, jsize len, int bidiFlags, jfloat x, jfloat y, SkCanvas* canvas) { |