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

Commit c802c8cd authored by Raph Levien's avatar Raph Levien Committed by Android (Google) Code Review
Browse files

Merge "Implement drawTextOnPath with Minikin"

parents bc8bd76b 9d2b5e19
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -969,22 +969,24 @@ class GLES20Canvas extends HardwareCanvas {
        }

        nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
                paint.mBidiFlags, paint.mNativePaint);
                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
    }

    private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint);
            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
            long typeface);

    @Override
    public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
        if (text.length() == 0) return;

        nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
                paint.mBidiFlags, paint.mNativePaint);
                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
    }

    private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint);
            long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
            long typeface);

    @Override
    public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
+61 −8
Original line number Diff line number Diff line
@@ -1123,29 +1123,82 @@ public:
        delete[] posPtr;
    }

#ifdef USE_MINIKIN
    class DrawTextOnPathFunctor {
    public:
        DrawTextOnPathFunctor(const Layout& layout, SkCanvas* canvas, float hOffset,
                    float vOffset, SkPaint* paint, SkPath* path)
                : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
                    paint(paint), path(path) {
        }
        void operator()(size_t start, size_t end) {
            uint16_t glyphs[1];
            for (size_t i = start; i < end; i++) {
                glyphs[0] = layout.getGlyphId(i);
                float x = hOffset + layout.getX(i);
                float y = vOffset + layout.getY(i);
                canvas->drawTextOnPathHV(glyphs, sizeof(glyphs), *path, x, y, *paint);
            }
        }
    private:
        const Layout& layout;
        SkCanvas* canvas;
        float hOffset;
        float vOffset;
        SkPaint* paint;
        SkPath* path;
    };
#endif

    static void doDrawTextOnPath(SkPaint* paint, const jchar* text, int count, int bidiFlags,
            float hOffset, float vOffset, SkPath* path, SkCanvas* canvas, TypefaceImpl* typeface) {
#ifdef USE_MINIKIN
        Layout layout;
        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
        layout.doLayout(text, 0, count, count, css);
        hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
        // Set align to left for drawing, as we don't want individual
        // glyphs centered or right-aligned; the offset above takes
        // care of all alignment.
        SkPaint::Align align = paint->getTextAlign();
        paint->setTextAlign(SkPaint::kLeft_Align);

        DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paint, path);
        MinikinUtils::forFontRun(layout, paint, f);
        paint->setTextAlign(align);
#else
        TextLayout::drawTextOnPath(paint, text, count, bidiFlags, hOffset, vOffset, path, canvas);
#endif
    }

    static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
            jlong canvasHandle, jcharArray text, jint index, jint count,
            jlong pathHandle, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
            jlong pathHandle, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle,
            jlong typefaceHandle) {
        SkCanvas* canvas = getNativeCanvas(canvasHandle);
        SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
        TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);

        jchar* textArray = env->GetCharArrayElements(text, NULL);
        TextLayout::drawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
                                   path, canvas);
        doDrawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
                                   path, canvas, typeface);
        env->ReleaseCharArrayElements(text, textArray, 0);
    }

    static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
            jlong canvasHandle, jstring text, jlong pathHandle,
            jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
            jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle,
            jlong typefaceHandle) {
        SkCanvas* canvas = getNativeCanvas(canvasHandle);
        SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
        TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);

        const jchar* text_ = env->GetStringChars(text, NULL);
        int count = env->GetStringLength(text);
        TextLayout::drawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
                                   path, canvas);
        doDrawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
                                   path, canvas, typeface);
        env->ReleaseStringChars(text, text_);
    }

