WebKit Bugzilla
Attachment 358000 Details for
Bug 192729
: Web Inspector: conic-gradient color picker doesn't accurately show color when saturation value is not 100%
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-192729-20181221172517.patch (text/plain), 30.95 KB, created by
Devin Rousso
on 2018-12-21 16:25:18 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Devin Rousso
Created:
2018-12-21 16:25:18 PST
Size:
30.95 KB
patch
obsolete
>diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index 41b0ed9502a871ecbe08e2832064a86781c28040..237a80104a336c41ade9c0ddc9e15f9bcf7d010c 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,56 @@ >+2018-12-21 Devin Rousso <drousso@apple.com> >+ >+ 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 NOBODY (OOPS!). >+ >+ 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. >+ > 2018-12-21 Devin Rousso <drousso@apple.com> > > Web Inspector: Settings: experimental setting editors are misaligned in other locales >diff --git a/Source/WebInspectorUI/UserInterface/Main.html b/Source/WebInspectorUI/UserInterface/Main.html >index 5636599176baba8abe6f92fe27d0cf923e1ab667..cc018bbd7a7deef074e3fb2ab167ce89164cb88d 100644 >--- a/Source/WebInspectorUI/UserInterface/Main.html >+++ b/Source/WebInspectorUI/UserInterface/Main.html >@@ -815,8 +815,6 @@ > <script src="Views/XHRBreakpointPopover.js"></script> > <script src="Views/XHRBreakpointTreeElement.js"></script> > >- <script src="Views/LegacyColorWheel.js"></script> >- > <script src="Controllers/Annotator.js"></script> > <script src="Controllers/CodeMirrorEditingController.js"></script> > >diff --git a/Source/WebInspectorUI/UserInterface/Models/Color.js b/Source/WebInspectorUI/UserInterface/Models/Color.js >index 68894893fe80ec6c59f4cc7943ae65c46b25eb84..4ca04a4e83d3fadf56d958d6077aa6fc148bbca2 100644 >--- a/Source/WebInspectorUI/UserInterface/Models/Color.js >+++ b/Source/WebInspectorUI/UserInterface/Models/Color.js >@@ -155,19 +155,19 @@ WI.Color = class Color > return null; > } > >- static rgb2hsv(r, g, b) >+ static rgb2hsl(r, g, b) > { > r = WI.Color._eightBitChannel(r) / 255; > g = WI.Color._eightBitChannel(g) / 255; > b = WI.Color._eightBitChannel(b) / 255; > >- let min = Math.min(Math.min(r, g), b); >- let max = Math.max(Math.max(r, g), b); >+ let min = Math.min(r, g, b); >+ let max = Math.max(r, g, b); > let delta = max - min; > >- let h; >- let s; >- let v = max; >+ let h = 0; >+ let s = 0; >+ let l = (max + min) / 2; > > if (delta === 0) > h = 0; >@@ -182,50 +182,57 @@ WI.Color = class Color > h += 360; > > // Saturation >- if (max === 0) >+ if (delta === 0) > s = 0; > else >- s = 1 - (min / max); >+ s = delta / (1 - Math.abs((2 * l) - 1)); > >- return [h, s, v]; >+ return [ >+ h, >+ s * 100, >+ l * 100, >+ ]; > } > >- static hsv2rgb(h, s, v) >+ static hsl2rgb(h, s, l) > { >- if (s === 0) >- return [v, v, v]; >+ h = Number.constrain(h, 0, 360) % 360; >+ s = Number.constrain(s, 0, 100) / 100; >+ l = Number.constrain(l, 0, 100) / 100; > >- h /= 60; >- let i = Math.floor(h); >- let data = [ >- v * (1 - s), >- v * (1 - s * (h - i)), >- v * (1 - s * (1 - (h - i))) >- ]; >- let rgb; >+ let c = (1 - Math.abs((2 * l) - 1)) * s; >+ let x = c * (1 - Math.abs(((h / 60) % 2) - 1)); >+ let m = l - (c / 2); > >- switch (i) { >- case 0: >- rgb = [v, data[2], data[0]]; >- break; >- case 1: >- rgb = [data[1], v, data[0]]; >- break; >- case 2: >- rgb = [data[0], v, data[2]]; >- break; >- case 3: >- rgb = [data[0], data[1], v]; >- break; >- case 4: >- rgb = [data[2], data[0], v]; >- break; >- default: >- rgb = [v, data[0], data[1]]; >- break; >+ let r = 0; >+ let g = 0; >+ let b = 0; >+ >+ if (h < 60) { >+ r = c; >+ g = x; >+ } else if (h < 120) { >+ r = x; >+ g = c; >+ } else if (h < 180) { >+ g = c; >+ b = x; >+ } else if (h < 240) { >+ g = x; >+ b = c; >+ } else if (h < 300) { >+ r = x; >+ b = c; >+ } else if (h < 360) { >+ r = c; >+ b = x; > } > >- return rgb; >+ return [ >+ (r + m) * 255, >+ (g + m) * 255, >+ (b + m) * 255, >+ ]; > } > > static cmyk2rgb(c, m, y, k) >@@ -234,11 +241,11 @@ WI.Color = class Color > m = Number.constrain(m, 0, 1); > y = Number.constrain(y, 0, 1); > k = Number.constrain(k, 0, 1); >- >- let r = 255 - ((Math.min(1, c * (1 - k) + k)) * 255); >- let g = 255 - ((Math.min(1, m * (1 - k) + k)) * 255); >- let b = 255 - ((Math.min(1, y * (1 - k) + k)) * 255); >- return [r, g, b]; >+ return [ >+ 255 * (1 - c) * (1 - k), >+ 255 * (1 - m) * (1 - k), >+ 255 * (1 - y) * (1 - k), >+ ]; > } > > static normalized2rgb(r, g, b) >@@ -391,7 +398,7 @@ WI.Color = class Color > if (!this.simple) > return Array.shallowEqual(this._rgba, [0, 0, 0, 0]) || Array.shallowEqual(this._hsla, [0, 0, 0, 0]); > >- let rgb = (this._rgba && this._rgba.slice(0, 3)) || this._hslToRGB(this._hsla); >+ let rgb = (this._rgba && this._rgba.slice(0, 3)) || WI.Color.hsl2rgb(...this._hsla); > return Object.keys(WI.Color.Keywords).some(key => Array.shallowEqual(WI.Color.Keywords[key], rgb)); > } > >@@ -511,17 +518,17 @@ WI.Color = class Color > if (!this.simple) > return this._toRGBAString(); > >- let r = WI.Color._eightBitChannel(this.rgb[0]); >- let g = WI.Color._eightBitChannel(this.rgb[1]); >- let b = WI.Color._eightBitChannel(this.rgb[2]); >+ let r = WI.Color._eightBitChannel(Math.round(this.rgba[0])); >+ let g = WI.Color._eightBitChannel(Math.round(this.rgba[1])); >+ let b = WI.Color._eightBitChannel(Math.round(this.rgba[2])); > return `rgb(${r}, ${g}, ${b})`; > } > > _toRGBAString() > { >- let r = WI.Color._eightBitChannel(this.rgb[0]); >- let g = WI.Color._eightBitChannel(this.rgb[1]); >- let b = WI.Color._eightBitChannel(this.rgb[2]); >+ let r = WI.Color._eightBitChannel(Math.round(this.rgba[0])); >+ let g = WI.Color._eightBitChannel(Math.round(this.rgba[1])); >+ let b = WI.Color._eightBitChannel(Math.round(this.rgba[2])); > return `rgba(${r}, ${g}, ${b}, ${this.alpha})`; > } > >@@ -530,16 +537,18 @@ WI.Color = class Color > if (!this.simple) > return this._toHSLAString(); > >- let hsla = this.hsla; >- hsla = hsla.map((value) => value.maxDecimals(2)); >- return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)"; >+ let h = this.hsla[0].maxDecimals(2); >+ let s = this.hsla[1].maxDecimals(2); >+ let l = this.hsla[2].maxDecimals(2); >+ return `hsl(${h}, ${s}%, ${l}%)`; > } > > _toHSLAString() > { >- let hsla = this.hsla; >- hsla = hsla.map((value) => value.maxDecimals(2)); >- return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")"; >+ let h = this.hsla[0].maxDecimals(2); >+ let s = this.hsla[1].maxDecimals(2); >+ let l = this.hsla[2].maxDecimals(2); >+ return `hsla(${h}, ${s}%, ${l}%, ${this.alpha})`; > } > > _componentToHexValue(value) >@@ -550,77 +559,16 @@ WI.Color = class Color > return hex; > } > >- _rgbToHSL(rgb) >- { >- let r = WI.Color._eightBitChannel(rgb[0]) / 255; >- let g = WI.Color._eightBitChannel(rgb[1]) / 255; >- let b = WI.Color._eightBitChannel(rgb[2]) / 255; >- let max = Math.max(r, g, b); >- let min = Math.min(r, g, b); >- let diff = max - min; >- let add = max + min; >- >- let h; >- let s; >- let l = 0.5 * add; >- >- if (min === max) >- h = 0; >- else if (r === max) >- h = ((60 * (g - b) / diff) + 360) % 360; >- else if (g === max) >- h = (60 * (b - r) / diff) + 120; >- else >- h = (60 * (r - g) / diff) + 240; >- >- if (l === 0) >- s = 0; >- else if (l === 1) >- s = 1; >- else if (l <= 0.5) >- s = diff / add; >- else >- s = diff / (2 - add); >- >- return [ >- Math.round(h), >- Math.round(s * 100), >- Math.round(l * 100) >- ]; >- } >- >- _hslToRGB(hsl) >- { >- let h = parseFloat(hsl[0]) / 360; >- let s = parseFloat(hsl[1]) / 100; >- let l = parseFloat(hsl[2]) / 100; >- >- h *= 6; >- let sArray = [ >- l += s *= l < .5 ? l : 1 - l, >- l - h % 1 * s * 2, >- l -= s *= 2, >- l, >- l + h % 1 * s, >- l + s >- ]; >- return [ >- Math.round(sArray[ ~~h % 6 ] * 255), >- Math.round(sArray[ (h | 16) % 6 ] * 255), >- Math.round(sArray[ (h | 8) % 6 ] * 255) >- ]; >- } >- > _rgbaToHSLA(rgba) > { >- let hsl = this._rgbToHSL(rgba); >- hsl.push(rgba[3]); >- return hsl; >+ let hsla = WI.Color.rgb2hsl(...rgba); >+ hsla.push(rgba[3]); >+ return hsla; > } > > _hslaToRGBA(hsla) > { >- let rgba = this._hslToRGB(hsla); >+ let rgba = WI.Color.hsl2rgb(...hsla); > rgba.push(hsla[3]); > return rgba; > } >diff --git a/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js b/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js >index 1db089da16f7ab3d5e38fd67f53d007f0f1b4922..6d7286fe0ce18c75559511b0cd93ba4ccd93a41d 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js >+++ b/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js >@@ -29,9 +29,7 @@ WI.ColorPicker = class ColorPicker extends WI.Object > { > super(); > >- this._colorWheel = WI.ColorPicker.supportsConicGradient() ? new WI.ColorWheel : new WI.LegacyColorWheel; >- this._colorWheel.delegate = this; >- this._colorWheel.dimension = 200; >+ this._colorWheel = new WI.ColorWheel(this, 200); > > this._brightnessSlider = new WI.Slider; > this._brightnessSlider.delegate = this; >@@ -90,24 +88,6 @@ WI.ColorPicker = class ColorPicker extends WI.Object > 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() >@@ -156,7 +136,7 @@ WI.ColorPicker = class ColorPicker extends WI.Object > this._color = color; > > this._colorWheel.tintedColor = this._color; >- this._brightnessSlider.value = this._colorWheel.brightness; >+ this._brightnessSlider.value = this._colorWheel.brightness / 100; > > this._opacitySlider.value = this._color.alpha; > this._updateSliders(this._colorWheel.rawColor, this._color); >@@ -187,7 +167,7 @@ WI.ColorPicker = class ColorPicker extends WI.Object > if (slider === this._opacitySlider) > this.opacity = value; > else if (slider === this._brightnessSlider) >- this.brightness = value; >+ this.brightness = value * 100; > } > > // Private >@@ -229,12 +209,7 @@ WI.ColorPicker = class ColorPicker extends WI.Object > 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(); > >- 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._brightnessSlider.element.style.setProperty("background-image", `linear-gradient(90deg, black, ${rawColor}, white)`); > > this._opacitySlider.element.style.setProperty("background-image", "linear-gradient(90deg, " + transparent + ", " + opaque + "), " + this._opacityPattern); > } >@@ -277,17 +252,17 @@ WI.ColorPicker = class ColorPicker extends WI.Object > case WI.Color.Format.ShortHEXAlpha: > case WI.Color.Format.Keyword: > var [r, g, b] = this._color.rgb; >- updateColorInput.call(this, "R", r); >- updateColorInput.call(this, "G", g); >- updateColorInput.call(this, "B", b); >+ updateColorInput.call(this, "R", Math.round(r)); >+ updateColorInput.call(this, "G", Math.round(g)); >+ updateColorInput.call(this, "B", Math.round(b)); > break; > > case WI.Color.Format.HSL: > case WI.Color.Format.HSLA: > var [h, s, l] = this._color.hsl; >- updateColorInput.call(this, "H", h); >- updateColorInput.call(this, "S", s); >- updateColorInput.call(this, "L", l); >+ updateColorInput.call(this, "H", h.maxDecimals(2)); >+ updateColorInput.call(this, "S", s.maxDecimals(2)); >+ updateColorInput.call(this, "L", l.maxDecimals(2)); > break; > > default: >diff --git a/Source/WebInspectorUI/UserInterface/Views/ColorWheel.css b/Source/WebInspectorUI/UserInterface/Views/ColorWheel.css >index 75a3c1a7d110c67e48650bcbf001f2989b47eb67..b313143390456e33ca55d7e6c2469e96f865c89a 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ColorWheel.css >+++ b/Source/WebInspectorUI/UserInterface/Views/ColorWheel.css >@@ -27,10 +27,9 @@ > position: relative; > } > >-.color-wheel > .gradient { >+.color-wheel > canvas { > width: 100%; > height: 100%; >- border-radius: 50%; > } > > .color-wheel > .crosshair { >diff --git a/Source/WebInspectorUI/UserInterface/Views/ColorWheel.js b/Source/WebInspectorUI/UserInterface/Views/ColorWheel.js >index 8124b8d49b24db2293382cf310527d5c848b4aa3..b8904d5452aacc03d84a060c254aed0a68e93206 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ColorWheel.js >+++ b/Source/WebInspectorUI/UserInterface/Views/ColorWheel.js >@@ -25,21 +25,28 @@ > > WI.ColorWheel = class ColorWheel extends WI.Object > { >- constructor() >+ constructor(delegate, dimension) > { >+ console.assert(!isNaN(dimension)); >+ > super(); > >- this._brightness = 0.5; >+ this._delegate = delegate; >+ >+ this._brightness = 50; > > this._element = document.createElement("div"); > this._element.className = "color-wheel"; > >- this._gradientElement = this._element.appendChild(document.createElement("div")); >- this._gradientElement.classList.add("gradient"); >- this._gradientElement.addEventListener("mousedown", this); >+ this._canvasElement = this._element.appendChild(document.createElement("canvas")); >+ this._canvasElement.addEventListener("mousedown", this); >+ >+ this._canvasContext = this._canvasElement.getContext("2d"); > > this._crosshairElement = this._element.appendChild(document.createElement("div")); > this._crosshairElement.className = "crosshair"; >+ >+ this.dimension = dimension; > } > > // Public >@@ -48,14 +55,18 @@ WI.ColorWheel = class ColorWheel extends WI.Object > > set dimension(dimension) > { >+ if (dimension === this._dimension) >+ return; >+ > this._dimension = dimension; > > this._element.style.width = this.element.style.height = `${this._dimension}px`; >+ this._canvasElement.width = this._canvasElement.height = this._dimension * window.devicePixelRatio; > > let center = this._dimension / 2; > this._setCrosshairPosition(new WI.Point(center, center)); > >- this._updateGradient(); >+ this._updateCanvas(); > } > > get brightness() >@@ -65,14 +76,18 @@ WI.ColorWheel = class ColorWheel extends WI.Object > > set brightness(brightness) > { >+ if (brightness === this._brightness) >+ return; >+ > this._brightness = brightness; >- this._updateGradient(); >+ >+ this._updateCanvas(); > } > > get tintedColor() > { > if (this._crosshairPosition) >- return new WI.Color(WI.Color.Format.HSL, [this._hue, this._saturation, this._brightness * 100]); >+ return new WI.Color(WI.Color.Format.HSL, [this._hue, this._saturation, this._brightness]); > return new WI.Color(WI.Color.Format.HSLA, [0, 0, 0, 0]); > } > >@@ -87,7 +102,7 @@ WI.ColorWheel = class ColorWheel extends WI.Object > let y = center - (cosHue * hsl[1]); > this._setCrosshairPosition(new WI.Point(x, y)); > >- this.brightness = hsl[2] / 100; >+ this.brightness = hsl[2]; > } > > get rawColor() >@@ -154,12 +169,12 @@ WI.ColorWheel = class ColorWheel extends WI.Object > > _updateColorForMouseEvent(event) > { >- var point = window.webkitConvertPointFromPageToNode(this._gradientElement, new WebKitPoint(event.pageX, event.pageY)); >+ var point = window.webkitConvertPointFromPageToNode(this._canvasElement, new WebKitPoint(event.pageX, event.pageY)); > > this._setCrosshairPosition(point); > >- if (this.delegate && typeof this.delegate.colorWheelColorDidChange === "function") >- this.delegate.colorWheelColorDidChange(this); >+ if (this._delegate && typeof this._delegate.colorWheelColorDidChange === "function") >+ this._delegate.colorWheelColorDidChange(this); > } > > _setCrosshairPosition(point) >@@ -177,12 +192,34 @@ WI.ColorWheel = class ColorWheel extends WI.Object > this._crosshairElement.style.setProperty("transform", "translate(" + Math.round(point.x) + "px, " + Math.round(point.y) + "px)"); > } > >- _updateGradient() >+ _updateCanvas() > { >- let stops = []; >- for (let i = 0; i <= 360; i += 60) >- stops.push(`hsl(${i}, 100%, ${this._brightness * 100}%)`); >+ let dimension = this._dimension * window.devicePixelRatio; >+ let center = dimension / 2; > >- this._gradientElement.style.setProperty("background-image", `conic-gradient(${stops.join(",")})`); >+ let imageData = this._canvasContext.createImageData(dimension, dimension); >+ for (let y = 0; y < dimension; ++y) { >+ for (let x = 0; x < dimension; ++x) { >+ let xDis = (x - center) / center; >+ let yDis = (y - center) / center; >+ let saturation = Math.sqrt(Math.pow(xDis, 2) + Math.pow(yDis, 2)) * 100; >+ if (saturation > 100) >+ continue; >+ >+ let hue = Math.atan2(x - center, center - y) * 180 / Math.PI; >+ if (hue < 0) >+ hue += 360; >+ >+ let rgb = WI.Color.hsl2rgb(hue, saturation, this._brightness); >+ >+ let index = ((y * dimension) + x) * 4; >+ imageData.data[index] = rgb[0]; >+ imageData.data[index + 1] = rgb[1]; >+ imageData.data[index + 2] = rgb[2]; >+ imageData.data[index + 3] = 255; >+ } >+ } >+ >+ this._canvasContext.putImageData(imageData, 0, 0); > } > }; >diff --git a/Source/WebInspectorUI/UserInterface/Views/LegacyColorWheel.js b/Source/WebInspectorUI/UserInterface/Views/LegacyColorWheel.js >deleted file mode 100644 >index cadbbee953611996525804b3a3b15b847675c96e..0000000000000000000000000000000000000000 >--- a/Source/WebInspectorUI/UserInterface/Views/LegacyColorWheel.js >+++ /dev/null >@@ -1,284 +0,0 @@ >-/* >- * 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._tintedColorToPointAndBrightness(tintedColor); >- 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 = imageData.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(); >- } >-};
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192729
:
357489
|
357491
|
358000
|
358005
|
358006
|
358013