Skip to content

Commit 325740f

Browse files
author
Romain Guy
committed
Add hooks to implement Canvas.drawTextOnPath() in GL
Change-Id: I165c9e05facf5365aa6850605688e538640c7fcc
1 parent 34c55d3 commit 325740f

File tree

9 files changed

+206
-10
lines changed

9 files changed

+206
-10
lines changed

core/java/android/view/GLES20Canvas.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,14 +1208,38 @@ public void drawText(String text, float x, float y, Paint paint) {
12081208
@Override
12091209
public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
12101210
float vOffset, Paint paint) {
1211-
// TODO: Implement
1211+
if (index < 0 || index + count > text.length) {
1212+
throw new ArrayIndexOutOfBoundsException();
1213+
}
1214+
1215+
int modifiers = setupModifiers(paint);
1216+
try {
1217+
nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
1218+
paint.mBidiFlags, paint.mNativePaint);
1219+
} finally {
1220+
if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1221+
}
12121222
}
12131223

1224+
private static native void nDrawTextOnPath(int renderer, char[] text, int index, int count,
1225+
int path, float hOffset, float vOffset, int bidiFlags, int nativePaint);
1226+
12141227
@Override
12151228
public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
1216-
// TODO: Implement
1229+
if (text.length() == 0) return;
1230+
1231+
int modifiers = setupModifiers(paint);
1232+
try {
1233+
nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
1234+
paint.mBidiFlags, paint.mNativePaint);
1235+
} finally {
1236+
if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
1237+
}
12171238
}
12181239

1240+
private static native void nDrawTextOnPath(int renderer, String text, int start, int end,
1241+
int path, float hOffset, float vOffset, int bidiFlags, int nativePaint);
1242+
12191243
@Override
12201244
public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
12211245
float x, float y, int dir, Paint paint) {

core/jni/android/graphics/TextLayout.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,6 @@ void TextLayout::drawTextOnPath(SkPaint* paint, const jchar* text, int count,
101101
SkScalar h_ = SkFloatToScalar(hOffset);
102102
SkScalar v_ = SkFloatToScalar(vOffset);
103103

104-
if (!needsLayout(text, count, bidiFlags)) {
105-
canvas->drawTextOnPathHV(text, count << 1, *path, h_, v_, *paint);
106-
return;
107-
}
108-
109104
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
110105
text, 0, count, count, bidiFlags);
111106
if (value == NULL) {

core/jni/android_view_GLES20Canvas.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,20 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
521521
renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint);
522522
}
523523

524+
static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
525+
SkPath* path, jfloat hOffset, jfloat vOffset, int flags, SkPaint* paint) {
526+
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
527+
text, 0, count, count, flags);
528+
if (value == NULL) {
529+
return;
530+
}
531+
const jchar* glyphs = value->getGlyphs();
532+
size_t glyphsCount = value->getGlyphsCount();
533+
int bytesCount = glyphsCount * sizeof(jchar);
534+
renderer->drawTextOnPath((const char*) glyphs, bytesCount, glyphsCount, path,
535+
hOffset, vOffset, paint);
536+
}
537+
524538
static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
525539
jint start, jint count, jint contextCount, jfloat x, jfloat y,
526540
int flags, SkPaint* paint) {
@@ -551,6 +565,24 @@ static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
551565
env->ReleaseStringChars(text, textArray);
552566
}
553567

