Changeset 239597 in webkit


Ignore:
Timestamp:
Jan 3, 2019 1:58:23 PM (5 years ago)
Author:
Devin Rousso
Message:

Web Inspector: conic-gradient color picker doesn't accurately show color when saturation value is not 100%
https://bugs.webkit.org/show_bug.cgi?id=192729
<rdar://problem/46746815>

Reviewed by Joseph Pecoraro.

Source/WebInspectorUI:

Rework WI.ColorWheel to use similar canvas drawing logic as WI.LegacyColorWheel so that
it's able to adjust the saturation value as the pixels gets closer to the center.

  • UserInterface/Models/Color.js:

(WI.Color.rgb2hsl): Added.
(WI.Color.hsl2rgb): Added.
(WI.Color.cmyk2rgb):
(WI.Color.prototype.isKeyword):
(WI.Color.prototype._toRGBString):
(WI.Color.prototype._toRGBAString):
(WI.Color.prototype._toHSLString):
(WI.Color.prototype._toHSLAString):
(WI.Color.prototype._rgbaToHSLA):
(WI.Color.prototype._hslaToRGBA):
(WI.Color.rgb2hsv): Deleted.
(WI.Color.hsv2rgb): Deleted.
(WI.Color.prototype._rgbToHSL): Deleted.
(WI.Color.prototype._hslToRGB): Deleted.
Adjust the conversion functions of WI.Color to be more accurate.

  • UserInterface/Views/ColorWheel.js:

(WI.ColorWheel):
(WI.ColorWheel.prototype.set dimension):
(WI.ColorWheel.prototype.set brightness):
(WI.ColorWheel.prototype.get tintedColor):
(WI.ColorWheel.prototype.set tintedColor):
(WI.ColorWheel.prototype._updateColorForMouseEvent):
(WI.ColorWheel.prototype._updateCanvas): Added.
(WI.ColorWheel.prototype._updateGradient): Deleted.

  • UserInterface/Views/ColorWheel.css:

(.color-wheel > canvas): Added.
(.color-wheel > .gradient): Deleted.

  • UserInterface/Views/ColorPicker.js:

(WI.ColorPicker):
(WI.ColorPicker.prototype.set color):
(WI.ColorPicker.prototype.sliderValueDidChange):
(WI.ColorPicker.prototype._updateSliders):
(WI.ColorPicker.prototype._showColorComponentInputs):
(WI.ColorPicker.supportsConicGradient): Deleted.

  • UserInterface/Main.html:
  • UserInterface/Views/LegacyColorWheel.js: Removed.

LayoutTests:

  • inspector/model/color.html:
  • inspector/model/color-expected.txt:
