Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7aa1b0a authored by Anish Athalye's avatar Anish Athalye
Browse files

Implement Paint.breakText() using Minikin

Change-Id: I36cee2d840ce1bd24a9a06f0c680880396b7398a
parent 2fc02ba0
Loading
Loading
Loading
Loading
+47 −17
Original line number Diff line number Diff line
@@ -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;
        SkScalar m;
        size_t bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
                maxWidth, &measured, tbd);
                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",
+14 −10
Original line number Diff line number Diff line
@@ -1532,19 +1532,21 @@ 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);
        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,
    private static native int native_breakText(long native_object, long native_typeface,
                                               char[] text, int index, int count,
                                               float maxWidth, int bidiFlags, float[] measuredWidth);

    /**
@@ -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);

    /**