Html.java revision 94d5e9ad6533864f098b99c231d69c77230a828f
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 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 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.ccil.cowan.tagsoup.HTMLSchema; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.ccil.cowan.tagsoup.Parser; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xml.sax.Attributes; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xml.sax.ContentHandler; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xml.sax.InputSource; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xml.sax.Locator; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xml.sax.SAXException; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xml.sax.XMLReader; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringertimport android.content.res.ColorStateList; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Typeface; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 32105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.text.style.AbsoluteSizeSpan; 33105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.text.style.AlignmentSpan; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.CharacterStyle; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.ForegroundColorSpan; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.ImageSpan; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.ParagraphStyle; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.QuoteSpan; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.RelativeSizeSpan; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.StrikethroughSpan; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.StyleSpan; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.SubscriptSpan; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.SuperscriptSpan; 449cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringertimport android.text.style.TextAppearanceSpan; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.TypefaceSpan; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.URLSpan; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.style.UnderlineSpan; 48105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.util.Log; 492269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackborn 502269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornimport com.android.internal.util.XmlUtils; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.StringReader; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.nio.CharBuffer; 559cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringertimport java.util.HashMap; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class processes HTML strings into displayable styled text. 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Not all HTML tags are supported. 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Html { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieves images for HTML <img> tags. 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static interface ImageGetter { 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This methos is called when the HTML parser encounters an 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <img> tag. The <code>source</code> argument is the 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * string from the "src" attribute; the return value should be 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a Drawable representation of the image or <code>null</code> 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for a generic replacement image. Make sure you call 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * setBounds() on your Drawable if it doesn't already have 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * its bounds set. 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable getDrawable(String source); 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Is notified when HTML tags are encountered that the parser does 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not know how to interpret. 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static interface TagHandler { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method will be called whenn the HTML parser encounters 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a tag that it does not know how to interpret. 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleTag(boolean opening, String tag, 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Editable output, XMLReader xmlReader); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Html() { } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns displayable styled text from the provided HTML string. 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Any <img> tags in the HTML will display as a generic 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * replacement image which your program can then go through and 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * replace with real images. 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>This uses TagSoup to handle real HTML, including all of the brokenness found in the wild. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Spanned fromHtml(String source) { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fromHtml(source, null, null); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Lazy initialization holder for HTML parser. This class will 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a) be preloaded by the zygote, or b) not loaded until absolutely 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * necessary. 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class HtmlParser { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final HTMLSchema schema = new HTMLSchema(); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns displayable styled text from the provided HTML string. 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Any <img> tags in the HTML will use the specified ImageGetter 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to request a representation of the image (use null if you don't 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * want this) and the specified TagHandler to handle unknown tags 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (specify null if you don't want this). 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>This uses TagSoup to handle real HTML, including all of the brokenness found in the wild. 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Spanned fromHtml(String source, ImageGetter imageGetter, 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TagHandler tagHandler) { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parser parser = new Parser(); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parser.setProperty(Parser.schemaProperty, HtmlParser.schema); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (org.xml.sax.SAXNotRecognizedException e) { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Should not happen. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException(e); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (org.xml.sax.SAXNotSupportedException e) { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Should not happen. 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException(e); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HtmlToSpannedConverter converter = 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new HtmlToSpannedConverter(source, imageGetter, tagHandler, 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parser); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return converter.convert(); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns an HTML representation of the provided Spanned text. 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String toHtml(Spanned text) { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder out = new StringBuilder(); 147105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project withinHtml(out, text); 148105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return out.toString(); 149105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 150105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 151105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void withinHtml(StringBuilder out, Spanned text) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int next; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < text.length(); i = next) { 156105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project next = text.nextSpanTransition(i, len, ParagraphStyle.class); 157105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project ParagraphStyle[] style = text.getSpans(i, next, ParagraphStyle.class); 15832048300e917c9181927ac017d02855bbde940efSatoshi Kataoka String elements = " "; 15900ba76670fd06d9c51cce36a74c384a212f705b5Eric Fischer boolean needDiv = false; 16000ba76670fd06d9c51cce36a74c384a212f705b5Eric Fischer 161105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project for(int j = 0; j < style.length; j++) { 162105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (style[j] instanceof AlignmentSpan) { 163105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Layout.Alignment align = 164105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project ((AlignmentSpan) style[j]).getAlignment(); 16500ba76670fd06d9c51cce36a74c384a212f705b5Eric Fischer needDiv = true; 166105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (align == Layout.Alignment.ALIGN_CENTER) { 16732048300e917c9181927ac017d02855bbde940efSatoshi Kataoka elements = "align=\"center\" " + elements; 168105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else if (align == Layout.Alignment.ALIGN_OPPOSITE) { 16932048300e917c9181927ac017d02855bbde940efSatoshi Kataoka elements = "align=\"right\" " + elements; 170105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 17132048300e917c9181927ac017d02855bbde940efSatoshi Kataoka elements = "align=\"left\" " + elements; 172105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 173105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 174105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 17500ba76670fd06d9c51cce36a74c384a212f705b5Eric Fischer if (needDiv) { 17632048300e917c9181927ac017d02855bbde940efSatoshi Kataoka out.append("<div " + elements + ">"); 177105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 178105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 179105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project withinDiv(out, text, i, next); 180105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 18100ba76670fd06d9c51cce36a74c384a212f705b5Eric Fischer if (needDiv) { 182105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project out.append("</div>"); 183105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 184105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 185105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 186105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 187105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void withinDiv(StringBuilder out, Spanned text, 188105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int start, int end) { 189105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int next; 190105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project for (int i = start; i < end; i = next) { 191105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project next = text.nextSpanTransition(i, end, QuoteSpan.class); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project QuoteSpan[] quotes = text.getSpans(i, next, QuoteSpan.class); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (QuoteSpan quote: quotes) { 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<blockquote>"); 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project withinBlockquote(out, text, i, next); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (QuoteSpan quote: quotes) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</blockquote>\n"); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void withinBlockquote(StringBuilder out, Spanned text, 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start, int end) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<p>"); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int next; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = start; i < end; i = next) { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next = TextUtils.indexOf(text, '\n', i, end); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (next < 0) { 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next = end; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nl = 0; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (next < end && text.charAt(next) == '\n') { 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nl++; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next++; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project withinParagraph(out, text, i, next - nl, nl, next == end); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</p>\n"); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void withinParagraph(StringBuilder out, Spanned text, 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start, int end, int nl, 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean last) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int next; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = start; i < end; i = next) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project next = text.nextSpanTransition(i, end, CharacterStyle.class); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharacterStyle[] style = text.getSpans(i, next, 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharacterStyle.class); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < style.length; j++) { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof StyleSpan) { 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int s = ((StyleSpan) style[j]).getStyle(); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((s & Typeface.BOLD) != 0) { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<b>"); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((s & Typeface.ITALIC) != 0) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<i>"); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof TypefaceSpan) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = ((TypefaceSpan) style[j]).getFamily(); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (s.equals("monospace")) { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<tt>"); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof SuperscriptSpan) { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<sup>"); 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof SubscriptSpan) { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<sub>"); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof UnderlineSpan) { 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<u>"); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof StrikethroughSpan) { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<strike>"); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof URLSpan) { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<a href=\""); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append(((URLSpan) style[j]).getURL()); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("\">"); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof ImageSpan) { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<img src=\""); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append(((ImageSpan) style[j]).getSource()); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("\">"); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't output the dummy character underlying the image. 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i = next; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 282105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (style[j] instanceof AbsoluteSizeSpan) { 283105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project out.append("<font size =\""); 284105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project out.append(((AbsoluteSizeSpan) style[j]).getSize() / 6); 285105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project out.append("\">"); 286105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 287105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (style[j] instanceof ForegroundColorSpan) { 288105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project out.append("<font color =\"#"); 289105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project String color = Integer.toHexString(((ForegroundColorSpan) 290105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project style[j]).getForegroundColor() + 0x01000000); 291105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project while (color.length() < 6) { 292105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project color = "0" + color; 293105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 294105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project out.append(color); 295105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project out.append("\">"); 296105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project withinStyle(out, text, i, next); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = style.length - 1; j >= 0; j--) { 302105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (style[j] instanceof ForegroundColorSpan) { 303105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project out.append("</font>"); 304105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 305105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (style[j] instanceof AbsoluteSizeSpan) { 306105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project out.append("</font>"); 307105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof URLSpan) { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</a>"); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof StrikethroughSpan) { 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</strike>"); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof UnderlineSpan) { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</u>"); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof SubscriptSpan) { 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</sub>"); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof SuperscriptSpan) { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</sup>"); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof TypefaceSpan) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = ((TypefaceSpan) style[j]).getFamily(); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (s.equals("monospace")) { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</tt>"); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (style[j] instanceof StyleSpan) { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int s = ((StyleSpan) style[j]).getStyle(); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((s & Typeface.BOLD) != 0) { 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</b>"); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((s & Typeface.ITALIC) != 0) { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("</i>"); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String p = last ? "" : "</p>\n<p>"; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nl == 1) { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<br>\n"); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (nl == 2) { 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append(p); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 2; i < nl; i++) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<br>"); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append(p); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void withinStyle(StringBuilder out, Spanned text, 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start, int end) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = start; i < end; i++) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = text.charAt(i); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == '<') { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("<"); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c == '>') { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append(">"); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c == '&') { 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("&"); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c > 0x7E || c < ' ') { 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append("&#" + ((int) c) + ";"); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (c == ' ') { 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (i + 1 < end && text.charAt(i + 1) == ' ') { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append(" "); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i++; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append(' '); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.append(c); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass HtmlToSpannedConverter implements ContentHandler { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final float[] HEADER_SIZES = { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1.5f, 1.4f, 1.3f, 1.2f, 1.1f, 1f, 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mSource; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private XMLReader mReader; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SpannableStringBuilder mSpannableStringBuilder; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Html.ImageGetter mImageGetter; 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Html.TagHandler mTagHandler; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public HtmlToSpannedConverter( 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler, 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parser parser) { 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSource = source; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpannableStringBuilder = new SpannableStringBuilder(); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mImageGetter = imageGetter; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTagHandler = tagHandler; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReader = parser; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Spanned convert() { 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReader.setContentHandler(this); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReader.parse(new InputSource(new StringReader(mSource))); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We are reading from a string. There should not be IO problems. 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException(e); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SAXException e) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TagSoup doesn't throw parse exceptions. 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException(e); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fix flags and range for paragraph-type markup. 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] obj = mSpannableStringBuilder.getSpans(0, mSpannableStringBuilder.length(), ParagraphStyle.class); 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < obj.length; i++) { 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = mSpannableStringBuilder.getSpanStart(obj[i]); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = mSpannableStringBuilder.getSpanEnd(obj[i]); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the last line of the range is blank, back off by one. 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end - 2 >= 0) { 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpannableStringBuilder.charAt(end - 1) == '\n' && 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpannableStringBuilder.charAt(end - 2) == '\n') { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end--; 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end == start) { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpannableStringBuilder.removeSpan(obj[i]); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpannableStringBuilder.setSpan(obj[i], start, end, Spannable.SPAN_PARAGRAPH); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpannableStringBuilder; 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleStartTag(String tag, Attributes attributes) { 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tag.equalsIgnoreCase("br")) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We don't need to handle this. TagSoup will ensure that there's a </br> for each <br> 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so we can safely emite the linebreaks when we handle the close tag. 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("p")) { 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleP(mSpannableStringBuilder); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("div")) { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleP(mSpannableStringBuilder); 45294d5e9ad6533864f098b99c231d69c77230a828fRomain Guy } else if (tag.equalsIgnoreCase("strong")) { 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Bold()); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("b")) { 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Bold()); 45694d5e9ad6533864f098b99c231d69c77230a828fRomain Guy } else if (tag.equalsIgnoreCase("em")) { 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Italic()); 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("cite")) { 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Italic()); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("dfn")) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Italic()); 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("i")) { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Italic()); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("big")) { 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Big()); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("small")) { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Small()); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("font")) { 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startFont(mSpannableStringBuilder, attributes); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("blockquote")) { 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleP(mSpannableStringBuilder); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Blockquote()); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("tt")) { 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Monospace()); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("a")) { 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startA(mSpannableStringBuilder, attributes); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("u")) { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Underline()); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("sup")) { 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Super()); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("sub")) { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Sub()); 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.length() == 2 && 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Character.toLowerCase(tag.charAt(0)) == 'h' && 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tag.charAt(1) >= '1' && tag.charAt(1) <= '6') { 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleP(mSpannableStringBuilder); 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(mSpannableStringBuilder, new Header(tag.charAt(1) - '1')); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("img")) { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startImg(mSpannableStringBuilder, attributes, mImageGetter); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mTagHandler != null) { 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTagHandler.handleTag(true, tag, mSpannableStringBuilder, mReader); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleEndTag(String tag) { 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tag.equalsIgnoreCase("br")) { 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleBr(mSpannableStringBuilder); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("p")) { 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleP(mSpannableStringBuilder); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("div")) { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleP(mSpannableStringBuilder); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("em")) { 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD)); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("b")) { 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD)); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("strong")) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("cite")) { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("dfn")) { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("i")) { 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("big")) { 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Big.class, new RelativeSizeSpan(1.25f)); 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("small")) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Small.class, new RelativeSizeSpan(0.8f)); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("font")) { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endFont(mSpannableStringBuilder); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("blockquote")) { 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleP(mSpannableStringBuilder); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Blockquote.class, new QuoteSpan()); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("tt")) { 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Monospace.class, 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new TypefaceSpan("monospace")); 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("a")) { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endA(mSpannableStringBuilder); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("u")) { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Underline.class, new UnderlineSpan()); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("sup")) { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Super.class, new SuperscriptSpan()); 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.equalsIgnoreCase("sub")) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end(mSpannableStringBuilder, Sub.class, new SubscriptSpan()); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (tag.length() == 2 && 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Character.toLowerCase(tag.charAt(0)) == 'h' && 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tag.charAt(1) >= '1' && tag.charAt(1) <= '6') { 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleP(mSpannableStringBuilder); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endHeader(mSpannableStringBuilder); 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mTagHandler != null) { 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTagHandler.handleTag(false, tag, mSpannableStringBuilder, mReader); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void handleP(SpannableStringBuilder text) { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len >= 1 && text.charAt(len - 1) == '\n') { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len >= 2 && text.charAt(len - 2) == '\n') { 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.append("\n"); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len != 0) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.append("\n\n"); 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void handleBr(SpannableStringBuilder text) { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.append("\n"); 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Object getLast(Spanned text, Class kind) { 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This knows that the last returned object from getSpans() 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be the most recently added. 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] objs = text.getSpans(0, text.length(), kind); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (objs.length == 0) { 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return objs[objs.length - 1]; 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void start(SpannableStringBuilder text, Object mark) { 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(mark, len, len, Spannable.SPAN_MARK_MARK); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void end(SpannableStringBuilder text, Class kind, 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object repl) { 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object obj = getLast(text, kind); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = text.getSpanStart(obj); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(obj); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where != len) { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(repl, where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void startImg(SpannableStringBuilder text, 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Attributes attributes, Html.ImageGetter img) { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String src = attributes.getValue("", "src"); 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Drawable d = null; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (img != null) { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project d = img.getDrawable(src); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (d == null) { 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project d = Resources.getSystem(). 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getDrawable(com.android.internal.R.drawable.unknown_image); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.append("\uFFFC"); 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(new ImageSpan(d, src), len, text.length(), 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void startFont(SpannableStringBuilder text, 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Attributes attributes) { 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String color = attributes.getValue("", "color"); 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String face = attributes.getValue("", "face"); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(new Font(color, face), len, len, Spannable.SPAN_MARK_MARK); 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void endFont(SpannableStringBuilder text) { 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object obj = getLast(text, Font.class); 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = text.getSpanStart(obj); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(obj); 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where != len) { 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Font f = (Font) obj; 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6409cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert if (!TextUtils.isEmpty(f.mColor)) { 6419cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert if (f.mColor.startsWith("@")) { 6429cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert Resources res = Resources.getSystem(); 6439cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert String name = f.mColor.substring(1); 6449cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert int colorRes = res.getIdentifier(name, "color", "android"); 6459cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert if (colorRes != 0) { 6469cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert ColorStateList colors = res.getColorStateList(colorRes); 6479cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert text.setSpan(new TextAppearanceSpan(null, 0, 0, colors, null), 6489cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert where, len, 6499cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 6509cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert } 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6529cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert int c = getHtmlColor(f.mColor); 6539cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert if (c != -1) { 6549cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert text.setSpan(new ForegroundColorSpan(c | 0xFF000000), 6559cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert where, len, 6569cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (f.mFace != null) { 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(new TypefaceSpan(f.mFace), where, len, 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void startA(SpannableStringBuilder text, Attributes attributes) { 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String href = attributes.getValue("", "href"); 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(new Href(href), len, len, Spannable.SPAN_MARK_MARK); 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void endA(SpannableStringBuilder text) { 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object obj = getLast(text, Href.class); 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = text.getSpanStart(obj); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(obj); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where != len) { 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Href h = (Href) obj; 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h.mHref != null) { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(new URLSpan(h.mHref), where, len, 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void endHeader(SpannableStringBuilder text) { 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = text.length(); 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object obj = getLast(text, Header.class); 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = text.getSpanStart(obj); 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(obj); 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Back off not to change only the text, not the blank line. 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (len > where && text.charAt(len - 1) == '\n') { 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len--; 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where != len) { 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Header h = (Header) obj; 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(new RelativeSizeSpan(HEADER_SIZES[h.mLevel]), 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(new StyleSpan(Typeface.BOLD), 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDocumentLocator(Locator locator) { 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void startDocument() throws SAXException { 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void endDocument() throws SAXException { 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void startPrefixMapping(String prefix, String uri) throws SAXException { 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void endPrefixMapping(String prefix) throws SAXException { 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void startElement(String uri, String localName, String qName, Attributes attributes) 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws SAXException { 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleStartTag(localName, attributes); 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void endElement(String uri, String localName, String qName) throws SAXException { 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleEndTag(localName); 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void characters(char ch[], int start, int length) throws SAXException { 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Ignore whitespace that immediately follows other whitespace; 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * newlines count as spaces. 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < length; i++) { 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = ch[i + start]; 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == ' ' || c == '\n') { 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char pred; 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = sb.length(); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len == 0) { 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len = mSpannableStringBuilder.length(); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len == 0) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pred = '\n'; 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pred = mSpannableStringBuilder.charAt(len - 1); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pred = sb.charAt(len - 1); 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pred != ' ' && pred != '\n') { 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(' '); 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(c); 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpannableStringBuilder.append(sb); 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void ignorableWhitespace(char ch[], int start, int length) throws SAXException { 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void processingInstruction(String target, String data) throws SAXException { 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void skippedEntity(String name) throws SAXException { 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Bold { } 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Italic { } 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Underline { } 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Big { } 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Small { } 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Monospace { } 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Blockquote { } 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Super { } 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Sub { } 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Font { 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String mColor; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String mFace; 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Font(String color, String face) { 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mColor = color; 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFace = face; 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Href { 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String mHref; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Href(String href) { 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHref = href; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Header { 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mLevel; 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Header(int level) { 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLevel = level; 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8219cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert 8229cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert private static HashMap<String,Integer> COLORS = buildColorMap(); 8239cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert 8249cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert private static HashMap<String,Integer> buildColorMap() { 8259cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert HashMap<String,Integer> map = new HashMap<String,Integer>(); 8269cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("aqua", 0x00FFFF); 8279cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("black", 0x000000); 8289cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("blue", 0x0000FF); 8299cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("fuchsia", 0xFF00FF); 8309cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("green", 0x008000); 8319cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("grey", 0x808080); 8329cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("lime", 0x00FF00); 8339cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("maroon", 0x800000); 8349cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("navy", 0x000080); 8359cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("olive", 0x808000); 8369cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("purple", 0x800080); 8379cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("red", 0xFF0000); 8389cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("silver", 0xC0C0C0); 8399cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("teal", 0x008080); 8409cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("white", 0xFFFFFF); 8419cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert map.put("yellow", 0xFFFF00); 8429cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert return map; 8439cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert } 8449cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert 8459cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert /** 8469cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert * Converts an HTML color (named or numeric) to an integer RGB value. 8479cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert * 8489cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert * @param color Non-null color string. 8499cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert * @return A color value, or {@code -1} if the color string could not be interpreted. 8509cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert */ 8519cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert private static int getHtmlColor(String color) { 8529cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert Integer i = COLORS.get(color.toLowerCase()); 8539cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert if (i != null) { 8549cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert return i; 8559cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert } else { 8569cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert try { 8579cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert return XmlUtils.convertValueToInt(color, -1); 8589cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert } catch (NumberFormatException nfe) { 8599cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert return -1; 8609cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert } 8619cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert } 8629cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert } 8639cab7f7684f046934e3d400482dbd1db67c93ee4Bjorn Bringert 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 865