[canvaskit] Expose parseColorString
This is handy for interacting with <input type=color>
Change-Id: I7946c08ef10a2481016885d58cc52f76f5cd40e7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272344
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/modules/canvaskit/CHANGELOG.md b/modules/canvaskit/CHANGELOG.md
index 2582285..bbb08e1 100644
--- a/modules/canvaskit/CHANGELOG.md
+++ b/modules/canvaskit/CHANGELOG.md
@@ -15,6 +15,7 @@
### 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 ca01cbf..d8bc9ac 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 @@
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 3171057..28752615 100644
--- a/modules/canvaskit/helper.js
+++ b/modules/canvaskit/helper.js
@@ -29,6 +29,76 @@
]
}
+// 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 7fe17a1..606d92e 100644
--- a/modules/canvaskit/htmlcanvas/color.js
+++ b/modules/canvaskit/htmlcanvas/color.js
@@ -30,69 +30,8 @@
}
}
-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 1569d64..97b9202 100644
--- a/modules/canvaskit/tests/canvas2d.spec.js
+++ b/modules/canvaskit/tests/canvas2d.spec.js
@@ -21,7 +21,7 @@
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 @@
});
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 @@
});
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));