@@ -1271,9 +1324,9 @@ static JNINativeMethod gCanvasMethods[] = {
        (void*) SkCanvasGlue::drawPosText___CII_FPaint},
    {"native_drawPosText","(JLjava/lang/String;[FJ)V",
        (void*) SkCanvasGlue::drawPosText__String_FPaint},
    {"native_drawTextOnPath","(J[CIIJFFIJ)V",
    {"native_drawTextOnPath","(J[CIIJFFIJJ)V",
        (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
    {"native_drawTextOnPath","(JLjava/lang/String;JFFIJ)V",
    {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V",
        (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},

    {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
+17 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <string>

#include "SkPaint.h"
#include "SkPathMeasure.h"
#include "minikin/Layout.h"
#include "TypefaceImpl.h"
#include "MinikinSkia.h"
@@ -76,4 +77,20 @@ float MinikinUtils::xOffsetForTextAlign(SkPaint* paint, const Layout& layout) {
    return 0;
}

float MinikinUtils::hOffsetForTextAlign(SkPaint* paint, const Layout& layout, const SkPath& path) {
    float align = 0;
    switch (paint->getTextAlign()) {
        case SkPaint::kCenter_Align:
            align = -0.5f;
            break;
        case SkPaint::kRight_Align:
            align = -1;
            break;
        default:
            return 0;
    }
    SkPathMeasure measure(path, false);
    return align * (layout.getAdvance() - measure.getLength());
}

}
+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ public:

    static float xOffsetForTextAlign(SkPaint* paint, const Layout& layout);

    static float hOffsetForTextAlign(SkPaint* paint, const Layout& layout, const SkPath& path);
    // f is a functor of type void f(size_t start, size_t end);
    template <typename F>
    static void forFontRun(const Layout& layout, SkPaint* paint, F& f) {
+52 −7
Original line number Diff line number Diff line
@@ -669,8 +669,48 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
#endif
}

#ifdef USE_MINIKIN
class RenderTextOnPathFunctor {
public:
    RenderTextOnPathFunctor(const Layout& layout, OpenGLRenderer* renderer, float hOffset,
                float vOffset, SkPaint* paint, SkPath* path)
            : layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset),
                paint(paint), path(path) {
    }
    void operator()(size_t start, size_t end) {
        uint16_t glyphs[1];
        for (size_t i = start; i < end; i++) {
            glyphs[0] = layout.getGlyphId(i);
            float x = hOffset + layout.getX(i);
            float y = vOffset + layout.getY(i);
            renderer->drawTextOnPath((const char*) glyphs, sizeof(glyphs), 1, path, x, y, paint);
        }
    }
private:
    const Layout& layout;
    OpenGLRenderer* renderer;
    float hOffset;
    float vOffset;
    SkPaint* paint;
    SkPath* path;
};
#endif

static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
        SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, SkPaint* paint) {
        SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, SkPaint* paint,
        TypefaceImpl* typeface) {
#ifdef USE_MINIKIN
    Layout layout;
    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
    layout.doLayout(text, 0, count, count, css);
    hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
    SkPaint::Align align = paint->getTextAlign();
    paint->setTextAlign(SkPaint::kLeft_Align);

    RenderTextOnPathFunctor f(layout, renderer, hOffset, vOffset, paint, path);
    MinikinUtils::forFontRun(layout, paint, f);
    paint->setTextAlign(align);
#else
    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
            text, 0, count, count, bidiFlags);
    if (value == NULL) {
@@ -681,6 +721,7 @@ static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int co
    int bytesCount = glyphsCount * sizeof(jchar);
    renderer->drawTextOnPath((const char*) glyphs, bytesCount, glyphsCount, path,
            hOffset, vOffset, paint);
#endif
}

static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
@@ -739,27 +780,31 @@ static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,

static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
        jlong rendererPtr, jcharArray text, jint index, jint count,
        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr) {
        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
        jlong typefacePtr) {
    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
    jchar* textArray = env->GetCharArrayElements(text, NULL);
    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);

    renderTextOnPath(renderer, textArray + index, count, path,
            hOffset, vOffset, bidiFlags, paint);
            hOffset, vOffset, bidiFlags, paint, typeface);
    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
}

static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
        jlong rendererPtr, jstring text, jint start, jint end,
        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr) {
        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
        jlong typefacePtr) {
    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
    const jchar* textArray = env->GetStringChars(text, NULL);
    SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
    TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);

    renderTextOnPath(renderer, textArray + start, end - start, path,
            hOffset, vOffset, bidiFlags, paint);
            hOffset, vOffset, bidiFlags, paint, typeface);
    env->ReleaseStringChars(text, textArray);
}

@@ -986,8 +1031,8 @@ static JNINativeMethod gMethods[] = {
    { "nDrawText",          "(JLjava/lang/String;IIFFIJJ)V",
            (void*) android_view_GLES20Canvas_drawText },

    { "nDrawTextOnPath",    "(J[CIIJFFIJ)V",   (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
    { "nDrawTextOnPath",    "(JLjava/lang/String;IIJFFIJ)V",
    { "nDrawTextOnPath",    "(J[CIIJFFIJJ)V",  (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
    { "nDrawTextOnPath",    "(JLjava/lang/String;IIJFFIJJ)V",
            (void*) android_view_GLES20Canvas_drawTextOnPath },

    { "nDrawTextRun",       "(J[CIIIIFFZJJ)V",  (void*) android_view_GLES20Canvas_drawTextRunArray },
Loading