• 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 
55     private int currentTextSize;
56 
BiDiTestView(Context context)57     public BiDiTestView(Context context) {
58         super(context);
59         init(context);
60     }
61 
BiDiTestView(Context context, AttributeSet attrs)62     public BiDiTestView(Context context, AttributeSet attrs) {
63         super(context, attrs);
64         init(context);
65     }
66 
BiDiTestView(Context context, AttributeSet attrs, int defStyle)67     public BiDiTestView(Context context, AttributeSet attrs, int defStyle) {
68         super(context, attrs, defStyle);
69         init(context);
70     }
71 
init(Context context)72     private void init(Context context) {
73         NORMAL_TEXT = context.getString(R.string.normal_text);
74         NORMAL_LONG_TEXT = context.getString(R.string.normal_long_text);
75         NORMAL_LONG_TEXT_2 = context.getString(R.string.normal_long_text_2);
76         NORMAL_LONG_TEXT_3 = context.getString(R.string.normal_long_text_3);
77         ITALIC_TEXT = context.getString(R.string.italic_text);
78         BOLD_TEXT = context.getString(R.string.bold_text);
79         BOLD_ITALIC_TEXT = context.getString(R.string.bold_italic_text);
80         ARABIC_TEXT = context.getString(R.string.arabic_text);
81         CHINESE_TEXT = context.getString(R.string.chinese_text);
82         MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
83         HEBREW_TEXT = context.getString(R.string.hebrew_text);
84         RTL_TEXT = context.getString(R.string.rtl);
85     }
86 
setCurrentTextSize(int size)87     public void setCurrentTextSize(int size) {
88         currentTextSize = size;
89         invalidate();
90     }
91 
92     @Override
onDraw(Canvas canvas)93     public void onDraw(Canvas canvas) {
94         drawInsideRect(canvas, new Paint(), Color.BLACK);
95 
96         int deltaX = 0;
97 
98         deltaX  = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN,
99                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
100 
101         deltaX += testString(canvas, ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
102                 true, false,  Paint.DIRECTION_LTR, currentTextSize);
103 
104         deltaX += testString(canvas, BOLD_TEXT, ORIGIN + deltaX, ORIGIN,
105                 false, true,  Paint.DIRECTION_LTR, currentTextSize);
106 
107         deltaX += testString(canvas, BOLD_ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
108                 true, true,  Paint.DIRECTION_LTR, currentTextSize);
109 
110         // Test with a long string
111         deltaX = testString(canvas, NORMAL_LONG_TEXT, ORIGIN, ORIGIN + 2 * currentTextSize,
112                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
113 
114         // Test with a long string
115         deltaX = testString(canvas, NORMAL_LONG_TEXT_2, ORIGIN, ORIGIN + 4 * currentTextSize,
116                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
117 
118         // Test with a long string
119         deltaX = testString(canvas, NORMAL_LONG_TEXT_3, ORIGIN, ORIGIN + 6 * currentTextSize,
120                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
121 
122         // Test Arabic ligature
123         deltaX = testString(canvas, ARABIC_TEXT, ORIGIN, ORIGIN + 8 * currentTextSize,
124                 false, false,  Paint.DIRECTION_RTL, currentTextSize);
125 
126         // Test Chinese
127         deltaX = testString(canvas, CHINESE_TEXT, ORIGIN, ORIGIN + 10 * currentTextSize,
128                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
129 
130         // Test Mixed (English and Arabic)
131         deltaX = testString(canvas, MIXED_TEXT_1, ORIGIN, ORIGIN + 12 * currentTextSize,
132                 false, false,  Paint.DIRECTION_LTR, currentTextSize);
133 
134         // Test Hebrew
135         deltaX = testString(canvas, RTL_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
136                 false, false,  Paint.DIRECTION_RTL, currentTextSize);
137     }
138 
testString(Canvas canvas, String text, int x, int y, boolean isItalic, boolean isBold, int dir, int textSize)139     private int testString(Canvas canvas, String text, int x, int y,
140             boolean isItalic, boolean isBold, int dir, int textSize) {
141 
142         TextPaint paint = new TextPaint();
143         paint.setAntiAlias(true);
144 
145         // Set paint properties
146         boolean oldFakeBold = paint.isFakeBoldText();
147         paint.setFakeBoldText(isBold);
148 
149         float oldTextSkewX = paint.getTextSkewX();
150         if (isItalic) {
151             paint.setTextSkewX(DEFAULT_ITALIC_SKEW_X);
152         }
153 
154         paint.setTextSize(textSize);
155         paint.setColor(Color.WHITE);
156         canvas.drawText(text, x, y, paint);
157 
158         int length = text.length();
159         float[] advances = new float[length];
160         float textWidthHB = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0);
161         setPaintDir(paint, dir);
162         float textWidthICU = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0,
163                 1 /* use ICU */);
164 
165         logAdvances(text, textWidthHB, textWidthICU, advances);
166         drawMetricsAroundText(canvas, x, y, textWidthHB, textWidthICU, textSize, Color.RED, Color.GREEN);
167 
168         // Restore old paint properties
169         paint.setFakeBoldText(oldFakeBold);
170         paint.setTextSkewX(oldTextSkewX);
171 
172         return (int) Math.ceil(textWidthHB) + TEXT_PADDING;
173     }
174 
setPaintDir(Paint paint, int dir)175     private void setPaintDir(Paint paint, int dir) {
176         Log.v(TAG, "Setting Paint dir=" + dir);
177         paint.setBidiFlags(dir);
178     }
179 
drawInsideRect(Canvas canvas, Paint paint, int color)180     private void drawInsideRect(Canvas canvas, Paint paint, int color) {
181         paint.setColor(color);
182         int width = getWidth();
183         int height = getHeight();
184         rect.set(BORDER_PADDING, BORDER_PADDING, width - BORDER_PADDING, height - BORDER_PADDING);
185         canvas.drawRect(rect, paint);
186     }
187 
drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB, float textWidthICU, int textSize, int color, int colorICU)188     private void drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB,
189             float textWidthICU, int textSize, int color, int colorICU) {
190         Paint paint = new Paint();
191         paint.setColor(color);
192         canvas.drawLine(x, y - textSize, x, y + 8, paint);
193         canvas.drawLine(x, y + 8, x + textWidthHB, y + 8, paint);
194         canvas.drawLine(x + textWidthHB, y - textSize, x + textWidthHB, y + 8, paint);
195         paint.setColor(colorICU);
196         canvas.drawLine(x + textWidthICU, y - textSize, x + textWidthICU, y + 8, paint);
197     }
198 
logAdvances(String text, float textWidth, float textWidthICU, float[] advances)199     private void logAdvances(String text, float textWidth, float textWidthICU, float[] advances) {
200         Log.v(TAG, "Advances for text: " + text + " total= " + textWidth + " - totalICU= " + textWidthICU);
201 //        int length = advances.length;
202 //        for(int n=0; n<length; n++){
203 //            Log.v(TAG, "adv[" + n + "]=" + advances[n]);
204 //        }
205     }
206 }
207