summaryrefslogtreecommitdiffstats
path: root/core/jni/android/graphics/TextLayout.cpp
diff options
context:
space:
mode:
authorFabrice Di Meglio <fdimeglio@google.com>2011-09-14 12:10:00 -0700
committerFabrice Di Meglio <fdimeglio@google.com>2011-09-16 13:47:34 -0700
commitd686d76814f18061e06995df0d5de9feb9f70a7e (patch)
treec8ab59b81d7fe718c79a23fb5744a1a32ebb74d2 /core/jni/android/graphics/TextLayout.cpp
parentfd4d90b8204d9a4e2ab8ce4974019b8d81287ad8 (diff)
downloadframeworks_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.cpp90
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) {