Merge "Implement Paint.breakText() using Minikin"

This commit is contained in:
Anish Athalye
2014-06-17 19:41:38 +00:00
committed by Android (Google) Code Review
2 changed files with 61 additions and 27 deletions

View File

@@ -936,32 +936,62 @@ public:
return paint->getLooper() && paint->getLooper()->asABlurShadow(NULL);
}
static int breakText(JNIEnv* env, SkPaint& paint, const jchar text[],
static int breakText(JNIEnv* env, const SkPaint& paint, TypefaceImpl* typeface, const jchar text[],
int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
SkPaint::TextBufferDirection tbd) {
SkPaint::TextBufferDirection textBufferDirection) {
size_t measuredCount = 0;
float measured = 0;
#ifdef USE_MINIKIN
Layout layout;
std::string css = MinikinUtils::setLayoutProperties(&layout, &paint, bidiFlags, typeface);
layout.doLayout(text, 0, count, count, css);
float* advances = new float[count];
layout.getAdvances(advances);
const bool forwardScan = (textBufferDirection == SkPaint::kForward_TextBufferDirection);
for (int i = 0; i < count; i++) {
// traverse in the given direction
int index = forwardScan ? i : (count - i - 1);
float width = advances[index];
if (measured + width > maxWidth) {
break;
}
// properly handle clusters when scanning backwards
if (forwardScan || width != 0.0f) {
measuredCount = i + 1;
}
measured += width;
}
delete[] advances;
#else
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
text, 0, count, count, bidiFlags);
if (value == NULL) {
return 0;
}
SkScalar measured;
size_t bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
maxWidth, &measured, tbd);
SkScalar m;
size_t bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
maxWidth, &m, textBufferDirection);
SkASSERT((bytes & 1) == 0);
measuredCount = bytes >> 1;
measured = SkScalarToFloat(m);
#endif
if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
jfloat* array = autoMeasured.ptr();
array[0] = SkScalarToFloat(measured);
array[0] = measured;
}
return bytes >> 1;
return measuredCount;
}
static jint breakTextC(JNIEnv* env, jobject jpaint, jcharArray jtext,
static jint breakTextC(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jcharArray jtext,
jint index, jint count, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
NPE_CHECK_RETURN_ZERO(env, jpaint);
NPE_CHECK_RETURN_ZERO(env, jtext);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
SkPaint::TextBufferDirection tbd;
if (count < 0) {
tbd = SkPaint::kBackward_TextBufferDirection;
@@ -976,28 +1006,28 @@ public:
return 0;
}
SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
const jchar* text = env->GetCharArrayElements(jtext, NULL);
count = breakText(env, *paint, text + index, count, maxWidth,
count = breakText(env, *paint, typeface, text + index, count, maxWidth,
bidiFlags, jmeasuredWidth, tbd);
env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text),
JNI_ABORT);
return count;
}
static jint breakTextS(JNIEnv* env, jobject jpaint, jstring jtext,
static jint breakTextS(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring jtext,
jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
NPE_CHECK_RETURN_ZERO(env, jpaint);
NPE_CHECK_RETURN_ZERO(env, jtext);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
SkPaint::TextBufferDirection tbd = forwards ?
SkPaint::kForward_TextBufferDirection :
SkPaint::kBackward_TextBufferDirection;
SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
int count = env->GetStringLength(jtext);
const jchar* text = env->GetStringChars(jtext, NULL);
count = breakText(env, *paint, text, count, maxWidth, bidiFlags, jmeasuredWidth, tbd);
count = breakText(env, *paint, typeface, text, count, maxWidth, bidiFlags, jmeasuredWidth, tbd);
env->ReleaseStringChars(jtext, text);
return count;
}
@@ -1108,8 +1138,8 @@ static JNINativeMethod methods[] = {
{"native_measureText","([CIII)F", (void*) SkPaintGlue::measureText_CIII},
{"native_measureText","(Ljava/lang/String;I)F", (void*) SkPaintGlue::measureText_StringI},
{"native_measureText","(Ljava/lang/String;III)F", (void*) SkPaintGlue::measureText_StringIII},
{"native_breakText","([CIIFI[F)I", (void*) SkPaintGlue::breakTextC},
{"native_breakText","(Ljava/lang/String;ZFI[F)I", (void*) SkPaintGlue::breakTextS},
{"native_breakText","(JJ[CIIFI[F)I", (void*) SkPaintGlue::breakTextC},
{"native_breakText","(JJLjava/lang/String;ZFI[F)I", (void*) SkPaintGlue::breakTextS},
{"native_getTextWidths","(JJ[CIII[F)I", (void*) SkPaintGlue::getTextWidths___CIII_F},
{"native_getTextWidths","(JJLjava/lang/String;III[F)I", (void*) SkPaintGlue::getTextWidths__StringIII_F},
{"native_getTextRunAdvances","(JJ[CIIIIZ[FI)F",

View File

@@ -1532,20 +1532,22 @@ public class Paint {
return 0;
}
if (!mHasCompatScaling) {
return native_breakText(text, index, count, maxWidth, mBidiFlags, measuredWidth);
return native_breakText(mNativePaint, mNativeTypeface, text, index, count, maxWidth,
mBidiFlags, measuredWidth);
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
int res = native_breakText(text, index, count, maxWidth*mCompatScaling, mBidiFlags,
measuredWidth);
setTextSize(oldSize * mCompatScaling);
int res = native_breakText(mNativePaint, mNativeTypeface, text, index, count,
maxWidth * mCompatScaling, mBidiFlags, measuredWidth);
setTextSize(oldSize);
if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
return res;
}
private native int native_breakText(char[] text, int index, int count,
float maxWidth, int bidiFlags, float[] measuredWidth);
private static native int native_breakText(long native_object, long native_typeface,
char[] text, int index, int count,
float maxWidth, int bidiFlags, float[] measuredWidth);
/**
* Measure the text, stopping early if the measured width exceeds maxWidth.
@@ -1622,19 +1624,21 @@ public class Paint {
return 0;
}
if (!mHasCompatScaling) {
return native_breakText(text, measureForwards, maxWidth, mBidiFlags, measuredWidth);
return native_breakText(mNativePaint, mNativeTypeface, text, measureForwards,
maxWidth, mBidiFlags, measuredWidth);
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
int res = native_breakText(text, measureForwards, maxWidth*mCompatScaling, mBidiFlags,
measuredWidth);
int res = native_breakText(mNativePaint, mNativeTypeface, text, measureForwards,
maxWidth*mCompatScaling, mBidiFlags, measuredWidth);
setTextSize(oldSize);
if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
return res;
}
private native int native_breakText(String text, boolean measureForwards,
private static native int native_breakText(long native_object, long native_typeface,
String text, boolean measureForwards,
float maxWidth, int bidiFlags, float[] measuredWidth);
/**