Merge "Consolidate native methods for text measurement."

This commit is contained in:
Keisuke Kuroyanagi
2015-09-29 21:31:56 +00:00
committed by Android (Google) Code Review
2 changed files with 70 additions and 218 deletions

View File

@@ -44,6 +44,7 @@
#include "TypefaceImpl.h"
#include <vector>
#include <memory>
// temporary for debugging
#include <Caches.h>
@@ -569,137 +570,9 @@ public:
return descent - ascent + leading;
}
static jfloat measureText_CIII(JNIEnv* env, jobject jpaint, jcharArray text, jint index, jint count,
jint bidiFlags) {
NPE_CHECK_RETURN_ZERO(env, jpaint);
NPE_CHECK_RETURN_ZERO(env, text);
size_t textLength = env->GetArrayLength(text);
if ((index | count) < 0 || (size_t)(index + count) > textLength) {
doThrowAIOOBE(env);
return 0;
}
if (count == 0) {
return 0;
}
Paint* paint = getNativePaint(env, jpaint);
const jchar* textArray = env->GetCharArrayElements(text, NULL);
jfloat result = 0;
Layout layout;
TypefaceImpl* typeface = getNativeTypeface(env, jpaint);
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray + index, 0, count,
count);
result = layout.getAdvance();
env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
return result;
}
static jfloat measureText_StringIII(JNIEnv* env, jobject jpaint, jstring text, jint start, jint end,
jint bidiFlags) {
NPE_CHECK_RETURN_ZERO(env, jpaint);
NPE_CHECK_RETURN_ZERO(env, text);
size_t textLength = env->GetStringLength(text);
int count = end - start;
if ((start | count) < 0 || (size_t)end > textLength) {
doThrowAIOOBE(env);
return 0;
}
if (count == 0) {
return 0;
}
const jchar* textArray = env->GetStringChars(text, NULL);
Paint* paint = getNativePaint(env, jpaint);
jfloat width = 0;
Layout layout;
TypefaceImpl* typeface = getNativeTypeface(env, jpaint);
// Only the substring is used for measurement, so no additional context is passed in. This
// behavior is consistent between char[] and String specializations.
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray + start, 0, count, count);
width = layout.getAdvance();
env->ReleaseStringChars(text, textArray);
return width;
}
static jfloat measureText_StringI(JNIEnv* env, jobject jpaint, jstring text, jint bidiFlags) {
NPE_CHECK_RETURN_ZERO(env, jpaint);
NPE_CHECK_RETURN_ZERO(env, text);
size_t textLength = env->GetStringLength(text);
if (textLength == 0) {
return 0;
}
const jchar* textArray = env->GetStringChars(text, NULL);
Paint* paint = getNativePaint(env, jpaint);
jfloat width = 0;
Layout layout;
TypefaceImpl* typeface = getNativeTypeface(env, jpaint);
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray, 0, textLength, textLength);
width = layout.getAdvance();
env->ReleaseStringChars(text, textArray);
return width;
}
static int dotextwidths(JNIEnv* env, Paint* paint, TypefaceImpl* typeface, const jchar text[], int count,
jfloatArray widths, jint bidiFlags) {
NPE_CHECK_RETURN_ZERO(env, paint);
NPE_CHECK_RETURN_ZERO(env, text);
if (count < 0 || !widths) {
doThrowAIOOBE(env);
return 0;
}
if (count == 0) {
return 0;
}
size_t widthsLength = env->GetArrayLength(widths);
if ((size_t)count > widthsLength) {
doThrowAIOOBE(env);
return 0;
}
AutoJavaFloatArray autoWidths(env, widths, count);
jfloat* widthsArray = autoWidths.ptr();
Layout layout;
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
layout.getAdvances(widthsArray);
return count;
}
static jint getTextWidths___CIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jcharArray text,
jint index, jint count, jint bidiFlags, jfloatArray widths) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
const jchar* textArray = env->GetCharArrayElements(text, NULL);
count = dotextwidths(env, paint, typeface, textArray + index, count, widths, bidiFlags);
env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
JNI_ABORT);
return count;
}
static jint getTextWidths__StringIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring text,
jint start, jint end, jint bidiFlags, jfloatArray widths) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
int count = dotextwidths(env, paint, typeface, textArray + start, end - start, widths, bidiFlags);
env->ReleaseStringChars(text, textArray);
return count;
}
static jfloat doTextRunAdvances(JNIEnv *env, Paint *paint, TypefaceImpl* typeface, const jchar *text,
jint start, jint count, jint contextCount, jboolean isRtl,
jfloatArray advances, jint advancesIndex) {
static jfloat doTextAdvances(JNIEnv *env, Paint *paint, TypefaceImpl* typeface,
const jchar *text, jint start, jint count, jint contextCount, jint bidiFlags,
jfloatArray advances, jint advancesIndex) {
NPE_CHECK_RETURN_ZERO(env, paint);
NPE_CHECK_RETURN_ZERO(env, text);
@@ -712,50 +585,45 @@ public:
}
if (advances) {
size_t advancesLength = env->GetArrayLength(advances);
if ((size_t)count > advancesLength) {
if ((size_t)(count + advancesIndex) > advancesLength) {
doThrowAIOOBE(env);
return 0;
}
}
jfloat* advancesArray = new jfloat[count];
jfloat totalAdvance = 0;
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
Layout layout;
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count, contextCount);
layout.getAdvances(advancesArray);
totalAdvance = layout.getAdvance();
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count,
contextCount);
if (advances != NULL) {
env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
std::unique_ptr<jfloat> advancesArray(new jfloat[count]);
layout.getAdvances(advancesArray.get());
env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray.get());
}
delete [] advancesArray;
return totalAdvance;
return layout.getAdvance();
}
static jfloat getTextRunAdvances___CIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
static jfloat getTextAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
jlong typefaceHandle,
jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
jboolean isRtl, jfloatArray advances, jint advancesIndex) {
jint bidiFlags, jfloatArray advances, jint advancesIndex) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
jchar* textArray = env->GetCharArrayElements(text, NULL);
jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextIndex,
index - contextIndex, count, contextCount, isRtl, advances, advancesIndex);
jfloat result = doTextAdvances(env, paint, typeface, textArray + contextIndex,
index - contextIndex, count, contextCount, bidiFlags, advances, advancesIndex);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
return result;
}
static jfloat getTextRunAdvances__StringIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
static jfloat getTextAdvances__StringIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
jlong typefaceHandle,
jstring text, jint start, jint end, jint contextStart, jint contextEnd, jboolean isRtl,
jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint bidiFlags,
jfloatArray advances, jint advancesIndex) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextStart,
start - contextStart, end - start, contextEnd - contextStart, isRtl,
jfloat result = doTextAdvances(env, paint, typeface, textArray + contextStart,
start - contextStart, end - start, contextEnd - contextStart, bidiFlags,
advances, advancesIndex);
env->ReleaseStringChars(text, textArray);
return result;
@@ -1160,18 +1028,13 @@ static const JNINativeMethod methods[] = {
(void*)PaintGlue::getFontMetrics},
{"getFontMetricsInt", "!(Landroid/graphics/Paint$FontMetricsInt;)I",
(void*)PaintGlue::getFontMetricsInt},
{"native_measureText","([CIII)F", (void*) PaintGlue::measureText_CIII},
{"native_measureText","(Ljava/lang/String;I)F", (void*) PaintGlue::measureText_StringI},
{"native_measureText","(Ljava/lang/String;III)F", (void*) PaintGlue::measureText_StringIII},
{"native_breakText","(JJ[CIIFI[F)I", (void*) PaintGlue::breakTextC},
{"native_breakText","(JJLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS},
{"native_getTextWidths","(JJ[CIII[F)I", (void*) PaintGlue::getTextWidths___CIII_F},
{"native_getTextWidths","(JJLjava/lang/String;III[F)I",
(void*) PaintGlue::getTextWidths__StringIII_F},
{"native_getTextRunAdvances","(JJ[CIIIIZ[FI)F",
(void*) PaintGlue::getTextRunAdvances___CIIIIZ_FI},
{"native_getTextRunAdvances","(JJLjava/lang/String;IIIIZ[FI)F",
(void*) PaintGlue::getTextRunAdvances__StringIIIIZ_FI},
{"native_getTextAdvances","(JJ[CIIIII[FI)F",
(void*) PaintGlue::getTextAdvances___CIIIII_FI},
{"native_getTextAdvances","(JJLjava/lang/String;IIIII[FI)F",
(void*) PaintGlue::getTextAdvances__StringIIIII_FI},
{"native_getTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C},
{"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I",

View File

@@ -1526,18 +1526,18 @@ public class Paint {
return 0f;
}
if (!mHasCompatScaling) {
return (float) Math.ceil(native_measureText(text, index, count, mBidiFlags));
return (float) Math.ceil(native_getTextAdvances(mNativePaint, mNativeTypeface, text,
index, count, index, count, mBidiFlags, null, 0));
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
float w = native_measureText(text, index, count, mBidiFlags);
setTextSize(oldSize * mCompatScaling);
float w = native_getTextAdvances(mNativePaint, mNativeTypeface, text, index, count, index,
count, mBidiFlags, null, 0);
setTextSize(oldSize);
return (float) Math.ceil(w*mInvCompatScaling);
}
private native float native_measureText(char[] text, int index, int count, int bidiFlags);
/**
* Return the width of the text.
*
@@ -1558,18 +1558,17 @@ public class Paint {
return 0f;
}
if (!mHasCompatScaling) {
return (float) Math.ceil(native_measureText(text, start, end, mBidiFlags));
return (float) Math.ceil(native_getTextAdvances(mNativePaint, mNativeTypeface, text,
start, end, start, end, mBidiFlags, null, 0));
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
float w = native_measureText(text, start, end, mBidiFlags);
setTextSize(oldSize * mCompatScaling);
float w = native_getTextAdvances(mNativePaint, mNativeTypeface, text, start, end, start,
end, mBidiFlags, null, 0);
setTextSize(oldSize);
return (float) Math.ceil(w*mInvCompatScaling);
return (float) Math.ceil(w * mInvCompatScaling);
}
private native float native_measureText(String text, int start, int end, int bidiFlags);
/**
* Return the width of the text.
*
@@ -1580,23 +1579,9 @@ public class Paint {
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
if (text.length() == 0) {
return 0f;
}
if (!mHasCompatScaling) {
return (float) Math.ceil(native_measureText(text, mBidiFlags));
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
float w = native_measureText(text, mBidiFlags);
setTextSize(oldSize);
return (float) Math.ceil(w*mInvCompatScaling);
return measureText(text, 0, text.length());
}
private native float native_measureText(String text, int bidiFlags);
/**
* Return the width of the text.
*
@@ -1795,17 +1780,20 @@ public class Paint {
return 0;
}
if (!mHasCompatScaling) {
return native_getTextWidths(mNativePaint, mNativeTypeface, text, index, count, mBidiFlags, widths);
native_getTextAdvances(mNativePaint, mNativeTypeface, text, index, count, index, count,
mBidiFlags, widths, 0);
return count;
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
int res = native_getTextWidths(mNativePaint, mNativeTypeface, text, index, count, mBidiFlags, widths);
setTextSize(oldSize * mCompatScaling);
native_getTextAdvances(mNativePaint, mNativeTypeface, text, index, count, index, count,
mBidiFlags, widths, 0);
setTextSize(oldSize);
for (int i=0; i<res; i++) {
for (int i = 0; i < count; i++) {
widths[i] *= mInvCompatScaling;
}
return res;
return count;
}
/**
@@ -1860,7 +1848,7 @@ public class Paint {
* @param end The end of the text slice to measure
* @param widths array to receive the advance widths of the characters.
* Must be at least a large as the text.
* @return the number of unichars in the specified text.
* @return the number of code units in the specified text.
*/
public int getTextWidths(String text, int start, int end, float[] widths) {
if (text == null) {
@@ -1877,17 +1865,20 @@ public class Paint {
return 0;
}
if (!mHasCompatScaling) {
return native_getTextWidths(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, widths);
native_getTextAdvances(mNativePaint, mNativeTypeface, text, start, end, start, end,
mBidiFlags, widths, 0);
return end - start;
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
int res = native_getTextWidths(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, widths);
setTextSize(oldSize * mCompatScaling);
native_getTextAdvances(mNativePaint, mNativeTypeface, text, start, end, start, end,
mBidiFlags, widths, 0);
setTextSize(oldSize);
for (int i=0; i<res; i++) {
for (int i = 0; i < end - start; i++) {
widths[i] *= mInvCompatScaling;
}
return res;
return end - start;
}
/**
@@ -1896,7 +1887,7 @@ public class Paint {
* @param text The text to measure
* @param widths array to receive the advance widths of the characters.
* Must be at least a large as the text.
* @return the number of unichars in the specified text.
* @return the number of code units in the specified text.
*/
public int getTextWidths(String text, float[] widths) {
return getTextWidths(text, 0, text.length(), widths);
@@ -1929,14 +1920,16 @@ public class Paint {
return 0f;
}
if (!mHasCompatScaling) {
return native_getTextRunAdvances(mNativePaint, mNativeTypeface, chars, index, count,
contextIndex, contextCount, isRtl, advances, advancesIndex);
return native_getTextAdvances(mNativePaint, mNativeTypeface, chars, index, count,
contextIndex, contextCount, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances,
advancesIndex);
}
final float oldSize = getTextSize();
setTextSize(oldSize * mCompatScaling);
float res = native_getTextRunAdvances(mNativePaint, mNativeTypeface, chars, index, count,
contextIndex, contextCount, isRtl, advances, advancesIndex);
float res = native_getTextAdvances(mNativePaint, mNativeTypeface, chars, index, count,
contextIndex, contextCount, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances,
advancesIndex);
setTextSize(oldSize);
if (advances != null) {
@@ -2039,7 +2032,6 @@ public class Paint {
*/
public float getTextRunAdvances(String text, int start, int end, int contextStart,
int contextEnd, boolean isRtl, float[] advances, int advancesIndex) {
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -2056,14 +2048,16 @@ public class Paint {
}
if (!mHasCompatScaling) {
return native_getTextRunAdvances(mNativePaint, mNativeTypeface, text, start, end,
contextStart, contextEnd, isRtl, advances, advancesIndex);
return native_getTextAdvances(mNativePaint, mNativeTypeface, text, start, end,
contextStart, contextEnd, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances,
advancesIndex);
}
final float oldSize = getTextSize();
setTextSize(oldSize * mCompatScaling);
float totalAdvance = native_getTextRunAdvances(mNativePaint, mNativeTypeface, text, start, end,
contextStart, contextEnd, isRtl, advances, advancesIndex);
float totalAdvance = native_getTextAdvances(mNativePaint, mNativeTypeface, text, start,
end, contextStart, contextEnd, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances,
advancesIndex);
setTextSize(oldSize);
if (advances != null) {
@@ -2511,21 +2505,16 @@ public class Paint {
private static native void native_setTextLocale(long native_object,
String locale);
private static native int native_getTextWidths(long native_object, long native_typeface,
char[] text, int index, int count, int bidiFlags, float[] widths);
private static native int native_getTextWidths(long native_object, long native_typeface,
String text, int start, int end, int bidiFlags, float[] widths);
private static native int native_getTextGlyphs(long native_object,
String text, int start, int end, int contextStart, int contextEnd,
int flags, char[] glyphs);
private static native float native_getTextRunAdvances(long native_object, long native_typeface,
private static native float native_getTextAdvances(long native_object, long native_typeface,
char[] text, int index, int count, int contextIndex, int contextCount,
boolean isRtl, float[] advances, int advancesIndex);
private static native float native_getTextRunAdvances(long native_object, long native_typeface,
int bidiFlags, float[] advances, int advancesIndex);
private static native float native_getTextAdvances(long native_object, long native_typeface,
String text, int start, int end, int contextStart, int contextEnd,
boolean isRtl, float[] advances, int advancesIndex);
int bidiFlags, float[] advances, int advancesIndex);
private native int native_getTextRunCursor(long native_object, char[] text,
int contextStart, int contextLength, int dir, int offset, int cursorOpt);