1e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt/* 2e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * Copyright (C) 2010 The Android Open Source Project 3e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * 4e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * Licensed under the Apache License, Version 2.0 (the "License"); 5e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * you may not use this file except in compliance with the License. 6e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * You may obtain a copy of the License at 7e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * 8e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * http://www.apache.org/licenses/LICENSE-2.0 9e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * 10e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * Unless required by applicable law or agreed to in writing, software 11e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * distributed under the License is distributed on an "AS IS" BASIS, 12e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * See the License for the specific language governing permissions and 14e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * limitations under the License. 15e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt */ 16e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 17e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltpackage android.text; 18e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 190c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Feltimport android.graphics.Canvas; 20e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltimport android.graphics.Paint; 21e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltimport android.text.style.MetricAffectingSpan; 22e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltimport android.text.style.ReplacementSpan; 23e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltimport android.util.Log; 24e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 259a3a8848643faf477335675136efba9a6e58db75Gilles Debunneimport com.android.internal.util.ArrayUtils; 269a3a8848643faf477335675136efba9a6e58db75Gilles Debunne 27e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt/** 28e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * @hide 29e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt */ 30e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltclass MeasuredText { 31fbc8630736d12676edc16f3932231713e23dd1dfKenny Root private static final boolean localLOGV = false; 32e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy CharSequence mText; 33e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy int mTextStart; 34e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy float[] mWidths; 35e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy char[] mChars; 36e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy byte[] mLevels; 37e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy int mDir; 38e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy boolean mEasy; 39e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy int mLen; 40e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy 41e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt private int mPos; 42e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt private TextPaint mWorkPaint; 43e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 44e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt private MeasuredText() { 45e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mWorkPaint = new TextPaint(); 46e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 47e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 48e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy private static final Object[] sLock = new Object[0]; 49e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy private static MeasuredText[] sCached = new MeasuredText[3]; 50e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 51e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt static MeasuredText obtain() { 52e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt MeasuredText mt; 53e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy synchronized (sLock) { 54e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy for (int i = sCached.length; --i >= 0;) { 55e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy if (sCached[i] != null) { 56e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy mt = sCached[i]; 57e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy sCached[i] = null; 58e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt return mt; 59e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 60e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 61e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 62e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mt = new MeasuredText(); 63fbc8630736d12676edc16f3932231713e23dd1dfKenny Root if (localLOGV) { 64fbc8630736d12676edc16f3932231713e23dd1dfKenny Root Log.v("MEAS", "new: " + mt); 65fbc8630736d12676edc16f3932231713e23dd1dfKenny Root } 66e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt return mt; 67e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 68e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 69e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt static MeasuredText recycle(MeasuredText mt) { 70e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mt.mText = null; 71e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (mt.mLen < 1000) { 72e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy synchronized(sLock) { 73e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy for (int i = 0; i < sCached.length; ++i) { 74e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy if (sCached[i] == null) { 75e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy sCached[i] = mt; 76e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy mt.mText = null; 77e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt break; 78e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 79e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 80e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 81e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 82e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt return null; 83e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 84e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 85cd943a7a013952af9b7286fd506fd63bf0993ac1Gilles Debunne void setPos(int pos) { 861341ab6f3808d8c11b147f82bc7735116c7d709fRaph Levien mPos = pos - mTextStart; 87cd943a7a013952af9b7286fd506fd63bf0993ac1Gilles Debunne } 88cd943a7a013952af9b7286fd506fd63bf0993ac1Gilles Debunne 89e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt /** 900c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt * Analyzes text for bidirectional runs. Allocates working buffers. 91e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt */ 92cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir) { 93e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mText = text; 94e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mTextStart = start; 95e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 96e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int len = end - start; 97e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mLen = len; 98e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mPos = 0; 99e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 100e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (mWidths == null || mWidths.length < len) { 101e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mWidths = new float[ArrayUtils.idealFloatArraySize(len)]; 102e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 103e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (mChars == null || mChars.length < len) { 104e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mChars = new char[ArrayUtils.idealCharArraySize(len)]; 105e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 106e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt TextUtils.getChars(text, start, end, mChars, 0); 107e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 108e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (text instanceof Spanned) { 109e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt Spanned spanned = (Spanned) text; 110e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt ReplacementSpan[] spans = spanned.getSpans(start, end, 111e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt ReplacementSpan.class); 112e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 113e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int i = 0; i < spans.length; i++) { 114e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int startInPara = spanned.getSpanStart(spans[i]) - start; 115e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int endInPara = spanned.getSpanEnd(spans[i]) - start; 116ba3634f35523224d9b4238dbd0b9b5e0cf3b0b9bGilles Debunne // The span interval may be larger and must be restricted to [start, end[ 117ba3634f35523224d9b4238dbd0b9b5e0cf3b0b9bGilles Debunne if (startInPara < 0) startInPara = 0; 118ba3634f35523224d9b4238dbd0b9b5e0cf3b0b9bGilles Debunne if (endInPara > len) endInPara = len; 119e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int j = startInPara; j < endInPara; j++) { 120cd943a7a013952af9b7286fd506fd63bf0993ac1Gilles Debunne mChars[j] = '\uFFFC'; // object replacement character 121e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 122e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 123e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 124e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 125cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt if ((textDir == TextDirectionHeuristics.LTR || 126cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt textDir == TextDirectionHeuristics.FIRSTSTRONG_LTR || 127cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt textDir == TextDirectionHeuristics.ANYRTL_LTR) && 128cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt TextUtils.doesNotNeedBidi(mChars, 0, len)) { 1290c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt mDir = Layout.DIR_LEFT_TO_RIGHT; 130e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mEasy = true; 131e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 132e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (mLevels == null || mLevels.length < len) { 133e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mLevels = new byte[ArrayUtils.idealByteArraySize(len)]; 134e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 135cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt int bidiRequest; 136cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt if (textDir == TextDirectionHeuristics.LTR) { 137cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = Layout.DIR_REQUEST_LTR; 138cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } else if (textDir == TextDirectionHeuristics.RTL) { 139cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = Layout.DIR_REQUEST_RTL; 140cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } else if (textDir == TextDirectionHeuristics.FIRSTSTRONG_LTR) { 141cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = Layout.DIR_REQUEST_DEFAULT_LTR; 142cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } else if (textDir == TextDirectionHeuristics.FIRSTSTRONG_RTL) { 143cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = Layout.DIR_REQUEST_DEFAULT_RTL; 144cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } else { 145cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt boolean isRtl = textDir.isRtl(mChars, 0, len); 146cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = isRtl ? Layout.DIR_REQUEST_RTL : Layout.DIR_REQUEST_LTR; 147cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } 148e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mDir = AndroidBidi.bidi(bidiRequest, mChars, mLevels, len, false); 149e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mEasy = false; 150e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 151e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 152e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 153e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm) { 1540c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (fm != null) { 1550c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt paint.getFontMetricsInt(fm); 1560c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 1570c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 158e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int p = mPos; 1590c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt mPos = p + len; 1600c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 1610c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (mEasy) { 1620c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int flags = mDir == Layout.DIR_LEFT_TO_RIGHT 1630c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ? Canvas.DIRECTION_LTR : Canvas.DIRECTION_RTL; 1640c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt return paint.getTextRunAdvances(mChars, p, len, p, len, flags, mWidths, p); 1650c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 1660c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 1670c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt float totalAdvance = 0; 1680c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int level = mLevels[p]; 1690c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt for (int q = p, i = p + 1, e = p + len;; ++i) { 1700c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (i == e || mLevels[i] != level) { 1710c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int flags = (level & 0x1) == 0 ? Canvas.DIRECTION_LTR : Canvas.DIRECTION_RTL; 1720c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt totalAdvance += 1730c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt paint.getTextRunAdvances(mChars, q, i - q, q, i - q, flags, mWidths, q); 1740c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (i == e) { 1750c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt break; 176e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 1770c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt q = i; 1780c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt level = mLevels[i]; 179e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 180e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 1810c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt return totalAdvance; 182e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 183e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 184e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float addStyleRun(TextPaint paint, MetricAffectingSpan[] spans, int len, 185e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt Paint.FontMetricsInt fm) { 186e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 187e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt TextPaint workPaint = mWorkPaint; 188e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt workPaint.set(paint); 189e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt // XXX paint should not have a baseline shift, but... 190e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt workPaint.baselineShift = 0; 191e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 192e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt ReplacementSpan replacement = null; 193e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int i = 0; i < spans.length; i++) { 194e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt MetricAffectingSpan span = spans[i]; 195e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (span instanceof ReplacementSpan) { 196e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt replacement = (ReplacementSpan)span; 197e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 198e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt span.updateMeasureState(workPaint); 199e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 200e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 201e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 202e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float wid; 203e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (replacement == null) { 204e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt wid = addStyleRun(workPaint, len, fm); 205e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 206e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt // Use original text. Shouldn't matter. 207e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt wid = replacement.getSize(workPaint, mText, mTextStart + mPos, 208e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mTextStart + mPos + len, fm); 209e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float[] w = mWidths; 210e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt w[mPos] = wid; 211e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int i = mPos + 1, e = mPos + len; i < e; i++) 212e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt w[i] = 0; 2139a3a8848643faf477335675136efba9a6e58db75Gilles Debunne mPos += len; 214e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 215e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 216e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (fm != null) { 217e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (workPaint.baselineShift < 0) { 218e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt fm.ascent += workPaint.baselineShift; 219e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt fm.top += workPaint.baselineShift; 220e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 221e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt fm.descent += workPaint.baselineShift; 222e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt fm.bottom += workPaint.baselineShift; 223e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 224e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 225e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 226e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt return wid; 227e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 228e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 229c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne int breakText(int limit, boolean forwards, float width) { 230e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float[] w = mWidths; 231e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (forwards) { 232c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne int i = 0; 233c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne while (i < limit) { 234c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne width -= w[i]; 235c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne if (width < 0.0f) break; 236c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne i++; 237e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 238c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne while (i > 0 && mChars[i - 1] == ' ') i--; 239c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne return i; 240e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 241c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne int i = limit - 1; 242c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne while (i >= 0) { 243c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne width -= w[i]; 244c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne if (width < 0.0f) break; 245c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne i--; 246e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 247c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne while (i < limit - 1 && mChars[i + 1] == ' ') i++; 248c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne return limit - i - 1; 249e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 250e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 251e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 252e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float measure(int start, int limit) { 253e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float width = 0; 254e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float[] w = mWidths; 255e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int i = start; i < limit; ++i) { 256e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt width += w[i]; 257e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 258e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt return width; 259e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 260fbc8630736d12676edc16f3932231713e23dd1dfKenny Root} 261