Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9cab7f76 authored by Bjorn Bringert's avatar Bjorn Bringert
Browse files

Allow system colors in <font> tags

parent 37b939a6
Loading
Loading
Loading
Loading
+62 −45
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
@@ -40,6 +41,7 @@ import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TextAppearanceSpan;
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
@@ -49,6 +51,7 @@ import com.android.internal.util.XmlUtils;
import java.io.IOException;
import java.io.StringReader;
import java.nio.CharBuffer;
import java.util.HashMap;

/**
 * This class processes HTML strings into displayable styled text.
@@ -633,55 +636,26 @@ class HtmlToSpannedConverter implements ContentHandler {
        if (where != len) {
            Font f = (Font) obj;

            if (f.mColor != null) {
                int c = -1;

                if (f.mColor.equalsIgnoreCase("aqua")) {
                    c = 0x00FFFF;
                } else if (f.mColor.equalsIgnoreCase("black")) {
                    c = 0x000000;
                } else if (f.mColor.equalsIgnoreCase("blue")) {
                    c = 0x0000FF;
                } else if (f.mColor.equalsIgnoreCase("fuchsia")) {
                    c = 0xFF00FF;
                } else if (f.mColor.equalsIgnoreCase("green")) {
                    c = 0x008000;
                } else if (f.mColor.equalsIgnoreCase("grey")) {
                    c = 0x808080;
                } else if (f.mColor.equalsIgnoreCase("lime")) {
                    c = 0x00FF00;
                } else if (f.mColor.equalsIgnoreCase("maroon")) {
                    c = 0x800000;
                } else if (f.mColor.equalsIgnoreCase("navy")) {
                    c = 0x000080;
                } else if (f.mColor.equalsIgnoreCase("olive")) {
                    c = 0x808000;
                } else if (f.mColor.equalsIgnoreCase("purple")) {
                    c = 0x800080;
                } else if (f.mColor.equalsIgnoreCase("red")) {
                    c = 0xFF0000;
                } else if (f.mColor.equalsIgnoreCase("silver")) {
                    c = 0xC0C0C0;
                } else if (f.mColor.equalsIgnoreCase("teal")) {
                    c = 0x008080;
                } else if (f.mColor.equalsIgnoreCase("white")) {
                    c = 0xFFFFFF;
                } else if (f.mColor.equalsIgnoreCase("yellow")) {
                    c = 0xFFFF00;
                } else {
                    try {
                        c = XmlUtils.convertValueToInt(f.mColor, -1);
                    } catch (NumberFormatException nfe) {
                        // Can't understand the color, so just drop it.
                    }
            if (!TextUtils.isEmpty(f.mColor)) {
                if (f.mColor.startsWith("@")) {
                    Resources res = Resources.getSystem();
                    String name = f.mColor.substring(1);
                    int colorRes = res.getIdentifier(name, "color", "android");
                    if (colorRes != 0) {
                        ColorStateList colors = res.getColorStateList(colorRes);
                        text.setSpan(new TextAppearanceSpan(null, 0, 0, colors, null),
                                where, len,
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }

                } else {
                    int c = getHtmlColor(f.mColor);
                    if (c != -1) {
                        text.setSpan(new ForegroundColorSpan(c | 0xFF000000),
                                where, len,
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                }
            }

            if (f.mFace != null) {
                text.setSpan(new TypefaceSpan(f.mFace), where, len,
@@ -843,4 +817,47 @@ class HtmlToSpannedConverter implements ContentHandler {
            mLevel = level;
        }
    }

    private static HashMap<String,Integer> COLORS = buildColorMap();

    private static HashMap<String,Integer> buildColorMap() {
        HashMap<String,Integer> map = new HashMap<String,Integer>();
        map.put("aqua", 0x00FFFF);
        map.put("black", 0x000000);
        map.put("blue", 0x0000FF);
        map.put("fuchsia", 0xFF00FF);
        map.put("green", 0x008000);
        map.put("grey", 0x808080);
        map.put("lime", 0x00FF00);
        map.put("maroon", 0x800000);
        map.put("navy", 0x000080);
        map.put("olive", 0x808000);
        map.put("purple", 0x800080);
        map.put("red", 0xFF0000);
        map.put("silver", 0xC0C0C0);
        map.put("teal", 0x008080);
        map.put("white", 0xFFFFFF);
        map.put("yellow", 0xFFFF00);
        return map;
    }

    /**
     * Converts an HTML color (named or numeric) to an integer RGB value.
     *
     * @param color Non-null color string.
     * @return A color value, or {@code -1} if the color string could not be interpreted.
     */
    private static int getHtmlColor(String color) {
        Integer i = COLORS.get(color.toLowerCase());
        if (i != null) {
            return i;
        } else {
            try {
                return XmlUtils.convertValueToInt(color, -1);
            } catch (NumberFormatException nfe) {
                return -1;
            }
        }
      }

}
+58 −4
Original line number Diff line number Diff line
@@ -16,11 +16,25 @@

