Title: [237605] trunk/Source/WebInspectorUI
Revision
237605
Author
[email protected]
Date
2018-10-30 15:15:16 -0700 (Tue, 30 Oct 2018)

Log Message

Web Inspector: change WI.ColorWheel to use conic-gradient()
https://bugs.webkit.org/show_bug.cgi?id=189485

Reviewed by Brian Burg.

Use the ("new") HSL `WI.ColorPicker` if `conic-gradient` is supported. Otherwise, use the
("old") RGB `WI.LegacyColorPicker`.

* 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.get rawColor):
(WI.ColorWheel.prototype.get _hue): Added.
(WI.ColorWheel.prototype.get _saturation): Added.
(WI.ColorWheel.prototype._updateColorForMouseEvent):
(WI.ColorWheel.prototype._setCrosshairPosition):
(WI.ColorWheel.prototype._updateGradient): Added.
(WI.ColorWheel.prototype._pointInCircleForEvent.distance): Deleted.
(WI.ColorWheel.prototype._pointInCircleForEvent.angleFromCenterToPoint): Deleted.
(WI.ColorWheel.prototype._pointInCircleForEvent.pointOnCircumference): Deleted.
(WI.ColorWheel.prototype._pointInCircleForEvent): Deleted.
(WI.ColorWheel.prototype._tintedColorToPointAndBrightness): Deleted.
(WI.ColorWheel.prototype._drawRawCanvas): Deleted.
(WI.ColorWheel.prototype._colorAtPointWithBrightness): Deleted.
(WI.ColorWheel.prototype._drawTintedCanvas): Deleted.
(WI.ColorWheel.prototype._draw): Deleted.
* UserInterface/Views/ColorWheel.css:
(.color-wheel > .gradient): Added.
(.color-wheel > .crosshair): Added.

* UserInterface/Views/LegacyColorWheel.js: Copied from Source/WebInspectorUI/UserInterface/Views/ColorWheel.js.

* UserInterface/Views/ColorPicker.js:
(WI.ColorPicker):
(WI.ColorPicker.supportsConicGradient): Added.
(WI.ColorPicker.prototype._updateSliders):

* UserInterface/Models/Geometry.js:
(WI.Point.prototype.distance):

* UserInterface/Main.html:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (237604 => 237605)


--- trunk/Source/WebInspectorUI/ChangeLog	2018-10-30 22:10:56 UTC (rev 237604)
+++ trunk/Source/WebInspectorUI/ChangeLog	2018-10-30 22:15:16 UTC (rev 237605)
@@ -1,5 +1,52 @@
 2018-10-30  Devin Rousso  <[email protected]>
 
+        Web Inspector: change WI.ColorWheel to use conic-gradient()
+        https://bugs.webkit.org/show_bug.cgi?id=189485
+
+        Reviewed by Brian Burg.
+
+        Use the ("new") HSL `WI.ColorPicker` if `conic-gradient` is supported. Otherwise, use the
+        ("old") RGB `WI.LegacyColorPicker`.
+
+        * 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.get rawColor):
+        (WI.ColorWheel.prototype.get _hue): Added.
+        (WI.ColorWheel.prototype.get _saturation): Added.
+        (WI.ColorWheel.prototype._updateColorForMouseEvent):
+        (WI.ColorWheel.prototype._setCrosshairPosition):
+        (WI.ColorWheel.prototype._updateGradient): Added.
+        (WI.ColorWheel.prototype._pointInCircleForEvent.distance): Deleted.
+        (WI.ColorWheel.prototype._pointInCircleForEvent.angleFromCenterToPoint): Deleted.
+        (WI.ColorWheel.prototype._pointInCircleForEvent.pointOnCircumference): Deleted.
+        (WI.ColorWheel.prototype._pointInCircleForEvent): Deleted.
+        (WI.ColorWheel.prototype._tintedColorToPointAndBrightness): Deleted.
+        (WI.ColorWheel.prototype._drawRawCanvas): Deleted.
+        (WI.ColorWheel.prototype._colorAtPointWithBrightness): Deleted.
+        (WI.ColorWheel.prototype._drawTintedCanvas): Deleted.
+        (WI.ColorWheel.prototype._draw): Deleted.
+        * UserInterface/Views/ColorWheel.css:
+        (.color-wheel > .gradient): Added.
+        (.color-wheel > .crosshair): Added.
+
+        * UserInterface/Views/LegacyColorWheel.js: Copied from Source/WebInspectorUI/UserInterface/Views/ColorWheel.js.
+
+        * UserInterface/Views/ColorPicker.js:
+        (WI.ColorPicker):
+        (WI.ColorPicker.supportsConicGradient): Added.
+        (WI.ColorPicker.prototype._updateSliders):
+
+        * UserInterface/Models/Geometry.js:
+        (WI.Point.prototype.distance):
+
+        * UserInterface/Main.html:
+
+2018-10-30  Devin Rousso  <[email protected]>
+
         Web Inspector: make the layers sidebar in the Elements tab always visible
         https://bugs.webkit.org/show_bug.cgi?id=190158
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (237604 => 237605)