568+
static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
569+
OpenGLRenderer* renderer, jcharArray text, jint index, jint count,
570+
SkPath* path, jfloat hOffset, jfloat vOffset, jint flags, SkPaint* paint) {
571+
jchar* textArray = env->GetCharArrayElements(text, NULL);
572+
renderTextOnPath(renderer, textArray + index, count, path,
573+
hOffset, vOffset, flags, paint);
574+
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
575+
}
576+
577+
static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
578+
OpenGLRenderer* renderer, jstring text, jint start, jint end,
579+
SkPath* path, jfloat hOffset, jfloat vOffset, jint flags, SkPaint* paint) {
580+
const jchar* textArray = env->GetStringChars(text, NULL);
581+
renderTextOnPath(renderer, textArray + start, end - start, path,
582+
hOffset, vOffset, flags, paint);
583+
env->ReleaseStringChars(text, textArray);
584+
}
585+
554586
static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
555587
OpenGLRenderer* renderer, jcharArray text, jint index, jint count,
556588
jint contextIndex, jint contextCount, jfloat x, jfloat y, jint dirFlags,
@@ -885,6 +917,10 @@ static JNINativeMethod gMethods[] = {
885917
{ "nDrawText", "(ILjava/lang/String;IIFFII)V",
886918
(void*) android_view_GLES20Canvas_drawText },
887919

920+
{ "nDrawTextOnPath", "(I[CIIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
921+
{ "nDrawTextOnPath", "(ILjava/lang/String;IIIFFII)V",
922+
(void*) android_view_GLES20Canvas_drawTextOnPath },
923+
888924
{ "nDrawTextRun", "(I[CIIIIFFII)V", (void*) android_view_GLES20Canvas_drawTextRunArray },
889925
{ "nDrawTextRun", "(ILjava/lang/String;IIIIFFII)V",
890926
(void*) android_view_GLES20Canvas_drawTextRun },

libs/hwui/DisplayListRenderer.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const char* DisplayList::OP_NAMES[] = {
6161
"DrawLines",
6262
"DrawPoints",
6363
"DrawText",
64+
"DrawTextOnPath",
6465
"DrawPosText",
6566
"ResetShader",
6667
"SetupShader",
@@ -483,7 +484,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
483484
break;
484485
case DrawText: {
485486
getText(&text);
486-
int count = getInt();
487+
int32_t count = getInt();
487488
float x = getFloat();
488489
float y = getFloat();
489490
SkPaint* paint = getPaint(renderer);
@@ -492,6 +493,17 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
492493
text.text(), text.length(), count, x, y, paint, length);
493494
}
494495
break;
496+
case DrawTextOnPath: {
497+
getText(&text);
498+
int32_t count = getInt();
499+
SkPath* path = getPath();
500+
float hOffset = getFloat();
501+
float vOffset = getFloat();
502+
SkPaint* paint = getPaint(renderer);
503+
ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
504+
text.text(), text.length(), count, paint);
505+
}
506+
break;
495507
case DrawPosText: {
496508
getText(&text);
497509
int count = getInt();
@@ -890,6 +902,19 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
890902
renderer.drawText(text.text(), text.length(), count, x, y, paint, length);
891903
}
892904
break;
905+
case DrawTextOnPath: {
906+
getText(&text);
907+
int32_t count = getInt();
908+
SkPath* path = getPath();
909+
float hOffset = getFloat();
910+
float vOffset = getFloat();
911+
SkPaint* paint = getPaint(renderer);
912+
DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
913+
text.text(), text.length(), count, paint);
914+
renderer.drawTextOnPath(text.text(), text.length(), count, path,
915+
hOffset, vOffset, paint);
916+
}
917+
break;
893918
case DrawPosText: {
894919
getText(&text);
895920
int32_t count = getInt();
@@ -1331,6 +1356,19 @@ void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
13311356
addSkip(location);
13321357
}
13331358

1359+
void DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
1360+
SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
1361+
if (!text || count <= 0) return;
1362+
addOp(DisplayList::DrawTextOnPath);
1363+
addText(text, bytesCount);
1364+
addInt(count);
1365+
addPath(path);
1366+
addFloat(hOffset);
1367+
addFloat(vOffset);
1368+
paint->setAntiAlias(true);
1369+
addPaint(paint);
1370+
}
1371+
13341372
void DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
13351373
const float* positions, SkPaint* paint) {
13361374
if (!text || count <= 0) return;

libs/hwui/DisplayListRenderer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class DisplayList {
9999
DrawLines,
100100
DrawPoints,
101101
DrawText,
102+
DrawTextOnPath,
102103
DrawPosText,
103104
ResetShader,
104105
SetupShader,
@@ -310,6 +311,8 @@ class DisplayListRenderer: public OpenGLRenderer {
310311
virtual void drawPoints(float* points, int count, SkPaint* paint);
311312
virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
312313
SkPaint* paint, float length = 1.0f);
314+
virtual void drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
315+
float hOffset, float vOffset, SkPaint* paint);
313316
virtual void drawPosText(const char* text, int bytesCount, int count, const float* positions,
314317
SkPaint* paint);
315318

libs/hwui/OpenGLRenderer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,6 +2292,11 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
22922292
drawTextDecorations(text, bytesCount, length, oldX, oldY, paint);
22932293
}
22942294

