Add text alignment support to drawText().
This change also integrates better support for RTL text.
Change-Id: I6da8f5cf5dc28ca7cf1b22e27b0d853c919e8481
diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp
index e2536ee..3de2c95 100644
--- a/core/jni/android/graphics/TextLayout.cpp
+++ b/core/jni/android/graphics/TextLayout.cpp
@@ -150,26 +150,22 @@
return result;
}
-// Draws or gets the path of a paragraph of text on a single line, running bidi and shaping.
-// This will draw if canvas is not null, otherwise path must be non-null and it will create
-// a path representing the text that would have been drawn.
-void TextLayout::handleText(SkPaint *paint, const jchar* text, jsize len,
- jint bidiFlags, jfloat x, jfloat y,SkCanvas *canvas, SkPath *path) {
-
+bool TextLayout::prepareText(SkPaint *paint, const jchar* text, jsize len, jint bidiFlags,
+ const jchar** outText, int32_t* outBytes) {
const jchar *workText = text;
jchar *buffer = NULL;
int dir = kDirection_LTR;
if (needsLayout(text, len, bidiFlags)) {
buffer =(jchar *) malloc(len * sizeof(jchar));
if (!buffer) {
- return;
+ return false;
}
UErrorCode status = U_ZERO_ERROR;
len = layoutLine(text, len, bidiFlags, dir, buffer, status); // might change len, dir
if (!U_SUCCESS(status)) {
LOG(LOG_WARN, "LAYOUT", "drawText error %d\n", status);
free(buffer);
- return; // can't render
+ return false; // can't render
}
workText = buffer; // use the shaped text
@@ -180,10 +176,10 @@
SkPaint::Align horiz = paint->getTextAlign();
switch (horiz) {
- case SkPaint::kLeft_Align: trimLeft = dir & kDirection_Mask; break;
- case SkPaint::kCenter_Align: trimLeft = trimRight = true; break;
- case SkPaint::kRight_Align: trimRight = !(dir & kDirection_Mask);
- default: break;
+ case SkPaint::kLeft_Align: trimLeft = dir & kDirection_Mask; break;
+ case SkPaint::kCenter_Align: trimLeft = trimRight = true; break;
+ case SkPaint::kRight_Align: trimRight = !(dir & kDirection_Mask);
+ default: break;
}
const jchar* workLimit = workText + len;
@@ -198,16 +194,29 @@
}
}
- int32_t workBytes = (workLimit - workText) << 1;
- SkScalar x_ = SkFloatToScalar(x);
- SkScalar y_ = SkFloatToScalar(y);
- if (canvas) {
- canvas->drawText(workText, workBytes, x_, y_, *paint);
- } else {
- paint->getTextPath(workText, workBytes, x_, y_, path);
- }
-
+ *outBytes = (workLimit - workText) << 1;
+ *outText = workText;
+
free(buffer);
+ return true;
+}
+
+// Draws or gets the path of a paragraph of text on a single line, running bidi and shaping.
+// This will draw if canvas is not null, otherwise path must be non-null and it will create
+// a path representing the text that would have been drawn.
+void TextLayout::handleText(SkPaint *paint, const jchar* text, jsize len,
+ jint bidiFlags, jfloat x, jfloat y,SkCanvas *canvas, SkPath *path) {
+ const jchar *workText;
+ int32_t workBytes;
+ if (prepareText(paint, text, len, bidiFlags, &workText, &workBytes)) {
+ SkScalar x_ = SkFloatToScalar(x);
+ SkScalar y_ = SkFloatToScalar(y);
+ if (canvas) {
+ canvas->drawText(workText, workBytes, x_, y_, *paint);
+ } else {
+ paint->getTextPath(workText, workBytes, x_, y_, path);
+ }
+ }
}
void TextLayout::drawTextRun(SkPaint* paint, const jchar* chars,
diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h
index c0d9f75..dc7208a 100644
--- a/core/jni/android/graphics/TextLayout.h
+++ b/core/jni/android/graphics/TextLayout.h
@@ -63,6 +63,9 @@
static void drawTextOnPath(SkPaint* paint, const jchar* text, jsize len,
int bidiFlags, jfloat hOffset, jfloat vOffset,
SkPath* path, SkCanvas* canvas);
+
+ static bool prepareText(SkPaint *paint, const jchar* text, jsize len, jint bidiFlags,
+ const jchar** outText, int32_t* outBytes);
private:
static bool needsLayout(const jchar* text, jint len, jint bidiFlags);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 2f1dcb6..d2e7faf 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -33,6 +33,8 @@
#include <Rect.h>
#include <ui/Rect.h>
+#include "TextLayout.h"
+
namespace android {
using namespace uirenderer;
@@ -251,12 +253,20 @@
// Text
// ----------------------------------------------------------------------------
+static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
+ jfloat x, jfloat y, int flags, SkPaint* paint) {
+ const jchar *workText;
+ int32_t workBytes;
+ if (TextLayout::prepareText(paint, text, count, flags, &workText, &workBytes)) {
+ renderer->drawText((const char*) workText, workBytes, count, x, y, paint);
+ }
+}
+
static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jcharArray text, int index, int count,
jfloat x, jfloat y, int flags, SkPaint* paint) {
jchar* textArray = env->GetCharArrayElements(text, NULL);
- // TODO: Prepare the text for RTL
- renderer->drawText((const char*) (textArray + index), count, x, y, paint);
+ renderText(renderer, textArray + index, count, x, y, flags, paint);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
}
@@ -264,8 +274,7 @@
OpenGLRenderer* renderer, jstring text, int start, int end,
jfloat x, jfloat y, int flags, SkPaint* paint) {
const jchar* textArray = env->GetStringChars(text, NULL);
- // TODO: Prepare the text for RTL
- renderer->drawText((const char*) (textArray + start), end - start, x, y, paint);
+ renderText(renderer, textArray + start, end - start, x, y, flags, paint);
env->ReleaseStringChars(text, textArray);
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index c6a2e33..d30d718 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -525,7 +525,26 @@
drawColorRect(left, top, right, bottom, color, mode);
}
-void OpenGLRenderer::drawText(const char* text, int count, float x, float y, SkPaint* paint) {
+void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
+ float x, float y, SkPaint* paint) {
+ if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) {
+ return;
+ }
+
+ float length;
+ switch (paint->getTextAlign()) {
+ case SkPaint::kCenter_Align:
+ length = paint->measureText(text, bytesCount);
+ x -= length / 2.0f;
+ break;
+ case SkPaint::kRight_Align:
+ length = paint->measureText(text, bytesCount);
+ x -= length;
+ break;
+ default:
+ break;
+ }
+
int alpha;
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
@@ -551,7 +570,7 @@
const Rect& clip = mSnapshot->getLocalClip();
mFontRenderer.setFont(SkTypeface::UniqueID(paint->getTypeface()), paint->getTextSize());
- mFontRenderer.renderText(paint, &clip, text, 0, count, count, x, y);
+ mFontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 43e568f..248c9c3 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -110,7 +110,7 @@
float* positions, int count, SkShader::TileMode tileMode,
SkMatrix* matrix, bool hasAlpha);
- void drawText(const char* text, int count, float x, float y, SkPaint* paint);
+ void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
private:
/**
diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/TextActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/TextActivity.java
index 4a94630..3b5cf43 100644
--- a/tests/HwAccelerationTest/src/com/google/android/test/hwui/TextActivity.java
+++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/TextActivity.java
@@ -51,7 +51,13 @@
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRGB(255, 255, 255);
-
+
+ canvas.drawText("Hello OpenGL renderer!", 100, 20, mMediumPaint);
+ mMediumPaint.setTextAlign(Paint.Align.CENTER);
+ canvas.drawText("Hello OpenGL renderer!", 100, 40, mMediumPaint);
+ mMediumPaint.setTextAlign(Paint.Align.RIGHT);
+ canvas.drawText("Hello OpenGL renderer!", 100, 60, mMediumPaint);
+ mMediumPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText("Hello OpenGL renderer!", 100, 100, mMediumPaint);
canvas.drawText("Hello OpenGL renderer!", 100, 200, mLargePaint);