• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.bidi;
18 
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.Color;
22 import android.graphics.Paint;
23 import android.graphics.Rect;
24 import android.text.TextPaint;
25 import android.util.AttributeSet;
26 import android.util.Log;
27 import android.view.View;
28 
29 public 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;
35     private static final int TEXT_SIZE = 16;
36     private static final int ORIGIN = 80;
37 
38     private static final float DEFAULT_ITALIC_SKEW_X = -0.25f;
39 
40     private Rect rect = new Rect();
41 
42     private String NORMAL_TEXT;
43     private String NORMAL_LONG_TEXT;
44     private String NORMAL_LONG_TEXT_2;
45     private String NORMAL_LONG_TEXT_3;
46     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;
51     private String MIXED_TEXT_1;
52     private String HEBREW_TEXT;
53     private String RTL_TEXT;
54     private String THAI_TEXT;
55 
56     private int currentTextSize;
57 
BiDiTestView(Context context)58     public BiDiTestView(Context context) {
59         super(context);
60         init(context);
61     }
62 
BiDiTestView(Context context, AttributeSet attrs)63     public BiDiTestView(Context context, AttributeSet attrs) {
64         super(context, attrs);
65         init(context);
66     }
67 
BiDiTestView(Context context, AttributeSet attrs, int defStyle)68     public BiDiTestView(Context context, AttributeSet attrs, int defStyle) {
69         super(context, attrs, defStyle);
70         init(context);
71     }
72 
init(Context context)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);
76         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);
78         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);
83         MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
84         HEBREW_TEXT = context.getString(R.string.hebrew_text);
85         RTL_TEXT = context.getString(R.string.rtl);
86         THAI_TEXT = context.getString(R.string.pointer_location);
87     }
88 
setCurrentTextSize(int size)89     public void setCurrentTextSize(int size) {
90         currentTextSize = size;
91         invalidate();
92     }
93 
94     @Override
onDraw(Canvas canvas)95     public void onDraw(Canvas canvas) {
96         drawInsideRect(canvas, new Paint(), Color.BLACK);
97 
98         int deltaX = 0;
99 
100         deltaX  = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN,
101                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
102 
103         deltaX += testString(canvas, ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
104                 true, false,  Paint.DIRECTION_LTR, currentTextSize);
105 
106         deltaX += testString(canvas, BOLD_TEXT, ORIGIN + deltaX, ORIGIN,
107                 false, true,  Paint.DIRECTION_LTR, currentTextSize);
108 
109         deltaX += testString(canvas, BOLD_ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
110                 true, true,  Paint.DIRECTION_LTR, currentTextSize);
111 
112         // Test with a long string
113         deltaX = testString(canvas, NORMAL_LONG_TEXT, ORIGIN, ORIGIN + 2 * currentTextSize,
114                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
115 
116         // Test with a long string
117         deltaX = testString(canvas, NORMAL_LONG_TEXT_2, ORIGIN, ORIGIN + 4 * currentTextSize,
118                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
119 
120         // Test with a long string
121         deltaX = testString(canvas, NORMAL_LONG_TEXT_3, ORIGIN, ORIGIN + 6 * currentTextSize,
122                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
123 
124         // Test Arabic ligature
125         deltaX = testString(canvas, ARABIC_TEXT, ORIGIN, ORIGIN + 8 * currentTextSize,
126                 false, false,  Paint.DIRECTION_RTL, currentTextSize);
127 
128         // Test Chinese
129         deltaX = testString(canvas, CHINESE_TEXT, ORIGIN, ORIGIN + 10 * currentTextSize,
130                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
131 
132         // Test Mixed (English and Arabic)
133         deltaX = testString(canvas, MIXED_TEXT_1, ORIGIN, ORIGIN + 12 * currentTextSize,
134                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
135 
136         // Test Hebrew
137         deltaX = testString(canvas, RTL_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
138                 false, false,  Paint.DIRECTION_RTL, currentTextSize);
139 
140         // Test Thai
141         deltaX = testString(canvas, THAI_TEXT, ORIGIN, ORIGIN + 16 * currentTextSize,
142                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
143     }
144 
testString(Canvas canvas, String text, int x, int y, boolean isItalic, boolean isBold, int dir, int textSize)145     private int testString(Canvas canvas, String text, int x, int y,
146             boolean isItalic, boolean isBold, int dir, int textSize) {
147 
148         TextPaint paint = new TextPaint();
149         paint.setAntiAlias(true);
150 
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 
160         paint.setTextSize(textSize);
161         paint.setColor(Color.WHITE);
162         canvas.drawText(text, x, y, paint);
163 
164         int length = text.length();
165         float[] advances = new float[length];
166         float textWidthHB = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0);
167         setPaintDir(paint, dir);
168         float textWidthICU = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0,
169                 1 /* use ICU */);
170 
171         logAdvances(text, textWidthHB, textWidthICU, advances);
172         drawMetricsAroundText(canvas, x, y, textWidthHB, textWidthICU, textSize, Color.RED, Color.GREEN);
173 
174         // Restore old paint properties
175         paint.setFakeBoldText(oldFakeBold);
176         paint.setTextSkewX(oldTextSkewX);
177 
178         return (int) Math.ceil(textWidthHB) + TEXT_PADDING;
179     }
180 
setPaintDir(Paint paint, int dir)181     private void setPaintDir(Paint paint, int dir) {
182         Log.v(TAG, "Setting Paint dir=" + dir);
183         paint.setBidiFlags(dir);
184     }
185 
drawInsideRect(Canvas canvas, Paint paint, int color)186     private void drawInsideRect(Canvas canvas, Paint paint, int color) {
187         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 
drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB, float textWidthICU, int textSize, int color, int colorICU)194     private void drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB,
195             float textWidthICU, int textSize, int color, int colorICU) {
196         Paint paint = new Paint();
197         paint.setColor(color);
198         canvas.drawLine(x, y - textSize, x, y + 8, paint);
199         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);
203     }
204 
logAdvances(String text, float textWidth, float textWidthICU, float[] advances)205     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 //        }
211     }
212 }
213