Implement Color, RGBColor & GrayColor.

This commit is contained in:
Jonathan Puckey 2011-02-19 16:48:59 +01:00
parent bd5c906047
commit 66105dd4ac
3 changed files with 360 additions and 0 deletions

89
src/color/GrayColor.js Normal file
View file

@ -0,0 +1,89 @@
GrayColor = Color.extend({
beans: true,
initialize: function() {
if (arguments.length) {
var arg = arguments[0];
if (typeof arg == 'number') {
this._gray = arg;
this.alpha = arg.alpha ? arg.alpha : -1;
} else if (arg instanceof Color) {
this._gray = arg.gray;
this.alpha = arg.alpha;
}
}
},
getType: function() {
return this.alpha == -1 ? 'gray' : 'agray';
},
getComponents: function() {
return [this._gray, this._alpha];
},
/**
* A value between 0 and 1 that specifies the amount of red in the RGB color.
*/
getGray: function() {
return this._gray;
},
setGray: function(gray) {
this._cssString = null;
this._gray = gray;
},
/**
* Checks if the component color values of the RGBColor are the
* same as those of the supplied one.
*
* @param obj the RGBColor to compare with
* @return {@true if the RGBColor is the same}
*/
equals: function(color) {
if (color instanceof GrayColor) {
return this.gray == color.gray &&
this.alpha == color.alpha;
}
return false;
},
toString: function() {
return '{ gray: ' + this.gray
+ ((this.alpha != -1) ? ', alpha: ' + this.alpha : '')
+ ' }';
},
getCssString: function() {
if (!this._cssString) {
var component = Math.round((1 - this.gray) * 255) + ',';
this._cssString = 'rgba('
+ component + component + component
+ ((this.alpha != -1) ? this.alpha : 1)
+ ')';
}
return this._cssString;
}
}, new function() {
var fields = { beans: true };
// Using the standard NTSC conversion formula that is used for
// calculating the effective luminance of an RGB color:
// http://www.mathworks.com/support/solutions/en/data/1-1ASCU/index.html?solution=1-1ASCU
var componentWeights = {
red: 0.2989,
green: 0.5870,
blue: 0.114
};
Base.each(componentWeights, function(weight, key) {
fields['get' + key.capitalize()] = function() {
return 1 - this._gray;
};
fields['set' + key.capitalize()] = function(value) {
this._gray = this._gray * (1 - weight) + weight * (1 - value);
};
});
return fields;
});

199
src/color/RGBColor.js Normal file
View file

