blob: 0b1974a5b11dc05b184823d301038a94e8ba24a9 [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;
Fabrice Di Meglioc6f247c2011-07-15 19:18:59 -070024import android.text.TextPaint;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080025import 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
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080040 private Rect rect = new Rect();
41
42 private String NORMAL_TEXT;
43 private String NORMAL_LONG_TEXT;
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070044 private String NORMAL_LONG_TEXT_2;
45 private String NORMAL_LONG_TEXT_3;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080046 private String ITALIC_TEXT;
47 private String BOLD_TEXT;
48 private String BOLD_ITALIC_TEXT;
49 private String ARABIC_TEXT;
50 private String CHINESE_TEXT;
Fabrice Di Meglio689e5152011-04-13 16:07:37 -070051 private String MIXED_TEXT_1;
Fabrice Di Meglio589e4e22011-04-25 16:48:51 -070052 private String HEBREW_TEXT;
Fabrice Di Meglioc6f247c2011-07-15 19:18:59 -070053 private String RTL_TEXT;
Fabrice Di Meglio03e250a2012-01-13 18:55:32 -080054 private String THAI_TEXT;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080055
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070056 private int currentTextSize;
57
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080058 public BiDiTestView(Context context) {
59 super(context);
60 init(context);
61 }
62
63 public BiDiTestView(Context context, AttributeSet attrs) {
64 super(context, attrs);
65 init(context);
66 }
67
68 public BiDiTestView(Context context, AttributeSet attrs, int defStyle) {
69 super(context, attrs, defStyle);
70 init(context);
71 }
72
73 private void init(Context context) {
74 NORMAL_TEXT = context.getString(R.string.normal_text);
75 NORMAL_LONG_TEXT = context.getString(R.string.normal_long_text);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070076 NORMAL_LONG_TEXT_2 = context.getString(R.string.normal_long_text_2);
77 NORMAL_LONG_TEXT_3 = context.getString(R.string.normal_long_text_3);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080078 ITALIC_TEXT = context.getString(R.string.italic_text);
79 BOLD_TEXT = context.getString(R.string.bold_text);
80 BOLD_ITALIC_TEXT = context.getString(R.string.bold_italic_text);
81 ARABIC_TEXT = context.getString(R.string.arabic_text);
82 CHINESE_TEXT = context.getString(R.string.chinese_text);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -070083 MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
Fabrice Di Meglio589e4e22011-04-25 16:48:51 -070084 HEBREW_TEXT = context.getString(R.string.hebrew_text);
Fabrice Di Meglioc6f247c2011-07-15 19:18:59 -070085 RTL_TEXT = context.getString(R.string.rtl);
Fabrice Di Meglio03e250a2012-01-13 18:55:32 -080086 THAI_TEXT = context.getString(R.string.pointer_location);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080087 }
88
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -070089 public void setCurrentTextSize(int size) {
90 currentTextSize = size;
91 invalidate();
92 }
93
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080094 @Override
95 public void onDraw(Canvas canvas) {
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -070096 drawInsideRect(canvas, new Paint(), Color.BLACK);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -080097
Fabrice Di Meglio589e4e22011-04-25 16:48:51 -070098 int deltaX = 0;
99
100 deltaX = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700101 false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700102
103 deltaX += testString(canvas, ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700104 true, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700105
106 deltaX += testString(canvas, BOLD_TEXT, ORIGIN + deltaX, ORIGIN,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700107 false, true, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700108
109 deltaX += testString(canvas, BOLD_ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700110 true, true, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800111
112 // Test with a long string
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700113 deltaX = testString(canvas, NORMAL_LONG_TEXT, ORIGIN, ORIGIN + 2 * currentTextSize,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700114 false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700115
116 // Test with a long string
117 deltaX = testString(canvas, NORMAL_LONG_TEXT_2, ORIGIN, ORIGIN + 4 * currentTextSize,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700118 false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700119
120 // Test with a long string
121 deltaX = testString(canvas, NORMAL_LONG_TEXT_3, ORIGIN, ORIGIN + 6 * currentTextSize,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700122 false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800123
124 // Test Arabic ligature
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700125 deltaX = testString(canvas, ARABIC_TEXT, ORIGIN, ORIGIN + 8 * currentTextSize,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700126 false, false, Paint.DIRECTION_RTL, currentTextSize);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800127
128 // Test Chinese
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700129 deltaX = testString(canvas, CHINESE_TEXT, ORIGIN, ORIGIN + 10 * currentTextSize,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700130 false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700131
132 // Test Mixed (English and Arabic)
133 deltaX = testString(canvas, MIXED_TEXT_1, ORIGIN, ORIGIN + 12 * currentTextSize,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700134 false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglio589e4e22011-04-25 16:48:51 -0700135
136 // Test Hebrew
Fabrice Di Meglioc6f247c2011-07-15 19:18:59 -0700137 deltaX = testString(canvas, RTL_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700138 false, false, Paint.DIRECTION_RTL, currentTextSize);
Fabrice Di Meglio03e250a2012-01-13 18:55:32 -0800139
140 // Test Thai
141 deltaX = testString(canvas, THAI_TEXT, ORIGIN, ORIGIN + 16 * currentTextSize,
142 false, false, Paint.DIRECTION_LTR, currentTextSize);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800143 }
144
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700145 private int testString(Canvas canvas, String text, int x, int y,
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700146 boolean isItalic, boolean isBold, int dir, int textSize) {
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700147
148 TextPaint paint = new TextPaint();
149 paint.setAntiAlias(true);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800150
151 // Set paint properties
152 boolean oldFakeBold = paint.isFakeBoldText();
153 paint.setFakeBoldText(isBold);
154
155 float oldTextSkewX = paint.getTextSkewX();
156 if (isItalic) {
157 paint.setTextSkewX(DEFAULT_ITALIC_SKEW_X);
158 }
159
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700160 paint.setTextSize(textSize);
161 paint.setColor(Color.WHITE);
162 canvas.drawText(text, x, y, paint);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800163
164 int length = text.length();
165 float[] advances = new float[length];
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700166 float textWidthHB = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0);
167 setPaintDir(paint, dir);
Fabrice Di Meglio0a1413e2011-04-21 17:36:26 -0700168 float textWidthICU = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0,
169 1 /* use ICU */);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800170
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700171 logAdvances(text, textWidthHB, textWidthICU, advances);
172 drawMetricsAroundText(canvas, x, y, textWidthHB, textWidthICU, textSize, Color.RED, Color.GREEN);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800173
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800174 // Restore old paint properties
175 paint.setFakeBoldText(oldFakeBold);
176 paint.setTextSkewX(oldTextSkewX);
177
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700178 return (int) Math.ceil(textWidthHB) + TEXT_PADDING;
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800179 }
180
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700181 private void setPaintDir(Paint paint, int dir) {
182 Log.v(TAG, "Setting Paint dir=" + dir);
183 paint.setBidiFlags(dir);
184 }
185
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700186 private void drawInsideRect(Canvas canvas, Paint paint, int color) {
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800187 paint.setColor(color);
188 int width = getWidth();
189 int height = getHeight();
190 rect.set(BORDER_PADDING, BORDER_PADDING, width - BORDER_PADDING, height - BORDER_PADDING);
191 canvas.drawRect(rect, paint);
192 }
193
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700194 private void drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB,
195 float textWidthICU, int textSize, int color, int colorICU) {
Fabrice Di Meglioc2063a52011-07-18 13:35:18 -0700196 Paint paint = new Paint();
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800197 paint.setColor(color);
198 canvas.drawLine(x, y - textSize, x, y + 8, paint);
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700199 canvas.drawLine(x, y + 8, x + textWidthHB, y + 8, paint);
200 canvas.drawLine(x + textWidthHB, y - textSize, x + textWidthHB, y + 8, paint);
201 paint.setColor(colorICU);
202 canvas.drawLine(x + textWidthICU, y - textSize, x + textWidthICU, y + 8, paint);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800203 }
204
Fabrice Di Meglioeee49c62011-03-24 17:21:23 -0700205 private void logAdvances(String text, float textWidth, float textWidthICU, float[] advances) {
206 Log.v(TAG, "Advances for text: " + text + " total= " + textWidth + " - totalICU= " + textWidthICU);
207// int length = advances.length;
208// for(int n=0; n<length; n++){
209// Log.v(TAG, "adv[" + n + "]=" + advances[n]);
210// }
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800211 }
212}