sass-planifolia

Vanilla Sass helper functions
git clone https://git.ce9e.org/sass-planifolia.git

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    73 
   63    -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    97 
   87    -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   231 
  221    -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 sRGB
  224    -1 /// colorspace.
  225    -1 ///
  226    -1 /// @param {number} $lightness 0 .. 100
  227    -1 /// @param {number} $chroma 0 .. ca. 140
  228    -1 /// @param {angle} $hue
  229    -1 /// @param {string} $colorspace ['lab'] one of 'lab', 'luv', 'hsl', 'yuv'
  230    -1 /// @return {color}
  231    -1 ///
  232    -1 /// @require pow
  233    -1 /// @require sin
  234    -1 /// @require cos
  235    -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');