@ -0,0 +1,199 @@
RGBColor = Color.extend(new function() {
// TODO: convert hex codes to [r,g,b]?
var namedColors = {
lightpink: 'FFB6C1', pink: 'FFC0CB', crimson: 'DC143C',
lavenderblush: 'FFF0F5', palevioletred: 'DB7093', hotpink: 'FF69B4',
deeppink: 'FF1493', mediumvioletred: 'C71585', orchid: 'DA70D6',
thistle: 'D8BFD8', plum: 'DDA0DD', violet: 'EE82EE', fuchsia: 'FF00FF',
darkmagenta: '8B008B', purple: '800080', mediumorchid: 'BA55D3',
darkviolet: '9400D3', darkorchid: '9932CC', indigo: '4B0082',
blueviolet: '8A2BE2', mediumpurple: '9370DB', mediumslateblue: '7B68EE',
slateblue: '6A5ACD', darkslateblue: '483D8B', ghostwhite: 'F8F8FF',
lavender: 'E6E6FA', blue: '0000FF', mediumblue: '0000CD',
darkblue: '00008B', navy: '000080', midnightblue: '191970',
royalblue: '4169E1', cornflowerblue: '6495ED', lightsteelblue: 'B0C4DE',
lightslategray: '778899', slategray: '708090', dodgerblue: '1E90FF',
aliceblue: 'F0F8FF', steelblue: '4682B4', lightskyblue: '87CEFA',
skyblue: '87CEEB', deepskyblue: '00BFFF', lightblue: 'ADD8E6',
powderblue: 'B0E0E6', cadetblue: '5F9EA0', darkturquoise: '00CED1',
azure: 'F0FFFF', lightcyan: 'E0FFFF', paleturquoise: 'AFEEEE',
aqua: '00FFFF', darkcyan: '008B8B', teal: '008080', darkslategray: '2F4F4F',
mediumturquoise: '48D1CC', lightseagreen: '20B2AA', turquoise: '40E0D0',
aquamarine: '7FFFD4', mediumaquamarine: '66CDAA', mediumspringgreen: '00FA9A',
mintcream: 'F5FFFA', springgreen: '00FF7F', mediumseagreen: '3CB371',
seagreen: '2E8B57', honeydew: 'F0FFF0', darkseagreen: '8FBC8F',
palegreen: '98FB98', lightgreen: '90EE90', limegreen: '32CD32',
lime: '00FF00', forestgreen: '228B22', green: '008000', darkgreen: '006400',
lawngreen: '7CFC00', chartreuse: '7FFF00', greenyellow: 'ADFF2F',
darkolivegreen: '556B2F', yellowgreen: '9ACD32', olivedrab: '6B8E23',
ivory: 'FFFFF0', beige: 'F5F5DC', lightyellow: 'FFFFE0',
lightgoldenrodyellow: 'FAFAD2', yellow: 'FFFF00', olive: '808000',
darkkhaki: 'BDB76B', palegoldenrod: 'EEE8AA', lemonchiffon: 'FFFACD',
khaki: 'F0E68C', gold: 'FFD700', cornsilk: 'FFF8DC', goldenrod: 'DAA520',
darkgoldenrod: 'B8860B', floralwhite: 'FFFAF0', oldlace: 'FDF5E6',
wheat: 'F5DEB3', orange: 'FFA500', moccasin: 'FFE4B5', papayawhip: 'FFEFD5',
blanchedalmond: 'FFEBCD', navajowhite: 'FFDEAD', antiquewhite: 'FAEBD7',
tan: 'D2B48C', burlywood: 'DEB887', darkorange: 'FF8C00', bisque: 'FFE4C4',
linen: 'FAF0E6', peru: 'CD853F', peachpuff: 'FFDAB9', sandybrown: 'F4A460',
chocolate: 'D2691E', saddlebrown: '8B4513', seashell: 'FFF5EE',
sienna: 'A0522D', lightsalmon: 'FFA07A', coral: 'FF7F50',
orangered: 'FF4500', darksalmon: 'E9967A', tomato: 'FF6347',
salmon: 'FA8072', mistyrose: 'FFE4E1', lightcoral: 'F08080', snow: 'FFFAFA',
rosybrown: 'BC8F8F', indianred: 'CD5C5C', red: 'FF0000', brown: 'A52A2A',
firebrick: 'B22222', darkred: '8B0000', maroon: '800000', white: 'FFFFFF',
whitesmoke: 'F5F5F5', gainsboro: 'DCDCDC', lightgrey: 'D3D3D3',
silver: 'C0C0C0', darkgray: 'A9A9A9', gray: '808080', dimgray: '696969',
black: '000000'
};
function stringToComponents(string) {
return string.match(/^#[0-9a-f]{3,6}$/i)
? hexToComponents(string)
: namedToComponents(string);
};
function hexToComponents(string) {
var hex = string.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
if (hex.length >= 4) {
var rgb = [];
for (var i = 1; i < 4; i++)
rgb.push((hex[i].length == 1 ? hex[i] + hex[i] : hex[i]).toInt(16) / 255);
return rgb;
}
};
function namedToComponents(name) {
var hex = namedColors[name];
if (!hex) throw Error('The named color "' + name + '" does not exist.');
return hex && hexToComponents(hex);
};
return {
beans: true,
initialize: function() {
if (arguments.length == 1) {
var arg = arguments[0];
if (typeof arg == 'string') {
var components = stringToComponents(arg);
this._red = components[0];
this._green = components[1];
this._blue = components[2];
this.alpha = -1;
} else if (Array.isArray(arg)) {
this._red = arg[0];
this._green = arg[1];
this._blue = arg[2];
this.alpha = (arg.length > 3) ? arg[3] : -1;
} else if (arg.red !== undefined) {
this._red = arg.red;
this._blue = arg.blue;
this._green = arg.green;
this.alpha = arg.alpha ? arg.alpha : -1;
} else if (arg.gray !== undefined) {
this._red = this._green = this._blue = 1 - arg.gray;
this.alpha = arg.alpha ? arg.alpha : -1;
};
} else if (arguments.length >= 3) {
this._red = arguments[0];
this._green = arguments[1];
this._blue = arguments[2];
this.alpha = (arguments.length > 3) ? arguments[3] : -1;
}
},
getType: function() {
return this.alpha == -1 ? 'rgb' : 'argb';
},
getComponents: function() {
return [this._red, this._blue, this._green, this._alpha];
},
/**
* A value between 0 and 1 that specifies the amount of red in the RGB color.
*/
getRed: function() {
return this._red;
},
setRed: function(red) {
this._cssString = null;
this._red = red;
},
/**
* A value between 0 and 1 that specifies the amount of green in the RGB color.
*/
getGreen: function() {
return this._green;
},
setGreen: function(green) {
this._cssString = null;
this._green = green;
},
/**
* A value between 0 and 1 that specifies the amount of blue in the RGB color.
*/
getBlue: function() {
return this._blue;
},
setBlue: function(blue) {
this._cssString = null;
this._blue = blue;
},
getGray: function() {
// Using the standard NTSC conversion formula that is used for
// calculating the effective luminance of an RGB color:
// http://www.mathworks.com/support/solutions/en/data/1-1ASCU/index.html?product=IP&solution=1-1ASCU
return 1 - (this._red * 0.2989 + this._green * 0.5870
+ this._blue * 0.114);
},
setGray: function(gray) {
this._red = this._green = this._blue = gray;
},
/**
* Checks if the component color values of the RGBColor are the
* same as those of the supplied one.
*
* @param obj the RGBColor to compare with
* @return {@true if the RGBColor is the same}
*/
equals: function(color) {
if (color instanceof RGBColor) {
return this.red == color.red &&
this.green == color.green &&
this.blue == color.blue &&
this.alpha == color.alpha;
}
return false;
},
toString: function() {
return '{ red: ' + this.red
+ ', green: ' + this.green
+ ', blue: ' + this.blue
+ ((this.alpha != -1) ? ', alpha: ' + this.alpha : '')
+ ' }';
},
getCssString: function() {
if (!this._cssString) {
this._cssString = 'rgba('
+ (Math.round(this.red * 255)) + ', '
+ (Math.round(this.green * 255)) + ', '
+ (Math.round(this.blue * 255)) + ', '
+ ((this.alpha != -1) ? this.alpha : 1)
+ ')';
}
return this._cssString;
}
};
});

72
test/tests/Color.js Normal file
View file

@ -0,0 +1,72 @@
module('RGB Color');
test('Set named color', function() {
var doc = new Doc();
var path = new Path();
path.fillColor = 'red';
compareRGBColors(path.fillColor, new RGBColor(1, 0, 0));
equals(path.fillColor.getCssString(), 'rgba(255, 0, 0, 1)');
});
test('Set color to hex', function() {
var doc = new Doc();
var path = new Path();
path.fillColor = '#ff0000';
compareRGBColors(path.fillColor, new RGBColor(1, 0, 0));
equals(path.fillColor.getCssString(), 'rgba(255, 0, 0, 1)');
var path = new Path();
path.fillColor = '#f00';
compareRGBColors(path.fillColor, new RGBColor(1, 0, 0));
equals(path.fillColor.getCssString(), 'rgba(255, 0, 0, 1)');
});
test('Set color to object', function() {
var doc = new Doc();
var path = new Path();
path.fillColor = { red: 1, green: 0, blue: 1};
compareRGBColors(path.fillColor, new RGBColor(1, 0, 1));
equals(path.fillColor.getCssString(), 'rgba(255, 0, 255, 1)');
var path = new Path();
path.fillColor = { gray: 0.2 };
compareRGBColors(path.fillColor, new RGBColor(0.8, 0.8, 0.8));
equals(path.fillColor.getCssString(), 'rgba(204, 204, 204, 1)');
});
test('Set color to array', function() {
var doc = new Doc();
var path = new Path();
path.fillColor = [1, 0, 0];
compareRGBColors(path.fillColor, new RGBColor(1, 0, 0));
equals(path.fillColor.getCssString(), 'rgba(255, 0, 0, 1)');
});
test('Get gray from RGBColor', function() {
var color = new RGBColor(1, 0.5, 0.2);
compareNumbers(color.gray, 0.38458251953125);
var color = new RGBColor(0.5, 0.2, 0.1);
compareNumbers(color.gray, 0.72137451171875);
});
test('Gray Color', function() {
var color = new GrayColor(1);
compareNumbers(color.gray, 1);
compareNumbers(color.red, 1);
color.red = 0.5;
compareNumbers(color.gray, '0.84999');
color.green = 0.2;
compareNumbers(color.gray, '0.82051');
});
test('Converting Colors', function() {
var color = new RGBColor(1, 0.5, 0.2);
compareNumbers(new GrayColor(color).gray, 0.38299560546875);
var color = new GrayColor(0.2);
var rgbColor = new RGBColor(color);
compareRGBColors(rgbColor, [ 0.8, 0.8, 0.8, 1 ]);
});