--- trunk/Source/WebInspectorUI/UserInterface/Main.html	2018-10-30 22:10:56 UTC (rev 237604)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html	2018-10-30 22:15:16 UTC (rev 237605)
@@ -780,6 +780,8 @@
     <script src=""
     <script src=""
 
+    <script src=""
+
     <script src=""
     <script src=""
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Geometry.js (237604 => 237605)


--- trunk/Source/WebInspectorUI/UserInterface/Models/Geometry.js	2018-10-30 22:10:56 UTC (rev 237604)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Geometry.js	2018-10-30 22:15:16 UTC (rev 237605)
@@ -63,9 +63,9 @@
 
     distance(anotherPoint)
     {
-        var dx = anotherPoint.x - this.x;
-        var dy = anotherPoint.y - this.y;
-        return Math.sqrt(dx * dx, dy * dy);
+        let dx = anotherPoint.x - this.x;
+        let dy = anotherPoint.y - this.y;
+        return Math.sqrt((dx * dx) + (dy * dy));
     }
 };
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js (237604 => 237605)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js	2018-10-30 22:10:56 UTC (rev 237604)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js	2018-10-30 22:15:16 UTC (rev 237605)
@@ -29,7 +29,7 @@
     {
         super();
 
-        this._colorWheel = new WI.ColorWheel;
+        this._colorWheel = WI.ColorPicker.supportsConicGradient() ? new WI.ColorWheel : new WI.LegacyColorWheel;
         this._colorWheel.delegate = this;
         this._colorWheel.dimension = 200;
 
@@ -90,6 +90,24 @@
         this._enableColorComponentInputs = true;
     }
 
+    // Static
+
+    static supportsConicGradient()
+    {
+        if (WI.ColorPicker._supportsConicGradient === undefined) {
+            const property = "background-image";
+            const conicGradient = "conic-gradient(black, white)";
+
+            let element = document.body.appendChild(document.createElement("div"));
+            element.style.setProperty(property, conicGradient);
+
+            WI.ColorPicker._supportsConicGradient = window.getComputedStyle(element).getPropertyValue(property).includes(conicGradient);
+
+            element.remove();
+        }
+        return WI.ColorPicker._supportsConicGradient;
+    }
+
     // Public
 
     get element()
@@ -211,8 +229,14 @@
         var opaque = new WI.Color(WI.Color.Format.RGBA, rgb.concat(1)).toString();
         var transparent = new WI.Color(WI.Color.Format.RGBA, rgb.concat(0)).toString();
 
-        this._opacitySlider.element.style.backgroundImage = "linear-gradient(90deg, " + transparent + ", " + opaque + "), " + this._opacityPattern;
-        this._brightnessSlider.element.style.backgroundImage = "linear-gradient(90deg, black, " + rawColor + ")";
+        let brightnessGradient = "";
+        if (WI.ColorPicker.supportsConicGradient())
+            brightnessGradient = `linear-gradient(90deg, black, ${rawColor}, white)`;
+        else
+            brightnessGradient = `linear-gradient(90deg, black, ${rawColor})`;
+        this._brightnessSlider.element.style.setProperty("background-image", brightnessGradient);
+
+        this._opacitySlider.element.style.setProperty("background-image", "linear-gradient(90deg, " + transparent + ", " + opaque + "), " + this._opacityPattern);
     }
 
     _handleFormatChange()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ColorWheel.css (237604 => 237605)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ColorWheel.css	2018-10-30 22:10:56 UTC (rev 237604)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ColorWheel.css	2018-10-30 22:15:16 UTC (rev 237605)
