Changeset 252168 in webkit


Ignore:
Timestamp:
Nov 6, 2019 6:53:40 PM (4 years ago)
Author:
Nikita Vasilyev
Message:

Web Inspector: Display color picker for p3 colors
https://bugs.webkit.org/show_bug.cgi?id=203436
<rdar://problem/56635062>

Reviewed by Brian Burg.

Source/WebInspectorUI:

For p3 colors, display ColorSquare with display-p3 gamut.
Continue showing ColorSquare with sRGB gamut by default.

  • UserInterface/Base/Setting.js:
  • UserInterface/Models/Color.js:

(WI.Color):
(WI.Color.rgb2hsv):
(WI.Color.hsv2rgb.fraction):
(WI.Color.hsv2rgb):
(WI.Color.prototype.get hsla):
(WI.Color.prototype.isKeyword):

  • UserInterface/Views/ColorPicker.css:

(.color-picker > .hue):
(@media (color-gamut: p3)):
(.color-picker.gamut-p3 > .hue):

  • UserInterface/Views/ColorPicker.js:

(WI.ColorPicker.prototype._updateColor):
(WI.ColorPicker.prototype._updateOpacitySlider):
(WI.ColorPicker.prototype._handleFormatChange):
Introduce gamut parameter. Previously, the only available gamut was sRGB.

  • UserInterface/Views/ColorSquare.css:

(.color-square > .crosshair):
Update the crosshair style to look better for both light and dark backgrounds.

  • UserInterface/Views/ColorSquare.js:

(WI.ColorSquare):
(WI.ColorSquare.prototype.get tintedColor):
(WI.ColorSquare.prototype.set tintedColor):
(WI.ColorSquare.prototype._setCrosshairPosition):
(WI.ColorSquare.prototype._updateBaseColor):
(WI.ColorSquare.prototype._updateCrosshairBackground):

  • UserInterface/Views/InlineSwatch.js:

Make p3 color picker a preview (e.g. STP-only) feature.

LayoutTests:

