- commit
- e6ec508aba8f09ee2afd36e01459583763dd6478
- parent
- 62c3888e5892903712171fc1375277ef5f6c5b00
- Author
- Tobias Bengfort <tobias.bengfort@gmx.net>
- Date
- 2016-07-20 19:28
color: reduce chroma to avoid clipping
Diffstat
| M | sass/color.scss | 70 | +++++++++++++++++++++++++++++++++++++++++++++---------------- |
| M | test/color.js | 30 | +++++++++++++++--------------- |
2 files changed, 67 insertions, 33 deletions
diff --git a/sass/color.scss b/sass/color.scss
@@ -19,6 +19,17 @@ $planifolia-colorspace: 'lab' !default; 19 19 @return if(unit($x) == '%', $x / 100%, $x); 20 20 } 21 21 -1 22 @function _pf-clip-needed($rgb) { -1 23 @for $i from 1 through 3 { -1 24 @if nth($rgb, $i) < 0 { -1 25 @return true; -1 26 } @else if nth($rgb, $i) > 255 { -1 27 @return true; -1 28 } -1 29 } -1 30 @return false; -1 31 } -1 32 22 33 @function _pf-srgb-to-rgb($c) { 23 34 $c: $c / 255; 24 35 @if $c <= .04045 { @@ -60,7 +71,7 @@ $planifolia-colorspace: 'lab' !default; 60 71 $g: _pf-rgb-to-srgb($g); 61 72 $b: _pf-rgb-to-srgb($b); 62 7363 -1 @return rgb($r, $g, $b);-1 74 @return ($r, $g, $b); 64 75 } 65 76 66 77 @function _pf-to-yuv($color) { @@ -84,7 +95,7 @@ $planifolia-colorspace: 'lab' !default; 84 95 $g: _pf-rgb-to-srgb($y + -0.21482 * $u + -0.38059 * $v); 85 96 $b: _pf-rgb-to-srgb($y + 2.12798 * $u); 86 9787 -1 @return rgb($r, $g, $b);-1 98 @return ($r, $g, $b); 88 99 } 89 100 90 101 @function _pf-xyz-to-lab-f($t) { @@ -218,21 +229,7 @@ $planifolia-colorspace: 'lab' !default; 218 229 } 219 230 } 220 231221 -1 /// Create a color from lightness, chroma, and hue values.222 -1 ///223 -1 /// Note that the result may be clipped if it lies outside of the sRGB224 -1 /// colorspace.225 -1 ///226 -1 /// @param {number} $lightness 0 .. 100227 -1 /// @param {number} $chroma 0 .. ca. 140228 -1 /// @param {angle} $hue229 -1 /// @param {string} $colorspace ['lab'] one of 'lab', 'luv', 'hsl', 'yuv'230 -1 /// @return {color}231 -1 ///232 -1 /// @require pow233 -1 /// @require sin234 -1 /// @require cos235 -1 @function lch($lightness, $chroma, $hue, $colorspace: $planifolia-colorspace) {-1 232 @function _lch-unclipped($lightness, $chroma, $hue, $colorspace) { 236 233 @if $colorspace == 'lab' { 237 234 $lab: _pf-lch-to-lab(($lightness, $chroma, $hue)); 238 235 $xyz: _pf-lab-to-xyz($lab); @@ -243,7 +240,8 @@ $planifolia-colorspace: 'lab' !default; 243 240 @return _pf-from-xyz($xyz); 244 241 } @else if $colorspace == 'hsl' { 245 242 $saturation: if($lightness == 0, 0, $chroma / $lightness * 100);246 -1 @return hsl($hue, $saturation * 1%, $lightness * 1%);-1 243 $color: hsl($hue, $saturation * 1%, $lightness * 1%); -1 244 @return (red($color), green($color), blue($color)); 247 245 } @else if $colorspace == 'yuv' { 248 246 $yuv: _pf-lch-to-lab(($lightness, $chroma, $hue)); 249 247 @return _pf-from-yuv($yuv); @@ -252,6 +250,42 @@ $planifolia-colorspace: 'lab' !default; 252 250 } 253 251 } 254 252 -1 253 /// Create a color from lightness, chroma, and hue values. -1 254 /// -1 255 /// Note that the chroma is reduced if the result would otherwise be outside -1 256 /// of the sRGB colorspace. -1 257 /// -1 258 /// @param {number} $lightness 0 .. 100 -1 259 /// @param {number} $chroma 0 .. ca. 140 -1 260 /// @param {angle} $hue -1 261 /// @param {string} $colorspace ['lab'] one of 'lab', 'luv', 'hsl', 'yuv' -1 262 /// @return {color} -1 263 /// -1 264 /// @require pow -1 265 /// @require sin -1 266 /// @require cos -1 267 @function lch($lightness, $chroma, $hue, $colorspace: $planifolia-colorspace) { -1 268 $rgb: _lch-unclipped($lightness, $chroma, $hue, $colorspace); -1 269 -1 270 @if _pf-clip-needed($rgb) { -1 271 $c-min: 0; -1 272 $c-max: $chroma; -1 273 $c-tmp: ($c-min + $c-max) / 2; -1 274 -1 275 @while $c-max - $c-min > 0.01 { -1 276 $rgb: _lch-unclipped($lightness, $c-tmp, $hue, $colorspace); -1 277 @if _pf-clip-needed($rgb) { -1 278 $c-max: $c-tmp; -1 279 } @else { -1 280 $c-min: $c-tmp; -1 281 } -1 282 $c-tmp: ($c-min + $c-max) / 2; -1 283 } -1 284 } -1 285 -1 286 @return rgb(nth($rgb, 1), nth($rgb, 2), nth($rgb, 3)); -1 287 } -1 288 255 289 /// Create a color from lightness, chroma, hue, and alpha values. 256 290 /// @param {number} $lightness 257 291 /// @param {number} $chroma
diff --git a/test/color.js b/test/color.js
@@ -82,10 +82,10 @@ describe('color', function() {
82 82 sassaby.func('pf-complement').calledWithArgs('white').equals('white');
83 83 });
84 84 it('red', function() {
85 -1 sassaby.func('pf-complement').calledWithArgs('red').equals('#00a1f3');
-1 85 sassaby.func('pf-complement').calledWithArgs('red').equals('#008ca1');
86 86 });
87 87 it('yellow', function() {
88 -1 sassaby.func('pf-complement').calledWithArgs('yellow').equals('#76f4ff');
-1 88 sassaby.func('pf-complement').calledWithArgs('yellow').equals('#f5f6ff');
89 89 });
90 90 });
91 91
@@ -130,22 +130,22 @@ describe('color', function() {
130 130 sassaby.func('pf-mix').calledWithArgs('black', 'white', '.2').equals('#c6c6c6');
131 131 });
132 132 it('blue, red', function() {
133 -1 sassaby.func('pf-mix').calledWithArgs('blue', 'red').equals('#f40093');
-1 133 sassaby.func('pf-mix').calledWithArgs('blue', 'red').equals('#c20081');
134 134 });
135 135 it('blue, red, 20%', function() {
136 -1 sassaby.func('pf-mix').calledWithArgs('blue', 'red', '20%').equals('#ff0045');
-1 136 sassaby.func('pf-mix').calledWithArgs('blue', 'red', '20%').equals('#e70051');
137 137 });
138 138 it('green, red', function() {
139 -1 sassaby.func('pf-mix').calledWithArgs('green', 'red').equals('#a76900');
-1 139 sassaby.func('pf-mix').calledWithArgs('green', 'red').equals('#9d6e00');
140 140 });
141 141 it('yellow, blue', function() {
142 -1 sassaby.func('pf-mix').calledWithArgs('yellow', 'blue').equals('#ff0079');
-1 142 sassaby.func('pf-mix').calledWithArgs('yellow', 'blue').equals('#ff6b89');
143 143 });
144 144 it('green, blue', function() {
145 -1 sassaby.func('pf-mix').calledWithArgs('green', 'blue').equals('#0077fb');
-1 145 sassaby.func('pf-mix').calledWithArgs('green', 'blue').equals('#006487');
146 146 });
147 147 it('white, blue', function() {
148 -1 sassaby.func('pf-mix').calledWithArgs('white', 'blue').equals('#b38bff');
-1 148 sassaby.func('pf-mix').calledWithArgs('white', 'blue').equals('#b38cff');
149 149 });
150 150 });
151 151 });
@@ -222,10 +222,10 @@ describe('color', function() {
222 222 sassaby.func('pf-complement').calledWithArgs('white', 'luv').equals('white');
223 223 });
224 224 it('red', function() {
225 -1 sassaby.func('pf-complement').calledWithArgs('red', 'luv').equals('#00b8b8');
-1 225 sassaby.func('pf-complement').calledWithArgs('red', 'luv').equals('#008e8e');
226 226 });
227 227 it('yellow', function() {
228 -1 sassaby.func('pf-complement').calledWithArgs('yellow', 'luv').equals('#eaeaff');
-1 228 sassaby.func('pf-complement').calledWithArgs('yellow', 'luv').equals('#f6f6ff');
229 229 });
230 230 });
231 231
@@ -249,19 +249,19 @@ describe('color', function() {
249 249 sassaby.func('pf-mix').calledWithArgs('black', 'white', '.2', 'luv').equals('#c6c6c6');
250 250 });
251 251 it('blue, red', function() {
252 -1 sassaby.func('pf-mix').calledWithArgs('blue', 'red', '50%', 'luv').equals('#f000b6');
-1 252 sassaby.func('pf-mix').calledWithArgs('blue', 'red', '50%', 'luv').equals('#bd0095');
253 253 });
254 254 it('blue, red, 20%', function() {
255 -1 sassaby.func('pf-mix').calledWithArgs('blue', 'red', '20%', 'luv').equals('#fc006e');
-1 255 sassaby.func('pf-mix').calledWithArgs('blue', 'red', '20%', 'luv').equals('#e40070');
256 256 });
257 257 it('green, red', function() {
258 -1 sassaby.func('pf-mix').calledWithArgs('green', 'red', '50%', 'luv').equals('#bb6100');
-1 258 sassaby.func('pf-mix').calledWithArgs('green', 'red', '50%', 'luv').equals('#a56a00');
259 259 });
260 260 it('yellow, blue', function() {
261 -1 sassaby.func('pf-mix').calledWithArgs('yellow', 'blue', '50%', 'luv').equals('#ff53af');
-1 261 sassaby.func('pf-mix').calledWithArgs('yellow', 'blue', '50%', 'luv').equals('#ff66ab');
262 262 });
263 263 it('green, blue', function() {
264 -1 sassaby.func('pf-mix').calledWithArgs('green', 'blue', '50%', 'luv').equals('#0079a6');
-1 264 sassaby.func('pf-mix').calledWithArgs('green', 'blue', '50%', 'luv').equals('#006678');
265 265 });
266 266 it('white, blue', function() {
267 267 sassaby.func('pf-mix').calledWithArgs('white', 'blue', '50%', 'luv').equals('#9999e8');