From 392846665c404222613c323c4e0049c14f1830f8 Mon Sep 17 00:00:00 2001 From: Kevin Lubick Date: Thu, 20 Feb 2020 10:29:55 -0500 Subject: [PATCH] [canvaskit] Expose parseColorString This is handy for interacting with Change-Id: I7946c08ef10a2481016885d58cc52f76f5cd40e7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272344 Reviewed-by: Kevin Lubick --- modules/canvaskit/CHANGELOG.md | 1 + modules/canvaskit/externs.js | 3 +- modules/canvaskit/helper.js | 70 ++++++++++++++++++++++++ modules/canvaskit/htmlcanvas/color.js | 63 +-------------------- modules/canvaskit/tests/canvas2d.spec.js | 6 +- 5 files changed, 78 insertions(+), 65 deletions(-) diff --git a/modules/canvaskit/CHANGELOG.md b/modules/canvaskit/CHANGELOG.md index 25822851ab..bbb08e1123 100644 --- a/modules/canvaskit/CHANGELOG.md +++ b/modules/canvaskit/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `SkSurface.drawOnce` for drawing a single frame (in addition to already existing `SkSurface.requestAnimationFrame` for animation logic). + - `CanvasKit.parseColorString` which processes color strings like "#2288FF". ### Changed - We now compile/ship with Emscripten v1.39.6. diff --git a/modules/canvaskit/externs.js b/modules/canvaskit/externs.js index ca01cbf399..d8bc9ac63a 100644 --- a/modules/canvaskit/externs.js +++ b/modules/canvaskit/externs.js @@ -23,7 +23,7 @@ */ var CanvasKit = { - // public API (i.e. things we declare in the pre-js file) + // public API (i.e. things we declare in the pre-js file or in the cpp bindings) Color: function() {}, /** @return {CanvasKit.SkRect} */ LTRBRect: function() {}, @@ -73,6 +73,7 @@ var CanvasKit = { getDecodeCacheUsageBytes: function() {}, getSkDataBytes: function() {}, multiplyByAlpha: function() {}, + parseColorString: function() {}, setCurrentContext: function() {}, setDecodeCacheLimitBytes: function() {}, diff --git a/modules/canvaskit/helper.js b/modules/canvaskit/helper.js index 3171057e41..28752615d8 100644 --- a/modules/canvaskit/helper.js +++ b/modules/canvaskit/helper.js @@ -29,6 +29,76 @@ CanvasKit.getColorComponents = function(color) { ] } +// parseColorString takes in a CSS color value and returns a CanvasKit.Color +// (which is just a 32 bit integer, 8 bits per channel). An optional colorMap +// may be provided which maps custom strings to values (e.g. {'springgreen':4278255487}). +// In the CanvasKit canvas2d shim layer, we provide this map for processing +// canvas2d calls, but not here for code size reasons. +CanvasKit.parseColorString = function(colorStr, colorMap) { + colorStr = colorStr.toLowerCase(); + // See https://drafts.csswg.org/css-color/#typedef-hex-color + if (colorStr.startsWith('#')) { + var r, g, b, a = 255; + switch (colorStr.length) { + case 9: // 8 hex chars #RRGGBBAA + a = parseInt(colorStr.slice(7, 9), 16); + case 7: // 6 hex chars #RRGGBB + r = parseInt(colorStr.slice(1, 3), 16); + g = parseInt(colorStr.slice(3, 5), 16); + b = parseInt(colorStr.slice(5, 7), 16); + break; + case 5: // 4 hex chars #RGBA + // multiplying by 17 is the same effect as + // appending another character of the same value + // e.g. e => ee == 14 => 238 + a = parseInt(colorStr.slice(4, 5), 16) * 17; + case 4: // 6 hex chars #RGB + r = parseInt(colorStr.slice(1, 2), 16) * 17; + g = parseInt(colorStr.slice(2, 3), 16) * 17; + b = parseInt(colorStr.slice(3, 4), 16) * 17; + break; + } + return CanvasKit.Color(r, g, b, a/255); + + } else if (colorStr.startsWith('rgba')) { + // Trim off rgba( and the closing ) + colorStr = colorStr.slice(5, -1); + var nums = colorStr.split(','); + return CanvasKit.Color(+nums[0], +nums[1], +nums[2], + valueOrPercent(nums[3])); + } else if (colorStr.startsWith('rgb')) { + // Trim off rgba( and the closing ) + colorStr = colorStr.slice(4, -1); + var nums = colorStr.split(','); + // rgb can take 3 or 4 arguments + return CanvasKit.Color(+nums[0], +nums[1], +nums[2], + valueOrPercent(nums[3])); + } else if (colorStr.startsWith('gray(')) { + // TODO + } else if (colorStr.startsWith('hsl')) { + // TODO + } else if (colorMap) { + // Try for named color + var nc = colorMap[colorStr]; + if (nc !== undefined) { + return nc; + } + } + SkDebug('unrecognized color ' + colorStr); + return CanvasKit.BLACK; +} + +function valueOrPercent(aStr) { + if (aStr === undefined) { + return 1; // default to opaque. + } + var a = parseFloat(aStr); + if (aStr && aStr.indexOf('%') !== -1) { + return a / 100; + } + return a; +} + CanvasKit.multiplyByAlpha = function(color, alpha) { if (alpha === 1) { return color; diff --git a/modules/canvaskit/htmlcanvas/color.js b/modules/canvaskit/htmlcanvas/color.js index 7fe17a1b5b..606d92e276 100644 --- a/modules/canvaskit/htmlcanvas/color.js +++ b/modules/canvaskit/htmlcanvas/color.js @@ -30,69 +30,8 @@ function colorToString(skcolor) { } } -function valueOrPercent(aStr) { - if (aStr === undefined) { - return 1; // default to opaque. - } - var a = parseFloat(aStr); - if (aStr && aStr.indexOf('%') !== -1) { - return a / 100; - } - return a; -} - function parseColor(colorStr) { - colorStr = colorStr.toLowerCase(); - // See https://drafts.csswg.org/css-color/#typedef-hex-color - if (colorStr.startsWith('#')) { - var r, g, b, a = 255; - switch (colorStr.length) { - case 9: // 8 hex chars #RRGGBBAA - a = parseInt(colorStr.slice(7, 9), 16); - case 7: // 6 hex chars #RRGGBB - r = parseInt(colorStr.slice(1, 3), 16); - g = parseInt(colorStr.slice(3, 5), 16); - b = parseInt(colorStr.slice(5, 7), 16); - break; - case 5: // 4 hex chars #RGBA - // multiplying by 17 is the same effect as - // appending another character of the same value - // e.g. e => ee == 14 => 238 - a = parseInt(colorStr.slice(4, 5), 16) * 17; - case 4: // 6 hex chars #RGB - r = parseInt(colorStr.slice(1, 2), 16) * 17; - g = parseInt(colorStr.slice(2, 3), 16) * 17; - b = parseInt(colorStr.slice(3, 4), 16) * 17; - break; - } - return CanvasKit.Color(r, g, b, a/255); - - } else if (colorStr.startsWith('rgba')) { - // Trim off rgba( and the closing ) - colorStr = colorStr.slice(5, -1); - var nums = colorStr.split(','); - return CanvasKit.Color(+nums[0], +nums[1], +nums[2], - valueOrPercent(nums[3])); - } else if (colorStr.startsWith('rgb')) { - // Trim off rgba( and the closing ) - colorStr = colorStr.slice(4, -1); - var nums = colorStr.split(','); - // rgb can take 3 or 4 arguments - return CanvasKit.Color(+nums[0], +nums[1], +nums[2], - valueOrPercent(nums[3])); - } else if (colorStr.startsWith('gray(')) { - // TODO - } else if (colorStr.startsWith('hsl')) { - // TODO - } else { - // Try for named color - var nc = colorMap[colorStr]; - if (nc !== undefined) { - return nc; - } - } - SkDebug('unrecognized color ' + colorStr); - return CanvasKit.BLACK; + return CanvasKit.parseColorString(colorStr, colorMap); } CanvasKit._testing['parseColor'] = parseColor; diff --git a/modules/canvaskit/tests/canvas2d.spec.js b/modules/canvaskit/tests/canvas2d.spec.js index 1569d646b6..97b9202c49 100644 --- a/modules/canvaskit/tests/canvas2d.spec.js +++ b/modules/canvaskit/tests/canvas2d.spec.js @@ -21,7 +21,7 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() { it('parses hex color strings', function(done) { LoadCanvasKit.then(catchException(done, () => { - const parseColor = CanvasKit._testing.parseColor; + const parseColor = CanvasKit.parseColorString; expect(parseColor('#FED')).toEqual( CanvasKit.Color(hex('FF'), hex('EE'), hex('DD'), 1)); expect(parseColor('#FEDC')).toEqual( @@ -35,7 +35,7 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() { }); it('parses rgba color strings', function(done) { LoadCanvasKit.then(catchException(done, () => { - const parseColor = CanvasKit._testing.parseColor; + const parseColor = CanvasKit.parseColorString; expect(parseColor('rgba(117, 33, 64, 0.75)')).toEqual( CanvasKit.Color(117, 33, 64, 0.75)); expect(parseColor('rgb(117, 33, 64, 0.75)')).toEqual( @@ -55,6 +55,8 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() { }); it('parses named color strings', function(done) { LoadCanvasKit.then(catchException(done, () => { + // Keep this one as the _testing version, because we don't include the large + // color map by default. const parseColor = CanvasKit._testing.parseColor; expect(parseColor('grey')).toEqual( CanvasKit.Color(128, 128, 128, 1.0));