StaticLayout.java revision 121c82c8130c2658f73fb19f3a62eb88c8679968
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 194e0c5e55e171532760d5f51e0165563827129d4eDoug Feltimport com.android.internal.util.ArrayUtils; 204e0c5e55e171532760d5f51e0165563827129d4eDoug Felt 21105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.graphics.Bitmap; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.LeadingMarginSpan; 246611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunneimport android.text.style.LeadingMarginSpan.LeadingMarginSpan2; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.LineHeightSpan; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.MetricAffectingSpan; 27c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Feltimport android.text.style.TabStopSpan; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * StaticLayout is a Layout for text that will not be edited after it 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is laid out. Use {@link DynamicLayout} for text that may change. 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>This is used by widgets to control text layout. You should not need 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to use this class directly unless you are implementing your own widget 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or custom display object, or would be tempted to call 354e0c5e55e171532760d5f51e0165563827129d4eDoug Felt * {@link android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, 364e0c5e55e171532760d5f51e0165563827129d4eDoug Felt * float, float, android.graphics.Paint) 374e0c5e55e171532760d5f51e0165563827129d4eDoug Felt * Canvas.drawText()} directly.</p> 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 39121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Megliopublic class StaticLayout extends Layout { 40121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public StaticLayout(CharSequence source, TextPaint paint, 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int width, 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alignment align, float spacingmult, float spacingadd, 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean includepad) { 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(source, 0, source.length(), paint, width, align, 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spacingmult, spacingadd, includepad); 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public StaticLayout(CharSequence source, int bufstart, int bufend, 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint paint, int outerwidth, 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alignment align, 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float spacingmult, float spacingadd, 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean includepad) { 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(source, bufstart, bufend, paint, outerwidth, align, 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spacingmult, spacingadd, includepad, null, 0); 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public StaticLayout(CharSequence source, int bufstart, int bufend, 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextPaint paint, int outerwidth, 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alignment align, 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float spacingmult, float spacingadd, 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean includepad, 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.TruncateAt ellipsize, int ellipsizedWidth) { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super((ellipsize == null) 654e0c5e55e171532760d5f51e0165563827129d4eDoug Felt ? source 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : (source instanceof Spanned) 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? new SpannedEllipsizer(source) 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : new Ellipsizer(source), 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint, outerwidth, align, spacingmult, spacingadd); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is annoying, but we can't refer to the layout until 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * superclass construction is finished, and the superclass 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * constructor wants the reference to the display text. 754e0c5e55e171532760d5f51e0165563827129d4eDoug Felt * 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This will break if the superclass constructor ever actually 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cares about the content instead of just holding the reference. 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ellipsize != null) { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Ellipsizer e = (Ellipsizer) getText(); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project e.mLayout = this; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project e.mWidth = ellipsizedWidth; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project e.mMethod = ellipsize; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEllipsizedWidth = ellipsizedWidth; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mColumns = COLUMNS_ELLIPSIZE; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mColumns = COLUMNS_NORMAL; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEllipsizedWidth = outerwidth; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)]; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLineDirections = new Directions[ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayUtils.idealIntArraySize(2 * mColumns)]; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 97e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mMeasured = MeasuredText.obtain(); 98e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project generate(source, bufstart, bufend, paint, outerwidth, align, 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spacingmult, spacingadd, includepad, includepad, 1010a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne ellipsizedWidth, ellipsize); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 103e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mMeasured = MeasuredText.recycle(mMeasured); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFontMetricsInt = null; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ StaticLayout(boolean ellipsize) { 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(null, null, 0, null, 0, 0); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mColumns = COLUMNS_ELLIPSIZE; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)]; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLineDirections = new Directions[ 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayUtils.idealIntArraySize(2 * mColumns)]; 114e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mMeasured = MeasuredText.obtain(); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 117121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio /* package */ void generate(CharSequence source, int bufStart, int bufEnd, 118121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio TextPaint paint, int outerWidth, 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alignment align, 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float spacingmult, float spacingadd, 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean includepad, boolean trackpad, 1220a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne float ellipsizedWidth, TextUtils.TruncateAt ellipsize) { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLineCount = 0; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int v = 0; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean needMultiply = (spacingmult != 1 || spacingadd != 0); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint.FontMetricsInt fm = mFontMetricsInt; 129121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int[] chooseHtv = null; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 131e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt MeasuredText measured = mMeasured; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned spanned = null; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (source instanceof Spanned) 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spanned = (Spanned) source; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int DEFAULT_DIR = DIR_LEFT_TO_RIGHT; // XXX 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 139e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int paraEnd; 140121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio for (int paraStart = bufStart; paraStart <= bufEnd; paraStart = paraEnd) { 141121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio paraEnd = TextUtils.indexOf(source, CHAR_NEW_LINE, paraStart, bufEnd); 142e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (paraEnd < 0) 143121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio paraEnd = bufEnd; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 145e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt paraEnd++; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 147c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt int firstWidthLineLimit = mLineCount + 1; 148121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int firstWidth = outerWidth; 149121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int restWidth = outerWidth; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 151121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio LineHeightSpan[] chooseHt = null; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanned != null) { 15474d31ef2b2c42b54fa1f7cf94ea955ea67ab69a0Eric Fischer LeadingMarginSpan[] sp = getParagraphSpans(spanned, paraStart, paraEnd, 155e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt LeadingMarginSpan.class); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < sp.length; i++) { 1577b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner LeadingMarginSpan lms = sp[i]; 158121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio firstWidth -= sp[i].getLeadingMargin(true); 159121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio restWidth -= sp[i].getLeadingMargin(false); 160c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt 161c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt // LeadingMarginSpan2 is odd. The count affects all 162c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt // leading margin spans, not just this particular one, 163c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt // and start from the top of the span, not the top of the 164c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt // paragraph. 165c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt if (lms instanceof LeadingMarginSpan2) { 166c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt LeadingMarginSpan2 lms2 = (LeadingMarginSpan2) lms; 167c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt int lmsFirstLine = getLineForOffset(spanned.getSpanStart(lms2)); 168121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio firstWidthLineLimit = lmsFirstLine + lms2.getLeadingMarginLineCount(); 1697b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 172121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHt = getParagraphSpans(spanned, paraStart, paraEnd, LineHeightSpan.class); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 174121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (chooseHt.length != 0) { 175121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (chooseHtv == null || 176121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHtv.length < chooseHt.length) { 177121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHtv = new int[ArrayUtils.idealIntArraySize( 178121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHt.length)]; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 181121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio for (int i = 0; i < chooseHt.length; i++) { 182121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int o = spanned.getSpanStart(chooseHt[i]); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 184e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (o < paraStart) { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // starts in this layout, before the 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // current paragraph 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 188121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHtv[i] = getLineTop(getLineForOffset(o)); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // starts in this paragraph 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 192121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHtv[i] = v; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 198e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt measured.setPara(source, paraStart, paraEnd, DIR_REQUEST_DEFAULT_LTR); 199e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt char[] chs = measured.mChars; 200e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float[] widths = measured.mWidths; 201e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt byte[] chdirs = measured.mLevels; 202e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int dir = measured.mDir; 203e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt boolean easy = measured.mEasy; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 205121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int width = firstWidth; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float w = 0; 208e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int here = paraStart; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 210e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int ok = paraStart; 211121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float okWidth = w; 212121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int okAscent = 0, okDescent = 0, okTop = 0, okBottom = 0; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 214e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int fit = paraStart; 215121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float fitWidth = w; 216121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int fitAscent = 0, fitDescent = 0, fitTop = 0, fitBottom = 0; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 218c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt boolean hasTabOrEmoji = false; 219c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt boolean hasTab = false; 220c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt TabStops tabStops = null; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22223241887515ed77687c23e29a4a3ffff671666bdDoug Felt for (int spanStart = paraStart, spanEnd = spanStart, nextSpanStart; 22323241887515ed77687c23e29a4a3ffff671666bdDoug Felt spanStart < paraEnd; spanStart = nextSpanStart) { 22423241887515ed77687c23e29a4a3ffff671666bdDoug Felt 22523241887515ed77687c23e29a4a3ffff671666bdDoug Felt if (spanStart == spanEnd) { 22623241887515ed77687c23e29a4a3ffff671666bdDoug Felt if (spanned == null) 22723241887515ed77687c23e29a4a3ffff671666bdDoug Felt spanEnd = paraEnd; 22823241887515ed77687c23e29a4a3ffff671666bdDoug Felt else 22923241887515ed77687c23e29a4a3ffff671666bdDoug Felt spanEnd = spanned.nextSpanTransition(spanStart, paraEnd, 23023241887515ed77687c23e29a4a3ffff671666bdDoug Felt MetricAffectingSpan.class); 23123241887515ed77687c23e29a4a3ffff671666bdDoug Felt 23223241887515ed77687c23e29a4a3ffff671666bdDoug Felt int spanLen = spanEnd - spanStart; 23323241887515ed77687c23e29a4a3ffff671666bdDoug Felt if (spanned == null) { 23423241887515ed77687c23e29a4a3ffff671666bdDoug Felt measured.addStyleRun(paint, spanLen, fm); 23523241887515ed77687c23e29a4a3ffff671666bdDoug Felt } else { 23623241887515ed77687c23e29a4a3ffff671666bdDoug Felt MetricAffectingSpan[] spans = 23723241887515ed77687c23e29a4a3ffff671666bdDoug Felt spanned.getSpans(spanStart, spanEnd, MetricAffectingSpan.class); 23823241887515ed77687c23e29a4a3ffff671666bdDoug Felt measured.addStyleRun(paint, spans, spanLen, fm); 23923241887515ed77687c23e29a4a3ffff671666bdDoug Felt } 24023241887515ed77687c23e29a4a3ffff671666bdDoug Felt } 24123241887515ed77687c23e29a4a3ffff671666bdDoug Felt 24223241887515ed77687c23e29a4a3ffff671666bdDoug Felt nextSpanStart = spanEnd; 2434e0c5e55e171532760d5f51e0165563827129d4eDoug Felt 244121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int fmTop = fm.top; 245121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int fmBottom = fm.bottom; 246121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int fmAscent = fm.ascent; 247121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int fmDescent = fm.descent; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int j = spanStart; j < spanEnd; j++) { 250e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt char c = chs[j - paraStart]; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 252121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (c == CHAR_NEW_LINE) { 2536611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne // intentionally left empty 254121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio } else if (c == CHAR_TAB) { 255c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt if (hasTab == false) { 256c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt hasTab = true; 257c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt hasTabOrEmoji = true; 25824ca4545f3fa9ffaf0a84af11f1ab74cd14d232eKenny Root if (spanned != null) { 25924ca4545f3fa9ffaf0a84af11f1ab74cd14d232eKenny Root // First tab this para, check for tabstops 26074d31ef2b2c42b54fa1f7cf94ea955ea67ab69a0Eric Fischer TabStopSpan[] spans = getParagraphSpans(spanned, paraStart, 26124ca4545f3fa9ffaf0a84af11f1ab74cd14d232eKenny Root paraEnd, TabStopSpan.class); 26224ca4545f3fa9ffaf0a84af11f1ab74cd14d232eKenny Root if (spans.length > 0) { 26324ca4545f3fa9ffaf0a84af11f1ab74cd14d232eKenny Root tabStops = new TabStops(TAB_INCREMENT, spans); 26424ca4545f3fa9ffaf0a84af11f1ab74cd14d232eKenny Root } 265c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt } 266c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt } 267c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt if (tabStops != null) { 268c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt w = tabStops.nextTab(w); 269c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt } else { 270c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt w = TabStops.nextDefaultStop(w, TAB_INCREMENT); 271c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt } 272121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio } else if (c >= CHAR_FIRST_HIGH_SURROGATE && c <= CHAR_LAST_LOW_SURROGATE 273121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio && j + 1 < spanEnd) { 274e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int emoji = Character.codePointAt(chs, j - paraStart); 275105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 276105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) { 2770a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne Bitmap bm = EMOJI_FACTORY.getBitmapFromAndroidPua(emoji); 278105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 279105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (bm != null) { 280423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer Paint whichPaint; 281423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer 282423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer if (spanned == null) { 283423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer whichPaint = paint; 284423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer } else { 285423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer whichPaint = mWorkPaint; 286423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer } 287423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer 2884e0c5e55e171532760d5f51e0165563827129d4eDoug Felt float wid = bm.getWidth() * 289423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer -whichPaint.ascent() / 290423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer bm.getHeight(); 291423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer 292423f0e4205e3c49c6a87b389fa6025772aa7010cEric Fischer w += wid; 293c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt hasTabOrEmoji = true; 294105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project j++; 295105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 296e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt w += widths[j - paraStart]; 297105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 298105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 299e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt w += widths[j - paraStart]; 300105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 301105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 302e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt w += widths[j - paraStart]; 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Log.e("text", "was " + before + " now " + w + " after " + c + " within " + width); 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (w <= width) { 308121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitWidth = w; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fit = j + 1; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 311121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fmTop < fitTop) 312121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitTop = fmTop; 313121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fmAscent < fitAscent) 314121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitAscent = fmAscent; 315121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fmDescent > fitDescent) 316121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitDescent = fmDescent; 317121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fmBottom > fitBottom) 318121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitBottom = fmBottom; 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * From the Unicode Line Breaking Algorithm: 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (at least approximately) 3234e0c5e55e171532760d5f51e0165563827129d4eDoug Felt * 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * .,:; are class IS: breakpoints 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * except when adjacent to digits 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * / is class SY: a breakpoint 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * except when followed by a digit. 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - is class HY: a breakpoint 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * except when followed by a digit. 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 331549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer * Ideographs are class ID: breakpoints when adjacent, 332549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer * except for NS (non-starters), which can be broken 333549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer * after but not before. 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 336121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (c == CHAR_SPACE || c == CHAR_TAB || 337121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio ((c == CHAR_DOT || c == CHAR_COMMA || 338121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio c == CHAR_COLON || c == CHAR_SEMICOLON) && 339e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt (j - 1 < here || !Character.isDigit(chs[j - 1 - paraStart])) && 340e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) || 341121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio ((c == CHAR_SLASH || c == CHAR_HYPHEN) && 342e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) || 343121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio (c >= CHAR_FIRST_CJK && isIdeographic(c, true) && 344e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt j + 1 < spanEnd && isIdeographic(chs[j + 1 - paraStart], false))) { 345121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio okWidth = w; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ok = j + 1; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 348121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fitTop < okTop) 349121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio okTop = fitTop; 350121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fitAscent < okAscent) 351121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio okAscent = fitAscent; 352121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fitDescent > okDescent) 353121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio okDescent = fitDescent; 354121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fitBottom > okBottom) 355121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio okBottom = fitBottom; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 357d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne } else { 3580a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne if (ellipsize != null) { 3590a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne // Break only at spaces using ok indexes. 360d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne if (ok != here) { 361d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne // Log.e("text", "output ok " + here + " to " +ok); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 363121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio while (ok < spanEnd && chs[ok - paraStart] == CHAR_SPACE) { 364d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne ok++; 365d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne } 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 367d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne v = out(source, 368d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne here, ok, 369121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio okAscent, okDescent, okTop, okBottom, 370d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne v, 371121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio spacingmult, spacingadd, chooseHt, 372121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHtv, fm, hasTabOrEmoji, 373d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne needMultiply, paraStart, chdirs, dir, easy, 374121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio ok == bufEnd, includepad, trackpad, 375d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne chs, widths, here - paraStart, 376121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio ellipsize, ellipsizedWidth, okWidth, 377d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne paint); 378d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne 379d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne here = ok; 380d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne } else { 381d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne // Act like it fit even though it didn't. 382d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne 383121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitWidth = w; 384d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne here = fit = j + 1; 385d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne 386121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fmTop < fitTop) 387121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitTop = fmTop; 388121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fmAscent < fitAscent) 389121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitAscent = fmAscent; 390121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fmDescent > fitDescent) 391121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitDescent = fmDescent; 392121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (fmBottom > fitBottom) 393121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitBottom = fmBottom; 394d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne } 3954cf435df2e485e405f085982ac8fd9c82fb57d47Gilles Debunne } else { 396d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne if (ok != here) { 397d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne // Log.e("text", "output ok " + here + " to " +ok); 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio while (ok < spanEnd && chs[ok - paraStart] == CHAR_SPACE) { 400d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne ok++; 401d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne } 4024cf435df2e485e405f085982ac8fd9c82fb57d47Gilles Debunne 403d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne v = out(source, 404d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne here, ok, 405121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio okAscent, okDescent, okTop, okBottom, 406d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne v, 407121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio spacingmult, spacingadd, chooseHt, 408121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHtv, fm, hasTabOrEmoji, 409d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne needMultiply, paraStart, chdirs, dir, easy, 410121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio ok == bufEnd, includepad, trackpad, 411d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne chs, widths, here - paraStart, 412121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio ellipsize, ellipsizedWidth, okWidth, 413d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne paint); 414d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne 415d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne here = ok; 416d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne } else if (fit != here) { 417d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne // Log.e("text", "output fit " + here + " to " +fit); 418d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne v = out(source, 419d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne here, fit, 420121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitAscent, fitDescent, 421121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitTop, fitBottom, 422d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne v, 423121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio spacingmult, spacingadd, chooseHt, 424121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHtv, fm, hasTabOrEmoji, 425d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne needMultiply, paraStart, chdirs, dir, easy, 426121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fit == bufEnd, includepad, trackpad, 427d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne chs, widths, here - paraStart, 428121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio ellipsize, ellipsizedWidth, fitWidth, 429d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne paint); 430d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne 431d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne here = fit; 432d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne } else { 433d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne // Log.e("text", "output one " + here + " to " +(here + 1)); 434d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne // XXX not sure why the existing fm wasn't ok. 435d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne // measureText(paint, mWorkPaint, 436d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne // source, here, here + 1, fm, tab, 437d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne // null); 438d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne 439d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne v = out(source, 440d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne here, here+1, 441d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne fm.ascent, fm.descent, 442d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne fm.top, fm.bottom, 443d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne v, 444121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio spacingmult, spacingadd, chooseHt, 445121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHtv, fm, hasTabOrEmoji, 446d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne needMultiply, paraStart, chdirs, dir, easy, 447121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio here + 1 == bufEnd, includepad, 448d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne trackpad, 449d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne chs, widths, here - paraStart, 4500a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne ellipsize, ellipsizedWidth, 451d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne widths[here - paraStart], paint); 452d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne 453d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne here = here + 1; 454d434d2334d2362f77d3a3fb0b1f788f667039bbfGilles Debunne } 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 457e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (here < spanStart) { 45823241887515ed77687c23e29a4a3ffff671666bdDoug Felt // didn't output all the text for this span 45923241887515ed77687c23e29a4a3ffff671666bdDoug Felt // we've measured the raw widths, though, so 46023241887515ed77687c23e29a4a3ffff671666bdDoug Felt // just reset the start point 46123241887515ed77687c23e29a4a3ffff671666bdDoug Felt j = nextSpanStart = here; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project j = here - 1; // continue looping 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ok = fit = here; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project w = 0; 468121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitAscent = fitDescent = fitTop = fitBottom = 0; 469121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio okAscent = okDescent = okTop = okBottom = 0; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 471c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt if (--firstWidthLineLimit <= 0) { 472121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio width = restWidth; 4737b5676e4d40a09ccdbc8b6f691a3d8be23e480d3Mark Wagner } 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 478e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (paraEnd != here) { 479121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if ((fitTop | fitBottom | fitDescent | fitAscent) == 0) { 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.getFontMetricsInt(fm); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 482121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitTop = fm.top; 483121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitBottom = fm.bottom; 484121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitAscent = fm.ascent; 485121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitDescent = fm.descent; 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Log.e("text", "output rest " + here + " to " + end); 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = out(source, 491121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio here, paraEnd, fitAscent, fitDescent, 492121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio fitTop, fitBottom, 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v, 494121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio spacingmult, spacingadd, chooseHt, 495121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHtv, fm, hasTabOrEmoji, 496e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt needMultiply, paraStart, chdirs, dir, easy, 497121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio paraEnd == bufEnd, includepad, trackpad, 498be46d1456beb7e2f3e8b82bda2d0a5023db3debdPaul Eastham chs, widths, here - paraStart, 4990a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne ellipsize, ellipsizedWidth, w, paint); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 502e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt paraStart = paraEnd; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 504121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (paraEnd == bufEnd) 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 508121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) { 509121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio // Log.e("text", "output last " + bufEnd); 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project paint.getFontMetricsInt(fm); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = out(source, 514121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio bufEnd, bufEnd, fm.ascent, fm.descent, 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.top, fm.bottom, 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v, 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spacingmult, spacingadd, null, 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project null, fm, false, 519121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio needMultiply, bufEnd, null, DEFAULT_DIR, true, 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true, includepad, trackpad, 521121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio null, null, bufStart, 5220a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne ellipsize, ellipsizedWidth, 0, paint); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns true if the specified character is one of those specified 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as being Ideographic (class ID) by the Unicode Line Breaking Algorithm 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (http://www.unicode.org/unicode/reports/tr14/), and is therefore OK 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to break between a pair of. 531549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer * 532549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer * @param includeNonStarters also return true for category NS 533549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer * (non-starters), which can be broken 534549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer * after but not before. 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 536549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer private static final boolean isIdeographic(char c, boolean includeNonStarters) { 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\u2E80' && c <= '\u2FFF') { 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // CJK, KANGXI RADICALS, DESCRIPTION SYMBOLS 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == '\u3000') { 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // IDEOGRAPHIC SPACE 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\u3040' && c <= '\u309F') { 544549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer if (!includeNonStarters) { 545549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer switch (c) { 546549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3041': // # HIRAGANA LETTER SMALL A 547549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3043': // # HIRAGANA LETTER SMALL I 548549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3045': // # HIRAGANA LETTER SMALL U 549549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3047': // # HIRAGANA LETTER SMALL E 550549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3049': // # HIRAGANA LETTER SMALL O 551549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3063': // # HIRAGANA LETTER SMALL TU 552549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3083': // # HIRAGANA LETTER SMALL YA 553549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3085': // # HIRAGANA LETTER SMALL YU 554549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3087': // # HIRAGANA LETTER SMALL YO 555549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u308E': // # HIRAGANA LETTER SMALL WA 556549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3095': // # HIRAGANA LETTER SMALL KA 557549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u3096': // # HIRAGANA LETTER SMALL KE 558549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u309B': // # KATAKANA-HIRAGANA VOICED SOUND MARK 559549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u309C': // # KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK 560549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u309D': // # HIRAGANA ITERATION MARK 561549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u309E': // # HIRAGANA VOICED ITERATION MARK 562549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer return false; 563549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer } 564549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer } 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // Hiragana (except small characters) 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\u30A0' && c <= '\u30FF') { 568549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer if (!includeNonStarters) { 569549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer switch (c) { 570549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30A0': // # KATAKANA-HIRAGANA DOUBLE HYPHEN 571549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30A1': // # KATAKANA LETTER SMALL A 572549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30A3': // # KATAKANA LETTER SMALL I 573549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30A5': // # KATAKANA LETTER SMALL U 574549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30A7': // # KATAKANA LETTER SMALL E 575549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30A9': // # KATAKANA LETTER SMALL O 576549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30C3': // # KATAKANA LETTER SMALL TU 577549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30E3': // # KATAKANA LETTER SMALL YA 578549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30E5': // # KATAKANA LETTER SMALL YU 579549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30E7': // # KATAKANA LETTER SMALL YO 580549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30EE': // # KATAKANA LETTER SMALL WA 581549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30F5': // # KATAKANA LETTER SMALL KA 582549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30F6': // # KATAKANA LETTER SMALL KE 583549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30FB': // # KATAKANA MIDDLE DOT 584549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30FC': // # KATAKANA-HIRAGANA PROLONGED SOUND MARK 585549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30FD': // # KATAKANA ITERATION MARK 586549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer case '\u30FE': // # KATAKANA VOICED ITERATION MARK 587549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer return false; 588549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer } 589549d7243ff9cf638a63a0d5cc82c792b39484e8eEric Fischer } 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // Katakana (except small characters) 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\u3400' && c <= '\u4DB5') { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // CJK UNIFIED IDEOGRAPHS EXTENSION A 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\u4E00' && c <= '\u9FBB') { 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // CJK UNIFIED IDEOGRAPHS 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\uF900' && c <= '\uFAD9') { 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // CJK COMPATIBILITY IDEOGRAPHS 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\uA000' && c <= '\uA48F') { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // YI SYLLABLES 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\uA490' && c <= '\uA4CF') { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // YI RADICALS 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\uFE62' && c <= '\uFE66') { 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // SMALL PLUS SIGN to SMALL EQUALS SIGN 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= '\uFF10' && c <= '\uFF19') { 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; // WIDE DIGITS 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void dump(byte[] data, int count, String label) { 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (false) { 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(label); 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(" " + data[i]); 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.println(); 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int out(CharSequence text, int start, int end, 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int above, int below, int top, int bottom, int v, 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float spacingmult, float spacingadd, 633121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio LineHeightSpan[] chooseHt, int[] chooseHtv, 634c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt Paint.FontMetricsInt fm, boolean hasTabOrEmoji, 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean needMultiply, int pstart, byte[] chdirs, 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dir, boolean easy, boolean last, 637121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio boolean includePad, boolean trackPad, 638121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio char[] chs, float[] widths, int widthStart, 639121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio TextUtils.TruncateAt ellipsize, float ellipsisWidth, 640121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float textWidth, TextPaint paint) { 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int j = mLineCount; 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int off = j * mColumns; 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int want = off + mColumns + TOP; 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] lines = mLines; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (want >= lines.length) { 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nlen = ArrayUtils.idealIntArraySize(want + 1); 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] grow = new int[nlen]; 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(lines, 0, grow, 0, lines.length); 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLines = grow; 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lines = grow; 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Directions[] grow2 = new Directions[nlen]; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mLineDirections, 0, grow2, 0, 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLineDirections.length); 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLineDirections = grow2; 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (chooseHt != null) { 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.ascent = above; 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.descent = below; 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.top = top; 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.bottom = bottom; 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 665121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio for (int i = 0; i < chooseHt.length; i++) { 666121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (chooseHt[i] instanceof LineHeightSpan.WithDensity) { 667121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio ((LineHeightSpan.WithDensity) chooseHt[i]). 668121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHeight(text, start, end, chooseHtv[i], v, fm, paint); 669a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer 670a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer } else { 671121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio chooseHt[i].chooseHeight(text, start, end, chooseHtv[i], v, fm); 672a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer } 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project above = fm.ascent; 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project below = fm.descent; 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top = fm.top; 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottom = fm.bottom; 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (j == 0) { 682121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (trackPad) { 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTopPadding = top - above; 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 686121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (includePad) { 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project above = top; 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (last) { 691121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (trackPad) { 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBottomPadding = bottom - below; 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 695121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (includePad) { 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project below = bottom; 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int extra; 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needMultiply) { 7031065758a0f8966a8597a61492112f7859a7050a4Doug Felt double ex = (below - above) * (spacingmult - 1) + spacingadd; 7041065758a0f8966a8597a61492112f7859a7050a4Doug Felt if (ex >= 0) { 705121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio extra = (int)(ex + EXTRA_ROUNDING); 7061065758a0f8966a8597a61492112f7859a7050a4Doug Felt } else { 707121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio extra = -(int)(-ex + EXTRA_ROUNDING); 7081065758a0f8966a8597a61492112f7859a7050a4Doug Felt } 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extra = 0; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lines[off + START] = start; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lines[off + TOP] = v; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lines[off + DESCENT] = below + extra; 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v += (below - above) + extra; 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lines[off + mColumns + START] = end; 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lines[off + mColumns + TOP] = v; 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 721c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt if (hasTabOrEmoji) 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lines[off + TAB] |= TAB_MASK; 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7249f7a4442b89cc06cb8cae6992484e7ae795323abDoug Felt lines[off + DIR] |= dir << DIR_SHIFT; 7259f7a4442b89cc06cb8cae6992484e7ae795323abDoug Felt Directions linedirs = DIRS_ALL_LEFT_TO_RIGHT; 7269f7a4442b89cc06cb8cae6992484e7ae795323abDoug Felt // easy means all chars < the first RTL, so no emoji, no nothing 7274e0c5e55e171532760d5f51e0165563827129d4eDoug Felt // XXX a run with no text or all spaces is easy but might be an empty 7289f7a4442b89cc06cb8cae6992484e7ae795323abDoug Felt // RTL paragraph. Make sure easy is false if this is the case. 7299f7a4442b89cc06cb8cae6992484e7ae795323abDoug Felt if (easy) { 7309f7a4442b89cc06cb8cae6992484e7ae795323abDoug Felt mLineDirections[j] = linedirs; 7319f7a4442b89cc06cb8cae6992484e7ae795323abDoug Felt } else { 732121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio mLineDirections[j] = AndroidBidi.directions(dir, chdirs, widthStart, chs, 733121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio widthStart, end - start); 7340a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7360a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne // If ellipsize is in marquee mode, do not apply ellipsis on the first line 7370a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne if (ellipsize != null && (ellipsize != TextUtils.TruncateAt.MARQUEE || j != 0)) { 738121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio calculateEllipsis(start, end, widths, widthStart, 739121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio ellipsisWidth, ellipsize, j, 740121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio textWidth, paint); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLineCount++; 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 747121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private void calculateEllipsis(int lineStart, int lineEnd, 748121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float[] widths, int widthStart, 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float avail, TextUtils.TruncateAt where, 750121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int line, float textWidth, TextPaint paint) { 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 752121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (textWidth <= avail) { 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Everything fits! 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLines[mColumns * line + ELLIPSIS_START] = 0; 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLines[mColumns * line + ELLIPSIS_COUNT] = 0; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float ellipsisWidth = paint.measureText(HORIZONTAL_ELLIPSIS); 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ellipsisStart, ellipsisCount; 761121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio int len = lineEnd - lineStart; 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where == TextUtils.TruncateAt.START) { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float sum = 0; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i; 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = len; i >= 0; i--) { 768121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float w = widths[i - 1 + lineStart - widthStart]; 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 770121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (w + sum + ellipsisWidth > avail) { 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sum += w; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ellipsisStart = 0; 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ellipsisCount = i; 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE) { 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float sum = 0; 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i; 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = 0; i < len; i++) { 784121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float w = widths[i + lineStart - widthStart]; 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 786121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio if (w + sum + ellipsisWidth > avail) { 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sum += w; 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ellipsisStart = i; 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ellipsisCount = len - i; 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else /* where = TextUtils.TruncateAt.MIDDLE */ { 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float lsum = 0, rsum = 0; 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int left = 0, right = len; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float ravail = (avail - ellipsisWidth) / 2; 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (right = len; right >= 0; right--) { 801121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float w = widths[right - 1 + lineStart - widthStart]; 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (w + rsum > ravail) { 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rsum += w; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 810121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float lavail = avail - ellipsisWidth - rsum; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (left = 0; left < right; left++) { 812121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio float w = widths[left + lineStart - widthStart]; 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (w + lsum > lavail) { 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lsum += w; 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ellipsisStart = left; 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ellipsisCount = right - left; 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLines[mColumns * line + ELLIPSIS_START] = ellipsisStart; 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLines[mColumns * line + ELLIPSIS_COUNT] = ellipsisCount; 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt // Override the base class so we can directly access our members, 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // rather than relying on member functions. 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The logic mirrors that of Layout.getLineForVertical 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FIXME: It may be faster to do a linear search for layouts without many lines. 8336611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLineForVertical(int vertical) { 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int high = mLineCount; 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int low = -1; 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int guess; 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] lines = mLines; 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (high - low > 1) { 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project guess = (high + low) >> 1; 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lines[mColumns * guess + TOP] > vertical){ 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project high = guess; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project low = guess; 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (low < 0) { 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return low; 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8546611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLineCount() { 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLineCount; 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8596611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLineTop(int line) { 8610a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne int top = mLines[mColumns * line + TOP]; 8620a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne if (mMaximumVisibleLineCount > 0 && line >= mMaximumVisibleLineCount && 8630a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne line != mLineCount) { 8640a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne top += getBottomPadding(); 8650a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne } 8660a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne return top; 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8696611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLineDescent(int line) { 8710a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne int descent = mLines[mColumns * line + DESCENT]; 8720a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne if (mMaximumVisibleLineCount > 0 && line >= mMaximumVisibleLineCount - 1 && 8730a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne line != mLineCount) { 8740a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne descent += getBottomPadding(); 8750a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne } 8760a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne return descent; 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8796611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLineStart(int line) { 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLines[mColumns * line + START] & START_MASK; 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8846611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getParagraphDirection(int line) { 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLines[mColumns * line + DIR] >> DIR_SHIFT; 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8896611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean getLineContainsTab(int line) { 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mLines[mColumns * line + TAB] & TAB_MASK) != 0; 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8946611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Directions getLineDirections(int line) { 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLineDirections[line]; 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8996611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getTopPadding() { 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTopPadding; 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9046611147383118cd91cc29b31bff9aaf4c853f39dGilles Debunne @Override 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getBottomPadding() { 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBottomPadding; 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getEllipsisCount(int line) { 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mColumns < COLUMNS_ELLIPSIZE) { 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLines[mColumns * line + ELLIPSIS_COUNT]; 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getEllipsisStart(int line) { 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mColumns < COLUMNS_ELLIPSIZE) { 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLines[mColumns * line + ELLIPSIS_START]; 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getEllipsizedWidth() { 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mEllipsizedWidth; 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9320a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne /** 9330a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne * @hide 9340a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne */ 9350a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne @Override 9360a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne public void setMaximumVisibleLineCount(int line) { 9370a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne mMaximumVisibleLineCount = line; 9380a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne } 9390a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mLineCount; 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mTopPadding, mBottomPadding; 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mColumns; 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mEllipsizedWidth; 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int COLUMNS_NORMAL = 3; 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int COLUMNS_ELLIPSIZE = 5; 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int START = 0; 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DIR = START; 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int TAB = START; 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int TOP = 1; 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DESCENT = 2; 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ELLIPSIS_START = 3; 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ELLIPSIS_COUNT = 4; 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mLines; 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Directions[] mLineDirections; 9570a4db3c5270440eeb7e4e44a7029926e239ec3bdGilles Debunne private int mMaximumVisibleLineCount = 0; 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int START_MASK = 0x1FFFFFFF; 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DIR_SHIFT = 30; 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int TAB_MASK = 0x20000000; 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 963c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Felt private static final int TAB_INCREMENT = 20; // same as Layout, but that's private 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 965121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_FIRST_CJK = '\u2E80'; 966121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio 967121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_NEW_LINE = '\n'; 968121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_TAB = '\t'; 969121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_SPACE = ' '; 970121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_DOT = '.'; 971121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_COMMA = ','; 972121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_COLON = ':'; 973121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_SEMICOLON = ';'; 974121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_SLASH = '/'; 975121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final char CHAR_HYPHEN = '-'; 976121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio 977121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final double EXTRA_ROUNDING = 0.5; 978121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final String HORIZONTAL_ELLIPSIS = "\u2026"; // this is "..." 979121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio 980121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final int CHAR_FIRST_HIGH_SURROGATE = 0xD800; 981121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio private static final int CHAR_LAST_LOW_SURROGATE = 0xDFFF; 982121c82c8130c2658f73fb19f3a62eb88c8679968Fabrice Di Meglio 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 984e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * This is reused across calls to generate() 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 986e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt private MeasuredText mMeasured; 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt(); 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 989