From f6dbf624c94e9736efa802cbb15bb1a6a1c33a3f Mon Sep 17 00:00:00 2001 From: Tom Carden Date: Wed, 17 Nov 2010 18:41:23 -0800 Subject: [PATCH] hsl and hsla support plus initial tests --- lib/context2d.js | 42 +++++++++++++++++++++++++++- test/canvas.test.js | 67 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/lib/context2d.js b/lib/context2d.js index 4161050..8acf9dc 100644 --- a/lib/context2d.js +++ b/lib/context2d.js @@ -126,6 +126,8 @@ var parseFont = exports.parseFont = function(str){ * - rgb(255,255,5) * - rgba(255,255,5,.8) * - rgba(255,255,5,0.8) + * - hsl(300,100%,50%) + * - hsla(300,100%,50%,0.5) * - white * - red * @@ -177,9 +179,47 @@ var parseColor = exports.parseColor = function(str){ , parseInt(captures[3] + captures[3], 16) , 1 ]; - } + // HSLA + } else if (0 == str.indexOf('hsla')) { + var captures = /hsla\((\d+\.\d+|\.\d+|\d+) *, *(\d+\.\d+|\.\d+|\d+)%? *, *(\d+\.\d+|\.\d+|\d+)%? *, *(\d+\.\d+|\.\d+|\d+) *\)/.exec(str); + if (!captures) return; + return cache[str] = hsl2rgb( + (((parseFloat(captures[1], 10) % 360) + 360) % 360) / 360 + , parseFloat(captures[2], 10) / 100.0 + , parseFloat(captures[3], 10) / 100.0 + , parseFloat(captures[4], 10) + ); + // HSL + } else if (0 == str.indexOf('hsl')) { + var captures = /hsl\((\d+\.\d+|\.\d+|\d+) *, *(\d+\.\d+|\.\d+|\d+)%? *, *(\d+\.\d+|\.\d+|\d+)%? *\)/.exec(str); + if (!captures) return; + return cache[str] = hsl2rgb( + (((parseFloat(captures[1], 10) % 360) + 360) % 360) / 360 + , parseFloat(captures[2], 10) / 100.0 + , parseFloat(captures[3], 10) / 100.0 + , 1 + ); + } }; +// adapted from ABC code at http://www.w3.org/TR/css3-color/#hsl-color +function hsl2rgb(h,s,l,a) { + var m2 = l <= 0.5 ? l*(s+1) : l+s-l*s + , m1 = l*2-m2; + return [ Math.round(hue2rgb(m1, m2, h+1/3) * 255), + Math.round(hue2rgb(m1, m2, h) * 255), + Math.round(hue2rgb(m1, m2, h-1/3) * 255), + a ] +} +function hue2rgb(m1,m2,h) { + if (h<0) h = h+1; + if (h>1) h = h-1; + if (h*6<1) return m1+(m2-m1)*h*6; + if (h*2<1) return m2; + if (h*3<2) return m1+(m2-m1)*(2/3-h)*6; + return m1; +} + /** * Add `color` stop at the given `offset`. * diff --git a/test/canvas.test.js b/test/canvas.test.js index 20ad6cd..a6fdb15 100644 --- a/test/canvas.test.js +++ b/test/canvas.test.js @@ -38,6 +38,73 @@ module.exports = { assert.equal(null, parseColor('rgba(2554,165 , 0 ,.6)')); assert.equal(null, parseColor('rgba()')); + // hsl() + assert.eql([255,0,0,1], parseColor('hsl(0,100.0,50.0)')); + assert.eql([255,0,0,1], parseColor('hsl(360,100.0,50.0)')); + assert.eql([0,255,0,1], parseColor('hsl(120,100.0,50.0)')); + assert.eql([0,0,255,1], parseColor('hsl(240,100.0,50.0)')); + assert.equal(null, parseColor('hsl()')); + + // adapted from tables at http://www.w3.org/TR/css3-color/#hsl-examples + // NB:- corrected rounded percents to precise percents + // e.g. 13% --> 12.5%, etc. + // ...presumably the precise values were used to generate the tables? + assert.eql(parseColor('#FFFFFF'), parseColor('hsl(0,100%,100%)')) + assert.eql(parseColor('#FFFFFF'), parseColor('hsl(0,75%,100%)')) + assert.eql(parseColor('#FFFFFF'), parseColor('hsl(0,50%,100%)')) + assert.eql(parseColor('#FFFFFF'), parseColor('hsl(0,25%,100%)')) + assert.eql(parseColor('#FFFFFF'), parseColor('hsl(0,0%,100%)')) + assert.eql(parseColor('#FFBFBF'), parseColor('hsl(0,100%,87.5%)')) + assert.eql(parseColor('#F7C7C7'), parseColor('hsl(0,75%,87.5%)')) + assert.eql(parseColor('#EFCFCF'), parseColor('hsl(0,50%,87.5%)')) + assert.eql(parseColor('#E7D7D7'), parseColor('hsl(0,25%,87.5%)')) + assert.eql(parseColor('#DFDFDF'), parseColor('hsl(0,0%,87.5%)')) + assert.eql(parseColor('#FF8080'), parseColor('hsl(0,100%,75%)')) + assert.eql(parseColor('#EF8F8F'), parseColor('hsl(0,75%,75%)')) + assert.eql(parseColor('#DF9F9F'), parseColor('hsl(0,50%,75%)')) + assert.eql(parseColor('#CFAFAF'), parseColor('hsl(0,25%,75%)')) + assert.eql(parseColor('#BFBFBF'), parseColor('hsl(0,0%,75%)')) + assert.eql(parseColor('#FF4040'), parseColor('hsl(0,100%,62.5%)')) + assert.eql(parseColor('#E75858'), parseColor('hsl(0,75%,62.5%)')) + assert.eql(parseColor('#CF7070'), parseColor('hsl(0,50%,62.5%)')) + assert.eql(parseColor('#B78787'), parseColor('hsl(0,25%,62.5%)')) + assert.eql(parseColor('#9F9F9F'), parseColor('hsl(0,0%,62.5%)')) + assert.eql(parseColor('#FF0000'), parseColor('hsl(0,100%,50%)')) + assert.eql(parseColor('#DF2020'), parseColor('hsl(0,75%,50%)')) + assert.eql(parseColor('#BF4040'), parseColor('hsl(0,50%,50%)')) + assert.eql(parseColor('#9F6060'), parseColor('hsl(0,25%,50%)')) + assert.eql(parseColor('#808080'), parseColor('hsl(0,0%,50%)')) + assert.eql(parseColor('#BF0000'), parseColor('hsl(0,100%,37.5%)')) + assert.eql(parseColor('#A71818'), parseColor('hsl(0,75%,37.5%)')) + assert.eql(parseColor('#8F3030'), parseColor('hsl(0,50%,37.5%)')) + assert.eql(parseColor('#784848'), parseColor('hsl(0,25%,37.5%)')) + assert.eql(parseColor('#606060'), parseColor('hsl(0,0%,37.5%)')) + assert.eql(parseColor('#800000'), parseColor('hsl(0,100%,25%)')) + assert.eql(parseColor('#701010'), parseColor('hsl(0,75%,25%)')) + assert.eql(parseColor('#602020'), parseColor('hsl(0,50%,25%)')) + assert.eql(parseColor('#503030'), parseColor('hsl(0,25%,25%)')) + assert.eql(parseColor('#404040'), parseColor('hsl(0,0%,25%)')) + assert.eql(parseColor('#400000'), parseColor('hsl(0,100%,12.5%)')) + assert.eql(parseColor('#380808'), parseColor('hsl(0,75%,12.5%)')) + assert.eql(parseColor('#301010'), parseColor('hsl(0,50%,12.5%)')) + assert.eql(parseColor('#281818'), parseColor('hsl(0,25%,12.5%)')) + assert.eql(parseColor('#202020'), parseColor('hsl(0,0%,12.5%)')) + assert.eql(parseColor('#000000'), parseColor('hsl(0,100%,0%)')) + assert.eql(parseColor('#000000'), parseColor('hsl(0,75%,0%)')) + assert.eql(parseColor('#000000'), parseColor('hsl(0,50%,0%)')) + assert.eql(parseColor('#000000'), parseColor('hsl(0,25%,0%)')) + assert.eql(parseColor('#000000'), parseColor('hsl(0,0%,0%)')) + + // TODO: there are 11 more tables to adapt from + // http://www.w3.org/TR/css3-color/#hsl-examples :) + + // hsla() + assert.eql([255,0,0,1], parseColor('hsla(0,100.0,50.0,1.0)')); + assert.eql([255,0,0,1], parseColor('hsla(360,100.0,50.0,1.0)')); + assert.eql([0,255,0,1], parseColor('hsla(120,100.0,50.0,1.0)')); + assert.eql([0,0,255,1], parseColor('hsla(240,100.0,50.0,1.0)')); + assert.equal(null, parseColor('hsl()')); + // hex assert.eql([165,89,89,1], parseColor('#A55959')); assert.eql([255,255,255,1], parseColor('#FFFFFF'));