@@ -27,14 +27,22 @@
     position: relative;
 }
 
+.color-wheel > .gradient {
+    width: 100%;
+    height: 100%;
+    border-radius: 50%;
+}
+
 .color-wheel > .crosshair {
     position: absolute;
-    top: -4px;
-    left: -3px;
-    width: 5px;
-    height: 5px;
+    top: calc(-1 * var(--crosshair-size) / 2);
+    left: calc(-1 * var(--crosshair-size) / 2);
+    width: var(--crosshair-size);
+    height: var(--crosshair-size);
+    background-color: white;
     border: 1px solid black;
     border-radius: 3px;
     pointer-events: none;
-    background-color: white;
+
+    --crosshair-size: 5px;
 }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ColorWheel.js (237604 => 237605)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ColorWheel.js	2018-10-30 22:10:56 UTC (rev 237604)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ColorWheel.js	2018-10-30 22:15:16 UTC (rev 237605)
@@ -29,46 +29,33 @@
     {
         super();
 
-        this._rawCanvas = document.createElement("canvas");
-        this._tintedCanvas = document.createElement("canvas");
-        this._finalCanvas = document.createElement("canvas");
+        this._brightness = 0.5;
 
-        this._crosshair = document.createElement("div");
-        this._crosshair.className = "crosshair";
-
         this._element = document.createElement("div");
         this._element.className = "color-wheel";
 
-        this._element.appendChild(this._finalCanvas);
-        this._element.appendChild(this._crosshair);
+        this._gradientElement = this._element.appendChild(document.createElement("div"));
+        this._gradientElement.classList.add("gradient");
+        this._gradientElement.addEventListener("mousedown", this);
 
-        this._finalCanvas.addEventListener("mousedown", this);
+        this._crosshairElement = this._element.appendChild(document.createElement("div"));
+        this._crosshairElement.className = "crosshair";
     }
 
     // Public
 
+    get element() { return this._element; }
+
     set dimension(dimension)
     {
-        this._element.style.width = this.element.style.height = `${dimension}px`;
-
-        this._finalCanvas.width = this._tintedCanvas.width = this._rawCanvas.width = dimension * window.devicePixelRatio;
-        this._finalCanvas.height = this._tintedCanvas.height = this._rawCanvas.height = dimension * window.devicePixelRatio;
-
-        this._finalCanvas.style.width = this._finalCanvas.style.height = dimension + "px";
-
         this._dimension = dimension;
-        // We shrink the radius a bit for better anti-aliasing.
-        this._radius = dimension / 2 - 2;
 
-        this._setCrosshairPosition(new WI.Point(dimension / 2, dimension / 2));
+        this._element.style.width = this.element.style.height = `${this._dimension}px`;
 
-        this._drawRawCanvas();
-        this._draw();
-    }
+        let center = this._dimension / 2;
+        this._setCrosshairPosition(new WI.Point(center, center));
 
-    get element()
-    {
-        return this._element;
+        this._updateGradient();
     }
 
     get brightness()
