Layout.java revision 2fb503f5102dd32a8ec391b26911528852703b90
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 19105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.emoji.EmojiFactory; 20105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.graphics.Bitmap; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 24c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischerimport android.graphics.RectF; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Path; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.util.ArrayUtils; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport junit.framework.Assert; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.*; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.method.TextKeyListener; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A base class that manages text layout in visual elements on 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the screen. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>For text that will be edited, use a {@link DynamicLayout}, 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which will be updated as the text changes. 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For text that will not change, use a {@link StaticLayout}. 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class Layout { 4176c0226008ee16633dc94ed4dbeadef2174f6bd9Dave Bort private static final boolean DEBUG = false; 4271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt private static final ParagraphStyle[] NO_PARA_SPANS = 4371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt ArrayUtils.emptyArray(ParagraphStyle.class); 4476c0226008ee16633dc94ed4dbeadef2174f6bd9Dave Bort 45105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /* package */ static final EmojiFactory EMOJI_FACTORY = 46105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project EmojiFactory.newAvailableInstance(); 47105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /* package */ static final int MIN_EMOJI, MAX_EMOJI; 48105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 49105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project static { 50105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (EMOJI_FACTORY != null) { 51105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project MIN_EMOJI = EMOJI_FACTORY.getMinimumAndroidPua(); 52105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project MAX_EMOJI = EMOJI_FACTORY.getMaximumAndroidPua(); 53105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 54105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project MIN_EMOJI = -1; 55105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project MAX_EMOJI = -1; 56105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 57105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project }; 58105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 59c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer private RectF mEmojiRect; 60c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Return how wide a layout must be in order to display the 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified text with one line per paragraph. 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static float getDesiredWidth(CharSequence source, 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint paint) { 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getDesiredWidth(source, 0, source.length(), paint); 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Return how wide a layout must be in order to display the 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified text slice with one line per paragraph. 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static float getDesiredWidth(CharSequence source, 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start, int end, 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint paint) { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float need = 0; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint = new TextPaint(); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int next; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = start; i <= end; i = next) { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next = TextUtils.indexOf(source, '\n', i, end); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (next < 0) 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next = end; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // note, omits trailing paragraph char 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float w = measureText(paint, workPaint, 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project source, i, next, null, true, null); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (w > need) 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project need = w; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next++; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return need; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Subclasses of Layout use this constructor to set the display text, 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * width, and other standard properties. 10371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param text the text to render 10471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param paint the default paint for the layout. Styles can override 10571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * various attributes of the paint. 10671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param width the wrapping width for the text. 10771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param align whether to left, right, or center the text. Styles can 10871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * override the alignment. 10971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param spacingMult factor by which to scale the font size to get the 11071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * default line spacing 11171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param spacingAdd amount to add to the default line spacing 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Layout(CharSequence text, TextPaint paint, 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int width, Alignment align, 11571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt float spacingMult, float spacingAdd) { 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (width < 0) 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Layout: " + width + " < 0"); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText = text; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint = paint; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWorkPaint = new TextPaint(); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = width; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAlignment = align; 12471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt mSpacingMult = spacingMult; 12571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt mSpacingAdd = spacingAdd; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpannedText = text instanceof Spanned; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Replace constructor properties of this Layout with new ones. Be careful. 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ void replaceWith(CharSequence text, TextPaint paint, 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int width, Alignment align, 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float spacingmult, float spacingadd) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (width < 0) { 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Layout: " + width + " < 0"); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText = text; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPaint = paint; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = width; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAlignment = align; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpacingMult = spacingmult; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpacingAdd = spacingadd; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpannedText = text instanceof Spanned; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Draw this Layout on the specified Canvas. 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void draw(Canvas c) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project draw(c, null, null, 0); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 15671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Draw this Layout on the specified canvas, with the highlight path drawn 15771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * between the background and the text. 15871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * 15971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param c the canvas 16071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param highlight the path of the highlight or cursor; can be null 16171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param highlightPaint the paint for the highlight 16271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param cursorOffsetVertical the amount to temporarily translate the 16371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * canvas while rendering the highlight 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt public void draw(Canvas c, Path highlight, Paint highlightPaint, 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int cursorOffsetVertical) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dtop, dbottom; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (sTempRect) { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!c.getClipBounds(sTempRect)) { 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dtop = sTempRect.top; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dbottom = sTempRect.bottom; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int top = 0; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bottom = getLineTop(getLineCount()); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dtop > top) { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top = dtop; 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dbottom < bottom) { 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottom = dbottom; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int first = getLineForVertical(top); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int last = getLineForVertical(bottom); 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int previousLineBottom = getLineTop(first); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int previousLineEnd = getLineStart(first); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt TextPaint paint = mPaint; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence buf = mText; 19771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt int width = mWidth; 19871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt boolean spannedText = mSpannedText; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt ParagraphStyle[] spans = NO_PARA_SPANS; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanend = 0; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int textLength = 0; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // First, draw LineBackgroundSpans. 20571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // LineBackgroundSpans know nothing about the alignment or direction of 20671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // the layout or line. XXX: Should they? 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spannedText) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project textLength = buf.length(); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = first; i <= last; i++) { 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = previousLineEnd; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getLineStart(i+1); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project previousLineEnd = end; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ltop = previousLineBottom; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lbottom = getLineTop(i+1); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project previousLineBottom = lbottom; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lbaseline = lbottom - getLineDescent(i); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start >= spanend) { 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) buf; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spanend = sp.nextSpanTransition(start, textLength, 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LineBackgroundSpan.class); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spans = sp.getSpans(start, spanend, 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LineBackgroundSpan.class); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int n = 0; n < spans.length; n++) { 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LineBackgroundSpan back = (LineBackgroundSpan) spans[n]; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt back.drawBackground(c, paint, 0, width, 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ltop, lbaseline, lbottom, 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf, start, end, 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // reset to their original values 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spanend = 0; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project previousLineBottom = getLineTop(first); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project previousLineEnd = getLineStart(first); 24071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt spans = NO_PARA_SPANS; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // There can be a highlight even without spans if we are drawing 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a non-spanned transformation of a spanned editing buffer. 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (highlight != null) { 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursorOffsetVertical != 0) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.translate(0, cursorOffsetVertical); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt c.drawPath(highlight, highlightPaint); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursorOffsetVertical != 0) { 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.translate(0, -cursorOffsetVertical); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alignment align = mAlignment; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // Next draw the lines, one at a time. 26071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // the baseline is the top of the following line minus the current 26171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // line's descent. 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = first; i <= last; i++) { 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = previousLineEnd; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project previousLineEnd = getLineStart(i+1); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getLineVisibleEnd(i, start, previousLineEnd); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ltop = previousLineBottom; 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lbottom = getLineTop(i+1); 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project previousLineBottom = lbottom; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lbaseline = lbottom - getLineDescent(i); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt boolean isFirstParaLine = false; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spannedText) { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start == 0 || buf.charAt(start - 1) == '\n') { 27671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt isFirstParaLine = true; 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // New batch of paragraph styles, compute the alignment. 27971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // Last alignment style wins. 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start >= spanend) { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) buf; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spanend = sp.nextSpanTransition(start, textLength, 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ParagraphStyle.class); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spans = sp.getSpans(start, spanend, ParagraphStyle.class); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project align = mAlignment; 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int n = spans.length-1; n >= 0; n--) { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[n] instanceof AlignmentSpan) { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project align = ((AlignmentSpan) spans[n]).getAlignment(); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir = getParagraphDirection(i); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int left = 0; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int right = mWidth; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // Draw all leading margin spans. Adjust left or right according 30171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // to the paragraph direction of the line. 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spannedText) { 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int length = spans.length; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int n = 0; n < length; n++) { 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[n] instanceof LeadingMarginSpan) { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LeadingMarginSpan margin = (LeadingMarginSpan) spans[n]; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project margin.drawLeadingMargin(c, paint, right, dir, ltop, 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lbaseline, lbottom, buf, 31171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt start, end, isFirstParaLine, this); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt right -= margin.getLeadingMargin(isFirstParaLine); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project margin.drawLeadingMargin(c, paint, left, dir, ltop, 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lbaseline, lbottom, buf, 31771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt start, end, isFirstParaLine, this); 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt boolean useMargin = isFirstParaLine; 3207b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner if (margin instanceof LeadingMarginSpan.LeadingMarginSpan2) { 3217b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner int count = ((LeadingMarginSpan.LeadingMarginSpan2)margin).getLeadingMarginLineCount(); 3227b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner useMargin = count > i; 3237b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner } 3247b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner left += margin.getLeadingMargin(useMargin); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // Adjust the point at which to start rendering depending on the 33171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // alignment of the paragraph. 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int x; 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (align == Alignment.ALIGN_NORMAL) { 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_LEFT_TO_RIGHT) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = left; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = right; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int max = (int)getLineMax(i, spans, false); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (align == Alignment.ALIGN_OPPOSITE) { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = left + max; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = right - max; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Alignment.ALIGN_CENTER 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project max = max & ~1; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int half = (right - left - max) >> 1; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = right - half; 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = left + half; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Directions directions = getLineDirections(i); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean hasTab = getLineContainsTab(i); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (directions == DIRS_ALL_LEFT_TO_RIGHT && 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project !spannedText && !hasTab) { 36376c0226008ee16633dc94ed4dbeadef2174f6bd9Dave Bort if (DEBUG) { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Assert.assertTrue(dir == DIR_LEFT_TO_RIGHT); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Assert.assertNotNull(c); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // XXX: assumes there's nothing additional to be done 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(buf, start, end, x, lbaseline, paint); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project drawText(c, buf, start, end, dir, directions, 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x, ltop, lbaseline, lbottom, paint, mWorkPaint, 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hasTab, spans); 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the text that is displayed by this Layout. 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final CharSequence getText() { 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mText; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the base Paint properties for this layout. 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Do NOT change the paint, which may result in funny 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * drawing for this layout. 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final TextPaint getPaint() { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPaint; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the width of this layout. 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getWidth() { 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mWidth; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the width to which this Layout is ellipsizing, or 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getWidth} if it is not doing anything special. 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getEllipsizedWidth() { 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mWidth; 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Increase the width of this layout to the specified width. 41071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Be careful to use this only when you know it is appropriate— 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it does not cause the text to reflow to use the full new width. 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final void increaseWidthTo(int wid) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (wid < mWidth) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("attempted to reduce Layout width"); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = wid; 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the total height of this layout. 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getHeight() { 42571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt return getLineTop(getLineCount()); 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the base alignment of this layout. 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Alignment getAlignment() { 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAlignment; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return what the text height is multiplied by to get the line height. 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final float getSpacingMultiplier() { 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpacingMult; 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the number of units of leading that are added to each line. 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final float getSpacingAdd() { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpacingAdd; 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the number of lines of text in this layout. 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int getLineCount(); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the baseline for the specified line (0…getLineCount() - 1) 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If bounds is not null, return the top, left, right, bottom extents 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the specified line in it. 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param line which line to examine (0..getLineCount() - 1) 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param bounds Optional. If not null, it returns the extent of the line 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the Y-coordinate of the baseline 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLineBounds(int line, Rect bounds) { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bounds != null) { 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bounds.left = 0; // ??? 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bounds.top = getLineTop(line); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bounds.right = mWidth; // ??? 46771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt bounds.bottom = getLineTop(line + 1); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getLineBaseline(line); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 47371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Return the vertical position of the top of the specified line 47471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * (0…getLineCount()). 47571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * If the specified line is equal to the line count, returns the 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * bottom of the last line. 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int getLineTop(int line); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 48171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Return the descent of the specified line(0…getLineCount() - 1). 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int getLineDescent(int line); 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 48671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Return the text offset of the beginning of the specified line ( 48771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * 0…getLineCount()). If the specified line is equal to the line 48871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * count, returns the length of the text. 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int getLineStart(int line); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 49371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Returns the primary directionality of the paragraph containing the 49471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * specified line, either 1 for left-to-right lines, or -1 for right-to-left 49571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * lines (see {@link #DIR_LEFT_TO_RIGHT}, {@link #DIR_RIGHT_TO_LEFT}). 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int getParagraphDirection(int line); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 500105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * Returns whether the specified line contains one or more 501105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * characters that need to be handled specially, like tabs 502105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * or emoji. 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract boolean getLineContainsTab(int line); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 50771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Returns the directional run information for the specified line. 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The array alternates counts of characters in left-to-right 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and right-to-left segments of the line. 51071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * 51171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * <p>NOTE: this is inadequate to support bidirectional text, and will change. 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract Directions getLineDirections(int line); 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the (negative) number of extra pixels of ascent padding in the 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * top line of the Layout. 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int getTopPadding(); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of extra pixels of descent padding in the 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * bottom line of the Layout. 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int getBottomPadding(); 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the primary horizontal position for the specified text offset. 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is the location where a new character would be inserted in 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the paragraph's primary direction. 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float getPrimaryHorizontal(int offset) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getHorizontal(offset, false, true); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the secondary horizontal position for the specified text offset. 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is the location where a new character would be inserted in 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the direction other than the paragraph's primary direction. 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float getSecondaryHorizontal(int offset) { 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getHorizontal(offset, true, true); 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private float getHorizontal(int offset, boolean trailing, boolean alt) { 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = getLineForOffset(offset); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getHorizontal(offset, trailing, alt, line); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private float getHorizontal(int offset, boolean trailing, boolean alt, 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line) { 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = getLineStart(line); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getLineVisibleEnd(line); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir = getParagraphDirection(line); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean tab = getLineContainsTab(line); 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Directions directions = getLineDirections(line); 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TabStopSpan[] tabs = null; 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tab && mText instanceof Spanned) { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tabs = ((Spanned) mText).getSpans(start, end, TabStopSpan.class); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float wid = measureText(mPaint, mWorkPaint, mText, start, offset, end, 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dir, directions, trailing, alt, tab, tabs); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset > end) { 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wid -= measureText(mPaint, mWorkPaint, 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText, end, offset, null, tab, tabs); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wid += measureText(mPaint, mWorkPaint, 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText, end, offset, null, tab, tabs); 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alignment align = getParagraphAlignment(line); 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int left = getParagraphLeft(line); 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int right = getParagraphRight(line); 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (align == Alignment.ALIGN_NORMAL) { 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return right + wid; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return left + wid; 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float max = getLineMax(line); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (align == Alignment.ALIGN_OPPOSITE) { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return left + max + wid; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return right - max + wid; 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { /* align == Alignment.ALIGN_CENTER */ 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int imax = ((int) max) & ~1; 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return right - (((right - left) - imax) / 2) + wid; 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return left + ((right - left) - imax) / 2 + wid; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the leftmost position that should be exposed for horizontal 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * scrolling on the specified line. 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float getLineLeft(int line) { 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir = getParagraphDirection(line); 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alignment align = getParagraphAlignment(line); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (align == Alignment.ALIGN_NORMAL) { 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getParagraphRight(line) - getLineMax(line); 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (align == Alignment.ALIGN_OPPOSITE) { 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mWidth - getLineMax(line); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { /* align == Alignment.ALIGN_CENTER */ 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int left = getParagraphLeft(line); 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int right = getParagraphRight(line); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int max = ((int) getLineMax(line)) & ~1; 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return left + ((right - left) - max) / 2; 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the rightmost position that should be exposed for horizontal 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * scrolling on the specified line. 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float getLineRight(int line) { 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir = getParagraphDirection(line); 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alignment align = getParagraphAlignment(line); 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (align == Alignment.ALIGN_NORMAL) { 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mWidth; 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getParagraphLeft(line) + getLineMax(line); 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (align == Alignment.ALIGN_OPPOSITE) { 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getLineMax(line); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mWidth; 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { /* align == Alignment.ALIGN_CENTER */ 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int left = getParagraphLeft(line); 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int right = getParagraphRight(line); 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int max = ((int) getLineMax(line)) & ~1; 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return right - ((right - left) - max) / 2; 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the horizontal extent of the specified line, excluding 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * trailing whitespace. 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float getLineMax(int line) { 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getLineMax(line, null, false); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the horizontal extent of the specified line, including 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * trailing whitespace. 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float getLineWidth(int line) { 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getLineMax(line, null, true); 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private float getLineMax(int line, Object[] tabs, boolean full) { 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = getLineStart(line); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end; 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (full) { 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end = getLineEnd(line); 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end = getLineVisibleEnd(line); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean tab = getLineContainsTab(line); 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tabs == null && tab && mText instanceof Spanned) { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tabs = ((Spanned) mText).getSpans(start, end, TabStopSpan.class); 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return measureText(mPaint, mWorkPaint, 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText, start, end, null, tab, tabs); 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the line number corresponding to the specified vertical position. 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If you ask for a position above 0, you get 0; if you ask for a position 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * below the bottom of the text, you get the last line. 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FIXME: It may be faster to do a linear search for layouts without many lines. 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLineForVertical(int vertical) { 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int high = getLineCount(), low = -1, guess; 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (high - low > 1) { 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project guess = (high + low) / 2; 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getLineTop(guess) > vertical) 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project high = guess; 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project low = guess; 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (low < 0) 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return low; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the line number on which the specified text offset appears. 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If you ask for a position before 0, you get 0; if you ask for a position 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * beyond the end of the text, you get the last line. 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLineForOffset(int offset) { 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int high = getLineCount(), low = -1, guess; 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (high - low > 1) { 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project guess = (high + low) / 2; 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getLineStart(guess) > offset) 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project high = guess; 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project low = guess; 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (low < 0) 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return low; 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the character offset on the specfied line whose position is 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * closest to the specified horizontal position. 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOffsetForHorizontal(int line, float horiz) { 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int max = getLineEnd(line) - 1; 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int min = getLineStart(line); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Directions dirs = getLineDirections(line); 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line == getLineCount() - 1) 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project max++; 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 75212122bf7929aab7417cda5642632b81e4e15eb4eTakako Ishibashi if (line != getLineCount() - 1) 75312122bf7929aab7417cda5642632b81e4e15eb4eTakako Ishibashi max = TextUtils.getOffsetBefore(mText, getLineEnd(line)); 75412122bf7929aab7417cda5642632b81e4e15eb4eTakako Ishibashi 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int best = min; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float bestdist = Math.abs(getPrimaryHorizontal(best) - horiz); 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int here = min; 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < dirs.mDirections.length; i++) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int there = here + dirs.mDirections[i]; 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int swap = ((i & 1) == 0) ? 1 : -1; 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (there > max) 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project there = max; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int high = there - 1 + 1, low = here + 1 - 1, guess; 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (high - low > 1) { 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project guess = (high + low) / 2; 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int adguess = getOffsetAtStartOf(guess); 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getPrimaryHorizontal(adguess) * swap >= horiz * swap) 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project high = guess; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project low = guess; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (low < here + 1) 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project low = here + 1; 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (low < there) { 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project low = getOffsetAtStartOf(low); 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float dist = Math.abs(getPrimaryHorizontal(low) - horiz); 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int aft = TextUtils.getOffsetAfter(mText, low); 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (aft < there) { 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float other = Math.abs(getPrimaryHorizontal(aft) - horiz); 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (other < dist) { 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dist = other; 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project low = aft; 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dist < bestdist) { 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bestdist = dist; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = low; 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float dist = Math.abs(getPrimaryHorizontal(here) - horiz); 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dist < bestdist) { 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bestdist = dist; 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = here; 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project here = there; 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float dist = Math.abs(getPrimaryHorizontal(max) - horiz); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dist < bestdist) { 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bestdist = dist; 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = max; 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return best; 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the text offset after the last character on the specified line. 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getLineEnd(int line) { 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getLineStart(line + 1); 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the text offset after the last visible character (so whitespace 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is not counted) on the specified line. 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLineVisibleEnd(int line) { 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getLineVisibleEnd(line, getLineStart(line), getLineStart(line+1)); 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getLineVisibleEnd(int line, int start, int end) { 83876c0226008ee16633dc94ed4dbeadef2174f6bd9Dave Bort if (DEBUG) { 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Assert.assertTrue(getLineStart(line) == start && getLineStart(line+1) == end); 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence text = mText; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char ch; 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line == getLineCount() - 1) { 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return end; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (; end > start; end--) { 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ch = text.charAt(end - 1); 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ch == '\n') { 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return end - 1; 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ch != ' ' && ch != '\t') { 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return end; 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the vertical position of the bottom of the specified line. 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getLineBottom(int line) { 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getLineTop(line + 1); 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the vertical position of the baseline of the specified line. 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getLineBaseline(int line) { 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // getLineTop(line+1) == getLineTop(line) 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getLineTop(line+1) - getLineDescent(line); 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the ascent of the text on the specified line. 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The return value is negative to match the Paint.ascent() convention. 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getLineAscent(int line) { 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // getLineTop(line+1) - getLineDescent(line) == getLineBaseLine(line) 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getLineTop(line) - (getLineTop(line+1) - getLineDescent(line)); 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the text offset that would be reached by moving left 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (possibly onto another line) from the specified offset. 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOffsetToLeftOf(int offset) { 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = getLineForOffset(offset); 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = getLineStart(line); 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getLineEnd(line); 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Directions dirs = getLineDirections(line); 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line != getLineCount() - 1) 89912122bf7929aab7417cda5642632b81e4e15eb4eTakako Ishibashi end = TextUtils.getOffsetBefore(mText, end); 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float horiz = getPrimaryHorizontal(offset); 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int best = offset; 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float besth = Integer.MIN_VALUE; 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int candidate; 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project candidate = TextUtils.getOffsetBefore(mText, offset); 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (candidate >= start && candidate <= end) { 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = getPrimaryHorizontal(candidate); 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h < horiz && h > besth) { 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = candidate; 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project candidate = TextUtils.getOffsetAfter(mText, offset); 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (candidate >= start && candidate <= end) { 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = getPrimaryHorizontal(candidate); 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h < horiz && h > besth) { 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = candidate; 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int here = start; 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < dirs.mDirections.length; i++) { 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int there = here + dirs.mDirections[i]; 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (there > end) 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project there = end; 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = getPrimaryHorizontal(here); 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h < horiz && h > besth) { 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = here; 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project candidate = TextUtils.getOffsetAfter(mText, here); 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (candidate >= start && candidate <= end) { 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h = getPrimaryHorizontal(candidate); 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h < horiz && h > besth) { 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = candidate; 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project candidate = TextUtils.getOffsetBefore(mText, there); 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (candidate >= start && candidate <= end) { 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h = getPrimaryHorizontal(candidate); 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h < horiz && h > besth) { 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = candidate; 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project here = there; 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = getPrimaryHorizontal(end); 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h < horiz && h > besth) { 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = end; 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (best != offset) 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return best; 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir = getParagraphDirection(line); 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir > 0) { 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line == 0) 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return best; 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getOffsetForHorizontal(line - 1, 10000); 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line == getLineCount() - 1) 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return best; 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getOffsetForHorizontal(line + 1, 10000); 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the text offset that would be reached by moving right 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (possibly onto another line) from the specified offset. 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOffsetToRightOf(int offset) { 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = getLineForOffset(offset); 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = getLineStart(line); 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getLineEnd(line); 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Directions dirs = getLineDirections(line); 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line != getLineCount() - 1) 99912122bf7929aab7417cda5642632b81e4e15eb4eTakako Ishibashi end = TextUtils.getOffsetBefore(mText, end); 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float horiz = getPrimaryHorizontal(offset); 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int best = offset; 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float besth = Integer.MAX_VALUE; 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int candidate; 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project candidate = TextUtils.getOffsetBefore(mText, offset); 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (candidate >= start && candidate <= end) { 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = getPrimaryHorizontal(candidate); 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h > horiz && h < besth) { 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = candidate; 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project candidate = TextUtils.getOffsetAfter(mText, offset); 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (candidate >= start && candidate <= end) { 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = getPrimaryHorizontal(candidate); 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h > horiz && h < besth) { 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = candidate; 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int here = start; 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < dirs.mDirections.length; i++) { 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int there = here + dirs.mDirections[i]; 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (there > end) 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project there = end; 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = getPrimaryHorizontal(here); 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h > horiz && h < besth) { 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = here; 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project candidate = TextUtils.getOffsetAfter(mText, here); 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (candidate >= start && candidate <= end) { 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h = getPrimaryHorizontal(candidate); 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h > horiz && h < besth) { 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = candidate; 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project candidate = TextUtils.getOffsetBefore(mText, there); 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (candidate >= start && candidate <= end) { 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h = getPrimaryHorizontal(candidate); 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h > horiz && h < besth) { 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = candidate; 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project here = there; 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = getPrimaryHorizontal(end); 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h > horiz && h < besth) { 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project best = end; 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project besth = h; 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (best != offset) 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return best; 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir = getParagraphDirection(line); 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir > 0) { 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line == getLineCount() - 1) 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return best; 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getOffsetForHorizontal(line + 1, -10000); 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line == 0) 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return best; 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getOffsetForHorizontal(line - 1, -10000); 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getOffsetAtStartOf(int offset) { 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset == 0) 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence text = mText; 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = text.charAt(offset); 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\uDC00' && c <= '\uDFFF') { 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c1 = text.charAt(offset - 1); 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c1 >= '\uD800' && c1 <= '\uDBFF') 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offset -= 1; 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpannedText) { 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset, 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ReplacementSpan.class); 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = ((Spanned) text).getSpanStart(spans[i]); 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = ((Spanned) text).getSpanEnd(spans[i]); 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start < offset && end > offset) 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offset = start; 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return offset; 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills in the specified Path with a representation of a cursor 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * at the specified offset. This will often be a vertical line 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but can be multiple discontinous lines in text with multiple 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * directionalities. 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void getCursorPath(int point, Path dest, 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence editingBuffer) { 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.reset(); 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = getLineForOffset(point); 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int top = getLineTop(line); 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bottom = getLineTop(line+1); 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h1 = getPrimaryHorizontal(point) - 0.5f; 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h2 = getSecondaryHorizontal(point) - 0.5f; 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int caps = TextKeyListener.getMetaState(editingBuffer, 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KeyEvent.META_SHIFT_ON) | 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextKeyListener.getMetaState(editingBuffer, 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextKeyListener.META_SELECTING); 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fn = TextKeyListener.getMetaState(editingBuffer, 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KeyEvent.META_ALT_ON); 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dist = 0; 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (caps != 0 || fn != 0) { 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dist = (bottom - top) >> 2; 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fn != 0) 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top += dist; 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (caps != 0) 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottom -= dist; 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h1 < 0.5f) 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h1 = 0.5f; 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h2 < 0.5f) 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h2 = 0.5f; 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11572fb503f5102dd32a8ec391b26911528852703b90Jozef BABJAK if (Float.compare(h1, h2) == 0) { 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h1, top); 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h1, bottom); 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h1, top); 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h1, (top + bottom) >> 1); 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h2, (top + bottom) >> 1); 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h2, bottom); 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (caps == 2) { 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h2, bottom); 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h2 - dist, bottom + dist); 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h2, bottom); 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h2 + dist, bottom + dist); 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (caps == 1) { 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h2, bottom); 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h2 - dist, bottom + dist); 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h2 - dist, bottom + dist - 0.5f); 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h2 + dist, bottom + dist - 0.5f); 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h2 + dist, bottom + dist); 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h2, bottom); 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fn == 2) { 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h1, top); 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h1 - dist, top - dist); 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h1, top); 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h1 + dist, top - dist); 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (fn == 1) { 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h1, top); 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h1 - dist, top - dist); 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h1 - dist, top - dist + 0.5f); 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h1 + dist, top - dist + 0.5f); 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.moveTo(h1 + dist, top - dist); 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.lineTo(h1, top); 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void addSelection(int line, int start, int end, 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int top, int bottom, Path dest) { 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int linestart = getLineStart(line); 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lineend = getLineEnd(line); 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Directions dirs = getLineDirections(line); 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lineend > linestart && mText.charAt(lineend - 1) == '\n') 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lineend--; 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int here = linestart; 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < dirs.mDirections.length; i++) { 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int there = here + dirs.mDirections[i]; 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (there > lineend) 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project there = lineend; 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start <= there && end >= here) { 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = Math.max(start, here); 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = Math.min(end, there); 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st != en) { 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h1 = getHorizontal(st, false, false, line); 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h2 = getHorizontal(en, true, false, line); 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.addRect(h1, top, h2, bottom, Path.Direction.CW); 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project here = there; 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills in the specified Path with a representation of a highlight 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * between the specified offsets. This will often be a rectangle 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or a potentially discontinuous set of rectangles. If the start 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and end are the same, the returned path is empty. 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void getSelectionPath(int start, int end, Path dest) { 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.reset(); 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start == end) 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end < start) { 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int temp = end; 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end = start; 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start = temp; 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int startline = getLineForOffset(start); 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int endline = getLineForOffset(end); 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int top = getLineTop(startline); 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bottom = getLineBottom(endline); 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startline == endline) { 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addSelection(startline, start, end, top, bottom, dest); 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final float width = mWidth; 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addSelection(startline, start, getLineEnd(startline), 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top, getLineBottom(startline), dest); 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getParagraphDirection(startline) == DIR_RIGHT_TO_LEFT) 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.addRect(getLineLeft(startline), top, 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0, getLineBottom(startline), Path.Direction.CW); 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.addRect(getLineRight(startline), top, 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project width, getLineBottom(startline), Path.Direction.CW); 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = startline + 1; i < endline; i++) { 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top = getLineTop(i); 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottom = getLineBottom(i); 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.addRect(0, top, width, bottom, Path.Direction.CW); 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top = getLineTop(endline); 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottom = getLineBottom(endline); 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addSelection(endline, getLineStart(endline), end, 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top, bottom, dest); 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getParagraphDirection(endline) == DIR_RIGHT_TO_LEFT) 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.addRect(width, top, getLineRight(endline), bottom, Path.Direction.CW); 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.addRect(0, top, getLineLeft(endline), bottom, Path.Direction.CW); 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the alignment of the specified paragraph, taking into account 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup attached to it. 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Alignment getParagraphAlignment(int line) { 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alignment align = mAlignment; 12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpannedText) { 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) mText; 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AlignmentSpan[] spans = sp.getSpans(getLineStart(line), 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getLineEnd(line), 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AlignmentSpan.class); 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanLength = spans.length; 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanLength > 0) { 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project align = spans[spanLength-1].getAlignment(); 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return align; 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the left edge of the specified paragraph, inset by left margins. 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getParagraphLeft(int line) { 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir = getParagraphDirection(line); 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int left = 0; 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean par = false; 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int off = getLineStart(line); 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off == 0 || mText.charAt(off - 1) == '\n') 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project par = true; 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_LEFT_TO_RIGHT) { 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpannedText) { 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) mText; 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LeadingMarginSpan[] spans = sp.getSpans(getLineStart(line), 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getLineEnd(line), 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LeadingMarginSpan.class); 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 13337b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner boolean margin = par; 13347b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner LeadingMarginSpan span = spans[i]; 13357b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner if (span instanceof LeadingMarginSpan.LeadingMarginSpan2) { 13367b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner int count = ((LeadingMarginSpan.LeadingMarginSpan2)span).getLeadingMarginLineCount(); 13377b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner margin = count >= line; 13387b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner } 13397b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner left += span.getLeadingMargin(margin); 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return left; 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the right edge of the specified paragraph, inset by right margins. 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getParagraphRight(int line) { 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir = getParagraphDirection(line); 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int right = mWidth; 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean par = false; 13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int off = getLineStart(line); 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off == 0 || mText.charAt(off - 1) == '\n') 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project par = true; 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) { 13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpannedText) { 13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) mText; 13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LeadingMarginSpan[] spans = sp.getSpans(getLineStart(line), 13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getLineEnd(line), 13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LeadingMarginSpan.class); 13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project right -= spans[i].getLeadingMargin(par); 13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return right; 13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1377c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer private void drawText(Canvas canvas, 13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence text, int start, int end, 13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir, Directions directions, 13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float x, int top, int y, int bottom, 13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint paint, 13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint, 13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean hasTabs, Object[] parspans) { 13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf; 13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!hasTabs) { 13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (directions == DIRS_ALL_LEFT_TO_RIGHT) { 138776c0226008ee16633dc94ed4dbeadef2174f6bd9Dave Bort if (DEBUG) { 13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Assert.assertTrue(DIR_LEFT_TO_RIGHT == dir); 13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Styled.drawText(canvas, text, start, end, dir, false, x, top, y, bottom, paint, workPaint, false); 13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf = null; 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf = TextUtils.obtain(end - start); 13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.getChars(text, start, end, buf, 0); 13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = 0; 14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int here = 0; 14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < directions.mDirections.length; i++) { 14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int there = here + directions.mDirections[i]; 14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (there > end - start) 14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project there = end - start; 14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int segstart = here; 14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = hasTabs ? here : there; j <= there; j++) { 14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (j == there || buf[j] == '\t') { 14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h += Styled.drawText(canvas, text, 14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start + segstart, start + j, 14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dir, (i & 1) != 0, x + h, 14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top, y, bottom, paint, workPaint, 14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start + j != end); 14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (j != there && buf[j] == '\t') 14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h = dir * nextTab(text, start, end, h * dir, parspans); 14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project segstart = j + 1; 1420105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else if (hasTabs && buf[j] >= 0xD800 && buf[j] <= 0xDFFF && j + 1 < there) { 1421105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int emoji = Character.codePointAt(buf, j); 1422105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1423105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) { 1424105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Bitmap bm = EMOJI_FACTORY. 1425105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project getBitmapFromAndroidPua(emoji); 1426105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1427105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (bm != null) { 1428105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project h += Styled.drawText(canvas, text, 1429105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project start + segstart, start + j, 1430105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dir, (i & 1) != 0, x + h, 1431105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project top, y, bottom, paint, workPaint, 1432105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project start + j != end); 1433105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1434c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer if (mEmojiRect == null) { 1435c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer mEmojiRect = new RectF(); 1436c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer } 1437c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 1438c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer workPaint.set(paint); 1439c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer Styled.measureText(paint, workPaint, text, 1440c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer start + j, start + j + 1, 1441c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer null); 1442c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 1443c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer float bitmapHeight = bm.getHeight(); 1444c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer float textHeight = -workPaint.ascent(); 1445c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer float scale = textHeight / bitmapHeight; 1446c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer float width = bm.getWidth() * scale; 1447c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 1448c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer mEmojiRect.set(x + h, y - textHeight, 1449c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer x + h + width, y); 1450c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 1451c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer canvas.drawBitmap(bm, null, mEmojiRect, paint); 1452c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer h += width; 1453c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 1454105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project j++; 1455105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project segstart = j + 1; 1456105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1457105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project here = there; 14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hasTabs) 14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static float measureText(TextPaint paint, 14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint, 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence text, 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start, int offset, int end, 14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir, Directions directions, 14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean trailing, boolean alt, 14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean hasTabs, Object[] tabs) { 14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = null; 14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hasTabs) { 14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf = TextUtils.obtain(end - start); 14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.getChars(text, start, end, buf, 0); 14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = 0; 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alt) { 14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project trailing = !trailing; 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int here = 0; 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < directions.mDirections.length; i++) { 14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alt) 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project trailing = !trailing; 14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int there = here + directions.mDirections[i]; 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (there > end - start) 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project there = end - start; 14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int segstart = here; 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = hasTabs ? here : there; j <= there; j++) { 1500105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int codept = 0; 1501105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Bitmap bm = null; 1502105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1503105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (hasTabs && j < there) { 1504105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project codept = buf[j]; 1505105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1506105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1507105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (codept >= 0xD800 && codept <= 0xDFFF && j + 1 < there) { 1508105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project codept = Character.codePointAt(buf, j); 1509105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1510105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (codept >= MIN_EMOJI && codept <= MAX_EMOJI) { 1511105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project bm = EMOJI_FACTORY.getBitmapFromAndroidPua(codept); 1512105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1513105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1514105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1515105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (j == there || codept == '\t' || bm != null) { 15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float segw; 15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset < start + j || 15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (trailing && offset <= start + j)) { 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_LEFT_TO_RIGHT && (i & 1) == 0) { 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h += Styled.measureText(paint, workPaint, text, 15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start + segstart, offset, 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project null); 15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return h; 15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT && (i & 1) != 0) { 15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h -= Styled.measureText(paint, workPaint, text, 15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start + segstart, offset, 15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project null); 15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return h; 15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project segw = Styled.measureText(paint, workPaint, text, 15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start + segstart, start + j, 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project null); 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset < start + j || 15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (trailing && offset <= start + j)) { 15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_LEFT_TO_RIGHT) { 15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h += segw - Styled.measureText(paint, workPaint, 15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text, 15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start + segstart, 15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offset, null); 15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return h; 15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) { 15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h -= segw - Styled.measureText(paint, workPaint, 15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text, 15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start + segstart, 15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offset, null); 15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return h; 15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) 15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h -= segw; 15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h += segw; 15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (j != there && buf[j] == '\t') { 15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset == start + j) 15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return h; 15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project h = dir * nextTab(text, start, end, h * dir, tabs); 15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 157012122bf7929aab7417cda5642632b81e4e15eb4eTakako Ishibashi if (j != there && bm != null) { 157112122bf7929aab7417cda5642632b81e4e15eb4eTakako Ishibashi if (offset == start + j) return h; 1572c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer workPaint.set(paint); 1573c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer Styled.measureText(paint, workPaint, text, 1574a82e99a89b7a12bd86d99d60d23a7a37624499b6Eric Fischer j, j + 2, null); 1575c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 1576c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer float wid = (float) bm.getWidth() * 1577c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer -workPaint.ascent() / bm.getHeight(); 1578c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 1579105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (dir == DIR_RIGHT_TO_LEFT) { 1580c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer h -= wid; 1581105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 1582c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer h += wid; 1583105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1584105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1585105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project j++; 1586105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1587105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project segstart = j + 1; 15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project here = there; 15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hasTabs) 15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return h; 15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 160171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt /** 160271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Measure width of a run of text on a single line that is known to all be 160371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * in the same direction as the paragraph base direction. Returns the width, 160471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * and the line metrics in fm if fm is not null. 160571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * 160671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param paint the paint for the text; will not be modified 160771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param workPaint paint available for modification 160871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param text text 160971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param start start of the line 161071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param end limit of the line 161171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param fm object to return integer metrics in, can be null 161271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param hasTabs true if it is known that the line has tabs 161371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param tabs tab position information 161471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @return the width of the text from start to end 161571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt */ 16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static float measureText(TextPaint paint, 16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint workPaint, 16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence text, 16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start, int end, 16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint.FontMetricsInt fm, 16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean hasTabs, Object[] tabs) { 16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = null; 16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hasTabs) { 16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf = TextUtils.obtain(end - start); 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.getChars(text, start, end, buf, 0); 16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = end - start; 16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 163171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt int lastPos = 0; 163271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt float width = 0; 163371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt int ascent = 0, descent = 0, top = 0, bottom = 0; 16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fm != null) { 16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.ascent = 0; 16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.descent = 0; 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 164071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt for (int pos = hasTabs ? 0 : len; pos <= len; pos++) { 1641105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int codept = 0; 1642105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Bitmap bm = null; 1643105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 164471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt if (hasTabs && pos < len) { 164571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt codept = buf[pos]; 1646105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1647105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 164871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt if (codept >= 0xD800 && codept <= 0xDFFF && pos < len) { 164971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt codept = Character.codePointAt(buf, pos); 1650105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1651105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (codept >= MIN_EMOJI && codept <= MAX_EMOJI) { 1652105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project bm = EMOJI_FACTORY.getBitmapFromAndroidPua(codept); 1653105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1654105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1655105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 165671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt if (pos == len || codept == '\t' || bm != null) { 16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project workPaint.baselineShift = 0; 16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 165971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt width += Styled.measureText(paint, workPaint, text, 166071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt start + lastPos, start + pos, 16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm); 16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fm != null) { 16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (workPaint.baselineShift < 0) { 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.ascent += workPaint.baselineShift; 16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.top += workPaint.baselineShift; 16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.descent += workPaint.baselineShift; 16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.bottom += workPaint.baselineShift; 16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 167371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt if (pos != len) { 1674105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (bm == null) { 167571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // no emoji, must have hit a tab 167671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt width = nextTab(text, start, end, width, tabs); 1677105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 167871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // This sets up workPaint with the font on the emoji 167971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // text, so that we can extract the ascent and scale. 168071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt 168171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // We can't use the result of the previous call to 168271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // measureText because the emoji might have its own style. 168371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // We have to initialize workPaint here because if the 168471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // text is unstyled measureText might not use workPaint 168571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // at all. 1686c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer workPaint.set(paint); 1687c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer Styled.measureText(paint, workPaint, text, 168871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt start + pos, start + pos + 1, null); 1689c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 169071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt width += (float) bm.getWidth() * 1691c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer -workPaint.ascent() / bm.getHeight(); 1692c2d54f46ac13e029e6d53f7471cd9c90fe6bbfe9Eric Fischer 169371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // Since we had an emoji, we bump past the second half 169471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // of the surrogate pair. 169571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt pos++; 1696105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 1697105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fm != null) { 170071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt if (fm.ascent < ascent) { 170171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt ascent = fm.ascent; 17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 170371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt if (fm.descent > descent) { 170471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt descent = fm.descent; 17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fm.top < top) { 17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top = fm.top; 17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 171071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt if (fm.bottom > bottom) { 171171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt bottom = fm.bottom; 17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1713105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 171471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // No need to take bitmap height into account here, 171571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // since it is scaled to match the text height. 17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 171871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt lastPos = pos + 1; 17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fm != null) { 172371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt fm.ascent = ascent; 172471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt fm.descent = descent; 17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.top = top; 172671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt fm.bottom = bottom; 17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hasTabs) 17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 173271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt return width; 17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 173571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt /** 173671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * Returns the position of the next tab stop after h on the line. 173771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * 173871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param text the text 173971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param start start of the line 174071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param end limit of the line 174171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param h the current horizontal offset 174271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @param tabs the tabs, can be null. If it is null, any tabs in effect 174371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * on the line will be used. If there are no tabs, a default offset 174471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * will be used to compute the tab stop. 174571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt * @return the offset of the next tab stop. 174671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt */ 17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static float nextTab(CharSequence text, int start, int end, 17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h, Object[] tabs) { 17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float nh = Float.MAX_VALUE; 17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean alltabs = false; 17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text instanceof Spanned) { 17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tabs == null) { 17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tabs = ((Spanned) text).getSpans(start, end, TabStopSpan.class); 17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alltabs = true; 17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < tabs.length; i++) { 17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!alltabs) { 17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!(tabs[i] instanceof TabStopSpan)) 17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = ((TabStopSpan) tabs[i]).getTabStop(); 17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where < nh && where > h) 17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nh = where; 17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nh != Float.MAX_VALUE) 17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return nh; 17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ((int) ((h + TAB_INCREMENT) / TAB_INCREMENT)) * TAB_INCREMENT; 17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected final boolean isSpanned() { 17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpannedText; 17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ellipsize(int start, int end, int line, 17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] dest, int destoff) { 17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ellipsisCount = getEllipsisCount(line); 17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ellipsisCount == 0) { 17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ellipsisStart = getEllipsisStart(line); 17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int linestart = getLineStart(line); 17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = ellipsisStart; i < ellipsisStart + ellipsisCount; i++) { 17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c; 17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i == ellipsisStart) { 17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c = '\u2026'; // ellipsis 17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c = '\uFEFF'; // 0-width space 17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int a = i + linestart; 18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a >= start && a < end) { 18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest[destoff + a - start] = c; 18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Stores information about bidirectional (left-to-right or right-to-left) 18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * text within the layout of a line. TODO: This work is not complete 18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or correct and will be fleshed out in a later revision. 18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class Directions { 18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private short[] mDirections; 18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 181771b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // The values in mDirections are the offsets from the first character 181871b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // in the line to the next flip in direction. Runs at even indices 181971b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // are left-to-right, the others are right-to-left. So, for example, 182071b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // a line that starts with a right-to-left run has 0 at mDirections[0], 182171b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // since the 'first' (ltr) run is zero length. 182271b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // 182371b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // The code currently assumes that each run is adjacent to the previous 182471b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // one, progressing in the base line direction. This isn't sufficient 182571b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // to handle nested runs, for example numeric text in an rtl context 182671b8dd71e49016e057c46a257f79162d186a3c3aDoug Felt // in an ltr paragraph. 18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ Directions(short[] dirs) { 18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDirections = dirs; 18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the offset of the first character to be ellipsized away, 18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * relative to the start of the line. (So 0 if the beginning of the 18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * line is ellipsized, not getLineStart().) 18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int getEllipsisStart(int line); 18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of characters to be ellipsized away, or 0 if 18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * no ellipsis is to take place. 18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract int getEllipsisCount(int line); 18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static class Ellipsizer implements CharSequence, GetChars { 18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ CharSequence mText; 18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ Layout mLayout; 18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ int mWidth; 18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ TextUtils.TruncateAt mMethod; 18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Ellipsizer(CharSequence s) { 18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText = s; 18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public char charAt(int off) { 18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(1); 18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(off, off + 1, buf, 0); 18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char ret = buf[0]; 18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void getChars(int start, int end, char[] dest, int destoff) { 18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line1 = mLayout.getLineForOffset(start); 18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line2 = mLayout.getLineForOffset(end); 18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.getChars(mText, start, end, dest, destoff); 18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = line1; i <= line2; i++) { 18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayout.ellipsize(start, end, i, dest, destoff); 18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int length() { 18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mText.length(); 18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence subSequence(int start, int end) { 18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] s = new char[end - start]; 18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, s, 0); 18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new String(s); 18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] s = new char[length()]; 18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(0, length(), s, 0); 18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new String(s); 18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static class SpannedEllipsizer 18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extends Ellipsizer implements Spanned { 18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Spanned mSpanned; 18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannedEllipsizer(CharSequence display) { 18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(display); 18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanned = (Spanned) display; 18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public <T> T[] getSpans(int start, int end, Class<T> type) { 19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpanned.getSpans(start, end, type); 19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanStart(Object tag) { 19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpanned.getSpanStart(tag); 19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanEnd(Object tag) { 19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpanned.getSpanEnd(tag); 19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanFlags(Object tag) { 19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpanned.getSpanFlags(tag); 19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int nextSpanTransition(int start, int limit, Class type) { 19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpanned.nextSpanTransition(start, limit, type); 19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence subSequence(int start, int end) { 19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] s = new char[end - start]; 19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, s, 0); 19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpannableString ss = new SpannableString(new String(s)); 19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.copySpansFrom(mSpanned, start, end, Object.class, ss, 0); 19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ss; 19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CharSequence mText; 19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private TextPaint mPaint; 19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ TextPaint mWorkPaint; 19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mWidth; 19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Alignment mAlignment = Alignment.ALIGN_NORMAL; 19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private float mSpacingMult; 19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private float mSpacingAdd; 19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Rect sTempRect = new Rect(); 19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mSpannedText; 19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int DIR_LEFT_TO_RIGHT = 1; 19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int DIR_RIGHT_TO_LEFT = -1; 194320178d62cf669af18467a16d3c4c4237ed42151cDoug Felt 194420178d62cf669af18467a16d3c4c4237ed42151cDoug Felt /* package */ static final int DIR_REQUEST_LTR = 1; 194520178d62cf669af18467a16d3c4c4237ed42151cDoug Felt /* package */ static final int DIR_REQUEST_RTL = -1; 194620178d62cf669af18467a16d3c4c4237ed42151cDoug Felt /* package */ static final int DIR_REQUEST_DEFAULT_LTR = 2; 194720178d62cf669af18467a16d3c4c4237ed42151cDoug Felt /* package */ static final int DIR_REQUEST_DEFAULT_RTL = -2; 19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public enum Alignment { 19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALIGN_NORMAL, 19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALIGN_OPPOSITE, 19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALIGN_CENTER, 19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // XXX ALIGN_LEFT, 19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // XXX ALIGN_RIGHT, 19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int TAB_INCREMENT = 20; 19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static final Directions DIRS_ALL_LEFT_TO_RIGHT = 19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Directions(new short[] { 32767 }); 19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ static final Directions DIRS_ALL_RIGHT_TO_LEFT = 19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Directions(new short[] { 0, 32767 }); 19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1965