Location:
trunk
Files:
1 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r239594 r239597  
     12019-01-03  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: conic-gradient color picker doesn't accurately show color when saturation value is not 100%
     4        https://bugs.webkit.org/show_bug.cgi?id=192729
     5        <rdar://problem/46746815>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        * inspector/model/color.html:
     10        * inspector/model/color-expected.txt:
     11
    1122019-01-03  Brent Fulgham  <bfulgham@apple.com>
    213
  • trunk/LayoutTests/inspector/model/color-expected.txt

    r222102 r239597  
    9999PASS: '#11122233' should not be a keyword.
    100100PASS: '#11122233' has rgba of [17, 18, 34, 0.2].
    101 PASS: '#11122233' has hsla of [236, 33, 10, 0.2].
     101PASS: '#11122233' has hsla of [236.47, 33.33, 10, 0.2].
    102102PASS: '#11122233' should not be serializable as a short Hex
    103103PASS: '#11223344' should be serializable as a short Hex
     
    113113PASS: Should have rgb of [128,128,128].
    114114PASS: Should have rgba of [128,128,128,0.5].
    115 PASS: Should have hsl of [0,0,50].
    116 PASS: Should have hsla of [0,0,50,0.5].
     115PASS: Should have hsl of [0,0,50.2].
     116PASS: Should have hsla of [0,0,50.2,0.5].
    117117Check components for color 'hsl(0, 0%, 50%)'.
    118 PASS: Should have rgb of [128,128,128].
    119 PASS: Should have rgba of [128,128,128,1].
     118PASS: Should have rgb of [127.5,127.5,127.5].
     119PASS: Should have rgba of [127.5,127.5,127.5,1].
    120120PASS: Should have hsl of [0,0,50].
    121121PASS: Should have hsla of [0,0,50,1].
    122122Check components for color 'hsla(0, 0%, 50%, 0.5)'.
    123 PASS: Should have rgb of [128,128,128].
    124 PASS: Should have rgba of [128,128,128,0.5].
     123PASS: Should have rgb of [127.5,127.5,127.5].
     124PASS: Should have rgba of [127.5,127.5,127.5,0.5].
    125125PASS: Should have hsl of [0,0,50].
    126126PASS: Should have hsla of [0,0,50,0.5].
     
    151151PASS: Color as 'RGB' should be 'rgba(100, 200, 255, 0.5)'
    152152PASS: Color as 'RGBA' should be 'rgba(100, 200, 255, 0.5)'
    153 PASS: Color as 'HSL' should be 'hsla(201, 100%, 70%, 0.5)'
    154 PASS: Color as 'HSLA' should be 'hsla(201, 100%, 70%, 0.5)'
     153PASS: Color as 'HSL' should be 'hsla(201.29, 100%, 69.61%, 0.5)'
     154PASS: Color as 'HSLA' should be 'hsla(201.29, 100%, 69.61%, 0.5)'
    155155
    156 -- Running test case: WI.Color.rgb2hsv
     156-- Running test case: WI.Color.rgb2hsl
    157157PASS: Should convert [0,0,0] to [0,0,0].
    158 PASS: Should convert [255,255,255] to [0,0,1].
    159 PASS: Should convert [255,0,0] to [0,1,1].
    160 PASS: Should convert [0,255,0] to [120,1,1].
    161 PASS: Should convert [0,0,255] to [240,1,1].
     158PASS: Should convert [255,255,255] to [0,0,100].
     159PASS: Should convert [255,0,0] to [0,100,50].
     160PASS: Should convert [0,255,0] to [120,100,50].
     161PASS: Should convert [0,0,255] to [240,100,50].
    162162PASS: Should convert [-1,-1,-1] to [0,0,0].
    163 PASS: Should convert [256,256,256] to [0,0,1].
    164 PASS: Should convert [254.9,0,0] to [0,1,1].
     163PASS: Should convert [256,256,256] to [0,0,100].
     164PASS: Should convert [254.9,0,0] to [0,100,50].
     165
     166-- Running test case: WI.Color.hsl2rgb
     167PASS: Should convert [0,0,0] to [0,0,0].
     168PASS: Should convert [0,0,100] to [255,255,255].
     169PASS: Should convert [0,100,50] to [255,0,0].
     170PASS: Should convert [120,100,50] to [0,255,0].
     171PASS: Should convert [240,100,50] to [0,0,255].
     172PASS: Should convert [-1,-1,-1] to [0,0,0].
     173PASS: Should convert [361,101,50] to [255,0,0].
     174PASS: Should convert [361,101,101] to [255,255,255].
    165175
    166176-- Running test case: WI.Color.cmyk2rgb
  • trunk/LayoutTests/inspector/model/color.html

    r222102 r239597  
    3333    }
    3434
    35     let suite = InspectorTest.createAsyncSuite("WI.Color");
     35    let suite = InspectorTest.createSyncSuite("WI.Color");
    3636
    3737    suite.addTestCase({
    3838        name: "WI.Color.fromString",
    3939        description: "Test we can detect colors from strings.",
    40         test(resolve, reject) {
     40        test() {
    4141            function testGood(string, expectedFormat) {
    4242                let color = WI.Color.fromString(string);
     
    108108            // testBad("hsla(0, 0, 50, 1)"); // missing %s
    109109
    110             resolve();
     110            return true;
    111111        }
    112112    });
     
    115115        name: "WI.Color properties",
    116116        description: "Test different color properties.",
    117         test(resolve, reject) {
     117        test() {
    118118            let color;
    119119
     
    143143            InspectorTest.expectThat(color.isKeyword() === false, "'#11122233' should not be a keyword.");
    144144            InspectorTest.expectShallowEqual(color.rgba, [17, 18, 34, 0.2], "'#11122233' has rgba of [17, 18, 34, 0.2].");
    145             InspectorTest.expectShallowEqual(color.hsla, [236, 33, 10, 0.2], "'#11122233' has hsla of [236, 33, 10, 0.2].");
     145            InspectorTest.expectShallowEqual(color.hsla.map((value) => value.maxDecimals(2)), [236.47, 33.33, 10, 0.2], "'#11122233' has hsla of [236.47, 33.33, 10, 0.2].");
    146146            InspectorTest.expectThat(color.canBeSerializedAsShortHEX() === false, "'#11122233' should not be serializable as a short Hex");
    147147
     
    152152            InspectorTest.expectThat(color.canBeSerializedAsShortHEX() === false, "'#11223345' should not be serializable as a short Hex");
    153153
    154             resolve();
     154            return true;
    155155        }
    156156    });
     
    159159        name: "WI.Color from components",
    160160        description: "Test different three- and four-component colors.",
    161         test(resolve, reject) {
     161        test() {
    162162            function test(color, components) {
    163163                InspectorTest.log(`Check components for color '${color.toString()}'.`);
    164164                for (let key in components) {
    165165                    let value = components[key];
    166                     InspectorTest.expectShallowEqual(color[key], value, `Should have ${key} of ${JSON.stringify(value)}.`);
     166                    InspectorTest.expectShallowEqual(color[key].map((value) => value.maxDecimals(2)), value, `Should have ${key} of ${JSON.stringify(value)}.`);
    167167                }
    168168            }
     
    178178                rgb: [128, 128, 128],
    179179                rgba: [128, 128, 128, 0.5],
     180                hsl: [0, 0, 50.2],
     181                hsla: [0, 0, 50.2, 0.5],
     182            });
     183
     184            test(new WI.Color(WI.Color.Format.HSL, [0, 0, 50]), {
     185                rgb: [127.5, 127.5, 127.5],
     186                rgba: [127.5, 127.5, 127.5, 1],
     187                hsl: [0, 0, 50],
     188                hsla: [0, 0, 50, 1],
     189            });
     190
     191            test(new WI.Color(WI.Color.Format.HSLA, [0, 0, 50, 0.5]), {
     192                rgb: [127.5, 127.5, 127.5],
     193                rgba: [127.5, 127.5, 127.5, 0.5],
    180194                hsl: [0, 0, 50],
    181195                hsla: [0, 0, 50, 0.5],
    182196            });
    183197
    184             test(new WI.Color(WI.Color.Format.HSL, [0, 0, 50]), {
    185                 rgb: [128, 128, 128],
    186                 rgba: [128, 128, 128, 1],
    187                 hsl: [0, 0, 50],
    188                 hsla: [0, 0, 50, 1],
    189             });
    190 
    191             test(new WI.Color(WI.Color.Format.HSLA, [0, 0, 50, 0.5]), {
    192                 rgb: [128, 128, 128],
    193                 rgba: [128, 128, 128, 0.5],
    194                 hsl: [0, 0, 50],
    195                 hsla: [0, 0, 50, 0.5],
    196             });
    197 
    198             resolve();
     198            return true;
    199199        }
    200200    });
     
    203203        name: "WI.Color.prototype.nextFormat",
    204204        description: "Test we can cycle through color formats for different colors.",
    205         test(resolve, reject) {
     205        test() {
    206206            function test(string, phases) {
    207207                let color = WI.Color.fromString(string);
     
    251251            ]);
    252252
    253             resolve();
     253            return true;
    254254        }
    255255    });
     
    258258        name: "WI.Color.prototype.toString",
    259259        description: "Test the different toString outputs.",
    260         test(resolve, reject) {
     260        test() {
    261261            let color;
    262262            function test(expected, format) {
     
    289289            test("rgba(100, 200, 255, 0.5)", WI.Color.Format.RGB); // fallback (rgba)
    290290            test("rgba(100, 200, 255, 0.5)", WI.Color.Format.RGBA);
    291             test("hsla(201, 100%, 70%, 0.5)", WI.Color.Format.HSL); // fallback (hsla)
    292             test("hsla(201, 100%, 70%, 0.5)", WI.Color.Format.HSLA);
     291            test("hsla(201.29, 100%, 69.61%, 0.5)", WI.Color.Format.HSL); // fallback (hsla)
     292            test("hsla(201.29, 100%, 69.61%, 0.5)", WI.Color.Format.HSLA);
    293293
    294294            // FIXME: Should we clamp rgb(300, 300, 300) => rgb(255, 255, 255) in toStrings?
    295295            // FIXME: Should we always stash the original string, no matter how poor?
    296296
    297             resolve();
     297            return true;
    298298        }
    299299    });
     
    305305
    306306    suite.addTestCase({
    307         name: "WI.Color.rgb2hsv",
    308         description: "Test conversion from RGB to HSV.",
    309         test(resolve, reject) {
    310             testColorConversion(WI.Color.rgb2hsv, [0, 0, 0], [0, 0, 0]);
    311             testColorConversion(WI.Color.rgb2hsv, [255, 255, 255], [0, 0, 1]);
    312             testColorConversion(WI.Color.rgb2hsv, [255, 0, 0], [0, 1, 1]);
    313             testColorConversion(WI.Color.rgb2hsv, [0, 255, 0], [120, 1, 1]);
    314             testColorConversion(WI.Color.rgb2hsv, [0, 0, 255], [240, 1, 1]);
     307        name: "WI.Color.rgb2hsl",
     308        description: "Test conversion from RGB to HSL.",
     309        test() {
     310            testColorConversion(WI.Color.rgb2hsl, [0, 0, 0], [0, 0, 0]);
     311            testColorConversion(WI.Color.rgb2hsl, [255, 255, 255], [0, 0, 100]);
     312            testColorConversion(WI.Color.rgb2hsl, [255, 0, 0], [0, 100, 50]);
     313            testColorConversion(WI.Color.rgb2hsl, [0, 255, 0], [120, 100, 50]);
     314            testColorConversion(WI.Color.rgb2hsl, [0, 0, 255], [240, 100, 50]);
    315315
    316316            // Out-of-bounds and floating point inputs.
    317             testColorConversion(WI.Color.rgb2hsv, [-1, -1, -1], [0, 0, 0]);
    318             testColorConversion(WI.Color.rgb2hsv, [256, 256, 256], [0, 0, 1]);
    319             testColorConversion(WI.Color.rgb2hsv, [254.9, 0, 0], [0, 1, 1]);
    320 
    321             resolve();
     317            testColorConversion(WI.Color.rgb2hsl, [-1, -1, -1], [0, 0, 0]);
     318            testColorConversion(WI.Color.rgb2hsl, [256, 256, 256], [0, 0, 100]);
     319            testColorConversion(WI.Color.rgb2hsl, [254.9, 0, 0], [0, 100, 50]);
     320
     321            return true;
     322        }
     323    });
     324
     325    suite.addTestCase({
     326        name: "WI.Color.hsl2rgb",
     327        description: "Test conversion from HSL to RGB.",
     328        test() {
     329            testColorConversion(WI.Color.hsl2rgb, [0, 0, 0], [0, 0, 0]);
     330            testColorConversion(WI.Color.hsl2rgb, [0, 0, 100], [255, 255, 255]);
     331            testColorConversion(WI.Color.hsl2rgb, [0, 100, 50], [255, 0, 0]);
     332            testColorConversion(WI.Color.hsl2rgb, [120, 100, 50], [0, 255, 0]);
     333            testColorConversion(WI.Color.hsl2rgb, [240, 100, 50], [0, 0, 255]);
     334
     335            // Out-of-bounds.
     336            testColorConversion(WI.Color.hsl2rgb, [-1, -1, -1], [0, 0, 0]);
     337            testColorConversion(WI.Color.hsl2rgb, [361, 101, 50], [255, 0, 0]);
     338            testColorConversion(WI.Color.hsl2rgb, [361, 101, 101], [255, 255, 255]);
     339
     340            return true;
    322341        }
    323342    });
     
    326345        name: "WI.Color.cmyk2rgb",
    327346        description: "Test conversion from CMYK to RGB.",
    328         test(resolve, reject) {
     347        test() {
    329348            testColorConversion(WI.Color.cmyk2rgb, [0, 0, 0, 1], [0, 0, 0]);
    330349            testColorConversion(WI.Color.cmyk2rgb, [1, 0, 0, 0], [0, 255, 255]);
     
    337356            testColorConversion(WI.Color.cmyk2rgb, [-1, 0, 0, 0], [255, 255, 255]);
    338357
    339             resolve();
     358            return true;
    340359        }
    341360    });
     
    344363        name: "WI.Color.normalized2rgb",
    345364        description: "Test conversion from normalized RGB to RGB.",
    346         test(resolve, reject) {
     365        test() {
    347366            testColorConversion(WI.Color.normalized2rgb, [0, 0, 0], [0, 0, 0]);
    348367            testColorConversion(WI.Color.normalized2rgb, [1, 1, 1], [255, 255, 255]);
     
    353372            testColorConversion(WI.Color.normalized2rgb, [-1, 0, 0], [0, 0, 0]);
    354373
    355             resolve();
     374            return true;
    356375        }
    357376    });
  • trunk/Source/WebInspectorUI/ChangeLog

    r239588 r239597  
     12019-01-03  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: conic-gradient color picker doesn't accurately show color when saturation value is not 100%
     4        https://bugs.webkit.org/show_bug.cgi?id=192729
     5        <rdar://problem/46746815>
     6
     7        Reviewed by Joseph Pecoraro.
     8
     9        Rework `WI.ColorWheel` to use similar canvas drawing logic as `WI.LegacyColorWheel` so that
     10        it's able to adjust the saturation value as the pixels gets closer to the center.
     11
     12        * UserInterface/Models/Color.js:
     13        (WI.Color.rgb2hsl): Added.
     14        (WI.Color.hsl2rgb): Added.
     15        (WI.Color.cmyk2rgb):
     16        (WI.Color.prototype.isKeyword):
     17        (WI.Color.prototype._toRGBString):
     18        (WI.Color.prototype._toRGBAString):
     19        (WI.Color.prototype._toHSLString):
     20        (WI.Color.prototype._toHSLAString):
     21        (WI.Color.prototype._rgbaToHSLA):
     22        (WI.Color.prototype._hslaToRGBA):
     23        (WI.Color.rgb2hsv): Deleted.
     24        (WI.Color.hsv2rgb): Deleted.
     25        (WI.Color.prototype._rgbToHSL): Deleted.
     26        (WI.Color.prototype._hslToRGB): Deleted.
     27        Adjust the conversion functions of `WI.Color` to be more accurate.
     28
     29        * UserInterface/Views/ColorWheel.js:
     30        (WI.ColorWheel):
     31        (WI.ColorWheel.prototype.set dimension):
     32        (WI.ColorWheel.prototype.set brightness):
     33        (WI.ColorWheel.prototype.get tintedColor):
     34        (WI.ColorWheel.prototype.set tintedColor):
     35        (WI.ColorWheel.prototype._updateColorForMouseEvent):
     36        (WI.ColorWheel.prototype._updateCanvas): Added.
     37        (WI.ColorWheel.prototype._updateGradient): Deleted.
     38        * UserInterface/Views/ColorWheel.css:
     39        (.color-wheel > canvas): Added.
     40        (.color-wheel > .gradient): Deleted.
     41
     42        * UserInterface/Views/ColorPicker.js:
     43        (WI.ColorPicker):
     44        (WI.ColorPicker.prototype.set color):
     45        (WI.ColorPicker.prototype.sliderValueDidChange):
     46        (WI.ColorPicker.prototype._updateSliders):
     47        (WI.ColorPicker.prototype._showColorComponentInputs):
     48        (WI.ColorPicker.supportsConicGradient): Deleted.
     49
     50        * UserInterface/Main.html:
     51
     52        * UserInterface/Views/LegacyColorWheel.js: Removed.
     53
    1542019-01-02  Nikita Vasilyev  <nvasilyev@apple.com>
    255
  • trunk/Source/WebInspectorUI/UserInterface/Main.html

    r239530 r239597  
    815815    <script src="Views/XHRBreakpointTreeElement.js"></script>
    816816
    817     <script src="Views/LegacyColorWheel.js"></script>
    818 
    819817    <script src="Controllers/Annotator.js"></script>
    820818    <script src="Controllers/CodeMirrorEditingController.js"></script>
  • trunk/Source/WebInspectorUI/UserInterface/Models/Color.js

    r223978 r239597  
    156156    }
    157157
    158     static rgb2hsv(r, g, b)
     158    static rgb2hsl(r, g, b)
    159159    {
    160160        r = WI.Color._eightBitChannel(r) / 255;
     
    162162        b = WI.Color._eightBitChannel(b) / 255;
    163163
    164         let min = Math.min(Math.min(r, g), b);
    165         let max = Math.max(Math.max(r, g), b);
     164        let min = Math.min(r, g, b);
     165        let max = Math.max(r, g, b);
    166166        let delta = max - min;
    167167
    168         let h;
    169         let s;
    170         let v = max;
     168        let h = 0;
     169        let s = 0;
     170        let l = (max + min) / 2;
    171171
    172172        if (delta === 0)
     
    183183
    184184        // Saturation
    185         if (max === 0)
     185        if (delta === 0)
    186186            s = 0;
    187187        else
    188             s = 1 - (min / max);
    189 
    190         return [h, s, v];
    191     }
    192 
    193     static hsv2rgb(h, s, v)
    194     {
    195         if (s === 0)
    196             return [v, v, v];
    197 
    198         h /= 60;
    199         let i = Math.floor(h);
    200         let data = [
    201             v * (1 - s),
    202             v * (1 - s * (h - i)),
    203             v * (1 - s * (1 - (h - i)))
     188            s = delta / (1 - Math.abs((2 * l) - 1));
     189
     190        return [
     191            h,
     192            s * 100,
     193            l * 100,
    204194        ];
    205         let rgb;
    206 
    207         switch (i) {
    208         case 0:
    209             rgb = [v, data[2], data[0]];
    210             break;
    211         case 1:
    212             rgb = [data[1], v, data[0]];
    213             break;
    214         case 2:
    215             rgb = [data[0], v, data[2]];
    216             break;
    217         case 3:
    218             rgb = [data[0], data[1], v];
    219             break;
    220         case 4:
    221             rgb = [data[2], data[0], v];
    222             break;
    223         default:
    224             rgb = [v, data[0], data[1]];
    225             break;
    226         }
    227 
    228         return rgb;
     195    }
     196
     197    static hsl2rgb(h, s, l)
     198    {
     199        h = Number.constrain(h, 0, 360) % 360;
     200        s = Number.constrain(s, 0, 100) / 100;
     201        l = Number.constrain(l, 0, 100) / 100;
     202
     203        let c = (1 - Math.abs((2 * l) - 1)) * s;
     204        let x = c * (1 - Math.abs(((h / 60) % 2) - 1));
     205        let m = l - (c / 2);
     206
     207        let r = 0;
     208        let g = 0;
     209        let b = 0;
     210
     211        if (h < 60) {
     212            r = c;
     213            g = x;
     214        } else if (h < 120) {
     215            r = x;
     216            g = c;
     217        } else if (h < 180) {
     218            g = c;
     219            b = x;
     220        } else if (h < 240) {
     221            g = x;
     222            b = c;
     223        } else if (h < 300) {
     224            r = x;
     225            b = c;
     226        } else if (h < 360) {
     227            r = c;
     228            b = x;
     229        }
     230
     231        return [
     232            (r + m) * 255,
     233            (g + m) * 255,
     234            (b + m) * 255,
     235        ];
    229236    }
    230237
     
    235242        y = Number.constrain(y, 0, 1);
    236243        k = Number.constrain(k, 0, 1);
    237 
    238         let r = 255 - ((Math.min(1, c * (1 - k) + k)) * 255);
    239         let g = 255 - ((Math.min(1, m * (1 - k) + k)) * 255);
    240         let b = 255 - ((Math.min(1, y * (1 - k) + k)) * 255);
    241         return [r, g, b];
     244        return [
     245            255 * (1 - c) * (1 - k),
     246            255 * (1 - m) * (1 - k),
     247            255 * (1 - y) * (1 - k),
     248        ];
    242249    }
    243250
     
    392399            return Array.shallowEqual(this._rgba, [0, 0, 0, 0]) || Array.shallowEqual(this._hsla, [0, 0, 0, 0]);
    393400
    394         let rgb = (this._rgba && this._rgba.slice(0, 3)) || this._hslToRGB(this._hsla);
     401        let rgb = (this._rgba && this._rgba.slice(0, 3)) || WI.Color.hsl2rgb(...this._hsla);
    395402        return Object.keys(WI.Color.Keywords).some(key => Array.shallowEqual(WI.Color.Keywords[key], rgb));
    396403    }
     
    512519            return this._toRGBAString();
    513520
    514         let r = WI.Color._eightBitChannel(this.rgb[0]);
    515         let g = WI.Color._eightBitChannel(this.rgb[1]);
    516         let b = WI.Color._eightBitChannel(this.rgb[2]);
     521        let r = WI.Color._eightBitChannel(Math.round(this.rgba[0]));
     522        let g = WI.Color._eightBitChannel(Math.round(this.rgba[1]));
     523        let b = WI.Color._eightBitChannel(Math.round(this.rgba[2]));
    517524        return `rgb(${r}, ${g}, ${b})`;
    518525    }
     
    520527    _toRGBAString()
    521528    {
    522         let r = WI.Color._eightBitChannel(this.rgb[0]);
    523         let g = WI.Color._eightBitChannel(this.rgb[1]);
    524         let b = WI.Color._eightBitChannel(this.rgb[2]);
     529        let r = WI.Color._eightBitChannel(Math.round(this.rgba[0]));
     530        let g = WI.Color._eightBitChannel(Math.round(this.rgba[1]));
     531        let b = WI.Color._eightBitChannel(Math.round(this.rgba[2]));
    525532        return `rgba(${r}, ${g}, ${b}, ${this.alpha})`;
    526533    }
     
    531538            return this._toHSLAString();
    532539
    533         let hsla = this.hsla;
    534         hsla = hsla.map((value) => value.maxDecimals(2));
    535         return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)";
     540        let h = this.hsla[0].maxDecimals(2);
     541        let s = this.hsla[1].maxDecimals(2);
     542        let l = this.hsla[2].maxDecimals(2);
     543        return `hsl(${h}, ${s}%, ${l}%)`;
    536544    }
    537545
    538546    _toHSLAString()
    539547    {
    540         let hsla = this.hsla;
    541         hsla = hsla.map((value) => value.maxDecimals(2));
    542         return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")";
     548        let h = this.hsla[0].maxDecimals(2);
     549        let s = this.hsla[1].maxDecimals(2);
     550        let l = this.hsla[2].maxDecimals(2);
     551        return `hsla(${h}, ${s}%, ${l}%, ${this.alpha})`;
    543552    }
    544553
     
    551560    }
    552561
    553     _rgbToHSL(rgb)
    554     {
    555         let r = WI.Color._eightBitChannel(rgb[0]) / 255;
    556         let g = WI.Color._eightBitChannel(rgb[1]) / 255;
    557         let b = WI.Color._eightBitChannel(rgb[2]) / 255;
    558         let max = Math.max(r, g, b);
    559         let min = Math.min(r, g, b);
    560         let diff = max - min;
    561         let add = max + min;
    562 
    563         let h;
    564         let s;
    565         let l = 0.5 * add;
    566 
    567         if (min === max)
    568             h = 0;
    569         else if (r === max)
    570             h = ((60 * (g - b) / diff) + 360) % 360;
    571         else if (g === max)
    572             h = (60 * (b - r) / diff) + 120;
    573         else
    574             h = (60 * (r - g) / diff) + 240;
    575 
    576         if (l === 0)
    577             s = 0;
    578         else if (l === 1)
    579             s = 1;
    580         else if (l <= 0.5)
    581             s = diff / add;
    582         else
    583             s = diff / (2 - add);
    584 
    585         return [
    586             Math.round(h),
    587             Math.round(s * 100),
    588             Math.round(l * 100)
    589         ];
    590     }
    591 
    592     _hslToRGB(hsl)
    593     {
    594         let h = parseFloat(hsl[0]) / 360;
    595         let s = parseFloat(hsl[1]) / 100;
    596         let l = parseFloat(hsl[2]) / 100;
    597 
    598         h *= 6;
    599         let sArray = [
    600             l += s *= l < .5 ? l : 1 - l,
    601             l - h % 1 * s * 2,
    602             l -= s *= 2,
    603             l,
    604             l + h % 1 * s,
    605             l + s
    606         ];
    607         return [
    608             Math.round(sArray[ ~~h      % 6 ] * 255),
    609             Math.round(sArray[ (h | 16) % 6 ] * 255),
    610             Math.round(sArray[ (h | 8)  % 6 ] * 255)
    611         ];
    612     }
    613 
    614562    _rgbaToHSLA(rgba)
    615563    {
    616         let hsl = this._rgbToHSL(rgba);
    617         hsl.push(rgba[3]);
    618         return hsl;
     564        let hsla = WI.Color.rgb2hsl(...rgba);
     565        hsla.push(rgba[3]);
     566        return hsla;
    619567    }
    620568
    621569    _hslaToRGBA(hsla)
    622570    {
    623         let rgba = this._hslToRGB(hsla);
     571        let rgba = WI.Color.hsl2rgb(...hsla);
    624572        rgba.push(hsla[3]);
    625573        return rgba;
  • trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js

    r237605 r239597  
    3030        super();
    3131
    32         this._colorWheel = WI.ColorPicker.supportsConicGradient() ? new WI.ColorWheel : new WI.LegacyColorWheel;
    33         this._colorWheel.delegate = this;
    34         this._colorWheel.dimension = 200;
     32        this._colorWheel = new WI.ColorWheel(this, 200);
    3533
    3634        this._brightnessSlider = new WI.Slider;
     
    9189    }
    9290
    93     // Static
    94 
    95     static supportsConicGradient()
    96     {
    97         if (WI.ColorPicker._supportsConicGradient === undefined) {
    98             const property = "background-image";
    99             const conicGradient = "conic-gradient(black, white)";
    100 
    101             let element = document.body.appendChild(document.createElement("div"));
    102             element.style.setProperty(property, conicGradient);
    103 
    104             WI.ColorPicker._supportsConicGradient = window.getComputedStyle(element).getPropertyValue(property).includes(conicGradient);
    105 
    106             element.remove();
    107         }
    108         return WI.ColorPicker._supportsConicGradient;
    109     }
    110 
    11191    // Public
    11292
     
    157137
    158138        this._colorWheel.tintedColor = this._color;
    159         this._brightnessSlider.value = this._colorWheel.brightness;
     139        this._brightnessSlider.value = this._colorWheel.brightness / 100;
    160140
    161141        this._opacitySlider.value = this._color.alpha;
     
    188168            this.opacity = value;
    189169        else if (slider === this._brightnessSlider)
    190             this.brightness = value;
     170            this.brightness = value * 100;
    191171    }
    192172
     
    230210        var transparent = new WI.Color(WI.Color.Format.RGBA, rgb.concat(0)).toString();
    231211
    232         let brightnessGradient = "";
    233         if (WI.ColorPicker.supportsConicGradient())
    234             brightnessGradient = `linear-gradient(90deg, black, ${rawColor}, white)`;
    235         else
    236             brightnessGradient = `linear-gradient(90deg, black, ${rawColor})`;
    237         this._brightnessSlider.element.style.setProperty("background-image", brightnessGradient);
     212        this._brightnessSlider.element.style.setProperty("background-image", `linear-gradient(90deg, black, ${rawColor}, white)`);
    238213
    239214        this._opacitySlider.element.style.setProperty("background-image", "linear-gradient(90deg, " + transparent + ", " + opaque + "), " + this._opacityPattern);
     
    278253        case WI.Color.Format.Keyword:
    279254            var [r, g, b] = this._color.rgb;
    280             updateColorInput.call(this, "R", r);
    281             updateColorInput.call(this, "G", g);
    282             updateColorInput.call(this, "B", b);
     255            updateColorInput.call(this, "R", Math.round(r));
     256            updateColorInput.call(this, "G", Math.round(g));
     257            updateColorInput.call(this, "B", Math.round(b));
    283258            break;
    284259
     
    286261        case WI.Color.Format.HSLA:
    287262            var [h, s, l] = this._color.hsl;
    288             updateColorInput.call(this, "H", h);
    289             updateColorInput.call(this, "S", s);
    290             updateColorInput.call(this, "L", l);
     263            updateColorInput.call(this, "H", h.maxDecimals(2));
     264            updateColorInput.call(this, "S", s.maxDecimals(2));
     265            updateColorInput.call(this, "L", l.maxDecimals(2));
    291266            break;
    292267
  • trunk/Source/WebInspectorUI/UserInterface/Views/ColorWheel.css

    r237605 r239597  
    2828}
    2929
    30 .color-wheel > .gradient {
     30.color-wheel > canvas {
    3131    width: 100%;
    3232    height: 100%;
    33     border-radius: 50%;
    3433}
    3534
  • trunk/Source/WebInspectorUI/UserInterface/Views/ColorWheel.js

    r237605 r239597  
    2626WI.ColorWheel = class ColorWheel extends WI.Object
    2727{
    28     constructor()
    29     {
     28    constructor(delegate, dimension)
     29    {
     30        console.assert(!isNaN(dimension));
     31
    3032        super();
    3133
    32         this._brightness = 0.5;
     34        this._delegate = delegate;
     35
     36        this._brightness = 50;
    3337
    3438        this._element = document.createElement("div");
    3539        this._element.className = "color-wheel";
    3640
    37         this._gradientElement = this._element.appendChild(document.createElement("div"));
    38         this._gradientElement.classList.add("gradient");
    39         this._gradientElement.addEventListener("mousedown", this);
     41        this._canvasElement = this._element.appendChild(document.createElement("canvas"));
     42        this._canvasElement.addEventListener("mousedown", this);
     43
     44        this._canvasContext = this._canvasElement.getContext("2d");
    4045
    4146        this._crosshairElement = this._element.appendChild(document.createElement("div"));
    4247        this._crosshairElement.className = "crosshair";
     48
     49        this.dimension = dimension;
    4350    }
    4451
     
    4956    set dimension(dimension)
    5057    {
     58        if (dimension === this._dimension)
     59            return;
     60
    5161        this._dimension = dimension;
    5262
    5363        this._element.style.width = this.element.style.height = `${this._dimension}px`;
     64        this._canvasElement.width = this._canvasElement.height = this._dimension * window.devicePixelRatio;
    5465
    5566        let center = this._dimension / 2;
    5667        this._setCrosshairPosition(new WI.Point(center, center));
    5768
    58         this._updateGradient();
     69        this._updateCanvas();
    5970    }
    6071
     
    6677    set brightness(brightness)
    6778    {
     79        if (brightness === this._brightness)
     80            return;
     81
    6882        this._brightness = brightness;
    69         this._updateGradient();
     83
     84        this._updateCanvas();
    7085    }
    7186
     
    7388    {
    7489        if (this._crosshairPosition)
    75             return new WI.Color(WI.Color.Format.HSL, [this._hue, this._saturation, this._brightness * 100]);
     90            return new WI.Color(WI.Color.Format.HSL, [this._hue, this._saturation, this._brightness]);
    7691        return new WI.Color(WI.Color.Format.HSLA, [0, 0, 0, 0]);
    7792    }
     
    88103        this._setCrosshairPosition(new WI.Point(x, y));
    89104
    90         this.brightness = hsl[2] / 100;
     105        this.brightness = hsl[2];
    91106    }
    92107
     
    155170    _updateColorForMouseEvent(event)
    156171    {
    157         var point = window.webkitConvertPointFromPageToNode(this._gradientElement, new WebKitPoint(event.pageX, event.pageY));
     172        var point = window.webkitConvertPointFromPageToNode(this._canvasElement, new WebKitPoint(event.pageX, event.pageY));
    158173
    159174        this._setCrosshairPosition(point);
    160175
    161         if (this.delegate && typeof this.delegate.colorWheelColorDidChange === "function")
    162             this.delegate.colorWheelColorDidChange(this);
     176        if (this._delegate && typeof this._delegate.colorWheelColorDidChange === "function")
     177            this._delegate.colorWheelColorDidChange(this);
    163178    }
    164179
     
    178193    }
    179194
    180     _updateGradient()
    181     {
    182         let stops = [];
    183         for (let i = 0; i <= 360; i += 60)
    184             stops.push(`hsl(${i}, 100%, ${this._brightness * 100}%)`);
    185 
    186         this._gradientElement.style.setProperty("background-image", `conic-gradient(${stops.join(",")})`);
     195    _updateCanvas()
     196    {
     197        let dimension = this._dimension * window.devicePixelRatio;
     198        let center = dimension / 2;
     199
     200        let imageData = this._canvasContext.createImageData(dimension, dimension);
     201        for (let y = 0; y < dimension; ++y) {
     202            for (let x = 0; x < dimension; ++x) {
     203                let xDis = (x - center) / center;
     204                let yDis = (y - center) / center;
     205                let saturation = Math.sqrt(Math.pow(xDis, 2) + Math.pow(yDis, 2)) * 100;
     206                if (saturation > 100)
     207                    continue;
     208
     209                let hue = Math.atan2(x - center, center - y) * 180 / Math.PI;
     210                if (hue < 0)
     211                    hue += 360;
     212
     213                let rgb = WI.Color.hsl2rgb(hue, saturation, this._brightness);
     214
     215                let index = ((y * dimension) + x) * 4;
     216                imageData.data[index] = rgb[0];
     217                imageData.data[index + 1] = rgb[1];
     218                imageData.data[index + 2] = rgb[2];
     219                imageData.data[index + 3] = 255;
     220            }
     221        }
     222
     223        this._canvasContext.putImageData(imageData, 0, 0);
    187224    }
    188225};
Note: See TracChangeset for help on using the changeset viewer.