Merge "Implement drawTextOnPath with Minikin"
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 95e50b1..68e2146 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -969,22 +969,24 @@
}
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,
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 4584c46..69e149e 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -1123,29 +1123,82 @@
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 @@
(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},
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index a9360ea..fc92d53 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -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 @@
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());
+}
+
}
diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h
index a96c6b1..b2662a1 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/core/jni/android/graphics/MinikinUtils.h
@@ -36,6 +36,7 @@
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) {
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 4a6e117..de00e59 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -669,8 +669,48 @@
#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 @@
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_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 @@
{ "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 },
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 158801c..13421aa 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1770,7 +1770,7 @@
}
native_drawTextOnPath(mNativeCanvasWrapper, text, index, count,
path.ni(), hOffset, vOffset,
- paint.mBidiFlags, paint.mNativePaint);
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
}
/**
@@ -1790,7 +1790,7 @@
float vOffset, @NonNull Paint paint) {
if (text.length() > 0) {
native_drawTextOnPath(mNativeCanvasWrapper, text, path.ni(), hOffset, vOffset,
- paint.mBidiFlags, paint.mNativePaint);
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
}
}
@@ -2021,11 +2021,11 @@
int count, long nativePath,
float hOffset,
float vOffset, int bidiFlags,
- long nativePaint);
+ long nativePaint, long nativeTypeface);
private static native void native_drawTextOnPath(long nativeCanvas,
String text, long nativePath,
float hOffset,
float vOffset,
- int flags, long nativePaint);
+ int flags, long nativePaint, long nativeTypeface);
private static native void finalizer(long nativeCanvas);
}