blob: 4f17e529eaae515835ff8771ba678270faa58af4 [file] [log] [blame]
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -08001/*
2 * Copyright (C) 2011 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
17package com.android.bidi;
18
19import android.content.Context;
20import android.graphics.Canvas;
21import android.graphics.Color;
22import android.graphics.Paint;
23import android.graphics.Rect;
24import android.graphics.Typeface;
25import android.util.AttributeSet;
26import android.util.Log;
27import android.view.View;
28
29public class BiDiTestView extends View {
30
31 private static final String TAG = "BiDiTestView";
32
33 private static final int BORDER_PADDING = 4;
34 private static final int TEXT_PADDING = 16;
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070035 private static final int TEXT_SIZE = 16;
36 private static final int ORIGIN = 80;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080037
38 private static final float DEFAULT_ITALIC_SKEW_X = -0.25f;
39
40 private Paint paint = new Paint();
41 private Rect rect = new Rect();
42
43 private String NORMAL_TEXT;
44 private String NORMAL_LONG_TEXT;
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070045 private String NORMAL_LONG_TEXT_2;
46 private String NORMAL_LONG_TEXT_3;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080047 private String ITALIC_TEXT;
48 private String BOLD_TEXT;
49 private String BOLD_ITALIC_TEXT;
50 private String ARABIC_TEXT;
51 private String CHINESE_TEXT;
Fabrice Di Meglio689e5152011-04-13 16:07:37 -070052 private String MIXED_TEXT_1;
Fabrice Di Meglio589e4e22011-04-25 16:48:51 -070053 private String HEBREW_TEXT;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080054
55 private Typeface typeface;
56
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070057 private int currentTextSize;
58
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080059 public BiDiTestView(Context context) {
60 super(context);
61 init(context);
62 }
63
64 public BiDiTestView(Context context, AttributeSet attrs) {
65 super(context, attrs);
66 init(context);
67 }
68
69 public BiDiTestView(Context context, AttributeSet attrs, int defStyle) {
70 super(context, attrs, defStyle);
71 init(context);
72 }
73
74 private void init(Context context) {
75 NORMAL_TEXT = context.getString(R.string.normal_text);
76 NORMAL_LONG_TEXT = context.getString(R.string.normal_long_text);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070077 NORMAL_LONG_TEXT_2 = context.getString(R.string.normal_long_text_2);
78 NORMAL_LONG_TEXT_3 = context.getString(R.string.normal_long_text_3);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080079 ITALIC_TEXT = context.getString(R.string.italic_text);
80 BOLD_TEXT = context.getString(R.string.bold_text);
81 BOLD_ITALIC_TEXT = context.getString(R.string.bold_italic_text);
82 ARABIC_TEXT = context.getString(R.string.arabic_text);
83 CHINESE_TEXT = context.getString(R.string.chinese_text);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -070084 MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
Fabrice Di Meglio589e4e22011-04-25 16:48:51 -070085 HEBREW_TEXT = context.getString(R.string.hebrew_text);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080086
87 typeface = paint.getTypeface();
88 paint.setAntiAlias(true);
89 }
90
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070091 public void setCurrentTextSize(int size) {
92 currentTextSize = size;
93 invalidate();
94 }
95
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080096 @Override
97 public void onDraw(Canvas canvas) {
98 drawInsideRect(canvas, Color.BLACK);
99
Fabrice Di Meglio589e4e22011-04-25 16:48:51 -0700100 int deltaX = 0;
101
102 deltaX = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN,
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700103 paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize);
104
105 deltaX += testString(canvas, ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
106 paint, typeface, true, false, Paint.DIRECTION_LTR, currentTextSize);
107
108 deltaX += testString(canvas, BOLD_TEXT, ORIGIN + deltaX, ORIGIN,
109 paint, typeface, false, true, Paint.DIRECTION_LTR, currentTextSize);
110
111 deltaX += testString(canvas, BOLD_ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
112 paint, typeface, true, true, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800113
114 // Test with a long string
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700115 deltaX = testString(canvas, NORMAL_LONG_TEXT, ORIGIN, ORIGIN + 2 * currentTextSize,
116 paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize);
117
118 // Test with a long string
119 deltaX = testString(canvas, NORMAL_LONG_TEXT_2, ORIGIN, ORIGIN + 4 * currentTextSize,
120 paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize);
121
122 // Test with a long string
123 deltaX = testString(canvas, NORMAL_LONG_TEXT_3, ORIGIN, ORIGIN + 6 * currentTextSize,
124 paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800125
126 // Test Arabic ligature
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700127 deltaX = testString(canvas, ARABIC_TEXT, ORIGIN, ORIGIN + 8 * currentTextSize,
128 paint, typeface, false, false, Paint.DIRECTION_RTL, currentTextSize);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800129
130 // Test Chinese
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700131 deltaX = testString(canvas, CHINESE_TEXT, ORIGIN, ORIGIN + 10 * currentTextSize,
132 paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700133
134 // Test Mixed (English and Arabic)
135 deltaX = testString(canvas, MIXED_TEXT_1, ORIGIN, ORIGIN + 12 * currentTextSize,
136 paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglio589e4e22011-04-25 16:48:51 -0700137
138 // Test Hebrew
139 deltaX = testString(canvas, HEBREW_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
140 paint, typeface, false, false, Paint.DIRECTION_RTL, currentTextSize);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800141 }
142
143 private int testString(Canvas canvas, String text, int x, int y, Paint paint, Typeface typeface,
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700144 boolean isItalic, boolean isBold, int dir, int textSize) {
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800145 paint.setTypeface(typeface);
146
147 // Set paint properties
148 boolean oldFakeBold = paint.isFakeBoldText();
149 paint.setFakeBoldText(isBold);
150
151 float oldTextSkewX = paint.getTextSkewX();
152 if (isItalic) {
153 paint.setTextSkewX(DEFAULT_ITALIC_SKEW_X);
154 }
155
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700156 Log.v(TAG, "START -- drawTextWithCanvasDrawText");
157 drawTextWithCanvasDrawText(text, canvas, x, y, textSize, Color.WHITE, dir);
158 Log.v(TAG, "END -- drawTextWithCanvasDrawText");
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800159
160 int length = text.length();
161 float[] advances = new float[length];
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700162 float textWidthHB = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0);
163 setPaintDir(paint, dir);
Fabrice Di Meglio0a1413e2011-04-21 17:36:26 -0700164 float textWidthICU = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0,
165 1 /* use ICU */);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800166
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700167 logAdvances(text, textWidthHB, textWidthICU, advances);
168 drawMetricsAroundText(canvas, x, y, textWidthHB, textWidthICU, textSize, Color.RED, Color.GREEN);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800169
170 paint.setColor(Color.WHITE);
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700171// char[] glyphs = new char[2*length];
172// int count = getGlyphs(text, glyphs, dir);
173//
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700174// logGlypths(glyphs, count);
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700175// drawTextWithDrawGlyph(canvas, glyphs, count, x, y + currentTextSize);
176
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700177 Log.v(TAG, "START -- drawTextWithGlyphs");
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700178 drawTextWithGlyphs(canvas, text, x, y + currentTextSize, dir);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700179 Log.v(TAG, "END -- drawTextWithGlyphs");
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800180
181 // Restore old paint properties
182 paint.setFakeBoldText(oldFakeBold);
183 paint.setTextSkewX(oldTextSkewX);
184
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700185 return (int) Math.ceil(textWidthHB) + TEXT_PADDING;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800186 }
187
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700188 private void setPaintDir(Paint paint, int dir) {
189 Log.v(TAG, "Setting Paint dir=" + dir);
190 paint.setBidiFlags(dir);
191 }
192
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800193 private void drawTextWithDrawGlyph(Canvas canvas, char[] glyphs, int count, int x, int y) {
194 canvas.drawGlyphs(glyphs, 0, count, x, y, paint);
195 }
196
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700197 private void drawTextWithGlyphs(Canvas canvas, String text, int x, int y, int dir) {
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700198 setPaintDir(paint, dir);
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700199 canvas.drawTextWithGlyphs(text, x, y, paint);
200 }
201
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800202 private void logGlypths(char[] glyphs, int count) {
203 Log.v(TAG, "GlyphIds - count=" + count);
204 for (int n = 0; n < count; n++) {
205 Log.v(TAG, "GlyphIds - Id[" + n + "]="+ (int)glyphs[n]);
206 }
207 }
208
209 private int getGlyphs(String text, char[] glyphs, int dir) {
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800210 return paint.getTextGlypths(text, 0, text.length(), 0, text.length(), dir, glyphs);
211 }
212
213 private void drawInsideRect(Canvas canvas, int color) {
214 paint.setColor(color);
215 int width = getWidth();
216 int height = getHeight();
217 rect.set(BORDER_PADDING, BORDER_PADDING, width - BORDER_PADDING, height - BORDER_PADDING);
218 canvas.drawRect(rect, paint);
219 }
220
221 private void drawTextWithCanvasDrawText(String text, Canvas canvas,
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700222 float x, float y, float textSize, int color, int dir) {
223 setPaintDir(paint, dir);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800224 paint.setColor(color);
225 paint.setTextSize(textSize);
226 canvas.drawText(text, x, y, paint);
227 }
228
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700229 private void drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB,
230 float textWidthICU, int textSize, int color, int colorICU) {
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800231 paint.setColor(color);
232 canvas.drawLine(x, y - textSize, x, y + 8, paint);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700233 canvas.drawLine(x, y + 8, x + textWidthHB, y + 8, paint);
234 canvas.drawLine(x + textWidthHB, y - textSize, x + textWidthHB, y + 8, paint);
235 paint.setColor(colorICU);
236 canvas.drawLine(x + textWidthICU, y - textSize, x + textWidthICU, y + 8, paint);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800237 }
238
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700239 private void logAdvances(String text, float textWidth, float textWidthICU, float[] advances) {
240 Log.v(TAG, "Advances for text: " + text + " total= " + textWidth + " - totalICU= " + textWidthICU);
241// int length = advances.length;
242// for(int n=0; n<length; n++){
243// Log.v(TAG, "adv[" + n + "]=" + advances[n]);
244// }
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800245 }
246}