Styled.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.text; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.CharacterStyle; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.MetricAffectingSpan; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.ReplacementSpan; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class provides static methods for drawing and measuring styled texts, like 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.text.Spanned} object with {@link android.text.style.ReplacementSpan}. 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Styled 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static float each(Canvas canvas, 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned text, int start, int end, 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir, boolean reverse, 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float x, int top, int y, int bottom, 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint.FontMetricsInt fmi, 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint paint, 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint, 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean needwid) { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean havewid = false; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float ret = 0; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharacterStyle[] spans = text.getSpans(start, end, CharacterStyle.class); 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ReplacementSpan replacement = null; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.bgColor = 0; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.baselineShift = 0; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.set(paint); 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans.length > 0) { 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharacterStyle span = spans[i]; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (span instanceof ReplacementSpan) { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replacement = (ReplacementSpan)span; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span.updateDrawState(workPaint); 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (replacement == null) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence tmp; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int tmpstart, tmpend; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (reverse) { 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tmp = TextUtils.getReverse(text, start, end); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tmpstart = 0; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tmpend = end - start; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tmp = text; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tmpstart = start; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tmpend = end; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fmi != null) { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.getFontMetricsInt(fmi); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (canvas != null) { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (workPaint.bgColor != 0) { 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int c = workPaint.getColor(); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint.Style s = workPaint.getStyle(); 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.setColor(workPaint.bgColor); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.setStyle(Paint.Style.FILL); 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!havewid) { 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = workPaint.measureText(tmp, tmpstart, tmpend); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project havewid = true; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == Layout.DIR_RIGHT_TO_LEFT) 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawRect(x - ret, top, x, bottom, workPaint); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawRect(x, top, x + ret, bottom, workPaint); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.setStyle(s); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.setColor(c); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == Layout.DIR_RIGHT_TO_LEFT) { 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!havewid) { 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = workPaint.measureText(tmp, tmpstart, tmpend); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project havewid = true; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawText(tmp, tmpstart, tmpend, 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x - ret, y + workPaint.baselineShift, workPaint); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needwid) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!havewid) { 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = workPaint.measureText(tmp, tmpstart, tmpend); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project havewid = true; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawText(tmp, tmpstart, tmpend, 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x, y + workPaint.baselineShift, workPaint); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needwid && !havewid) { 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = workPaint.measureText(tmp, tmpstart, tmpend); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project havewid = true; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = replacement.getSize(workPaint, text, start, end, fmi); 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (canvas != null) { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == Layout.DIR_RIGHT_TO_LEFT) 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replacement.draw(canvas, text, start, end, 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x - ret, top, y, bottom, workPaint); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replacement.draw(canvas, text, start, end, 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x, top, y, bottom, workPaint); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == Layout.DIR_RIGHT_TO_LEFT) 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -ret; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the advance widths for the characters in the string. 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See also {@link android.graphics.Paint#getTextWidths(CharSequence, int, int, float[])}. 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param paint The main {@link TextPaint} object. 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param workPaint The {@link TextPaint} object used for temporal workspace. 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text The text to measure 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param start The index of the first char to to measure 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param end The end of the text slice to measure 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param widths Array to receive the advance widths of the characters. 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Must be at least a large as (end - start). 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param fmi FontMetrics information. Can be null. 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The actual number of widths returned. 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getTextWidths(TextPaint paint, 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint, 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned text, int start, int end, 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float[] widths, Paint.FontMetricsInt fmi) { 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Keep workPaint as is so that developers reuse the workspace. 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MetricAffectingSpan[] spans = text.getSpans(start, end, MetricAffectingSpan.class); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ReplacementSpan replacement = null; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.set(paint); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MetricAffectingSpan span = spans[i]; 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (span instanceof ReplacementSpan) { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replacement = (ReplacementSpan)span; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project span.updateMeasureState(workPaint); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (replacement == null) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.getFontMetricsInt(fmi); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.getTextWidths(text, start, end, widths); 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int wid = replacement.getSize(workPaint, text, start, end, fmi); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end > start) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widths[0] = wid; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = start + 1; i < end; i++) 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widths[i - start] = 0; 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return end - start; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static float foreach(Canvas canvas, 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence text, int start, int end, 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir, boolean reverse, 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float x, int top, int y, int bottom, 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint.FontMetricsInt fmi, 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint paint, 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint, 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean needWidth) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (! (text instanceof Spanned)) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float ret = 0; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (reverse) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence tmp = TextUtils.getReverse(text, start, end); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int tmpend = end - start; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (canvas != null || needWidth) 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = paint.measureText(tmp, 0, tmpend); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (canvas != null) 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawText(tmp, 0, tmpend, 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x - ret, y, paint); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needWidth) 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = paint.measureText(text, start, end); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (canvas != null) 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawText(text, start, end, x, y, paint); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fmi != null) { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.getFontMetricsInt(fmi); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret * dir; //Layout.DIR_RIGHT_TO_LEFT == -1 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float ox = x; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int asc = 0, desc = 0; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ftop = 0, fbot = 0; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) text; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Class division; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (canvas == null) 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project division = MetricAffectingSpan.class; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project division = CharacterStyle.class; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int next; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = start; i < end; i = next) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next = sp.nextSpanTransition(i, end, division); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x += each(canvas, sp, i, next, dir, reverse, 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x, top, y, bottom, fmi, paint, workPaint, 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project needWidth || next != end); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fmi != null) { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fmi.ascent < asc) 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asc = fmi.ascent; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fmi.descent > desc) 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project desc = fmi.descent; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fmi.top < ftop) 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ftop = fmi.top; 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fmi.bottom > fbot) 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fbot = fmi.bottom; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fmi != null) { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start == end) { 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.getFontMetricsInt(fmi); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fmi.ascent = asc; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fmi.descent = desc; 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fmi.top = ftop; 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fmi.bottom = fbot; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return x - ox; 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static float drawText(Canvas canvas, 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence text, int start, int end, 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int direction, boolean reverse, 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float x, int top, int y, int bottom, 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint paint, 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint, 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean needWidth) { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((direction == Layout.DIR_RIGHT_TO_LEFT && !reverse) || 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (reverse && direction == Layout.DIR_LEFT_TO_RIGHT)) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float ch = foreach(null, text, start, end, Layout.DIR_LEFT_TO_RIGHT, 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project false, 0, 0, 0, 0, null, paint, workPaint, 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ch *= direction; // DIR_RIGHT_TO_LEFT == -1 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foreach(canvas, text, start, end, -direction, 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project reverse, x + ch, top, y, bottom, null, paint, 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint, true); 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ch; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return foreach(canvas, text, start, end, direction, reverse, 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x, top, y, bottom, null, paint, workPaint, 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project needWidth); 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Draw the specified range of text, specified by start/end, with its origin at (x,y), 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the specified Paint. The origin is interpreted based on the Align setting in the 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Paint. 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method considers style information in the text 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (e.g. Even when text is an instance of {@link android.text.Spanned}, this method 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * correctly draws the text). 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See also 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.graphics.Canvas#drawText(CharSequence, int, int, float, float, Paint)} 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.graphics.Canvas#drawRect(float, float, float, float, Paint)}. 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param canvas The target canvas. 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text The text to be drawn 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param start The index of the first character in text to draw 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param end (end - 1) is the index of the last character in text to draw 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction The direction of the text. This must be 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.text.Layout#DIR_LEFT_TO_RIGHT} or 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.text.Layout#DIR_RIGHT_TO_LEFT}. 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param x The x-coordinate of origin for where to draw the text 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param top The top side of the rectangle to be drawn 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y The y-coordinate of origin for where to draw the text 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param bottom The bottom side of the rectangle to be drawn 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param paint The main {@link TextPaint} object. 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param workPaint The {@link TextPaint} object used for temporal workspace. 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param needWidth If true, this method returns the width of drawn text. 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Width of the drawn text if needWidth is true. 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static float drawText(Canvas canvas, 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence text, int start, int end, 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int direction, 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float x, int top, int y, int bottom, 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint paint, 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint, 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean needWidth) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // For safety. 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project direction = direction >= 0 ? Layout.DIR_LEFT_TO_RIGHT : Layout.DIR_RIGHT_TO_LEFT; 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Hided "reverse" parameter since it is meaningless for external developers. 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Kept workPaint as is so that developers reuse the workspace. 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return drawText(canvas, text, start, end, direction, false, 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x, top, y, bottom, paint, workPaint, needWidth); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the width of the text, considering style information in the text 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (e.g. Even when text is an instance of {@link android.text.Spanned}, this method 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * correctly mesures the width of the text). 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param paint The main {@link TextPaint} object. 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param workPaint The {@link TextPaint} object used for temporal workspace. 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param text The text to measure 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param start The index of the first character to start measuring 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param end 1 beyond the index of the last character to measure 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param fmi FontMetrics information. Can be null 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The width of the text 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static float measureText(TextPaint paint, 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint, 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence text, int start, int end, 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint.FontMetricsInt fmi) { 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Keep workPaint as is so that developers reuse the workspace. 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return foreach(null, text, start, end, 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Layout.DIR_LEFT_TO_RIGHT, false, 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0, 0, 0, 0, fmi, paint, workPaint, true); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 376