/*
* CPColor.j
* AppKit
*
* Created by Francisco Tolmasky.
* Copyright 2008, 280 North, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
import CPColor can be used to represent color
in an RGB or HSB model with an optional transparency value.
It also provides some class helper methods that returns instances of commonly used colors.
The class does not have a set: method
like NextStep based frameworks to change the color of
the current context. To change the color of the current
context, use white for the RGB components.
For the alpha component, a value of 1.0 is opaque, and 0.0 means completely transparent.
@param white a float between 0.0 and 1.0
@param alpha the alpha component between 0.0 and 1.0
@return a color initialized to the values specified
*/
+ (CPColor)colorWithCalibratedWhite:(float)white alpha:(float)alpha
{
return [[CPColor alloc] _initWithRGBA:[white, white, white, alpha]];
}
/*
Creates a new color in HSB space.
@param hue the hue value
@param saturation the saturation value
@param brightness the brightness value
@return the initialized color
*/
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness
{
if(saturation == 0.0)
return [CPColor colorWithCalibratedWhite: brightness/100.0 alpha: 1.0];
var f = hue % 60,
p = (brightness * (100 - saturation)) / 10000,
q = (brightness * (6000 - saturation * f)) / 600000,
t = (brightness * (6000 - saturation * (60 -f))) / 600000,
b = brightness / 100.0;
switch(FLOOR(hue / 60))
{
case 0: return [CPColor colorWithCalibratedRed: b green: t blue: p alpha: 1.0];
case 1: return [CPColor colorWithCalibratedRed: q green: b blue: p alpha: 1.0];
case 2: return [CPColor colorWithCalibratedRed: p green: b blue: t alpha: 1.0];
case 3: return [CPColor colorWithCalibratedRed: p green: q blue: b alpha: 1.0];
case 4: return [CPColor colorWithCalibratedRed: t green: p blue: b alpha: 1.0];
case 5: return [CPColor colorWithCalibratedRed: b green: p blue: q alpha: 1.0];
}
}
/*
Creates an RGB color from a hexadecimal string. For example,
the a string of "FFFFFF" would return a white CPColor.
"FF0000" would return a pure red, "00FF00" would return a
pure blue, and "0000FF" would return a pure green.
@param hex a 6 character long string of hex
@return an initialized RGB color
*/
+ (CPColor)colorWithHexString:(string)hex
{
return [[CPColor alloc] _initWithRGBA: hexToRGB(hex)];
}
/*
Returns a black color object. (RGBA=[0.0, 0.0, 0.0, 1.0])
*/
+ (CPColor)blackColor
{
return [[CPColor alloc] _initWithRGBA:[0.0, 0.0, 0.0, 1.0]];
}
/*
Returns a blue color object. (RGBA=[0.0, 0.0, 1.0, 1.0])
*/
+ (CPColor)blueColor
{
return [[CPColor alloc] _initWithRGBA:[0.0, 0.0, 1.0, 1.0]];
}
/*
Returns a dark gray color object. (RGBA=[0.33 ,0.33, 0.33, 1.0])
*/
+ (CPColor)darkGrayColor
{
return [CPColor colorWithCalibratedWhite:1.0 / 3.0 alpha:1.0];
}
/*
Returns a gray color object. (RGBA=[0.5, 0.5, 0.5, 1.0])
*/
+ (CPColor)grayColor
{
return [CPColor colorWithCalibratedWhite:0.5 alpha: 1.0];
}
/*
Returns a green color object. (RGBA=[0.0, 1.0, 0.0, 1.0])
*/
+ (CPColor)greenColor
{
return [[CPColor alloc] _initWithRGBA:[0.0, 1.0, 0.0, 1.0]];
}
/*
Returns a light gray color object (RGBA=[0.66, 0.66, 0.66, 1.0])
*/
+ (CPColor)lightGrayColor
{
return [CPColor colorWithCalibratedWhite:2.0 / 3.0 alpha:1.0];
}
/*
Returns a red color object (RGBA=[1.0, 0.0, 0.0, 1.0])
*/
+ (CPColor)redColor
{
return [[CPColor alloc] _initWithRGBA:[1.0, 0.0, 0.0, 1.0]];
}
/*
Returns a white color object (RGBA=[1.0, 1.0, 1.0, 1.0])
*/
+ (CPColor)whiteColor
{
return [[CPColor alloc] _initWithRGBA:[1.0, 1.0, 1.0, 1.0]];
}
/*
Returns a yellow color object (RGBA=[1.0, 1.0, 0.0, 1.0])
*/
+ (CPColor)yellowColor
{
return [[CPColor alloc] _initWithRGBA:[1.0, 1.0, 0.0, 1.0]];
}
/*
Returns a shadow looking color (RGBA=[0.0, 0.0, 0.0, 0.33])
*/
+ (CPColor)shadowColor
{
return [[CPColor alloc] _initWithRGBA:[0.0, 0.0, 0.0, 1.0 / 3.0]];
}
/*
Creates a color using a tile pattern with anImage
@param the image to tile
@return a tiled image color object
*/
+ (CPColor)colorWithPatternImage:(CPImage)anImage
{
return [[CPColor alloc] _initWithPatternImage:anImage];
}
/*
Creates a
Index Component 0 Red 1 Green 2 Blue 3 Alpha*/ - (CPArray)components { return _components; } /* Returns a new color with the same RGB as the receiver but a new alpha component. @param anAlphaComponent the alpha component for the new color @return a new color object */ - (CPColor)colorWithAlphaComponent:(float)anAlphaComponent { var components = _components.slice(); components[components.length - 1] = anAlphaComponent; return [[[self class] alloc] _initWithRGBA:components]; } /* Returns an array with the HSB values for this color. The index values are ordered as:
Index Component 0 Hue 1 Saturation 2 Brightness*/ - (CPArray)hsbComponents { var red = ROUND(_components[_redComponent] * 255.0), green = ROUND(_components[_greenComponent] * 255.0), blue = ROUND(_components[_blueComponent] * 255.0); var max = MAX(red, green, blue), min = MIN(red, green, blue), delta = max - min; var brightness = max / 255.0, saturation = (max != 0) ? delta / max : 0; var hue; if(saturation == 0) hue = 0; else { var rr = (max - red) / delta; var gr = (max - green) / delta; var br = (max - blue) / delta; if (red == max) hue = br - gr; else if (green == max) hue = 2 + rr - br; else hue = 4 + gr - rr; hue /= 6; if (hue < 0) hue++; } return [ ROUND(hue * 360.0), ROUND(saturation * 100.0), ROUND(brightness * 100.0) ]; } /* Returns the CSS representation of this color. The color will be in one of the following forms:
rgb(22,44,88)
rgba(22,44,88,0.5) // if there is an alpha
url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
*/
- (CPString)cssString
{
return _cssString;
}
/*
Returns a 6 character long hex string of this color.
*/
- (CPString)hexString
{
return rgbToHex([self redComponent], [self greenComponent], [self blueComponent])
}
@end
var CPColorComponentsKey = @"CPColorComponentsKey",
CPColorPatternImageKey = @"CPColorPatternImageKey";
@implementation CPColor (CPCoding)
/*
Initializes this color from the data archived in a coder.
@param aCoder the coder from which the color will be loaded
*/
- (id)initWithCoder:(CPCoder)aCoder
{
if ([aCoder containsValueForKey:CPColorPatternImageKey])
return [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
return [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
}
/*
Archives this color into a coder.
@param aCoder the coder into which the color will be archived.
*/
- (void)encodeWithCoder:(CPCoder)aCoder
{
if (_patternImage)
[aCoder encodeObject:_patternImage forKey:CPColorPatternImageKey];
else
[aCoder encodeObject:_components forKey:CPColorComponentsKey];
}
@end
var hexCharacters = "0123456789ABCDEF";
/*
Used for the colorWithHexString: implementation
@ignore
@class CPColor
@return an array of rgb components
*/
function hexToRGB(hex)
{
if(hex.length != 6)
return null;
hex = hex.toUpperCase();
for(var i=0; i