Strings in format #rgb not handled by Color.decode() (affects CSS / Swing)

XMLWordPrintable

    • b10
    • x86
    • linux, windows_2000



        Name: jk109818 Date: 07/24/2003


        FULL PRODUCT VERSION :
        java version "1.4.1_01"
        Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
        Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)


        FULL OPERATING SYSTEM VERSION :
        Linux jupiter 2.4.19-4GB #1 Fri Sep 13 13:19:15 UTC 2002
        i686 unknown


        A DESCRIPTION OF THE PROBLEM :
        I wrote a simple web browser using the JEditorPane class.
        When I viewed some sites, I detected that JEditorPane
        displayed wrong colors. When I took a look at the style
        sheets, I detected that the colors were given in three
        instead of six sedecimal digits, like
        "background-color:#eee";, which is completely legal CSS and
        should be expanded to #eeeeee; on 24 bit color systems.
        Java does not expand #eee; to #eeeeee; but instead to
        #000eee; which of course produces the wrong colors.

        I believe that Swing simply uses AWT's
        Color.decode(String)-Method to create the required Color object.

        I've found out that Color.decode() doesn't handle
        3-digit-color values as they may be used in CSS.


        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        1. Write a browser (source below)
        2. Run it
        3. load the page (source below)

        Or:
        1. Create a Color-Object.
        2. Print it out.
        3. Look at it's RGB values

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        Expected result: light light gray background
        Actual result: blue background

        Interpretation:
        Instead of expanding #eee to #eeeeee to generate the color
        value, #eee is interpreted as #000eee;

        Or:

        System.out.println(Color.decode("#eee"));
        expected result: java.awt.Color[r=238,g=238,b=238]
        actual result: java.awt.Color[r=0,g=14,b=238]


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        Source code of Java Browser:

        import java.awt.Toolkit;
        import java.awt.event.WindowAdapter;
        import java.awt.event.WindowEvent;
        import java.io.IOException;
        import java.net.MalformedURLException;
        import java.net.URL;
        import javax.swing.JDialog;
        import javax.swing.JEditorPane;
        import javax.swing.JFrame;
        import javax.swing.JScrollPane;
        import javax.swing.event.HyperlinkEvent;
        import javax.swing.event.HyperlinkListener;
        import javax.swing.text.html.HTMLFrameHyperlinkEvent;
        import javax.swing.text.html.HTMLDocument;

        public class Browser extends JFrame implements HyperlinkListener {

            public static final String revision = "$Revision: 1.7 $";

            private static Browser b;

            public static void main(final String[] args) throws IOException,
        MalformedURLException {
                if ("1.4.0".compareTo(System.getProperty("java.version")) >= 0) {
                    JDialog.setDefaultLookAndFeelDecorated(true);
                    JFrame.setDefaultLookAndFeelDecorated(true);
                    Toolkit.getDefaultToolkit().setDynamicLayout(true);
                }
                if (args.length != 0) {
                    b = new Browser(args[0]);
                } else {
                    b = new Browser();
                }
                // System.out.println(Toolkit.getDefaultToolkit().getScreenSize());
                b.setSize(Toolkit.getDefaultToolkit().getScreenSize());
                b.setVisible(true);
                b.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                b.addWindowListener(new WindowAdapter() {
                    public void windowClosing(WindowEvent e) {
                        b.dispose();
                        b = null;
                    }
                });
            }

            private JEditorPane browser;

            public Browser() throws IOException, MalformedURLException {
                this("file:///usr/lib/jax/sun/j2sdkse/latest/docs/index.html");
            }

            public Browser(final String url) throws IOException, MalformedURLException {
                super(url);
                browser = new JEditorPane(new URL(url));
                browser.setEditable(false);
                browser.addHyperlinkListener(this);
                JScrollPane scroll = new JScrollPane(browser);
                getContentPane().add(scroll);
            }

            public void hyperlinkUpdate(final HyperlinkEvent e) {
                if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
                    JEditorPane pane = (JEditorPane) e.getSource();
                    if (e instanceof HTMLFrameHyperlinkEvent) {
                        HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e;
                        HTMLDocument doc = (HTMLDocument) pane.getDocument();
                        doc.processHTMLFrameHyperlinkEvent(evt);
                    } else {
                        try {
                            pane.setPage(e.getURL());
                        } catch (Throwable t) {
                            t.printStackTrace();
                        }
                    }
                }
            }
        }


        Source code of html / css file demonstrating the problem:
        <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
        <html>
            <head>
                <title>Problem</title>
                <style type="text/css">
                    body {
                        background-color:#eee;
                    }
                </style>
            </head>
            <body>
                <h1>Text</h1>
            </body>
        </html>


        Or source code demonstrating the problem with class Color:
        import java.awt.Color;

        public class ColorTest {
            public static void main(String[] args) {
                System.out.println("The following two should be equal:");
                System.out.println(Color.decode("#eeeeee"));
                System.out.println(Color.decode("#eee"));
                assert
                    Color.decode("#eee").equals(Color.decode("#eeeeee")) :
                    "3 hex-digit Colors must be interpreted the same way as their
        corresponding 6 hex-digit Colors";
            }
        }

        ---------- END SOURCE ----------

        CUSTOMER WORKAROUND :
        There is no workaround for this possible, as one can't
        change other site's stylesheets.


        I think the bug can be fixed by changing
        java.awt.Color.decode() to: (untested)

            /**
             * Converts a <code>String</code> to an integer and
        returns the
             * specified opaque <code>Color</code>. This method
        handles string
             * formats that are used to represent octal and
        hexidecimal numbers.
             * @param nm a <code>String</code> that represents
             * an opaque color as a
        24-bit integer
             * or as a 12-bit sedecimal
        integer #rgb
             * @return the new <code>Color</code> object.
             * @see java.lang.Integer#decode
             * @exception NumberFormatException if the specified
        string cannot
             * be interpreted as a decimal,
             * octal, or hexidecimal integer.
             * @since JDK1.1
             */
            public static Color decode(final String nm) throws
        NumberFormatException {
                Integer intval;
                if (nm.startsWith("#") && nm.length() == 4) {
                    intval = Integer.decode("#" + nm.charAt(1) +
        nm.charAt(1) + nm.charAt(2) + nm.charAt(2) + nm.charAt(3) +
        nm.charAt(3));
                } else {
                    intval = Integer.decode(nm);
                }
                int i = intval.intValue();
                return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF,
        i & 0xFF);
            }
        (Incident Review ID: 179135)
        ======================================================================

              Assignee:
              Prasanta Sadhukhan
              Reporter:
              Jeffrey Kim (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: