Bug 577395 - Overview ruler colors have poor contrast, discovered logic error in code
Summary: Overview ruler colors have poor contrast, discovered logic error in code
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Text (show other bugs)
Version: 4.21   Edit
Hardware: PC All
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Platform-Text-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: helpwanted
Depends on:
Blocks:
 
Reported: 2021-11-22 08:18 EST by John Hendrikx CLA
Modified: 2021-12-13 08:00 EST (History)
3 users (show)

See Also:


Attachments
Before, Light Theme (45.31 KB, image/png)
2021-12-03 04:13 EST, John Hendrikx CLA
no flags Details
Before, Dark Theme (45.13 KB, image/png)
2021-12-03 04:15 EST, John Hendrikx CLA
no flags Details
After, Light Theme (46.06 KB, image/png)
2021-12-03 04:15 EST, John Hendrikx CLA
no flags Details
After, Dark Theme (45.08 KB, image/png)
2021-12-03 04:15 EST, John Hendrikx CLA
no flags Details
After, Dark theme without restoring defaults (45.24 KB, image/png)
2021-12-03 04:34 EST, John Hendrikx CLA
no flags Details
After, Dark theme without restoring defaults (v2) (45.25 KB, image/png)
2021-12-03 04:41 EST, John Hendrikx CLA
no flags Details
After, Light Theme (after saturation adjustment) (47.40 KB, image/png)
2021-12-06 16:54 EST, John Hendrikx CLA
no flags Details
light_theme_with patch set 7 (227.63 KB, image/png)
2021-12-09 08:33 EST, Andrey Loskutov CLA
no flags Details
After, Light Theme, Different Contrast Ratio's (121.75 KB, image/png)
2021-12-09 13:48 EST, John Hendrikx CLA
no flags Details
After, Light Theme, Comparison with Dimming (154.29 KB, image/png)
2021-12-10 04:18 EST, John Hendrikx CLA
no flags Details
After, Dark Theme, With Dimming (46.03 KB, image/png)
2021-12-10 05:25 EST, John Hendrikx CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description John Hendrikx CLA 2021-11-22 08:18:20 EST
Reason for my investigation:

The highlight occurrences marker has poor contrast on Windows.  It is a light grey marker which is basically put on a light grey overview ruler, and almost impossible to see.

Why not change it to a darker color?

If I change the color of the marker, it also changes the background color of the text highlighted in the editor.  Make it too dark (so it is well visible on the ruler) and the text (a dark block with black letters) becomes too hard to read.  I don't want to change the way the text is highlighted.

Investigation:

I checked out the source code of org.eclipse.jface.text/src/org/eclipse/jface/text/source/OverviewRuler.java.

It has some logic to ensure that the marker color works well depending on the background it is rendered on.  A dark marker on a dark background will be adjusted to become a bit lighter, and a light marker on a light background will be adjusted to become a bit darker:

                RGB baseRGB= base.getRGB();
                RGB background= fCanvas.getBackground().getRGB();

                boolean darkBase= isDark(baseRGB);
                boolean darkBackground= isDark(background);
                if (darkBase && darkBackground)
                        background= new RGB(255, 255, 255);
                else if (!darkBase && !darkBackground)
                        background= new RGB(0, 0, 0);

                return fSharedTextColors.getColor(interpolate(baseRGB, background, scale));

No adjustment is done if the background is dark and the color is light or vice versa. 

This looks okay at first glance.

However, this makes use of the "isDark" function to determine if a background is dark or light.  If it is dark, you want to adjust towards a lighter color (white), and if it is light you want to adjust towards a darker color (black).

The isDark function contains this:

        private static boolean isDark(RGB rgb) {
                return greyLevel(rgb) > 128;
        }

Basically this says, if the color is quite bright then return that it is dark...

So the adjustment logic above will then make a color that is already quite hard to see (light on light) and adjust it a bit further towards white making it near impossible to see.

There is however an additional problem.  The entire code assumes that adjusting towards black or white is a good idea.  Let's consider these scenarios where all colors involved are light colors:

    bg             marker           adjustment?           adjusted    contrast?
    255 (white)    255 (white)    yes, darker to black      204         41 [OK-ish]
    204 (lgray)    255 (white)    yes, darker to black      204          0 [BAD]
    255 (white)    204 (lgray)    yes, darker to black      163         92 [OK]
    204 (lgray)    204 (lgray)    yes, darker to black      163         41 [OK-ish]

As you can see, one of the cases fails spectacularly while another produces insufficient contrast (although that can be a matter of opinion).

With the current broken logic the adjustment is done in the wrong direction, which also fails but in different ways:

    bg             marker           adjustment?           adjusted    contrast?
    255 (white)    255 (white)    yes, lighter to white     255          0 [BAD]
    204 (lgray)    255 (white)    yes, lighter to white     255         41 [OK-ish]
    255 (white)    204 (lgray)    yes, lighter to white     255          0 [BAD]
    204 (lgray)    204 (lgray)    yes, lighter to white     255         41 [OK-ish]

The code does a poor job of getting a good contrast and sometimes makes things worse.  Instead, what is needed is to look at the difference in grey levels of both the bg and the annotation color.  If it is large enough, do nothing, if it isn't then adjust the annotation color *AWAY* from the bg color.  If the bg color is lighter than the annotation color, then adjust towards black.  If the bg color is darker than the annotation color than adjust towards white.  If they're the same grey level, then adjust towards black if it is a light color, or to white if it is a dark color.  After the adjustment, check if the difference is now large enough, otherwise repeat this process.
Comment 1 Andrey Loskutov CLA 2021-11-22 08:59:52 EST
John, thanks for a good summary. Do you want to contribute a patch?
https://wiki.eclipse.org/Platform/How_to_Contribute
Comment 2 John Hendrikx CLA 2021-11-22 15:28:45 EST
I rarely contribute, but I did have a setup that worked before. Worst case I can provide a patch.
Comment 3 John Hendrikx CLA 2021-11-26 18:10:48 EST
Spent way too much time on finding a good algorithm to pick a good contrasting color given a background color, but I think I got something now that will look nice.

Sample output of this function can be seen here using html to show the colors (paste it somewhere that renders HTML):

<html>
<br>Contrast Ratio 1: <svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg>
<br>Contrast Ratio 3: <svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg>
<br>Contrast Ratio 5: <svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg>
<br>Contrast Ratio 1: <svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg>
<br>Contrast Ratio 3: <svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#494949" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#555555" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#606060" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#6b6b6b" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#767676" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#808080" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#8a8a8a" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#949494" /></svg>
<br>Contrast Ratio 5: <svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffffff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#161616" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#272727" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#343434" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#404040" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#4a4a4a" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#545454" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#5d5d5d" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#666666" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#6f6f6f" /></svg>
<br>Contrast Ratio 1: <svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ededed" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg>
<br>Contrast Ratio 3: <svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#eaeaea" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#494949" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#555555" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#606060" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#6b6b6b" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#767676" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#808080" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#8a8a8a" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#949494" /></svg>
<br>Contrast Ratio 5: <svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e1e1e1" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e7e7e7" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#161616" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#272727" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#343434" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#404040" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#4a4a4a" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#545454" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#5d5d5d" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#666666" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#6f6f6f" /></svg>
<br>Contrast Ratio 3: <svg width="20" height="20"><rect width="20" height="20" style="fill:#ff8000;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8d36" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffad6f" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffca9d" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffe6cc" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#773800" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#894100" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#9a4a00" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#aa5300" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ba5b00" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ca6400" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#d96c00" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e97400" /></svg>
<br>Contrast Ratio 5: <svg width="20" height="20"><rect width="20" height="20" style="fill:#ff8000;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff9a51" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffc08d" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffe3c6" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#290f00" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#431d00" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#572700" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#683000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#783800" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#864000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#954800" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#a24f00" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#b05600" /></svg>
<br>Contrast Ratio 3: <svg width="20" height="20"><rect width="20" height="20" style="fill:#ff8000;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0700;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e0f00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d1600;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c1e00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b2500;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a2d00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#693400;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#783c00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#874300;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8214" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#964b00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff984d" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a55200;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffac6e" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b45a00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffc08c" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c36100;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffd2a9" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d26900;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffe4c8" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e17000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#fff5e9" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f07800;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#7b3a00" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ff7f00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#864000" /></svg>
<br>Contrast Ratio 5: <svg width="20" height="20"><rect width="20" height="20" style="fill:#ff8000;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0700;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e0f00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d1600;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c1e00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b2500;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a2d00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#693400;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff8210" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#783c00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ff9d55" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#874300;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffb57b" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#964b00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffcda0" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a55200;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ffe2c5" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b45a00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#fff8f0" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c36100;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#020000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d26900;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#270e00" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e17000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#391700" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f07800;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#481f00" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ff7f00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#542500" /></svg>
<br>Contrast Ratio 3: <svg width="20" height="20"><rect width="20" height="20" style="fill:#0000ff;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#3030ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#3c3cff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#4b4bff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#5f5fff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#7474ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#8a8aff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#00001a" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000078" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000aa" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000d3" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000f8" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg>
<br>Contrast Ratio 5: <svg width="20" height="20"><rect width="20" height="20" style="fill:#0000ff;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#3030ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0f0f;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#4242ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e1e1e;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#5959ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d2d2d;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#7272ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c3c3c;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#8e8eff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b4b4b;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#ababff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a5a5a;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#c8c8ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#696969;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e5e5ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#787878;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000000" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#878787;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000060" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#969696;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000092" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a5a5a5;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000b9" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b4b4b4;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000db" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c3c3c3;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000fa" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d2d2d2;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e1e1e1;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f0f0f0;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ffffff;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg>
<br>Contrast Ratio 3: <svg width="20" height="20"><rect width="20" height="20" style="fill:#0000ff;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#3030ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0700;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#3636ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e0f00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#3f3fff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d1600;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#4848ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c1e00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#5555ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b2500;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#6161ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a2d00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#6f6fff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#693400;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#7d7dff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#783c00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#8c8cff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#874300;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#9a9aff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#964b00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#00004a" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a55200;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#000077" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b45a00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#00009a" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c36100;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000b6" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d26900;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000d0" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e17000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000e8" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f07800;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ff7f00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000ff" /></svg>
<br>Contrast Ratio 5: <svg width="20" height="20"><rect width="20" height="20" style="fill:#0000ff;stroke-width:3;stroke:rgb(0,0,0)" /></svg>, range:<svg width="20" height="20"><rect width="20" height="20" style="fill:#000000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#3030ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#0f0700;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#3a3aff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#1e0f00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#4747ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#2d1600;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#5555ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#3c1e00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#6565ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#4b2500;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#7676ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#5a2d00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#8888ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#693400;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#9a9aff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#783c00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#adadff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#874300;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#bfbfff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#964b00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#d2d2ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#a55200;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#e5e5ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#b45a00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#f8f8ff" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#c36100;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#00000d" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#d26900;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#00005b" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#e17000;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#00007e" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#f07800;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#00009b" /></svg><svg width="20" height="20"><rect width="20" height="20" style="fill:#ff7f00;stroke-width:3;stroke:rgb(0,0,0)" /><rect x="8" y="8" width="5" height="5" style="fill:#0000b3" /></svg>

</html>
Comment 4 John Hendrikx CLA 2021-11-26 18:20:23 EST
Basically it will calculate the contrast ratio between the background and foreground, and if it is less than a threshold value it will adjust the foreground color.

If adjustment is needed, it will pick a new color based on the input color which has a luminance value (either lower or higher) that satisfies the desired contrast ratio.

The color selection logic will attempt to get sufficient luminance first while keeping the hue and saturation the same.  If that's impossible (for example getting a fully saturated blue 0x0000ff to appear even brighter) it will start reducing saturation (0x1111ff -> 0x2222ff, etc) while adhering to the intended target luminance.  If that also fails, for example because the desired luminance is less than 0 or greater than 1, it will pick black or white respectively.
Comment 5 Eclipse Genie CLA 2021-12-02 17:25:51 EST
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.text/+/188488
Comment 6 Mickael Istria CLA 2021-12-03 03:23:46 EST
Can you please post a screenshot comparing before/after on the main themes?
Comment 7 John Hendrikx CLA 2021-12-03 04:13:29 EST
Created attachment 287614 [details]
Before, Light Theme
Comment 8 John Hendrikx CLA 2021-12-03 04:15:07 EST
Created attachment 287615 [details]
Before, Dark Theme
Comment 9 John Hendrikx CLA 2021-12-03 04:15:34 EST
Created attachment 287616 [details]
After, Light Theme
Comment 10 John Hendrikx CLA 2021-12-03 04:15:53 EST
Created attachment 287617 [details]
After, Dark Theme
Comment 11 John Hendrikx CLA 2021-12-03 04:28:42 EST
I attached screenshots, but noticed an issue in the dark theme (not related to this change).

When you switch to the dark theme, the colors for Occurences and Write Occurences get set to some dark gray and dark blue.  This is probably because the same color is also used for highlighting in the editor itself and the standard bright gray and orange doesn't work well for highlighting in the editor.

My screenshot "After, Dark Theme" however shows the default colors (after doing Restore Defaults), which switches the Occurences and Write Occurences colors back to bright gray and orange.

This looks like two separate issues that should be resolved as well -- the text highlighting color should probably be a separate color to choose, and Restore Defaults should probably be theme sensitive.

I will attach another screenshot showing the after situation with the standard dark theme colors "After, Dark Theme without restoring default colors".
Comment 12 John Hendrikx CLA 2021-12-03 04:34:05 EST
Created attachment 287618 [details]
After, Dark theme without restoring defaults
Comment 13 Andrey Loskutov CLA 2021-12-03 04:40:29 EST
(In reply to John Hendrikx from comment #11)
> I attached screenshots

Thanks. Contrast is clearly better, but the Light theme colors seem "too grayish" now. 
Is there a way to increase saturation a bit, and move less towards black?
Comment 14 John Hendrikx CLA 2021-12-03 04:41:09 EST
Created attachment 287619 [details]
After, Dark theme without restoring defaults (v2)
Comment 15 John Hendrikx CLA 2021-12-03 05:08:53 EST
(In reply to Andrey Loskutov from comment #13)
> 
> Thanks. Contrast is clearly better, but the Light theme colors seem "too
> grayish" now. 
> Is there a way to increase saturation a bit, and move less towards black?

They are definitely more gray, and I do want to keep the saturation better. I think this is an artifact of the way I scale the colors now (in RGB colorspace). I will do an attempt to do the scaling in HSY.

An easier solution might be to just separate the colors for the Overview Ruler and the Text Highlight in the editor.  One of the reasons the contrast was so poor to begin with is that you can't really adjust the colors without messing up the highlight colors in the editor, and it is hard to have one color for these that will work in both the ruler and the editor.
Comment 16 Eclipse Genie CLA 2021-12-06 16:53:30 EST
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.text/+/188588
Comment 17 John Hendrikx CLA 2021-12-06 16:54:09 EST
Created attachment 287628 [details]
After, Light Theme (after saturation adjustment)
Comment 18 John Hendrikx CLA 2021-12-06 16:59:45 EST
(In reply to Andrey Loskutov from comment #13)
> (In reply to John Hendrikx from comment #11)
> > I attached screenshots
> 
> Thanks. Contrast is clearly better, but the Light theme colors seem "too
> grayish" now. 
> Is there a way to increase saturation a bit, and move less towards black?

I've adjusted the code (significantly, new algorithm) to first adjust the color for the desired luminance, and if that would fall outside the sRGB color space, to reduce its saturation until it becomes a valid sRGB color.  This adjustment does not affect its luminance or hue.

I've attached a new screenshot, and you can see that the "write occurences" markers are a bit more saturated.  The other markers visible on those screenshots (warning, info and read occurence) were unaffected.

Note however that the light theme colors are always going to be a bit harder to adjust as it is harder to get sufficient contrast when the background is bright.
Comment 19 Andrey Loskutov CLA 2021-12-09 08:33:20 EST
Created attachment 287649 [details]
light_theme_with patch set 7

See attached screen shot with side by side example of old/new colors. 

I like the new contrast, it is clearly way better, but could we have a proposal example somewhere in the middle, so the annotations are not that dark?
Comment 20 John Hendrikx CLA 2021-12-09 10:12:14 EST
(In reply to Andrey Loskutov from comment #19)
> Created attachment 287649 [details]
> light_theme_with patch set 7
> 
> See attached screen shot with side by side example of old/new colors. 
> 
> I like the new contrast, it is clearly way better, but could we have a
> proposal example somewhere in the middle, so the annotations are not that
> dark?

If you would like to experiment yourself, you can adjust the contrast ratio value found at line 1305 in OverviewRuler:

RGB adjustedRGB= ColorContrastUtil.adjustForSufficientContrast(baseRGB, background, 2);

The value is now set to 2, but it can be tuned down all the way to 1 (no change).  Try for example 1.8 or 1.5 to reduce the contrast a bit further.
Comment 21 Andrey Loskutov CLA 2021-12-09 12:40:47 EST
(In reply to John Hendrikx from comment #20)
> (In reply to Andrey Loskutov from comment #19)
> > Created attachment 287649 [details]
> > light_theme_with patch set 7
> > 
> > See attached screen shot with side by side example of old/new colors. 
> > 
> > I like the new contrast, it is clearly way better, but could we have a
> > proposal example somewhere in the middle, so the annotations are not that
> > dark?
> 
> If you would like to experiment yourself, you can adjust the contrast ratio
> value found at line 1305 in OverviewRuler

Thanks, unfortunately I have no time for that.

What I see is that markers with already good contrast (errors, breakpoints) gets exceptionally bright/strong in the new code. Try to introduce errors in Java file with breakpoints, you will see what I mean. I don't have a proposal how to deal with that.

@Matthias: may be this enhancement is interesting for you too?
Comment 22 John Hendrikx CLA 2021-12-09 13:37:13 EST
I'll post some screenshots then with some lower contrast ratio for your convience.
Comment 23 John Hendrikx CLA 2021-12-09 13:48:10 EST
Created attachment 287653 [details]
After, Light Theme, Different Contrast Ratio's
Comment 24 John Hendrikx CLA 2021-12-09 13:55:17 EST
Note that as part of this change I removed the standard 20% dimming of the stroke color and the standard 50% dimming of the fill color.  It's possible that the default colors are now just chosen poorly as in the past they probably were tuned taking this dimming into account.

The breakpoint color for example is not exactly as it appears in the Preferences dialog, and since it has sufficient contrast, is not altered by the new code. However, before, it was dimmed 20%.

As a single color is used to configure three completely different mechanisms (vertical rules, overview ruler and text underline/highlight) it may not be possible to make it look satisfactory in all cases -- I think the Dark Theme designers probably have run into this as well as their colors are tuned for good display in the editor, but are really poor choices in the rulers.

What I can do is put the 20% dimming back in place, and then adjust the dimmed colors for sufficient contrast if needed, which probably won't be the case for the error/breakpoint colors.
Comment 25 John Hendrikx CLA 2021-12-09 13:56:16 EST
...is now exactly... (*)
Comment 26 Matthias Becker CLA 2021-12-10 02:11:23 EST
(In reply to Andrey Loskutov from comment #19)
> I like the new contrast, it is clearly way better, but could we have a
> proposal example somewhere in the middle, so the annotations are not that
> dark?

What do you mean with "annotations"? Do you mean the the highlight in "Overview ruler" on the right side?
Comment 27 Andrey Loskutov CLA 2021-12-10 02:13:50 EST
(In reply to Matthias Becker from comment #26)
> What do you mean with "annotations"? Do you mean the the highlight in
> "Overview ruler" on the right side?

Yes.
Comment 28 Matthias Becker CLA 2021-12-10 02:14:30 EST
(In reply to John Hendrikx from comment #24)
> Note that as part of this change I removed the standard 20% dimming of the
> stroke color and the standard 50% dimming of the fill color.  It's possible
> that the default colors are now just chosen poorly as in the past they
> probably were tuned taking this dimming into account.
> 
> The breakpoint color for example is not exactly as it appears in the
> Preferences dialog, and since it has sufficient contrast, is not altered by
> the new code. However, before, it was dimmed 20%.
> 
> As a single color is used to configure three completely different mechanisms
> (vertical rules, overview ruler and text underline/highlight) it may not be
> possible to make it look satisfactory in all cases -- I think the Dark Theme
> designers probably have run into this as well as their colors are tuned for
> good display in the editor, but are really poor choices in the rulers.
> 
> What I can do is put the 20% dimming back in place, and then adjust the
> dimmed colors for sufficient contrast if needed, which probably won't be the
> case for the error/breakpoint colors.

I clearly see that the 1.5x and 2x versions are better as todays version.
But I honestly don't see a difference between 1.5x and 2x. 
I also don't see a difference between the Breakpoint and Error markers in today's version and your two new versions.
I also don't see where this dimming had an effect.
Comment 29 John Hendrikx CLA 2021-12-10 04:18:26 EST
(In reply to Matthias Becker from comment #28)
> I clearly see that the 1.5x and 2x versions are better as todays version.
> But I honestly don't see a difference between 1.5x and 2x. 

The difference is only visible for the Occurences and Write Occurences annotations.  The others are unaffected as they have sufficient contrast already.

> I also don't see a difference between the Breakpoint and Error markers in
> today's version and your two new versions.
> I also don't see where this dimming had an effect.

I removed the dimming which was done by default in the OverviewRuler. The OverviewRuler uses the color it obtains from `setAnnotationTypeColor`, but for some reason never uses that color directly, instead it changes it a bit in this (old) bit of code:

    private Color getStrokeColor(Object annotationType, boolean temporary) {
        return getColor(annotationType, temporary && fIsTemporaryAnnotationDiscolored ? 0.5 : 0.2);
    }

The 0.2 factor here is what I called the 20% dimming of the color.  I've set this to 0.0.

It then proceeded to apply its algorithm to calculate a suitable color for a given background which, as I pointed out in my first comment, is a bit flawed.

My motivation for removing it was to have a more direct mapping to what color was chosen by the user and what the OverviewRuler uses and only fixing the contrast if needed -- this saves second guessing the color actually used (ie, the user would have to select a 20% brighter color to get the color they actually wanted).  

So in effect, without the 20% dimming, you are getting exactly what you said you wanted in the Preferences unless the contrast needs adjusting.

As however there is only a single color for the two rulers and text highlighting/underlining I guess this 20% factor was added to OverviewRuler to make the colors used there a bit more palatable given that you are restricted by how the color would look in the editor as well. 

This is very noticable in the dark theme where the need for having a readable highlight color (not too bright) trumps the needs of the overview ruler (which would prefer brighter colors).  For example, the "highlight occurences" annotation in dark theme is a very dark blue so that highlighted text in the editor is a black background, with a dark blue highlight and light colored text.  In the ruler however you get a black background with a tiny dark blue marker that is hard to see.

As I think this is not solvable without being able to specify colors that are only used in the overview ruler I've adjusted the code to do a compromise.

See the screenshot I attached in the next comment.
Comment 30 John Hendrikx CLA 2021-12-10 04:18:58 EST
Created attachment 287657 [details]
After, Light Theme, Comparison with Dimming
Comment 31 Andrey Loskutov CLA 2021-12-10 04:26:45 EST
(In reply to John Hendrikx from comment #30)
> Created attachment 287657 [details]
> After, Light Theme, Comparison with Dimming

This is moving in the right direction (20% dimming + 2.0 ratio).
Could you please push that patch set (and please rebase first)?
Comment 32 John Hendrikx CLA 2021-12-10 04:27:41 EST
What the code now does vs original

Original:
- Stroke color
  - Take annotation color
  - Blend with background color (20%)
- Fill color
  - Take annotation color
  - Blend with background color (75%)

New:
- Stroke color
  - Take annotation color
  - Blend with background color (20%)
  - Adjust color for sufficient contrast if needed (contrast ratio = 2.0)
- Fill color
  - Take stroke color (which is already adjusted for contrast)
  - Blend with background color (60%, a bit less as it is based on stroke)

This pretty closely produces the original colors for markers which were already well visible, and produces more distinct colors for markers that lacked in contrast.
Comment 33 Matthias Becker CLA 2021-12-10 05:19:49 EST
(In reply to John Hendrikx from comment #30)
> Created attachment 287657 [details]
> After, Light Theme, Comparison with Dimming

How does this look like in the dark theme?
Comment 34 John Hendrikx CLA 2021-12-10 05:25:55 EST
Created attachment 287658 [details]
After, Dark Theme, With Dimming

I added a screenshot with dark theme for the current version.
Comment 35 Matthias Becker CLA 2021-12-10 08:28:15 EST
(In reply to John Hendrikx from comment #34)
> Created attachment 287658 [details]
> After, Dark Theme, With Dimming
> 
> I added a screenshot with dark theme for the current version.

Thanks. How did it look before? As I am on macOS I cannot see this myself.
Comment 36 John Hendrikx CLA 2021-12-10 12:21:00 EST
This one is before: https://bugzillaattachments.eclipsecontent.org/bugs/attachment.cgi?id=287615
Comment 37 Matthias Becker CLA 2021-12-13 02:14:31 EST
(In reply to John Hendrikx from comment #34)
> Created attachment 287658 [details]
> After, Dark Theme, With Dimming
> 
> I added a screenshot with dark theme for the current version.

I think this is also better compared to the current version.

Is this all windows specific or do we have these issues also on other OSes?
Comment 38 John Hendrikx CLA 2021-12-13 07:04:37 EST
> (In reply to John Hendrikx from comment #34)
> > Created attachment 287658 [details]
> > After, Dark Theme, With Dimming
> > 
> > I added a screenshot with dark theme for the current version.
> 
> I think this is also better compared to the current version.
> 
> Is this all windows specific or do we have these issues also on other OSes?

It is not windows specific, the issue can occur on all platforms.  It depends on the background color of the Overview ruler.  On Windows it is a light gray which makes the "mark occurrences" markers (which are also light gray) really hard to see.  

If however on those other platforms the colors already have sufficient contrast (because their ruler is white or black for example) then this code won't change the colors, it only changes when it is absolutely required for the marker to have a decent level of visibility.

The old ruler code already did adjustments, but its logic would sometimes make adjustments that would make the problem worse.  This has now been replaced with logic that will guarantee a minimum amount of contrast, and leaves the colors untouched otherwise.
Comment 39 Matthias Becker CLA 2021-12-13 08:00:12 EST
(In reply to John Hendrikx from comment #38)
> It is not windows specific, the issue can occur on all platforms.  It
> depends on the background color of the Overview ruler.  On Windows it is a
> light gray which makes the "mark occurrences" markers (which are also light
> gray) really hard to see.  
> 
> If however on those other platforms the colors already have sufficient
> contrast (because their ruler is white or black for example) then this code
> won't change the colors, it only changes when it is absolutely required for
> the marker to have a decent level of visibility.

So it would be a good idea to also test this change on all the major OSes we support. I can do this for macOS.