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.content.res; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guyimport android.graphics.Color; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.*; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.*; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Typeface; 272269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackborn 28a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guyimport java.util.Arrays; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Conveniences for retrieving data out of a compiled string resource. 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectfinal class StringBlock { 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "AssetManager"; 37a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy private static final boolean localLOGV = false; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39896043d67d3ac75760bd99db8a1561e31ebee1e1Ashok Bhat private final long mNative; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean mUseSparse; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final boolean mOwnsNative; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CharSequence[] mStrings; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SparseArray<CharSequence> mSparseStrings; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StyleIDs mStyleIDs = null; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public StringBlock(byte[] data, boolean useSparse) { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNative = nativeCreate(data, 0, data.length); 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUseSparse = useSparse; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnsNative = true; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "Created string block " + this 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ": " + nativeGetSize(mNative)); 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public StringBlock(byte[] data, int offset, int size, boolean useSparse) { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNative = nativeCreate(data, offset, size); 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUseSparse = useSparse; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnsNative = true; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "Created string block " + this 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ": " + nativeGetSize(mNative)); 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence get(int idx) { 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStrings != null) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence res = mStrings[idx]; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res != null) { 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return res; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mSparseStrings != null) { 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence res = mSparseStrings.get(idx); 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (res != null) { 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return res; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int num = nativeGetSize(mNative); 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mUseSparse && num > 250) { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSparseStrings = new SparseArray<CharSequence>(); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrings = new CharSequence[num]; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String str = nativeGetString(mNative, idx); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence res = str; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] style = nativeGetStyle(mNative, idx); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "Got string: " + str); 86a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy if (localLOGV) Log.v(TAG, "Got styles: " + Arrays.toString(style)); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style != null) { 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStyleIDs == null) { 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStyleIDs = new StyleIDs(); 90ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } 91ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson 92ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson // the style array is a flat array of <type, start, end> hence 93ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson // the magic constant 3. 94ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson for (int styleIndex = 0; styleIndex < style.length; styleIndex += 3) { 95ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson int styleId = style[styleIndex]; 96ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson 97ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson if (styleId == mStyleIDs.boldId || styleId == mStyleIDs.italicId 98ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson || styleId == mStyleIDs.underlineId || styleId == mStyleIDs.ttId 99ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson || styleId == mStyleIDs.bigId || styleId == mStyleIDs.smallId 100ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson || styleId == mStyleIDs.subId || styleId == mStyleIDs.supId 101ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson || styleId == mStyleIDs.strikeId || styleId == mStyleIDs.listItemId 102ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson || styleId == mStyleIDs.marqueeId) { 103ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson // id already found skip to next style 104ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson continue; 105ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } 106ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson 107ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson String styleTag = nativeGetString(mNative, styleId); 108ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson 109ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson if (styleTag.equals("b")) { 110ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.boldId = styleId; 111ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("i")) { 112ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.italicId = styleId; 113ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("u")) { 114ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.underlineId = styleId; 115ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("tt")) { 116ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.ttId = styleId; 117ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("big")) { 118ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.bigId = styleId; 119ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("small")) { 120ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.smallId = styleId; 121ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("sup")) { 122ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.supId = styleId; 123ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("sub")) { 124ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.subId = styleId; 125ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("strike")) { 126ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.strikeId = styleId; 127ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("li")) { 128ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.listItemId = styleId; 129ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } else if (styleTag.equals("marquee")) { 130ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson mStyleIDs.marqueeId = styleId; 131ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson } 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = applyStyles(str, style, mStyleIDs); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStrings != null) mStrings[idx] = res; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else mSparseStrings.put(idx, res); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return res; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 143a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy try { 144a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy super.finalize(); 145a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } finally { 146a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy if (mOwnsNative) { 147a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy nativeDestroy(mNative); 148a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final class StyleIDs { 153ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int boldId = -1; 154ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int italicId = -1; 155ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int underlineId = -1; 156ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int ttId = -1; 157ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int bigId = -1; 158ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int smallId = -1; 159ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int subId = -1; 160ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int supId = -1; 161ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int strikeId = -1; 162ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int listItemId = -1; 163ac4a181d2e02f2dd375c61ce231d35e50d0d1836Peter Eliasson private int marqueeId = -1; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CharSequence applyStyles(String str, int[] style, StyleIDs ids) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style.length == 0) 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return str; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpannableString buffer = new SpannableString(str); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i=0; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (i < style.length) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int type = style[i]; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "Applying style span id=" + type 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", start=" + style[i+1] + ", end=" + style[i+2]); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (type == ids.boldId) { 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new StyleSpan(Typeface.BOLD), 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.italicId) { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new StyleSpan(Typeface.ITALIC), 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.underlineId) { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new UnderlineSpan(), 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.ttId) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new TypefaceSpan("monospace"), 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.bigId) { 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new RelativeSizeSpan(1.25f), 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.smallId) { 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new RelativeSizeSpan(0.8f), 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.subId) { 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new SubscriptSpan(), 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.supId) { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new SuperscriptSpan(), 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.strikeId) { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new StrikethroughSpan(), 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.listItemId) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addParagraphSpan(buffer, new BulletSpan(10), 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == ids.marqueeId) { 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(TextUtils.TruncateAt.MARQUEE, 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_INCLUSIVE_INCLUSIVE); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String tag = nativeGetString(mNative, type); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tag.startsWith("font;")) { 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String sub; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sub = subtag(tag, ";height="); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sub != null) { 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = Integer.parseInt(sub); 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addParagraphSpan(buffer, new Height(size), 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sub = subtag(tag, ";size="); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sub != null) { 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = Integer.parseInt(sub); 237a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer buffer.setSpan(new AbsoluteSizeSpan(size, true), 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sub = subtag(tag, ";fgcolor="); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sub != null) { 244a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy buffer.setSpan(getColor(sub, true), 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy sub = subtag(tag, ";color="); 250a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy if (sub != null) { 251a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy buffer.setSpan(getColor(sub, true), 252a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy style[i+1], style[i+2]+1, 253a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 254a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } 255a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sub = subtag(tag, ";bgcolor="); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sub != null) { 258a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy buffer.setSpan(getColor(sub, false), 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 262a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy 263a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy sub = subtag(tag, ";face="); 264a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy if (sub != null) { 265a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy buffer.setSpan(new TypefaceSpan(sub), 266a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy style[i+1], style[i+2]+1, 267a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 268a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.startsWith("a;")) { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String sub; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sub = subtag(tag, ";href="); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sub != null) { 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new URLSpan(sub), 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.startsWith("annotation;")) { 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = tag.length(); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int next; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int t = tag.indexOf(';'); t < len; t = next) { 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int eq = tag.indexOf('=', t); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (eq < 0) { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next = tag.indexOf(';', eq); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (next < 0) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next = len; 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String key = tag.substring(t + 1, eq); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String value = tag.substring(eq + 1, next); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(new Annotation(key, value), 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project style[i+1], style[i+2]+1, 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i += 3; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SpannedString(buffer); 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 309a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * Returns a span for the specified color string representation. 310a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * If the specified string does not represent a color (null, empty, etc.) 311a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * the color black is returned instead. 312a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * 313a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * @param color The color as a string. Can be a resource reference, 314a987d9af69ca5447a888a3d5b50f3511d4b8f0daStefan Wysocki * hexadecimal, octal or a name 315a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * @param foreground True if the color will be used as the foreground color, 316a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * false otherwise 317a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * 318a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * @return A CharacterStyle 319a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy * 320a987d9af69ca5447a888a3d5b50f3511d4b8f0daStefan Wysocki * @see Color#parseColor(String) 321a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy */ 322a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy private static CharacterStyle getColor(String color, boolean foreground) { 323a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy int c = 0xff000000; 324a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy 325a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy if (!TextUtils.isEmpty(color)) { 326a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy if (color.startsWith("@")) { 327a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy Resources res = Resources.getSystem(); 328a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy String name = color.substring(1); 329a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy int colorRes = res.getIdentifier(name, "color", "android"); 330a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy if (colorRes != 0) { 3314a357cd2e55293402d7172766f7f9419815fc1e8Alan Viverette ColorStateList colors = res.getColorStateList(colorRes, null); 332a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy if (foreground) { 333a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy return new TextAppearanceSpan(null, 0, 0, colors, null); 334a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } else { 335a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy c = colors.getDefaultColor(); 336a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } 337a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } 338a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } else { 339a987d9af69ca5447a888a3d5b50f3511d4b8f0daStefan Wysocki try { 340a987d9af69ca5447a888a3d5b50f3511d4b8f0daStefan Wysocki c = Color.parseColor(color); 341a987d9af69ca5447a888a3d5b50f3511d4b8f0daStefan Wysocki } catch (IllegalArgumentException e) { 342a987d9af69ca5447a888a3d5b50f3511d4b8f0daStefan Wysocki c = Color.BLACK; 343a987d9af69ca5447a888a3d5b50f3511d4b8f0daStefan Wysocki } 344a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } 345a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } 346a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy 347a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy if (foreground) { 348a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy return new ForegroundColorSpan(c); 349a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } else { 350a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy return new BackgroundColorSpan(c); 351a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } 352a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy } 353a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy 354a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy /** 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If a translator has messed up the edges of paragraph-level markup, 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fix it to actually cover the entire paragraph that it is attached to 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instead of just whatever range they put it on. 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void addParagraphSpan(Spannable buffer, Object what, 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start, int end) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = buffer.length(); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start != 0 && start != len && buffer.charAt(start - 1) != '\n') { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (start--; start > 0; start--) { 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buffer.charAt(start - 1) == '\n') { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end != 0 && end != len && buffer.charAt(end - 1) != '\n') { 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (end++; end < len; end++) { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buffer.charAt(end - 1) == '\n') { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.setSpan(what, start, end, Spannable.SPAN_PARAGRAPH); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String subtag(String full, String attribute) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = full.indexOf(attribute); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start < 0) { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += attribute.length(); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = full.indexOf(';', start); 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end < 0) { 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return full.substring(start); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return full.substring(start, end); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Forces the text line to be the specified height, shrinking/stretching 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the ascent if possible, or the descent if shrinking the ascent further 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will make the text unreadable. 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 403a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer private static class Height implements LineHeightSpan.WithDensity { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mSize; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static float sProportion = 0; 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Height(int size) { 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSize = size; 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void chooseHeight(CharSequence text, int start, int end, 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanstartv, int v, 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint.FontMetricsInt fm) { 414a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer // Should not get called, at least not by StaticLayout. 415a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer chooseHeight(text, start, end, spanstartv, v, fm, null); 416a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer } 417a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer 418a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer public void chooseHeight(CharSequence text, int start, int end, 419a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer int spanstartv, int v, 420a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer Paint.FontMetricsInt fm, TextPaint paint) { 421a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer int size = mSize; 422a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer if (paint != null) { 423a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer size *= paint.density; 424a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer } 425a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer 426a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer if (fm.bottom - fm.top < size) { 427a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer fm.top = fm.bottom - size; 428a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer fm.ascent = fm.ascent - size; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sProportion == 0) { 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calculate what fraction of the nominal ascent 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the height of a capital letter actually is, 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so that we won't reduce the ascent to less than 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that unless we absolutely have to. 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Paint p = new Paint(); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.setTextSize(100); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Rect r = new Rect(); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.getTextBounds("ABCDEFG", 0, 7, r); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sProportion = (r.top) / p.ascent(); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int need = (int) Math.ceil(-fm.top * sProportion); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 448a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer if (size - fm.descent >= need) { 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * It is safe to shrink the ascent this much. 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 453a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer fm.top = fm.bottom - size; 454a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer fm.ascent = fm.descent - size; 455a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer } else if (size >= need) { 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We can't show all the descent, but we can at least 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * show all the ascent. 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.top = fm.ascent = -need; 462a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer fm.bottom = fm.descent = fm.top + size; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Show as much of the ascent as we can, and no descent. 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 468a9f1dd021f8f6ee777bc4d27913bd40c42e753afEric Fischer fm.top = fm.ascent = -size; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.bottom = fm.descent = 0; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create from an existing string block native object. This is 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * -extremely- dangerous -- only use it if you absolutely know what you 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are doing! The given native object must exist for the entire lifetime 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of this newly creating StringBlock. 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 481896043d67d3ac75760bd99db8a1561e31ebee1e1Ashok Bhat StringBlock(long obj, boolean useSparse) { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNative = obj; 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUseSparse = useSparse; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnsNative = false; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "Created string block " + this 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ": " + nativeGetSize(mNative)); 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489896043d67d3ac75760bd99db8a1561e31ebee1e1Ashok Bhat private static native long nativeCreate(byte[] data, 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int offset, 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size); 492896043d67d3ac75760bd99db8a1561e31ebee1e1Ashok Bhat private static native int nativeGetSize(long obj); 493896043d67d3ac75760bd99db8a1561e31ebee1e1Ashok Bhat private static native String nativeGetString(long obj, int idx); 494896043d67d3ac75760bd99db8a1561e31ebee1e1Ashok Bhat private static native int[] nativeGetStyle(long obj, int idx); 495896043d67d3ac75760bd99db8a1561e31ebee1e1Ashok Bhat private static native void nativeDestroy(long obj); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 497