package com.android.unit_tests;

import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.*;
import android.text.style.*;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.QuoteSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TextAppearanceSpan;
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;

import junit.framework.TestCase;

@@ -35,14 +49,54 @@ public class HtmlTest extends TestCase {

        s = Html.fromHtml("<font color=\"#00FF00\">something</font>");
        colors = s.getSpans(0, s.length(), ForegroundColorSpan.class);
        assertEquals(colors[0].getForegroundColor(), 0xFF00FF00);
        assertEquals(1, colors.length);
        assertEquals(0xFF00FF00, colors[0].getForegroundColor());

        s = Html.fromHtml("<font color=\"navy\">something</font>");
        colors = s.getSpans(0, s.length(), ForegroundColorSpan.class);
        assertEquals(colors[0].getForegroundColor(), 0xFF000080);
        assertEquals(1, colors.length);
        assertEquals(0xFF000080, colors[0].getForegroundColor());

        s = Html.fromHtml("<font color=\"gibberish\">something</font>");
        colors = s.getSpans(0, s.length(), ForegroundColorSpan.class);
        assertEquals(0, colors.length);
    }

    @MediumTest
    public void testResourceColor() throws Exception {
        ColorStateList c =
                Resources.getSystem().getColorStateList(android.R.color.primary_text_dark);
        Spanned s;
        TextAppearanceSpan[] colors;

        s = Html.fromHtml("<font color=\"@android:color/primary_text_dark\">something</font>");
        colors = s.getSpans(0, s.length(), TextAppearanceSpan.class);
        assertEquals(1, colors.length);
        assertEquals(c.toString(), colors[0].getTextColor().toString());

        s = Html.fromHtml("<font color=\"@android:primary_text_dark\">something</font>");
        colors = s.getSpans(0, s.length(), TextAppearanceSpan.class);
        assertEquals(1, colors.length);
        assertEquals(c.toString(), colors[0].getTextColor().toString());

        s = Html.fromHtml("<font color=\"@color/primary_text_dark\">something</font>");
        colors = s.getSpans(0, s.length(), TextAppearanceSpan.class);
        assertEquals(1, colors.length);
        assertEquals(c.toString(), colors[0].getTextColor().toString());

        s = Html.fromHtml("<font color=\"@primary_text_dark\">something</font>");
        colors = s.getSpans(0, s.length(), TextAppearanceSpan.class);
        assertEquals(1, colors.length);
        assertEquals(c.toString(), colors[0].getTextColor().toString());

        s = Html.fromHtml("<font color=\"@" + android.R.color.primary_text_dark
                + "\">something</font>");
        colors = s.getSpans(0, s.length(), TextAppearanceSpan.class);
        assertEquals(1, colors.length);
        assertEquals(c.toString(), colors[0].getTextColor().toString());

        s = Html.fromHtml("<font color=\"gibberish\">something</font>");
        colors = s.getSpans(0, s.length(), TextAppearanceSpan.class);
        assertEquals(colors.length, 0);
    }