From 472996247b3f407b0a044d5cda8b9a06e20f6eed Mon Sep 17 00:00:00 2001 From: Lauren Budorick Date: Tue, 14 Apr 2015 18:17:32 -0700 Subject: [PATCH] Color operations, take two --- js/style/paint_properties.js | 9 +++++- js/style/style_constant.js | 15 ++++++++++ js/style/style_declaration.js | 25 +++++++++++++++- package.json | 1 + test/js/style/style_constant.test.js | 39 +++++++++++++++++++++++++ test/js/style/style_declaration.test.js | 5 ++++ 6 files changed, 92 insertions(+), 2 deletions(-) diff --git a/js/style/paint_properties.js b/js/style/paint_properties.js index ab9b162a9ed..ad0885f2b15 100644 --- a/js/style/paint_properties.js +++ b/js/style/paint_properties.js @@ -2,6 +2,7 @@ var reference = require('./reference'); var parseCSSColor = require('csscolorparser').parseCSSColor; +var colorOps = require('color-ops'); module.exports = {}; @@ -14,7 +15,13 @@ reference.paint.forEach(function(className) { value = prop.default; if (value === undefined) continue; - if (prop.type === 'color') value = parseCSSColor(value); + if (prop.type === 'color') { + if (Array.isArray(value)) { + value = colorOps[value[0]](value[2], value[1]); + } else { + value = parseCSSColor(value); + } + } Calculated.prototype[p] = value; } diff --git a/js/style/style_constant.js b/js/style/style_constant.js index 7e2a58a8abe..5026be0300a 100644 --- a/js/style/style_constant.js +++ b/js/style/style_constant.js @@ -11,6 +11,20 @@ exports.resolve = function(value, constants) { value = resolve(value); + function resolveArray(value) { + if (Array.isArray(value)) { + for (var x in value) { + value[x] = resolveArray(value[x]); + if (value[x] in constants) { + value[x] = resolve(value[x]); + } + } + } + return value; + } + + value = resolveArray(value); + if (Array.isArray(value)) { value = value.slice(); @@ -26,6 +40,7 @@ exports.resolve = function(value, constants) { value.stops = value.stops.slice(); for (i = 0; i < value.stops.length; i++) { + value.stops[i][1] = resolveArray(value.stops[i][1]); if (value.stops[i][1] in constants) { value.stops[i] = [ value.stops[i][0], diff --git a/js/style/style_declaration.js b/js/style/style_declaration.js index d7b0aff3a60..5b972126cc6 100644 --- a/js/style/style_declaration.js +++ b/js/style/style_declaration.js @@ -2,6 +2,7 @@ var parseCSSColor = require('csscolorparser').parseCSSColor; var mapboxGLFunction = require('mapbox-gl-function'); +var colorOps = require('color-ops'); var util = require('../util/util'); module.exports = StyleDeclaration; @@ -63,9 +64,31 @@ function transitioned(calculate) { var colorCache = {}; +function parseColorArray(value) { + if (typeof value[0] === 'number') return value; + + var op = value[0]; + var degree = value[1]; + + value[2] = parseColorArray(value[2]); + if (op === 'mix') { + value[3] = parseColorArray(value[3]); + return colorOps[op](value[2], value[3], degree); + } + return colorOps[op](value[2], degree); +} + +function replaceStrings(color) { + if (typeof color === 'string') return parseCSSColor(color); + color[2] = replaceStrings(color[2]); + if (color[3]) color[3] = replaceStrings(color[3]); + return color; +} + function parseColor(value) { if (colorCache[value]) return colorCache[value]; - var color = prepareColor(parseCSSColor(value)); + var parsed = parseColorArray(replaceStrings(value)); + var color = prepareColor(parsed); colorCache[value] = color; return color; } diff --git a/package.json b/package.json index a64274fc90a..34a33ea4bd2 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "brfs": "1.2.0", + "color-ops": "^1.0.2", "csscolorparser": "~1.0.2", "envify": "2.0.1", "feature-filter": "1.0.0", diff --git a/test/js/style/style_constant.test.js b/test/js/style/style_constant.test.js index 4cd9b962791..73ba95ae799 100644 --- a/test/js/style/style_constant.test.js +++ b/test/js/style/style_constant.test.js @@ -34,6 +34,45 @@ test('StyleConstant.resolve', function(t) { }); t.end(); }); + + t.test('resolves color operation values', function(t) { + var simple = ["lighten", -20, "@black"]; + var lighten = ["lighten", 20, ["mix", 50, "@white", "@black"]]; + var darken = ["mix", 50, ["lighten", 20, "@black"], "green"]; + + var constants = { + "@white": "#FFF", + "@black": "#000", + "@a": "a" + }; + + t.deepEqual(StyleConstant.resolve(simple, constants), + ["lighten", -20, "#000"] + ); + t.deepEqual(StyleConstant.resolve(lighten, constants), + ["lighten", 20, ["mix", 50, "#FFF", "#000"]] + ); + t.deepEqual(StyleConstant.resolve(darken, constants), + ["mix", 50, ["lighten", 20, "#000"], "green"] + ); + + t.end(); + }); + + t.test('resolves color operations in functions', function(t) { + var fun = { + "stops": [[0, "@a"], [1, ["lighten", -20, "@a"]]] + }; + var constants = { + "@a": "#ccc" + }; + + t.deepEqual(StyleConstant.resolve(fun, constants), { + "stops": [[0, "#ccc"], [1, ["lighten", -20, "#ccc"]]] + }); + + t.end(); + }); }); test('StyleConstant.resolveAll', function(t) { diff --git a/test/js/style/style_declaration.test.js b/test/js/style/style_declaration.test.js index 560126d5721..7e0a8279034 100644 --- a/test/js/style/style_declaration.test.js +++ b/test/js/style/style_declaration.test.js @@ -48,6 +48,11 @@ test('StyleDeclaration', function(t) { t.deepEqual(new StyleDeclaration(reference, 'red').calculate(0), [ 1, 0, 0, 1 ]); t.deepEqual(new StyleDeclaration(reference, '#ff00ff').calculate(0), [ 1, 0, 1, 1 ]); t.deepEqual(new StyleDeclaration(reference, { stops: [[0, '#f00'], [1, '#0f0']] }).calculate(0), [1, 0, 0, 1]); + t.deepEqual(new StyleDeclaration(reference, ['lighten', -50, '#FFF']).calculate(0), + [0.5, 0.5, 0.5, 1]); + t.deepEqual(new StyleDeclaration(reference, ['lighten', -30, ['mix', 20, '#551A8B', + ['saturate', 10, '#FF0000']]]).calculate(0), + [0.2804597701149426, 0.006599053414469202, 0.035279554792739365, 1]); // cached t.deepEqual(new StyleDeclaration(reference, '#ff00ff').calculate(0), [ 1, 0, 1, 1 ]); t.deepEqual(new StyleDeclaration(reference, 'rgba(255, 51, 0, 1)').calculate(0), [ 1, 0.2, 0, 1 ]);