2295+
void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
2296+
float hOffset, float vOffset, SkPaint* paint) {
2297+
// TODO: Implement
2298+
}
2299+
22952300
void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
22962301
if (mSnapshot->isIgnored()) return;
22972302

libs/hwui/OpenGLRenderer.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,10 @@ class OpenGLRenderer {
124124
virtual void drawPoints(float* points, int count, SkPaint* paint);
125125
virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
126126
SkPaint* paint, float length = -1.0f);
127-
virtual void drawPosText(const char* text, int bytesCount, int count, const float* positions,
128-
SkPaint* paint);
127+
virtual void drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
128+
float hOffset, float vOffset, SkPaint* paint);
129+
virtual void drawPosText(const char* text, int bytesCount, int count,
130+
const float* positions, SkPaint* paint);
129131

130132
virtual void resetShader();
131133
virtual void setupShader(SkiaShader* shader);

tests/HwAccelerationTest/AndroidManifest.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,15 @@
567567
</intent-filter>
568568
</activity>
569569

570+
<activity
571+
android:name="TextOnPathActivity"
572+
android:label="_TextOnPath">
573+
<intent-filter>
574+
<action android:name="android.intent.action.MAIN" />
575+
<category android:name="android.intent.category.LAUNCHER" />
576+
</intent-filter>
577+
</activity>
578+
570579
<activity
571580
android:name="PathsCacheActivity"
572581
android:label="_PathsCache">
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (C) 2010 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.android.test.hwui;
18+
19+
import android.app.Activity;
20+
import android.content.Context;
21+
import android.graphics.Canvas;
22+
import android.graphics.Paint;
23+
import android.graphics.Path;
24+
import android.os.Bundle;
25+
import android.view.View;
26+
27+
@SuppressWarnings({"UnusedDeclaration"})
28+
public class TextOnPathActivity extends Activity {
29+
private Path mPath;
30+
31+
@Override
32+
protected void onCreate(Bundle savedInstanceState) {
33+
super.onCreate(savedInstanceState);
34+
35+
mPath = makePath();
36+
37+
final TextOnPathView view = new TextOnPathView(this);
38+
setContentView(view);
39+
}
40+
41+
private Path makePath() {
42+
Path path = new Path();
43+
buildPath(path);
44+
return path;
45+
}
46+
47+
private void buildPath(Path path) {
48+
path.moveTo(0.0f, 0.0f);
49+
path.cubicTo(0.0f, 0.0f, 100.0f, 150.0f, 100.0f, 200.0f);
50+
path.cubicTo(100.0f, 200.0f, 50.0f, 300.0f, -80.0f, 200.0f);
51+
path.cubicTo(-80.0f, 200.0f, 100.0f, 200.0f, 200.0f, 0.0f);
52+
}
53+
54+
public class TextOnPathView extends View {
55+
private static final String TEST_STRING = "Hello OpenGL renderer, text on path! ";
56+
57+
private final Paint mPaint;
58+
private final String mText;
59+
60+
public TextOnPathView(Context c) {
61+
super(c);
62+
63+
mPaint = new Paint();
64+
mPaint.setAntiAlias(true);
65+
mPaint.setColor(0xff000000);
66+
67+
StringBuilder builder = new StringBuilder(TEST_STRING.length() * 5);
68+
for (int i = 0; i < 5; i++) {
69+
builder.append(TEST_STRING);
70+
}
71+
mText = builder.toString();
72+
}
73+
74+
@Override
75+
protected void onDraw(Canvas canvas) {
76+
super.onDraw(canvas);
77+
78+
canvas.drawARGB(255, 255, 255, 255);
79+
80+
canvas.translate(550.0f, 60.0f);
81+
canvas.drawTextOnPath(mText, mPath, 0.0f, 0.0f, mPaint);
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)