Merge "Add text alignment support to drawText()."
This commit is contained in:
@@ -150,26 +150,22 @@ jint TextLayout::layoutLine(const jchar* text, jint len, jint flags, int &dir, j
|
||||
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 @@ void TextLayout::handleText(SkPaint *paint, const jchar* text, jsize len,
|
||||
|
||||
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 @@ void TextLayout::handleText(SkPaint *paint, const jchar* text, jsize len,
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -63,6 +63,9 @@ public:
|
||||
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);
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include <Rect.h>
|
||||
#include <ui/Rect.h>
|
||||
|
||||
#include "TextLayout.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
using namespace uirenderer;
|
||||
@@ -251,12 +253,20 @@ static void android_view_GLES20Canvas_setupLinearShader(JNIEnv* env, jobject can
|
||||
// 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 @@ static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject canvas,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -525,7 +525,26 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
|
||||
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 @@ void OpenGLRenderer::drawText(const char* text, int count, float x, float y, SkP
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
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:
|
||||
/**
|
||||
|
||||
@@ -51,7 +51,13 @@ public class TextActivity extends Activity {
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user