aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Rogan Creswick <creswick@gmail.com>2013-06-13 18:03:15 -0700
committerGravatar Rogan Creswick <creswick@gmail.com>2013-06-13 18:03:15 -0700
commit467a34d97f29701463030c2b5c6c775a0a8342ed (patch)
tree739a49fd29d74d34dfa7ec568992bfe6fd8f8f28 /src
parent8e595706fc7fc7e3f51268efef59dfc276634bd9 (diff)
added color combination utilities to the prelude
Diffstat (limited to 'src')
-rw-r--r--src/js/fiveui/injected/prelude.js84
-rw-r--r--src/js/tests/specs/prelude.js52
2 files changed, 100 insertions, 36 deletions
diff --git a/src/js/fiveui/injected/prelude.js b/src/js/fiveui/injected/prelude.js
index 161682f..fbe5307 100644
--- a/src/js/fiveui/injected/prelude.js
+++ b/src/js/fiveui/injected/prelude.js
@@ -320,7 +320,7 @@ fiveui.color.colorToHex = function(color) {
* Covert color to RGB color object.
*
* @param {!String} color The color string to convert. This should be either of the form rgb(...) or #...
- * @returns {!Object} An RGB color object with attributes: r, g, b
+ * @returns {!Object} An RGB color object with attributes: r, g, b, a
* @throws {ParseError} if the rgb color string cannot be parsed
*/
fiveui.color.colorToRGB = function(color) {
@@ -329,20 +329,84 @@ fiveui.color.colorToRGB = function(color) {
return fiveui.color.hexToRGB(fiveui.color.colorToHex(color));
}
- var digits = /rgba?\((\d+), (\d+), (\d+)(, (\d+))?/.exec(color);
+ var digits = /rgba?\((\d+), (\d+), (\d+)(, (\d.\d+))?/.exec(color);
if (!digits) {
throw new ParseError('could not parse color string: ' + color);
}
- // HACK: return white if transparency is set to 0
- if (digits[5] == 0) {
- return { r: 255, g: 255, b: 255 };
- }
- else {
- return { r: parseInt(digits[1]),
- g: parseInt(digits[2]),
- b: parseInt(digits[3]) };
+ var alpha = 1;
+ if (digits[5]) {
+ alpha = parseFloat(digits[5]);
+ }
+
+ return { r: parseInt(digits[1]),
+ g: parseInt(digits[2]),
+ b: parseInt(digits[3]),
+ a: alpha };
+};
+
+/**
+ * Computationally determine the actual displayed background color for
+ * an object. This accounts for parent colors that may appear when
+ * a bg color is unspecified, or fully transparent.
+ *
+ * It does not account for elements that are shifted out of their
+ * parent containers.
+ *
+ * @param {!Object} A jquery object.
+ * @returns {color} an RGB color object. (no alpha - this does not
+ * return transparent colors)
+ */
+fiveui.color.findBGColor = function(obj) {
+ var fc = fiveui.color;
+ var real = fc.colorToRGB(obj.css('background-color'));
+ var none = fc.colorToRGB('rgba(0, 0, 0, 0)');
+
+ if (real.a != 1) {
+ // find parents with a non-default bg color:
+ var parents = obj.parents().filter(
+ function() {
+ var color = fc.colorToRGB($(this).css('background-color'));
+ return color != none;
+ }).map(
+ function(i) {
+ return fc.colorToRGB($(this).css('background-color'));
+ });
+
+ // push a white element onto the end of parents
+ parents.push({ r: 255, g: 255, b: 255, a: 1});
+
+ var colors = [];
+ for (var i=0; i < parents.length; i++) {
+ colors.push(parents[i]);
+ if (parents[i].a == 1) {
+ break;
+ }
}
+
+ // compose the colors and return:
+ return _.reduce(colors, fc.alphaCombine, none);
+ } else {
+ return real;
+ }
+};
+
+/**
+ * Combines two colors, accounting for alpha values less than 1.
+ *
+ * @param {color} top The color "on top"
+ * @param {color} bot The color "on bottom"
+ * @return {color} the composite RGBA color.
+ */
+fiveui.color.alphaCombine = function(top, bot) {
+ var result = { };
+ result.r = Math.floor(top.r * top.a + bot.r * bot.a * (1 - top.a));
+ result.g = Math.floor(top.g * top.a + bot.g * bot.a * (1 - top.a));
+ result.b = Math.floor(top.b * top.a + bot.b * bot.a * (1 - top.a));
+
+ result.a = top.a + bot.a * (1 - top.a);
+
+ return result;
};
/**
diff --git a/src/js/tests/specs/prelude.js b/src/js/tests/specs/prelude.js
index 7b37494..93a12cb 100644
--- a/src/js/tests/specs/prelude.js
+++ b/src/js/tests/specs/prelude.js
@@ -4,16 +4,8 @@ describe('prelude', function() {
var addTestSet = function(fn, tests) {
_.each(tests, function(test) {
it(test[0], function() {
- expect(fn(test[1])).toEqual(test[2]);
- });
- });
- };
-
- // 3 argument version of addTestSet
- var addTestSet3 = function(fn, tests) {
- _.each(tests, function(test) {
- it(test[0], function() {
- expect(fn(test[1], test[2], test[3])).toEqual(test[4]);
+ var args = test.slice(1, test.length - 1);
+ expect(fn.apply(undefined, args)).toEqual(test[test.length - 1]);
});
});
};
@@ -96,28 +88,28 @@ describe('prelude', function() {
addTestSet(fiveui.color.hexToRGB, [
// name , input , oracle
- ['hexToRGB: full white' , '#000000', { r: 0, g: 0, b: 0 }],
- ['hexToRGB: full black' , '#FFFFFF', { r: 255, g: 255, b: 255 }],
+ ['hexToRGB: full black' , '#000000', { r: 0, g: 0, b: 0 }],
+ ['hexToRGB: full white' , '#FFFFFF', { r: 255, g: 255, b: 255 }],
['hexToRGB: C7 grey' , '#C7C7C7', { r: 199, g: 199, b: 199 }],
['hexToRGB: full red' , '#FF0000', { r: 255, g: 0, b: 0 }],
['hexToRGB: full blue' , '#0000FF', { r: 0, g: 0, b: 255 }],
]);
- addTestSet3(fiveui.color.rgbToHex, [
+ addTestSet(fiveui.color.rgbToHex, [
// name , 3 inputs, oracle
- ['rgbToHex: full white' , 0, 0, 0, '#000000'],
- ['rgbToHex: full black' , 255, 255, 255, '#FFFFFF'],
+ ['rgbToHex: full black' , 0, 0, 0, '#000000'],
+ ['rgbToHex: full white' , 255, 255, 255, '#FFFFFF'],
['rgbToHex: C7 grey' , 199, 199, 199, '#C7C7C7'],
['rgbToHex: full red' , 255, 0, 0, '#FF0000'],
- ['rgbToHex: full blue' , 0, 0, 255, '#0000FF'],
+ ['rgbToHex: full blue' , 0, 0, 255, '#0000FF']
]);
addTestSet(fiveui.color.colorToHex, [
- ['colorToHex: full white' , '#000000', '#000000'],
- ['colorToHex: abreviated white 1' , '#0', '#000000'],
- ['colorToHex: abreviated white 2' , '#00', '#000000'],
- ['colorToHex: black' , '#FFFFFF', '#FFFFFF'],
- ['colorToHex: abreviated black' , '#FF', '#FFFFFF'],
+ ['colorToHex: full black' , '#000000', '#000000'],
+ ['colorToHex: abreviated black 1' , '#0', '#000000'],
+ ['colorToHex: abreviated black 2' , '#00', '#000000'],
+ ['colorToHex: white' , '#FFFFFF', '#FFFFFF'],
+ ['colorToHex: abreviated white' , '#FF', '#FFFFFF'],
['colorToHex: abreviated C7 grey' , '#C7', '#C7C7C7'],
['colorToHex: rgb(0, 0, 0)' , 'rgb(0, 0, 0)', '#000000'],
['colorToHex: rgb(255, 255, 255)' , 'rgb(255, 255, 255)', '#FFFFFF'],
@@ -126,11 +118,19 @@ describe('prelude', function() {
]);
addTestSet(fiveui.color.colorToRGB, [
- ['colorToRGB: full white' , '#000000', {r: 0, g: 0, b:0} ],
- ['colorToRGB: abreviated white 1' , '#0', {r: 0, g: 0, b:0} ],
- ['colorToRGB: black' , '#FFFFFF', {r: 255, g: 255, b: 255} ],
- ['colorToRGB: rgb(222, 173, 190)' , 'rgb(222, 173, 190)', {r: 222, g: 173, b: 190} ],
- ['colorToRGB: rgba(255, 255, 255, 100)', 'rgba(255, 255, 255, 100)', {r: 255, g: 255, b: 255} ],
+ ['colorToRGB: full black' , '#000000', {r: 0, g: 0, b:0} ],
+ ['colorToRGB: abreviated black 1' , '#0', {r: 0, g: 0, b:0} ],
+ ['colorToRGB: white' , '#FFFFFF', {r: 255, g: 255, b: 255} ],
+ ['colorToRGB: rgb(222, 173, 190)' , 'rgb(222, 173, 190)', {r: 222, g: 173, b: 190, a: 1} ],
+ ['colorToRGB: rgba(255, 255, 255, 0.7)', 'rgba(255, 255, 255, 0.7)', {r: 255, g: 255, b: 255, a: 0.7 } ]
+ ]);
+
+ addTestSet(fiveui.color.alphaCombine, [
+ ['red and white make pinkish', {r: 255, g: 0, b: 0, a: 0.5}, {r: 255, g: 255, b: 255, a: 1},
+ {r: 255, g: 127, b: 127, a: 1} ],
+ ['red and yellow make orange', {r: 255, g: 0, b: 0, a: 0.5}, {r: 255, g: 255, b: 0, a: 1},
+ {r: 255, g: 127, b: 0, a: 1} ]
+
]);
var getFontTests = [