Add tests for WI.Color.rgb2hsv and WI.Color.hsv2rgb.

  • inspector/model/color-expected.txt:
  • inspector/model/color.html:
Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r252164 r252168  
     12019-11-06  Nikita Vasilyev  <nvasilyev@apple.com>
     2
     3        Web Inspector: Display color picker for p3 colors
     4        https://bugs.webkit.org/show_bug.cgi?id=203436
     5        <rdar://problem/56635062>
     6
     7        Reviewed by Brian Burg.
     8
     9        Add tests for WI.Color.rgb2hsv and WI.Color.hsv2rgb.
     10
     11        * inspector/model/color-expected.txt:
     12        * inspector/model/color.html:
     13
    1142019-11-06  Justin Fan  <justin_fan@apple.com>
    215
  • trunk/LayoutTests/inspector/model/color-expected.txt

    r251933 r252168  
    484484PASS: Should convert [361,101,101] to [360,100,50].
    485485
     486-- Running test case: WI.Color.rgb2hsv
     487PASS: Should convert [0,0,0] to [0,0,0].
     488PASS: Should convert [1,1,1] to [0,0,100].
     489PASS: Should convert [1,0,0] to [0,100,100].
     490PASS: Should convert [0,1,0] to [120,100,100].
     491PASS: Should convert [0,0,1] to [240,100,100].
     492PASS: Should convert [-1,-1,-1] to [0,0,0].
     493PASS: Should convert [1.1,1.1,1.1] to [0,0,100].
     494
     495-- Running test case: WI.Color.hsv2rgb
     496PASS: Should convert [42,100,0] to [0,0,0].
     497PASS: Should convert [42,50,100] to [1,0.8500000000000001,0.5].
     498PASS: Should convert [42,100,50] to [0.5,0.3500000000000001,0].
     499PASS: Should convert [42,50,50] to [0.5,0.42500000000000004,0.25].
     500PASS: Should convert [42,100,100] to [1,0.7000000000000002,0].
     501PASS: Should convert [-1,-1,-1] to [0,0,0].
     502PASS: Should convert [361,101,50] to [0.5,0,0].
     503PASS: Should convert [361,101,101] to [1,0,0].
     504
    486505-- Running test case: WI.Color.cmyk2rgb
    487506PASS: Should convert [0,0,0,1] to [0,0,0].
  • trunk/LayoutTests/inspector/model/color.html

    r251933 r252168  
    543543
    544544    suite.addTestCase({
     545        name: "WI.Color.rgb2hsv",
     546        description: "Test conversion from RGB to HSV.",
     547        test() {
     548            testColorConversion(WI.Color.rgb2hsv, [0, 0, 0], [0, 0, 0]);
     549            testColorConversion(WI.Color.rgb2hsv, [1, 1, 1], [0, 0, 100]);
     550            testColorConversion(WI.Color.rgb2hsv, [1, 0, 0], [0, 100, 100]);
     551            testColorConversion(WI.Color.rgb2hsv, [0, 1, 0], [120, 100, 100]);
     552            testColorConversion(WI.Color.rgb2hsv, [0, 0, 1], [240, 100, 100]);
     553
     554            // Out-of-bounds.
     555            testColorConversion(WI.Color.rgb2hsv, [-1, -1, -1], [0, 0, 0]);
     556            testColorConversion(WI.Color.rgb2hsv, [1.1, 1.1, 1.1], [0, 0, 100]);
     557
     558            return true;
     559        }
     560    });
     561
     562    suite.addTestCase({
     563        name: "WI.Color.hsv2rgb",
     564        description: "Test conversion from HSV to RGB.",
     565        test() {
     566            testColorConversion(WI.Color.hsv2rgb, [42, 100, 0], [0, 0, 0]);
     567            testColorConversion(WI.Color.hsv2rgb, [42, 50, 100], [1, 0.8500000000000001, 0.5]);
     568            testColorConversion(WI.Color.hsv2rgb, [42, 100, 50], [0.5, 0.3500000000000001, 0]);
     569            testColorConversion(WI.Color.hsv2rgb, [42, 50, 50], [0.5, 0.42500000000000004, 0.25]);
     570            testColorConversion(WI.Color.hsv2rgb, [42, 100, 100], [1, 0.7000000000000002, 0]);
     571
     572            // Out-of-bounds.
     573            testColorConversion(WI.Color.hsv2rgb, [-1, -1, -1], [0, 0, 0]);
     574            testColorConversion(WI.Color.hsv2rgb, [361, 101, 50], [0.5, 0, 0]);
     575            testColorConversion(WI.Color.hsv2rgb, [361, 101, 101], [1, 0, 0]);
     576
     577            return true;
     578        }
     579    });
     580
     581    suite.addTestCase({
    545582        name: "WI.Color.cmyk2rgb",
    546583        description: "Test conversion from CMYK to RGB.",
  • trunk/Source/WebInspectorUI/ChangeLog

    r252063 r252168  
     12019-11-06  Nikita Vasilyev  <nvasilyev@apple.com>
     2
     3        Web Inspector: Display color picker for p3 colors
     4        https://bugs.webkit.org/show_bug.cgi?id=203436
     5        <rdar://problem/56635062>
     6
     7        Reviewed by Brian Burg.
     8
     9        For p3 colors, display ColorSquare with display-p3 gamut.
     10        Continue showing ColorSquare with sRGB gamut by default.
     11
     12        * UserInterface/Base/Setting.js:
     13        * UserInterface/Models/Color.js:
     14        (WI.Color):
     15        (WI.Color.rgb2hsv):
     16        (WI.Color.hsv2rgb.fraction):
     17        (WI.Color.hsv2rgb):
     18        (WI.Color.prototype.get hsla):
     19        (WI.Color.prototype.isKeyword):
     20
     21        * UserInterface/Views/ColorPicker.css:
     22        (.color-picker > .hue):
     23        (@media (color-gamut: p3)):
     24        (.color-picker.gamut-p3 > .hue):
     25
     26        * UserInterface/Views/ColorPicker.js:
     27        (WI.ColorPicker.prototype._updateColor):
     28        (WI.ColorPicker.prototype._updateOpacitySlider):
     29        (WI.ColorPicker.prototype._handleFormatChange):
     30        Introduce `gamut` parameter. Previously, the only available `gamut` was sRGB.
     31
     32        * UserInterface/Views/ColorSquare.css:
     33        (.color-square > .crosshair):
     34        Update the crosshair style to look better for both light and dark backgrounds.
     35
     36        * UserInterface/Views/ColorSquare.js:
     37        (WI.ColorSquare):
     38        (WI.ColorSquare.prototype.get tintedColor):
     39        (WI.ColorSquare.prototype.set tintedColor):
     40        (WI.ColorSquare.prototype._setCrosshairPosition):
     41        (WI.ColorSquare.prototype._updateBaseColor):
     42        (WI.ColorSquare.prototype._updateCrosshairBackground):
     43
     44        * UserInterface/Views/InlineSwatch.js:
     45        Make p3 color picker a preview (e.g. STP-only) feature.
     46
    1472019-11-05  Ross Kirsling  <ross.kirsling@sony.com>
    248
  • trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js

    r252063 r252168  
    212212};
    213213
    214 WI.previewFeatures = [];
     214WI.previewFeatures = [
     215    "p3-gamut-color-picker" // FIXME: <https://webkit.org/b/203931> Web Inspector: Enable p3 color picker by default
     216];
    215217
    216218WI.isTechnologyPreviewBuild = function()
  • trunk/Source/WebInspectorUI/UserInterface/Models/Color.js

    r251933 r252168  
    3333    {
    3434        this.format = format;
    35         this.gamut = gamut || "srgb";
     35
     36        console.assert(gamut === undefined || Object.values(WI.Color.Gamut).includes(gamut));
     37        this.gamut = gamut || WI.Color.Gamut.SRGB;
    3638
    3739        if (components.length === 3)
     
    179181
    180182            let gamut = components[0].toLowerCase();
    181             if (gamut !== "srgb" && gamut !== "display-p3")
     183            if (!Object.values(WI.Color.Gamut).includes(gamut))
    182184                return null;
    183185
     
    299301    }
    300302
     303    // https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
     304    static rgb2hsv(r, g, b)
     305    {
     306        r = Number.constrain(r, 0, 1);
     307        g = Number.constrain(g, 0, 1);
     308        b = Number.constrain(b, 0, 1);
     309
     310        let max = Math.max(r, g, b);
     311        let min = Math.min(r, g, b);
     312        let h = 0;
     313        let delta = max - min;
     314        let s = max === 0 ? 0 : delta / max;
     315        let v = max;
     316
     317        if (max === min)
     318            h = 0; // Grayscale.
     319        else {
     320            switch (max) {
     321            case r:
     322                h = ((g - b) / delta) + ((g < b) ? 6 : 0);
     323                break;
     324            case g:
     325                h = ((b - r) / delta) + 2;
     326                break;
     327            case b:
     328                h = ((r - g) / delta) + 4;
     329                break;
     330            }
     331            h /= 6;
     332        }
     333
     334        return [h * 360, s * 100, v * 100];
     335    }
     336
     337    // https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative
     338    static hsv2rgb(h, s, v)
     339    {
     340        h = Number.constrain(h, 0, 360);
     341        s = Number.constrain(s, 0, 100) / 100;
     342        v = Number.constrain(v, 0, 100) / 100;
     343
     344        function fraction(n) {
     345            let k = (n + (h / 60)) % 6;
     346            return v - (v * s * Math.max(Math.min(k, 4 - k, 1), 0));
     347        }
     348        return [fraction(5), fraction(3), fraction(1)];
     349    }
     350
    301351    static cmyk2rgb(c, m, y, k)
    302352    {
     
    400450    get hsla()
    401451    {
    402         if (!this._hsla)
    403             this._hsla = this._rgbaToHSLA(this.rgba);
     452        if (!this._hsla) {
     453            let rgba = this.rgba;
     454            if (this.format === WI.Color.Format.ColorFunction) {
     455                rgba = [
     456                    rgba[0] * 255,
     457                    rgba[1] * 255,
     458                    rgba[2] * 255,
     459                    rgba[3],
     460                ];
     461            }
     462            this._hsla = this._rgbaToHSLA(rgba);
     463        }
     464
    404465        return this._hsla;
    405466    }
     
    462523            return true;
    463524
    464         if (this.gamut !== "srgb")
     525        if (this.gamut !== WI.Color.Gamut.SRGB)
    465526            return false;
    466527
     
    664725    HSLA: "color-format-hsla",
    665726    ColorFunction: "color-format-color-function",
     727};
     728
     729WI.Color.Gamut = {
     730    SRGB: "srgb",
     731    DisplayP3: "display-p3",
    666732};
    667733
  • trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.css

    r251487 r252168  
    5656
    5757.color-picker > .hue {
    58     background-image: linear-gradient(to right, red 0%, yellow 16.6%, lime 33.2%, aqua 50%, blue 66.6%, fuchsia 83.2%, red 100%);
     58    background-image: linear-gradient(to right,
     59        red 0%,
     60        yellow 16.6%,
     61        lime 33.2%,
     62        cyan 50%,
     63        blue 66.6%,
     64        fuchsia 83.2%,
     65        red 100%
     66    );
     67}
     68
     69@media (color-gamut: p3) {
     70    .color-picker.gamut-p3 > .hue {
     71        background-image: linear-gradient(to right,
     72            color(display-p3 1 0 0) 0%,
     73            color(display-p3 1 1 0) 16.6%,
     74            color(display-p3 0 1 0) 33.2%,
     75            color(display-p3 0 1 1) 50%,
     76            color(display-p3 0 0 1) 66.6%,
     77            color(display-p3 1 0 1) 83.2%,
     78            color(display-p3 1 0 0) 100%
     79        );
     80    }
    5981}
    6082
  • trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js

    r251744 r252168  
    6161        };
    6262
     63        // FIXME: <https://webkit.org/b/203928> Web Inspector: Show RGBA input fields for p3 color picker
    6364        this._colorInputs = new Map([
    6465            ["R", createColorInput("R", {max: 255})],
     
    168169
    169170        let format = this._color.format;
     171        let gamut = this._color.gamut;
    170172        let components = null;
    171173        if (format === WI.Color.Format.HSL || format === WI.Color.Format.HSLA) {
     
    181183        let formatChanged = this._color.format === format;
    182184
    183         this._color = new WI.Color(format, components);
     185        this._color = new WI.Color(format, components, gamut);
    184186
    185187        this._showColorComponentInputs();
     
    194196    {
    195197        let rgb = this._colorSquare.tintedColor.rgb;
    196         let opaque = new WI.Color(WI.Color.Format.RGBA, rgb.concat(1)).toString();
    197         let transparent = new WI.Color(WI.Color.Format.RGBA, rgb.concat(0)).toString();
     198        let gamut = this._colorSquare.tintedColor.gamut;
     199        let format = gamut === WI.Color.Gamut.DisplayP3 ? WI.Color.Format.ColorFunction : WI.Color.Format.RGBA;
     200        let opaque = new WI.Color(format, rgb.concat(1), gamut).toString();
     201        let transparent = new WI.Color(format, rgb.concat(0), gamut).toString();
    198202        this._opacitySlider.element.style.setProperty("background-image", "linear-gradient(90deg, " + transparent + ", " + opaque + "), " + this._opacityPattern);
    199203    }
     
    210214            && this._color.format !== WI.Color.Format.HSL
    211215            && this._color.format !== WI.Color.Format.HSLA);
     216
     217        this._element.classList.toggle("gamut-p3", this._color.gamut === WI.Color.Gamut.DisplayP3);
    212218
    213219        this.dispatchEventToListeners(WI.ColorPicker.Event.FormatChanged);
  • trunk/Source/WebInspectorUI/UserInterface/Views/ColorSquare.css

    r251487 r252168  
    4646.color-square > .crosshair {
    4747    position: absolute;
    48     top: calc(-1 * var(--crosshair-size) / 2);
    49     left: calc(-1 * var(--crosshair-size) / 2);
     48    top: calc(-1 * (var(--crosshair-size) + var(--border-width)) / 2);
     49    left: calc(-1 * (var(--crosshair-size) + var(--border-width)) / 2);
    5050    width: var(--crosshair-size);
    5151    height: var(--crosshair-size);
    52     background-color: white;
    53     border: 0.5px solid black;
     52    border: var(--border-width) solid white;
     53    box-shadow: 0 0 2px black;
    5454    border-radius: 3px;
    5555    pointer-events: none;
    5656
     57    --border-width: 1px;
    5758    --crosshair-size: 7px;
    5859}
  • trunk/Source/WebInspectorUI/UserInterface/Views/ColorSquare.js

    r251885 r252168  
    3333        this._x = 0;
    3434        this._y = 0;
     35        this._gamut = null;
    3536        this._crosshairPosition = null;
    3637
     
    8182    {
    8283        if (this._crosshairPosition) {
     84            if (this._gamut === WI.Color.Gamut.DisplayP3) {
     85                let rgb = WI.Color.hsv2rgb(this._hue, this._saturation, this._brightness);
     86                rgb = rgb.map(((x) => Math.roundTo(x, 0.001)));
     87                return new WI.Color(WI.Color.Format.ColorFunction, rgb, this._gamut);
     88            }
     89
    8390            let hsl = WI.Color.hsv2hsl(this._hue, this._saturation, this._brightness);
    8491            return new WI.Color(WI.Color.Format.HSL, hsl);
     
    9198    {
    9299        console.assert(tintedColor instanceof WI.Color);
    93         let hsl = tintedColor.hsl;
    94         let saturation = Number.constrain(hsl[1], 0, 100);
    95         let x = saturation / 100 * this._dimension;
    96 
    97         let lightness = hsl[2];
    98 
    99         // The color picker is HSB-based. (HSB is also known as HSV.)
    100         // Derive lightness by using HSB to HSL equation.
    101         let y = 2 * lightness / (200 - saturation);
    102         y = -1 * (y - 1) * this._dimension;
    103 
    104         this._setCrosshairPosition(new WI.Point(x, y));
    105     }
    106 
    107     get rawColor()
    108     {
    109         if (this._crosshairPosition)
    110             return new WI.Color(WI.Color.Format.HSL, [this._hue, this._saturation, 50]);
    111 
    112         return new WI.Color(WI.Color.Format.HSLA, WI.Color.Keywords.transparent);
     100
     101        this._gamut = tintedColor.gamut;
     102
     103        if (tintedColor.format === WI.Color.Format.ColorFunction) {
     104            // CSS color function only supports RGB. It doesn't support HSL.
     105            let hsv = WI.Color.rgb2hsv(...tintedColor.rgb);
     106            let x = hsv[1] / 100 * this._dimension;
     107            let y = (1 - (hsv[2] / 100)) * this._dimension;
     108            this._setCrosshairPosition(new WI.Point(x, y));
     109        } else {
     110            let hsl = tintedColor.hsl;
     111            let saturation = Number.constrain(hsl[1], 0, 100);
     112            let x = saturation / 100 * this._dimension;
     113
     114            let lightness = hsl[2];
     115
     116            // The color picker is HSV-based. (HSV is also known as HSB.)
     117            // Derive lightness by using HSV to HSL equation.
     118            let y = 2 * lightness / (200 - saturation);
     119            y = -1 * (y - 1) * this._dimension;
     120
     121            this._setCrosshairPosition(new WI.Point(x, y));
     122        }
     123
     124        this._updateBaseColor();
    113125    }
    114126
     
    183195        this._y = Number.constrain(Math.round(point.y), 0, this._dimension);
    184196        this._crosshairElement.style.setProperty("transform", `translate(${this._x}px, ${this._y}px)`);
     197
     198        this._updateCrosshairBackground();
    185199    }
    186200
    187201    _updateBaseColor()
    188202    {
    189         this._element.style.backgroundColor = `hsl(${this._hue}, 100%, 50%)`;
     203        if (this._gamut === WI.Color.Gamut.DisplayP3) {
     204            let [r, g, b] = WI.Color.hsl2rgb(this._hue, 100, 50);
     205            this._element.style.backgroundColor = `color(display-p3 ${r / 255} ${g / 255} ${b / 255})`;
     206        } else
     207            this._element.style.backgroundColor = `hsl(${this._hue}, 100%, 50%)`;
     208
     209        this._updateCrosshairBackground();
     210    }
     211
     212    _updateCrosshairBackground()
     213    {
     214        this._crosshairElement.style.backgroundColor = this.tintedColor.toString();
    190215    }
    191216};
  • trunk/Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js

    r248279 r252168  
    160160            if (this._type === WI.InlineSwatch.Type.Color) {
    161161                let nextFormat = value.nextFormat();
     162                // FIXME: <https://webkit.org/b/203534> Provide UI to convert between sRGB and p3 color spaces
    162163                console.assert(nextFormat);
    163164                if (nextFormat) {
     
    177178
    178179        if (this._valueEditor)
     180            return;
     181
     182        if (!WI.arePreviewFeaturesEnabled() && value.format === WI.Color.Format.ColorFunction)
    179183            return;
    180184
Note: See TracChangeset for help on using the changeset viewer.