@@ -79,30 +66,35 @@
     set brightness(brightness)
     {
         this._brightness = brightness;
-        this._draw();
+        this._updateGradient();
     }
 
     get tintedColor()
     {
         if (this._crosshairPosition)
-            return this._colorAtPointWithBrightness(this._crosshairPosition.x * window.devicePixelRatio, this._crosshairPosition.y * window.devicePixelRatio, this._brightness);
-
-        return new WI.Color(WI.Color.Format.RGBA, [0, 0, 0, 0]);
+            return new WI.Color(WI.Color.Format.HSL, [this._hue, this._saturation, this._brightness * 100]);
+        return new WI.Color(WI.Color.Format.HSLA, [0, 0, 0, 0]);
     }
 
     set tintedColor(tintedColor)
     {
-        var data = ""
-        this._setCrosshairPosition(data.point);
-        this.brightness = data.brightness;
+        let hsl = tintedColor.hsl;
+
+        let cosHue = Math.cos(hsl[0] * Math.PI / 180);
+        let sinHue = Math.sin(hsl[0] * Math.PI / 180);
+        let center = this._dimension / 2;
+        let x = center + (sinHue * hsl[1]);
+        let y = center - (cosHue * hsl[1]);
+        this._setCrosshairPosition(new WI.Point(x, y));
+
+        this.brightness = hsl[2] / 100;
     }
 
     get rawColor()
     {
         if (this._crosshairPosition)
-            return this._colorAtPointWithBrightness(this._crosshairPosition.x * window.devicePixelRatio, this._crosshairPosition.y * window.devicePixelRatio, 1);
-
-        return new WI.Color(WI.Color.Format.RGBA, [0, 0, 0, 0]);
+            return new WI.Color(WI.Color.Format.HSL, [this._hue, this._saturation, 50]);
+        return new WI.Color(WI.Color.Format.HSLA, [0, 0, 0, 0]);
     }
 
     // Protected
@@ -124,6 +116,23 @@
 
     // Private
 
+    get _hue()
+    {
+        let center = this._dimension / 2;
+        let hue = Math.atan2(this._crosshairPosition.x - center, center - this._crosshairPosition.y) * 180 / Math.PI;
+        if (hue < 0)
+            hue += 360;
+        return hue;
+    }
+
+    get _saturation()
+    {
+        let center = this._dimension / 2;
+        let xDis = (this._crosshairPosition.x - center) / center;
+        let yDis = (this._crosshairPosition.y - center) / center;
+        return Math.sqrt(Math.pow(xDis, 2) + Math.pow(yDis, 2)) * 100;
+    }
+
     _handleMousedown(event)
     {
         window.addEventListener("mousemove", this, true);
@@ -143,36 +152,9 @@
         window.removeEventListener("mouseup", this, true);
     }
 
