Introduce TextLine#measureAllbounds
This new method computes the horizontal character bounds by making
use of the character advances returned from native layer. It'll be
used in TextView to populate character bounds, and it's much efficent
compared to calling getPrimaryHorizontal for each character.
Bug: 233922052
Test: atest android.text.TextLineTest
Change-Id: Icdd53e61e2d1513b2231affb19bb00ea5d938d48
diff --git a/libs/hwui/jni/Paint.cpp b/libs/hwui/jni/Paint.cpp
index 0aa1465..ed453b1 100644
--- a/libs/hwui/jni/Paint.cpp
+++ b/libs/hwui/jni/Paint.cpp
@@ -497,16 +497,29 @@
return true;
}
- static jfloat doRunAdvance(const Paint* paint, const Typeface* typeface, const jchar buf[],
- jint start, jint count, jint bufSize, jboolean isRtl, jint offset) {
+ static jfloat doRunAdvance(JNIEnv* env, const Paint* paint, const Typeface* typeface,
+ const jchar buf[], jint start, jint count, jint bufSize,
+ jboolean isRtl, jint offset, jfloatArray advances,
+ jint advancesIndex) {
+ if (advances) {
+ size_t advancesLength = env->GetArrayLength(advances);
+ if ((size_t)(count + advancesIndex) > advancesLength) {
+ doThrowAIOOBE(env);
+ return 0;
+ }
+ }
minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
- if (offset == start + count) {
+ if (offset == start + count && advances == nullptr) {
return MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count,
bufSize, nullptr);
}
std::unique_ptr<float[]> advancesArray(new float[count]);
MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count, bufSize,
advancesArray.get());
+
+ if (advances) {
+ env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray.get());
+ }
return minikin::getRunAdvance(advancesArray.get(), buf, start, count, offset);
}
@@ -515,9 +528,23 @@
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
const Typeface* typeface = paint->getAndroidTypeface();
ScopedCharArrayRO textArray(env, text);
- jfloat result = doRunAdvance(paint, typeface, textArray.get() + contextStart,
- start - contextStart, end - start, contextEnd - contextStart, isRtl,
- offset - contextStart);
+ jfloat result = doRunAdvance(env, paint, typeface, textArray.get() + contextStart,
+ start - contextStart, end - start, contextEnd - contextStart,
+ isRtl, offset - contextStart, nullptr, 0);
+ return result;
+ }
+
+ static jfloat getRunCharacterAdvance___CIIIIZI_FI_F(JNIEnv* env, jclass, jlong paintHandle,
+ jcharArray text, jint start, jint end,
+ jint contextStart, jint contextEnd,
+ jboolean isRtl, jint offset,
+ jfloatArray advances, jint advancesIndex) {
+ const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+ const Typeface* typeface = paint->getAndroidTypeface();
+ ScopedCharArrayRO textArray(env, text);
+ jfloat result = doRunAdvance(env, paint, typeface, textArray.get() + contextStart,
+ start - contextStart, end - start, contextEnd - contextStart,
+ isRtl, offset - contextStart, advances, advancesIndex);
return result;
}
@@ -1034,113 +1061,112 @@
}; // namespace PaintGlue
static const JNINativeMethod methods[] = {
- {"nGetNativeFinalizer", "()J", (void*) PaintGlue::getNativeFinalizer},
- {"nInit","()J", (void*) PaintGlue::init},
- {"nInitWithPaint","(J)J", (void*) PaintGlue::initWithPaint},
- {"nBreakText","(J[CIIFI[F)I", (void*) PaintGlue::breakTextC},
- {"nBreakText","(JLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS},
- {"nGetTextAdvances","(J[CIIIII[FI)F",
- (void*) PaintGlue::getTextAdvances___CIIIII_FI},
- {"nGetTextAdvances","(JLjava/lang/String;IIIII[FI)F",
- (void*) PaintGlue::getTextAdvances__StringIIIII_FI},
+ {"nGetNativeFinalizer", "()J", (void*)PaintGlue::getNativeFinalizer},
+ {"nInit", "()J", (void*)PaintGlue::init},
+ {"nInitWithPaint", "(J)J", (void*)PaintGlue::initWithPaint},
+ {"nBreakText", "(J[CIIFI[F)I", (void*)PaintGlue::breakTextC},
+ {"nBreakText", "(JLjava/lang/String;ZFI[F)I", (void*)PaintGlue::breakTextS},
+ {"nGetTextAdvances", "(J[CIIIII[FI)F", (void*)PaintGlue::getTextAdvances___CIIIII_FI},
+ {"nGetTextAdvances", "(JLjava/lang/String;IIIII[FI)F",
+ (void*)PaintGlue::getTextAdvances__StringIIIII_FI},
- {"nGetTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C},
- {"nGetTextRunCursor", "(JLjava/lang/String;IIIII)I",
- (void*) PaintGlue::getTextRunCursor__String},
- {"nGetTextPath", "(JI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C},
- {"nGetTextPath", "(JILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String},
- {"nGetStringBounds", "(JLjava/lang/String;IIILandroid/graphics/Rect;)V",
- (void*) PaintGlue::getStringBounds },
- {"nGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
- (void*) PaintGlue::getCharArrayBounds },
- {"nHasGlyph", "(JILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },
- {"nGetRunAdvance", "(J[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F},
- {"nGetOffsetForAdvance", "(J[CIIIIZF)I",
- (void*) PaintGlue::getOffsetForAdvance___CIIIIZF_I},
- {"nGetFontMetricsIntForText", "(J[CIIIIZLandroid/graphics/Paint$FontMetricsInt;)V",
- (void*)PaintGlue::getFontMetricsIntForText___C},
- {"nGetFontMetricsIntForText",
- "(JLjava/lang/String;IIIIZLandroid/graphics/Paint$FontMetricsInt;)V",
- (void*)PaintGlue::getFontMetricsIntForText___String},
+ {"nGetTextRunCursor", "(J[CIIIII)I", (void*)PaintGlue::getTextRunCursor___C},
+ {"nGetTextRunCursor", "(JLjava/lang/String;IIIII)I",
+ (void*)PaintGlue::getTextRunCursor__String},
+ {"nGetTextPath", "(JI[CIIFFJ)V", (void*)PaintGlue::getTextPath___C},
+ {"nGetTextPath", "(JILjava/lang/String;IIFFJ)V", (void*)PaintGlue::getTextPath__String},
+ {"nGetStringBounds", "(JLjava/lang/String;IIILandroid/graphics/Rect;)V",
+ (void*)PaintGlue::getStringBounds},
+ {"nGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
+ (void*)PaintGlue::getCharArrayBounds},
+ {"nHasGlyph", "(JILjava/lang/String;)Z", (void*)PaintGlue::hasGlyph},
+ {"nGetRunAdvance", "(J[CIIIIZI)F", (void*)PaintGlue::getRunAdvance___CIIIIZI_F},
+ {"nGetRunCharacterAdvance", "(J[CIIIIZI[FI)F",
+ (void*)PaintGlue::getRunCharacterAdvance___CIIIIZI_FI_F},
+ {"nGetOffsetForAdvance", "(J[CIIIIZF)I", (void*)PaintGlue::getOffsetForAdvance___CIIIIZF_I},
+ {"nGetFontMetricsIntForText", "(J[CIIIIZLandroid/graphics/Paint$FontMetricsInt;)V",
+ (void*)PaintGlue::getFontMetricsIntForText___C},
+ {"nGetFontMetricsIntForText",
+ "(JLjava/lang/String;IIIIZLandroid/graphics/Paint$FontMetricsInt;)V",
+ (void*)PaintGlue::getFontMetricsIntForText___String},
- // --------------- @FastNative ----------------------
+ // --------------- @FastNative ----------------------
- {"nSetTextLocales","(JLjava/lang/String;)I", (void*) PaintGlue::setTextLocales},
- {"nSetFontFeatureSettings","(JLjava/lang/String;)V",
- (void*) PaintGlue::setFontFeatureSettings},
- {"nGetFontMetrics", "(JLandroid/graphics/Paint$FontMetrics;)F",
- (void*)PaintGlue::getFontMetrics},
- {"nGetFontMetricsInt", "(JLandroid/graphics/Paint$FontMetricsInt;)I",
- (void*)PaintGlue::getFontMetricsInt},
+ {"nSetTextLocales", "(JLjava/lang/String;)I", (void*)PaintGlue::setTextLocales},
+ {"nSetFontFeatureSettings", "(JLjava/lang/String;)V",
+ (void*)PaintGlue::setFontFeatureSettings},
+ {"nGetFontMetrics", "(JLandroid/graphics/Paint$FontMetrics;)F",
+ (void*)PaintGlue::getFontMetrics},
+ {"nGetFontMetricsInt", "(JLandroid/graphics/Paint$FontMetricsInt;)I",
+ (void*)PaintGlue::getFontMetricsInt},
- // --------------- @CriticalNative ------------------
+ // --------------- @CriticalNative ------------------
- {"nReset","(J)V", (void*) PaintGlue::reset},
- {"nSet","(JJ)V", (void*) PaintGlue::assign},
- {"nGetFlags","(J)I", (void*) PaintGlue::getFlags},
- {"nSetFlags","(JI)V", (void*) PaintGlue::setFlags},
- {"nGetHinting","(J)I", (void*) PaintGlue::getHinting},
- {"nSetHinting","(JI)V", (void*) PaintGlue::setHinting},
- {"nSetAntiAlias","(JZ)V", (void*) PaintGlue::setAntiAlias},
- {"nSetSubpixelText","(JZ)V", (void*) PaintGlue::setSubpixelText},
- {"nSetLinearText","(JZ)V", (void*) PaintGlue::setLinearText},
- {"nSetUnderlineText","(JZ)V", (void*) PaintGlue::setUnderlineText},
- {"nSetStrikeThruText","(JZ)V", (void*) PaintGlue::setStrikeThruText},
- {"nSetFakeBoldText","(JZ)V", (void*) PaintGlue::setFakeBoldText},
- {"nSetFilterBitmap","(JZ)V", (void*) PaintGlue::setFilterBitmap},
- {"nSetDither","(JZ)V", (void*) PaintGlue::setDither},
- {"nGetStyle","(J)I", (void*) PaintGlue::getStyle},
- {"nSetStyle","(JI)V", (void*) PaintGlue::setStyle},
- {"nSetColor","(JI)V", (void*) PaintGlue::setColor},
- {"nSetColor","(JJJ)V", (void*) PaintGlue::setColorLong},
- {"nSetAlpha","(JI)V", (void*) PaintGlue::setAlpha},
- {"nGetStrokeWidth","(J)F", (void*) PaintGlue::getStrokeWidth},
- {"nSetStrokeWidth","(JF)V", (void*) PaintGlue::setStrokeWidth},
- {"nGetStrokeMiter","(J)F", (void*) PaintGlue::getStrokeMiter},
- {"nSetStrokeMiter","(JF)V", (void*) PaintGlue::setStrokeMiter},
- {"nGetStrokeCap","(J)I", (void*) PaintGlue::getStrokeCap},
- {"nSetStrokeCap","(JI)V", (void*) PaintGlue::setStrokeCap},
- {"nGetStrokeJoin","(J)I", (void*) PaintGlue::getStrokeJoin},
- {"nSetStrokeJoin","(JI)V", (void*) PaintGlue::setStrokeJoin},
- {"nGetFillPath","(JJJ)Z", (void*) PaintGlue::getFillPath},
- {"nSetShader","(JJ)J", (void*) PaintGlue::setShader},
- {"nSetColorFilter","(JJ)J", (void*) PaintGlue::setColorFilter},
- {"nSetXfermode","(JI)V", (void*) PaintGlue::setXfermode},
- {"nSetPathEffect","(JJ)J", (void*) PaintGlue::setPathEffect},
- {"nSetMaskFilter","(JJ)J", (void*) PaintGlue::setMaskFilter},
- {"nSetTypeface","(JJ)V", (void*) PaintGlue::setTypeface},
- {"nGetTextAlign","(J)I", (void*) PaintGlue::getTextAlign},
- {"nSetTextAlign","(JI)V", (void*) PaintGlue::setTextAlign},
- {"nSetTextLocalesByMinikinLocaleListId","(JI)V",
- (void*) PaintGlue::setTextLocalesByMinikinLocaleListId},
- {"nIsElegantTextHeight","(J)Z", (void*) PaintGlue::isElegantTextHeight},
- {"nSetElegantTextHeight","(JZ)V", (void*) PaintGlue::setElegantTextHeight},
- {"nGetTextSize","(J)F", (void*) PaintGlue::getTextSize},
- {"nSetTextSize","(JF)V", (void*) PaintGlue::setTextSize},
- {"nGetTextScaleX","(J)F", (void*) PaintGlue::getTextScaleX},
- {"nSetTextScaleX","(JF)V", (void*) PaintGlue::setTextScaleX},
- {"nGetTextSkewX","(J)F", (void*) PaintGlue::getTextSkewX},
- {"nSetTextSkewX","(JF)V", (void*) PaintGlue::setTextSkewX},
- {"nGetLetterSpacing","(J)F", (void*) PaintGlue::getLetterSpacing},
- {"nSetLetterSpacing","(JF)V", (void*) PaintGlue::setLetterSpacing},
- {"nGetWordSpacing","(J)F", (void*) PaintGlue::getWordSpacing},
- {"nSetWordSpacing","(JF)V", (void*) PaintGlue::setWordSpacing},
- {"nGetStartHyphenEdit", "(J)I", (void*) PaintGlue::getStartHyphenEdit},
- {"nGetEndHyphenEdit", "(J)I", (void*) PaintGlue::getEndHyphenEdit},
- {"nSetStartHyphenEdit", "(JI)V", (void*) PaintGlue::setStartHyphenEdit},
- {"nSetEndHyphenEdit", "(JI)V", (void*) PaintGlue::setEndHyphenEdit},
- {"nAscent","(J)F", (void*) PaintGlue::ascent},
- {"nDescent","(J)F", (void*) PaintGlue::descent},
- {"nGetUnderlinePosition","(J)F", (void*) PaintGlue::getUnderlinePosition},
- {"nGetUnderlineThickness","(J)F", (void*) PaintGlue::getUnderlineThickness},
- {"nGetStrikeThruPosition","(J)F", (void*) PaintGlue::getStrikeThruPosition},
- {"nGetStrikeThruThickness","(J)F", (void*) PaintGlue::getStrikeThruThickness},
- {"nSetShadowLayer", "(JFFFJJ)V", (void*)PaintGlue::setShadowLayer},
- {"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer},
- {"nEqualsForTextMeasurement", "(JJ)Z", (void*)PaintGlue::equalsForTextMeasurement},
+ {"nReset", "(J)V", (void*)PaintGlue::reset},
+ {"nSet", "(JJ)V", (void*)PaintGlue::assign},
+ {"nGetFlags", "(J)I", (void*)PaintGlue::getFlags},
+ {"nSetFlags", "(JI)V", (void*)PaintGlue::setFlags},
+ {"nGetHinting", "(J)I", (void*)PaintGlue::getHinting},
+ {"nSetHinting", "(JI)V", (void*)PaintGlue::setHinting},
+ {"nSetAntiAlias", "(JZ)V", (void*)PaintGlue::setAntiAlias},
+ {"nSetSubpixelText", "(JZ)V", (void*)PaintGlue::setSubpixelText},
+ {"nSetLinearText", "(JZ)V", (void*)PaintGlue::setLinearText},
+ {"nSetUnderlineText", "(JZ)V", (void*)PaintGlue::setUnderlineText},
+ {"nSetStrikeThruText", "(JZ)V", (void*)PaintGlue::setStrikeThruText},
+ {"nSetFakeBoldText", "(JZ)V", (void*)PaintGlue::setFakeBoldText},
+ {"nSetFilterBitmap", "(JZ)V", (void*)PaintGlue::setFilterBitmap},
+ {"nSetDither", "(JZ)V", (void*)PaintGlue::setDither},
+ {"nGetStyle", "(J)I", (void*)PaintGlue::getStyle},
+ {"nSetStyle", "(JI)V", (void*)PaintGlue::setStyle},
+ {"nSetColor", "(JI)V", (void*)PaintGlue::setColor},
+ {"nSetColor", "(JJJ)V", (void*)PaintGlue::setColorLong},
+ {"nSetAlpha", "(JI)V", (void*)PaintGlue::setAlpha},
+ {"nGetStrokeWidth", "(J)F", (void*)PaintGlue::getStrokeWidth},
+ {"nSetStrokeWidth", "(JF)V", (void*)PaintGlue::setStrokeWidth},
+ {"nGetStrokeMiter", "(J)F", (void*)PaintGlue::getStrokeMiter},
+ {"nSetStrokeMiter", "(JF)V", (void*)PaintGlue::setStrokeMiter},
+ {"nGetStrokeCap", "(J)I", (void*)PaintGlue::getStrokeCap},
+ {"nSetStrokeCap", "(JI)V", (void*)PaintGlue::setStrokeCap},
+ {"nGetStrokeJoin", "(J)I", (void*)PaintGlue::getStrokeJoin},
+ {"nSetStrokeJoin", "(JI)V", (void*)PaintGlue::setStrokeJoin},
+ {"nGetFillPath", "(JJJ)Z", (void*)PaintGlue::getFillPath},
+ {"nSetShader", "(JJ)J", (void*)PaintGlue::setShader},
+ {"nSetColorFilter", "(JJ)J", (void*)PaintGlue::setColorFilter},
+ {"nSetXfermode", "(JI)V", (void*)PaintGlue::setXfermode},
+ {"nSetPathEffect", "(JJ)J", (void*)PaintGlue::setPathEffect},
+ {"nSetMaskFilter", "(JJ)J", (void*)PaintGlue::setMaskFilter},
+ {"nSetTypeface", "(JJ)V", (void*)PaintGlue::setTypeface},
+ {"nGetTextAlign", "(J)I", (void*)PaintGlue::getTextAlign},
+ {"nSetTextAlign", "(JI)V", (void*)PaintGlue::setTextAlign},
+ {"nSetTextLocalesByMinikinLocaleListId", "(JI)V",
+ (void*)PaintGlue::setTextLocalesByMinikinLocaleListId},
+ {"nIsElegantTextHeight", "(J)Z", (void*)PaintGlue::isElegantTextHeight},
+ {"nSetElegantTextHeight", "(JZ)V", (void*)PaintGlue::setElegantTextHeight},
+ {"nGetTextSize", "(J)F", (void*)PaintGlue::getTextSize},
+ {"nSetTextSize", "(JF)V", (void*)PaintGlue::setTextSize},
+ {"nGetTextScaleX", "(J)F", (void*)PaintGlue::getTextScaleX},
+ {"nSetTextScaleX", "(JF)V", (void*)PaintGlue::setTextScaleX},
+ {"nGetTextSkewX", "(J)F", (void*)PaintGlue::getTextSkewX},
+ {"nSetTextSkewX", "(JF)V", (void*)PaintGlue::setTextSkewX},
+ {"nGetLetterSpacing", "(J)F", (void*)PaintGlue::getLetterSpacing},
+ {"nSetLetterSpacing", "(JF)V", (void*)PaintGlue::setLetterSpacing},
+ {"nGetWordSpacing", "(J)F", (void*)PaintGlue::getWordSpacing},
+ {"nSetWordSpacing", "(JF)V", (void*)PaintGlue::setWordSpacing},
+ {"nGetStartHyphenEdit", "(J)I", (void*)PaintGlue::getStartHyphenEdit},
+ {"nGetEndHyphenEdit", "(J)I", (void*)PaintGlue::getEndHyphenEdit},
+ {"nSetStartHyphenEdit", "(JI)V", (void*)PaintGlue::setStartHyphenEdit},
+ {"nSetEndHyphenEdit", "(JI)V", (void*)PaintGlue::setEndHyphenEdit},
+ {"nAscent", "(J)F", (void*)PaintGlue::ascent},
+ {"nDescent", "(J)F", (void*)PaintGlue::descent},
+ {"nGetUnderlinePosition", "(J)F", (void*)PaintGlue::getUnderlinePosition},
+ {"nGetUnderlineThickness", "(J)F", (void*)PaintGlue::getUnderlineThickness},
+ {"nGetStrikeThruPosition", "(J)F", (void*)PaintGlue::getStrikeThruPosition},
+ {"nGetStrikeThruThickness", "(J)F", (void*)PaintGlue::getStrikeThruThickness},
+ {"nSetShadowLayer", "(JFFFJJ)V", (void*)PaintGlue::setShadowLayer},
+ {"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer},
+ {"nEqualsForTextMeasurement", "(JJ)Z", (void*)PaintGlue::equalsForTextMeasurement},
};
-
int register_android_graphics_Paint(JNIEnv* env) {
return RegisterMethodsOrDie(env, "android/graphics/Paint", methods, NELEM(methods));
}