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 19e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltimport android.graphics.Paint; 20e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltimport android.text.style.MetricAffectingSpan; 21e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltimport android.text.style.ReplacementSpan; 22e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltimport android.util.Log; 23e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 249a3a8848643faf477335675136efba9a6e58db75Gilles Debunneimport com.android.internal.util.ArrayUtils; 259a3a8848643faf477335675136efba9a6e58db75Gilles Debunne 26e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt/** 27e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt * @hide 28e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt */ 29e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Feltclass MeasuredText { 30fbc8630736d12676edc16f3932231713e23dd1dfKenny Root private static final boolean localLOGV = false; 31e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy CharSequence mText; 32e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy int mTextStart; 33e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy float[] mWidths; 34e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy char[] mChars; 35e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy byte[] mLevels; 36e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy int mDir; 37e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy boolean mEasy; 38e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy int mLen; 39e5ea4403ce58982522554b7ff23f41e6551923c1Romain Guy 40e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt private int mPos; 41e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt private TextPaint mWorkPaint; 4270616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien private StaticLayout.Builder mBuilder; 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]; 49d4f4526cb4bfa343714dbb63b82c82798db5a4e0Brian Carlstrom private static final 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) { 70d3ab692d28018825578ff05832644cfad60233fbRaph Levien mt.finish(); 71d3ab692d28018825578ff05832644cfad60233fbRaph Levien synchronized(sLock) { 72d3ab692d28018825578ff05832644cfad60233fbRaph Levien for (int i = 0; i < sCached.length; ++i) { 73d3ab692d28018825578ff05832644cfad60233fbRaph Levien if (sCached[i] == null) { 74d3ab692d28018825578ff05832644cfad60233fbRaph Levien sCached[i] = mt; 75d3ab692d28018825578ff05832644cfad60233fbRaph Levien mt.mText = null; 76d3ab692d28018825578ff05832644cfad60233fbRaph Levien break; 77e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 78e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 79e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 80e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt return null; 81e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 82e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 83d3ab692d28018825578ff05832644cfad60233fbRaph Levien void finish() { 84d3ab692d28018825578ff05832644cfad60233fbRaph Levien mText = null; 8570616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien mBuilder = null; 86d3ab692d28018825578ff05832644cfad60233fbRaph Levien if (mLen > 1000) { 87d3ab692d28018825578ff05832644cfad60233fbRaph Levien mWidths = null; 88d3ab692d28018825578ff05832644cfad60233fbRaph Levien mChars = null; 89d3ab692d28018825578ff05832644cfad60233fbRaph Levien mLevels = null; 90d3ab692d28018825578ff05832644cfad60233fbRaph Levien } 91d3ab692d28018825578ff05832644cfad60233fbRaph Levien } 92d3ab692d28018825578ff05832644cfad60233fbRaph Levien 93cd943a7a013952af9b7286fd506fd63bf0993ac1Gilles Debunne void setPos(int pos) { 941341ab6f3808d8c11b147f82bc7735116c7d709fRaph Levien mPos = pos - mTextStart; 95cd943a7a013952af9b7286fd506fd63bf0993ac1Gilles Debunne } 96cd943a7a013952af9b7286fd506fd63bf0993ac1Gilles Debunne 97e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt /** 980c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt * Analyzes text for bidirectional runs. Allocates working buffers. 99e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt */ 10070616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir, 10170616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien StaticLayout.Builder builder) { 10270616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien mBuilder = builder; 103e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mText = text; 104e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mTextStart = start; 105e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 106e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int len = end - start; 107e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mLen = len; 108e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mPos = 0; 109e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 110e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (mWidths == null || mWidths.length < len) { 111776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski mWidths = ArrayUtils.newUnpaddedFloatArray(len); 112e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 113e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (mChars == null || mChars.length < len) { 114776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski mChars = ArrayUtils.newUnpaddedCharArray(len); 115e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 116e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt TextUtils.getChars(text, start, end, mChars, 0); 117e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 118e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (text instanceof Spanned) { 119e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt Spanned spanned = (Spanned) text; 120e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt ReplacementSpan[] spans = spanned.getSpans(start, end, 121e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt ReplacementSpan.class); 122e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 123e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int i = 0; i < spans.length; i++) { 124e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int startInPara = spanned.getSpanStart(spans[i]) - start; 125e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int endInPara = spanned.getSpanEnd(spans[i]) - start; 126ba3634f35523224d9b4238dbd0b9b5e0cf3b0b9bGilles Debunne // The span interval may be larger and must be restricted to [start, end[ 127ba3634f35523224d9b4238dbd0b9b5e0cf3b0b9bGilles Debunne if (startInPara < 0) startInPara = 0; 128ba3634f35523224d9b4238dbd0b9b5e0cf3b0b9bGilles Debunne if (endInPara > len) endInPara = len; 129e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int j = startInPara; j < endInPara; j++) { 130cd943a7a013952af9b7286fd506fd63bf0993ac1Gilles Debunne mChars[j] = '\uFFFC'; // object replacement character 131e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 132e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 133e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 134e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 135cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt if ((textDir == TextDirectionHeuristics.LTR || 136cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt textDir == TextDirectionHeuristics.FIRSTSTRONG_LTR || 137cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt textDir == TextDirectionHeuristics.ANYRTL_LTR) && 138cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt TextUtils.doesNotNeedBidi(mChars, 0, len)) { 1390c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt mDir = Layout.DIR_LEFT_TO_RIGHT; 140e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mEasy = true; 141e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 142e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (mLevels == null || mLevels.length < len) { 143776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski mLevels = ArrayUtils.newUnpaddedByteArray(len); 144e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 145cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt int bidiRequest; 146cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt if (textDir == TextDirectionHeuristics.LTR) { 147cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = Layout.DIR_REQUEST_LTR; 148cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } else if (textDir == TextDirectionHeuristics.RTL) { 149cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = Layout.DIR_REQUEST_RTL; 150cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } else if (textDir == TextDirectionHeuristics.FIRSTSTRONG_LTR) { 151cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = Layout.DIR_REQUEST_DEFAULT_LTR; 152cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } else if (textDir == TextDirectionHeuristics.FIRSTSTRONG_RTL) { 153cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = Layout.DIR_REQUEST_DEFAULT_RTL; 154cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } else { 155cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt boolean isRtl = textDir.isRtl(mChars, 0, len); 156cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt bidiRequest = isRtl ? Layout.DIR_REQUEST_RTL : Layout.DIR_REQUEST_LTR; 157cb379120456d8065d742021fc5c66748fc8a11a8Doug Felt } 158e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mDir = AndroidBidi.bidi(bidiRequest, mChars, mLevels, len, false); 159e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mEasy = false; 160e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 161e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 162e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 163e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm) { 1640c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (fm != null) { 1650c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt paint.getFontMetricsInt(fm); 1660c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 1670c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 168e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt int p = mPos; 1690c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt mPos = p + len; 1700c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 17170616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien // try to do widths measurement in native code, but use Java if paint has been subclassed 17270616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien // FIXME: may want to eliminate special case for subclass 17370616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien float[] widths = null; 17470616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien if (mBuilder == null || paint.getClass() != TextPaint.class) { 17570616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien widths = mWidths; 17670616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien } 1770c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (mEasy) { 178051910b9f998030dacb8a0722588cc715813fde1Raph Levien boolean isRtl = mDir != Layout.DIR_LEFT_TO_RIGHT; 17970616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien float width = 0; 18070616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien if (widths != null) { 18170616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien width = paint.getTextRunAdvances(mChars, p, len, p, len, isRtl, widths, p); 18270616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien if (mBuilder != null) { 18370616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien mBuilder.addMeasuredRun(p, p + len, widths); 18470616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien } 18570616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien } else { 18670616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien width = mBuilder.addStyleRun(paint, p, p + len, isRtl); 18770616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien } 18870616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien return width; 1890c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 1900c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 1910c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt float totalAdvance = 0; 1920c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int level = mLevels[p]; 1930c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt for (int q = p, i = p + 1, e = p + len;; ++i) { 1940c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (i == e || mLevels[i] != level) { 195051910b9f998030dacb8a0722588cc715813fde1Raph Levien boolean isRtl = (level & 0x1) != 0; 19670616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien if (widths != null) { 19770616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien totalAdvance += 19870616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien paint.getTextRunAdvances(mChars, q, i - q, q, i - q, isRtl, widths, q); 19970616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien if (mBuilder != null) { 20070616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien mBuilder.addMeasuredRun(q, i, widths); 20170616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien } 20270616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien } else { 20370616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien totalAdvance += mBuilder.addStyleRun(paint, q, i, isRtl); 20470616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien } 2050c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (i == e) { 2060c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt break; 207e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 2080c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt q = i; 2090c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt level = mLevels[i]; 210e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 211e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 2120c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt return totalAdvance; 213e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 214e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 215e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float addStyleRun(TextPaint paint, MetricAffectingSpan[] spans, int len, 216e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt Paint.FontMetricsInt fm) { 217e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 218e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt TextPaint workPaint = mWorkPaint; 219e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt workPaint.set(paint); 220e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt // XXX paint should not have a baseline shift, but... 221e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt workPaint.baselineShift = 0; 222e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 223e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt ReplacementSpan replacement = null; 224e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int i = 0; i < spans.length; i++) { 225e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt MetricAffectingSpan span = spans[i]; 226e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (span instanceof ReplacementSpan) { 227e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt replacement = (ReplacementSpan)span; 228e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 229e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt span.updateMeasureState(workPaint); 230e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 231e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 232e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 233e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float wid; 234e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (replacement == null) { 235e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt wid = addStyleRun(workPaint, len, fm); 236e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 237e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt // Use original text. Shouldn't matter. 238e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt wid = replacement.getSize(workPaint, mText, mTextStart + mPos, 239e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt mTextStart + mPos + len, fm); 24070616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien if (mBuilder == null) { 24170616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien float[] w = mWidths; 24270616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien w[mPos] = wid; 24370616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien for (int i = mPos + 1, e = mPos + len; i < e; i++) 24470616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien w[i] = 0; 24570616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien } else { 24670616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien mBuilder.addReplacementRun(mPos, mPos + len, wid); 24770616ecd22fafccf2fab7565ccfbb3b5f91c5580Raph Levien } 2489a3a8848643faf477335675136efba9a6e58db75Gilles Debunne mPos += len; 249e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 250e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 251e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (fm != null) { 252e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (workPaint.baselineShift < 0) { 253e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt fm.ascent += workPaint.baselineShift; 254e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt fm.top += workPaint.baselineShift; 255e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 256e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt fm.descent += workPaint.baselineShift; 257e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt fm.bottom += workPaint.baselineShift; 258e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 259e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 260e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 261e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt return wid; 262e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 263e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 264c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne int breakText(int limit, boolean forwards, float width) { 265e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float[] w = mWidths; 266e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt if (forwards) { 267c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne int i = 0; 268c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne while (i < limit) { 269c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne width -= w[i]; 270c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne if (width < 0.0f) break; 271c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne i++; 272e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 273c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne while (i > 0 && mChars[i - 1] == ' ') i--; 274c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne return i; 275e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } else { 276c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne int i = limit - 1; 277c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne while (i >= 0) { 278c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne width -= w[i]; 279c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne if (width < 0.0f) break; 280c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne i--; 281e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 282c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne while (i < limit - 1 && mChars[i + 1] == ' ') i++; 283c70e7a0b8add16d2e6cec4d58c3cc74d08cc20b4Gilles Debunne return limit - i - 1; 284e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 285e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 286e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt 287e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float measure(int start, int limit) { 288e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float width = 0; 289e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt float[] w = mWidths; 290e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt for (int i = start; i < limit; ++i) { 291e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt width += w[i]; 292e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 293e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt return width; 294e8e45f2c05cb3b6d23f30c8f96d8e0b3699cea7aDoug Felt } 295fbc8630736d12676edc16f3932231713e23dd1dfKenny Root} 296