-    _pointInCircleForEvent(event)
-    {
-        function distance(a, b)
-        {
-            return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
-        }
-
-        function angleFromCenterToPoint(center, point)
-        {
-            return Math.atan2(point.y - center.y, point.x - center.x);
-        }
-
-        function pointOnCircumference(c, r, a)
-        {
-            return new WI.Point(c.x + r * Math.cos(a), c.y + r * Math.sin(a));
-        }
-
-        var dimension = this._dimension;
-        var point = window.webkitConvertPointFromPageToNode(this._finalCanvas, new WebKitPoint(event.pageX, event.pageY));
-        var center = new WI.Point(dimension / 2, dimension / 2);
-        if (distance(point, center) > this._radius) {
-            var angle = angleFromCenterToPoint(center, point);
-            point = pointOnCircumference(center, this._radius, angle);
-        }
-        return point;
-    }
-
     _updateColorForMouseEvent(event)
     {
-        var point = this._pointInCircleForEvent(event);
+        var point = window.webkitConvertPointFromPageToNode(this._gradientElement, new WebKitPoint(event.pageX, event.pageY));
 
         this._setCrosshairPosition(point);
 
@@ -182,103 +164,25 @@
 
     _setCrosshairPosition(point)
     {
-        this._crosshairPosition = point;
-        this._crosshair.style.webkitTransform = "translate(" + Math.round(point.x) + "px, " + Math.round(point.y) + "px)";
-    }
+        let radius = this._dimension / 2;
+        let center = new WI.Point(radius, radius);
 
-    _tintedColorToPointAndBrightness(color)
-    {
-        var rgb = color.rgb;
-        var hsv = WI.Color.rgb2hsv(rgb[0], rgb[1], rgb[2]);
-        var cosHue = Math.cos(hsv[0] * Math.PI / 180);
-        var sinHue = Math.sin(hsv[0] * Math.PI / 180);
-        var center = this._dimension / 2;
-        var x = center + (center * cosHue * hsv[1]);
-        var y = center - (center * sinHue * hsv[1]);
-        return {
-            point: new WI.Point(x, y),
-            brightness: hsv[2]
-        };
-    }
-
-    _drawRawCanvas() {
-        var ctx = this._rawCanvas.getContext("2d");
-
-        var dimension = this._dimension * window.devicePixelRatio;
-
-        ctx.fillStyle = "white";
-        ctx.fillRect(0, 0, dimension, dimension);
-
-        var imageData = ctx.getImageData(0, 0, dimension, dimension);
-        var data = ""
-        for (var j = 0; j < dimension; ++j) {
-            for (var i = 0; i < dimension; ++i) {
-                var color = this._colorAtPointWithBrightness(i, j, 1);
-                if (!color)
-                    continue;
-                var pos = (j * dimension + i) * 4;
-                data[pos] = color.rgb[0];
-                data[pos + 1] = color.rgb[1];
-                data[pos + 2] = color.rgb[2];
-            }
+        // Prevents the crosshair from being dragged outside the wheel.
+        if (center.distance(point) > radius) {
+            let angle = Math.atan2(point.y - center.y, point.x - center.x);
+            point = new WI.Point(center.x + radius * Math.cos(angle), center.y + radius * Math.sin(angle));
         }
-        ctx.putImageData(imageData, 0, 0);
-    }
 
-    _colorAtPointWithBrightness(x, y, brightness)
-    {
-        var center = this._dimension / 2 * window.devicePixelRatio;
-        var xDis = x - center;
-        var yDis = y - center;
-        var distance = Math.sqrt(xDis * xDis + yDis * yDis);
-
-        if (distance - center > 0.001)
-            return new WI.Color(WI.Color.Format.RGBA, [0, 0, 0, 0]);
-
-        var h = Math.atan2(y - center, center - x) * 180 / Math.PI;
-        h = (h + 180) % 360;
-        var v = brightness;
-        var s = Math.max(0, distance) / center;
-
-        var rgb = WI.Color.hsv2rgb(h, s, v);
-        return new WI.Color(WI.Color.Format.RGBA, [
-            Math.round(rgb[0] * 255),
-            Math.round(rgb[1] * 255),
-            Math.round(rgb[2] * 255),
-            1
-        ]);
+        this._crosshairPosition = point;
+        this._crosshairElement.style.setProperty("transform", "translate(" + Math.round(point.x) + "px, " + Math.round(point.y) + "px)");
     }
 
-    _drawTintedCanvas()
+    _updateGradient()
     {
-        var ctx = this._tintedCanvas.getContext("2d");
-        var dimension = this._dimension * window.devicePixelRatio;
+        let stops = [];
+        for (let i = 0; i <= 360; i += 60)
+            stops.push(`hsl(${i}, 100%, ${this._brightness * 100}%)`);
 
-        ctx.save();
-        ctx.drawImage(this._rawCanvas, 0, 0, dimension, dimension);
-        if (this._brightness !== 1) {
-            ctx.globalAlpha = 1 - this._brightness;
-            ctx.fillStyle = "black";
-            ctx.fillRect(0, 0, dimension, dimension);
-        }
-        ctx.restore();
+        this._gradientElement.style.setProperty("background-image", `conic-gradient(${stops.join(",")})`);
     }
-
-    _draw()
-    {
-        this._drawTintedCanvas();
-
-        var ctx = this._finalCanvas.getContext("2d");
-        var dimension = this._dimension * window.devicePixelRatio;
-        var radius = this._radius * window.devicePixelRatio;
-
-        ctx.save();
-        ctx.clearRect(0, 0, dimension, dimension);
-        ctx.beginPath();
-        ctx.arc(dimension / 2, dimension / 2, radius + 1, 0, Math.PI * 2, true);
-        ctx.closePath();
-        ctx.clip();
-        ctx.drawImage(this._tintedCanvas, 0, 0, dimension, dimension);
-        ctx.restore();
-    }
 };

Copied: trunk/Source/WebInspectorUI/UserInterface/Views/LegacyColorWheel.js (from rev 237604, trunk/Source/WebInspectorUI/UserInterface/Views/ColorWheel.js) (0 => 237605)


--- trunk/Source/WebInspectorUI/UserInterface/Views/LegacyColorWheel.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LegacyColorWheel.js	2018-10-30 22:15:16 UTC (rev 237605)
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WI.LegacyColorWheel = class LegacyColorWheel extends WI.Object
+{
+    constructor()
+    {
+        super();
+
+        this._rawCanvas = document.createElement("canvas");
+        this._tintedCanvas = document.createElement("canvas");
+        this._finalCanvas = document.createElement("canvas");
+
+        this._crosshair = document.createElement("div");
+        this._crosshair.className = "crosshair";
+
+        this._element = document.createElement("div");
+        this._element.className = "color-wheel";
+
+        this._element.appendChild(this._finalCanvas);
+        this._element.appendChild(this._crosshair);
+
+        this._finalCanvas.addEventListener("mousedown", this);
+    }
+
+    // Public
+
+    set dimension(dimension)
+    {
+        this._element.style.width = this.element.style.height = `${dimension}px`;
+
+        this._finalCanvas.width = this._tintedCanvas.width = this._rawCanvas.width = dimension * window.devicePixelRatio;
+        this._finalCanvas.height = this._tintedCanvas.height = this._rawCanvas.height = dimension * window.devicePixelRatio;
+
+        this._finalCanvas.style.width = this._finalCanvas.style.height = dimension + "px";
+
+        this._dimension = dimension;
+        // We shrink the radius a bit for better anti-aliasing.
+        this._radius = dimension / 2 - 2;
+
+        this._setCrosshairPosition(new WI.Point(dimension / 2, dimension / 2));
+
+        this._drawRawCanvas();
+        this._draw();
+    }
+
+    get element()
+    {
+        return this._element;
+    }
+
+    get brightness()
+    {
+        return this._brightness;
+    }
+
+    set brightness(brightness)
+    {
+        this._brightness = brightness;
+        this._draw();
+    }
+
+    get tintedColor()
+    {
+        if (this._crosshairPosition)
+            return this._colorAtPointWithBrightness(this._crosshairPosition.x * window.devicePixelRatio, this._crosshairPosition.y * window.devicePixelRatio, this._brightness);
+
+        return new WI.Color(WI.Color.Format.RGBA, [0, 0, 0, 0]);
+    }
+
+    set tintedColor(tintedColor)
+    {
+        var data = ""
+        this._setCrosshairPosition(data.point);
+        this.brightness = data.brightness;
+    }
+
+    get rawColor()
+    {
+        if (this._crosshairPosition)
+            return this._colorAtPointWithBrightness(this._crosshairPosition.x * window.devicePixelRatio, this._crosshairPosition.y * window.devicePixelRatio, 1);
+
+        return new WI.Color(WI.Color.Format.RGBA, [0, 0, 0, 0]);
+    }
+
+    // Protected
+
+    handleEvent(event)
+    {
+        switch (event.type) {
+        case "mousedown":
+            this._handleMousedown(event);
+            break;
+        case "mousemove":
+            this._handleMousemove(event);
+            break;
+        case "mouseup":
+            this._handleMouseup(event);
+            break;
+        }
+    }
+
+    // Private
+
+    _handleMousedown(event)
+    {
+        window.addEventListener("mousemove", this, true);
+        window.addEventListener("mouseup", this, true);
+
+        this._updateColorForMouseEvent(event);
+    }
+
+    _handleMousemove(event)
+    {
+        this._updateColorForMouseEvent(event);
+    }
+
+    _handleMouseup(event)
+    {
+        window.removeEventListener("mousemove", this, true);
+        window.removeEventListener("mouseup", this, true);
+    }
+
+    _pointInCircleForEvent(event)
+    {
+        function distance(a, b)
+        {
+            return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
+        }
+
+        function angleFromCenterToPoint(center, point)
+        {
+            return Math.atan2(point.y - center.y, point.x - center.x);
+        }
+
+        function pointOnCircumference(c, r, a)
+        {
+            return new WI.Point(c.x + r * Math.cos(a), c.y + r * Math.sin(a));
+        }
+
+        var dimension = this._dimension;
+        var point = window.webkitConvertPointFromPageToNode(this._finalCanvas, new WebKitPoint(event.pageX, event.pageY));
+        var center = new WI.Point(dimension / 2, dimension / 2);
+        if (distance(point, center) > this._radius) {
+            var angle = angleFromCenterToPoint(center, point);
+            point = pointOnCircumference(center, this._radius, angle);
+        }
+        return point;
+    }
+
+    _updateColorForMouseEvent(event)
+    {
+        var point = this._pointInCircleForEvent(event);
+
+        this._setCrosshairPosition(point);
+
+        if (this.delegate && typeof this.delegate.colorWheelColorDidChange === "function")
+            this.delegate.colorWheelColorDidChange(this);
+    }
+
+    _setCrosshairPosition(point)
+    {
+        this._crosshairPosition = point;
+        this._crosshair.style.webkitTransform = "translate(" + Math.round(point.x) + "px, " + Math.round(point.y) + "px)";
+    }
+
+    _tintedColorToPointAndBrightness(color)
+    {
+        var rgb = color.rgb;
+        var hsv = WI.Color.rgb2hsv(rgb[0], rgb[1], rgb[2]);
+        var cosHue = Math.cos(hsv[0] * Math.PI / 180);
+        var sinHue = Math.sin(hsv[0] * Math.PI / 180);
+        var center = this._dimension / 2;
+        var x = center + (center * cosHue * hsv[1]);
+        var y = center - (center * sinHue * hsv[1]);
+        return {
+            point: new WI.Point(x, y),
+            brightness: hsv[2]
+        };
+    }
+
+    _drawRawCanvas() {
+        var ctx = this._rawCanvas.getContext("2d");
+
+        var dimension = this._dimension * window.devicePixelRatio;
+
+        ctx.fillStyle = "white";
+        ctx.fillRect(0, 0, dimension, dimension);
+
+        var imageData = ctx.getImageData(0, 0, dimension, dimension);
+        var data = ""
+        for (var j = 0; j < dimension; ++j) {
+            for (var i = 0; i < dimension; ++i) {
+                var color = this._colorAtPointWithBrightness(i, j, 1);
+                if (!color)
+                    continue;
+                var pos = (j * dimension + i) * 4;
+                data[pos] = color.rgb[0];
+                data[pos + 1] = color.rgb[1];
+                data[pos + 2] = color.rgb[2];
+            }
+        }
+        ctx.putImageData(imageData, 0, 0);
+    }
+
+    _colorAtPointWithBrightness(x, y, brightness)
+    {
+        var center = this._dimension / 2 * window.devicePixelRatio;
+        var xDis = x - center;
+        var yDis = y - center;
+        var distance = Math.sqrt(xDis * xDis + yDis * yDis);
+
+        if (distance - center > 0.001)
+            return new WI.Color(WI.Color.Format.RGBA, [0, 0, 0, 0]);
+
+        var h = Math.atan2(y - center, center - x) * 180 / Math.PI;
+        h = (h + 180) % 360;
+        var v = brightness;
+        var s = Math.max(0, distance) / center;
+
+        var rgb = WI.Color.hsv2rgb(h, s, v);
+        return new WI.Color(WI.Color.Format.RGBA, [
+            Math.round(rgb[0] * 255),
+            Math.round(rgb[1] * 255),
+            Math.round(rgb[2] * 255),
+            1
+        ]);
+    }
+
+    _drawTintedCanvas()
+    {
+        var ctx = this._tintedCanvas.getContext("2d");
+        var dimension = this._dimension * window.devicePixelRatio;
+
+        ctx.save();
+        ctx.drawImage(this._rawCanvas, 0, 0, dimension, dimension);
+        if (this._brightness !== 1) {
+            ctx.globalAlpha = 1 - this._brightness;
+            ctx.fillStyle = "black";
+            ctx.fillRect(0, 0, dimension, dimension);
+        }
+        ctx.restore();
+    }
+
+    _draw()
+    {
+        this._drawTintedCanvas();
+
+        var ctx = this._finalCanvas.getContext("2d");
+        var dimension = this._dimension * window.devicePixelRatio;
+        var radius = this._radius * window.devicePixelRatio;
+
+        ctx.save();
+        ctx.clearRect(0, 0, dimension, dimension);
+        ctx.beginPath();
+        ctx.arc(dimension / 2, dimension / 2, radius + 1, 0, Math.PI * 2, true);
+        ctx.closePath();
+        ctx.clip();
+        ctx.drawImage(this._tintedCanvas, 0, 0, dimension, dimension);
+        ctx.restore();
+    }
+};
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to