Merge branch 'refs/heads/slevenbits-cpcolor-hsb-fix'

This commit is contained in:
Alexander Ljungberg
2013-04-21 15:03:53 +01:00
4 changed files with 134 additions and 37 deletions
+87 -20
View File
@@ -156,11 +156,15 @@ var cachedBlackColor,
}
/*!
Creates a new color in HSB space.
Creates a new color based on the given HSB components.
@param hue the hue value
@param saturation the saturation value
@param brightness the brightness value
Note: earlier versions of this method took a hue component as degrees between 0-360,
and saturation and brightness components as percent between 0-100. This method has
now been corrected to take all components in the 0-1 range as in Cocoa.
@param hue the hue component (0.0-1.0)
@param saturation the saturation component (0.0-1.0)
@param brightness the brightness component (0.0-1.0)
@return the initialized color
*/
@@ -169,25 +173,61 @@ var cachedBlackColor,
return [self colorWithHue:hue saturation:saturation brightness:brightness alpha:1.0];
}
/*!
Calibrated colors are not supported in Cappuccino.
This method has the same result as [CPColor colorWithHue:saturation:brightness:alpha:].
*/
+ (CPColor)colorWithCalibratedHue:(float)hue saturation:(float)saturation brightness:(float)brightness alpha:(float)alpha
{
return [self colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha];
}
/*!
Creates a new color based on the given HSB components.
Note: earlier versions of this method took a hue component as degrees between 0-360,
and saturation and brightness components as percent between 0-100. This method has
now been corrected to take all components in the 0-1 range as in Cocoa.
@param hue the hue component (0.0-1.0)
@param saturation the saturation component (0.0-1.0)
@param brightness the brightness component (0.0-1.0)
@param alpha the opacity component (0.0-1.0)
@return the initialized color
*/
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness alpha:(float)alpha
{
// Clamp values.
hue = MAX(MIN(hue, 1.0), 0.0);
saturation = MAX(MIN(saturation, 1.0), 0.0);
brightness = MAX(MIN(brightness, 1.0), 0.0);
if (saturation === 0.0)
return [CPColor colorWithCalibratedWhite:brightness / 100.0 alpha:alpha];
return [CPColor colorWithCalibratedWhite:brightness alpha:alpha];
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;
var f = (hue * 360) % 60,
p = (brightness * (1 - saturation)),
q = (brightness * (60 - saturation * f)) / 60,
t = (brightness * (60 - saturation * (60 - f))) / 60,
b = brightness;
switch (FLOOR(hue / 60))
switch (FLOOR(hue * 6))
{
case 0: return [CPColor colorWithCalibratedRed:b green:t blue:p alpha:alpha];
case 1: return [CPColor colorWithCalibratedRed:q green:b blue:p alpha:alpha];
case 2: return [CPColor colorWithCalibratedRed:p green:b blue:t alpha:alpha];
case 3: return [CPColor colorWithCalibratedRed:p green:q blue:b alpha:alpha];
case 4: return [CPColor colorWithCalibratedRed:t green:p blue:b alpha:alpha];
case 5: return [CPColor colorWithCalibratedRed:b green:p blue:q alpha:alpha];
case 0:
case 6:
return [CPColor colorWithCalibratedRed:b green:t blue:p alpha:alpha];
case 1:
return [CPColor colorWithCalibratedRed:q green:b blue:p alpha:alpha];
case 2:
return [CPColor colorWithCalibratedRed:p green:b blue:t alpha:alpha];
case 3:
return [CPColor colorWithCalibratedRed:p green:q blue:b alpha:alpha];
case 4:
return [CPColor colorWithCalibratedRed:t green:p blue:b alpha:alpha];
case 5:
return [CPColor colorWithCalibratedRed:b green:p blue:q alpha:alpha];
}
}
@@ -575,6 +615,9 @@ var cachedBlackColor,
/*!
Returns an array with the HSB values for this color.
The values are expressed as fractions between 0.0-1.0.
The index values are ordered as:
<pre>
<b>Index</b> <b>Component</b>
@@ -621,12 +664,36 @@ var cachedBlackColor,
}
return [
ROUND(hue * 360.0),
ROUND(saturation * 100.0),
ROUND(brightness * 100.0)
hue,
saturation,
brightness
];
}
/*!
Returns the hue component, the H in HSB, of the receiver.
*/
- (float)hueComponent
{
return [self hsbComponents][0];
}
/*!
Returns the saturation component, the S in HSB, of the receiver.
*/
- (float)saturationComponent
{
return [self hsbComponents][1];
}
/*!
Returns the brightness component, the B in HSB, of the receiver.
*/
- (float)brightnessComponent
{
return [self hsbComponents][2];
}
/*!
Returns the CSS representation of this color. The color will
be in one of the following forms:
+7 -7
View File
@@ -158,12 +158,12 @@
brightness = [_brightnessSlider floatValue];
[_hueSaturationView setWheelBrightness:brightness / 100.0];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hue saturation:saturation brightness:100]];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hue / 360.0 saturation:saturation / 100.0 brightness:1]];
var colorPanel = [self colorPanel],
opacity = [colorPanel opacity];
_cachedColor = [CPColor colorWithHue:hue saturation:saturation brightness:brightness alpha:opacity];
_cachedColor = [CPColor colorWithHue:hue / 360.0 saturation:saturation / 100.0 brightness:brightness / 100.0 alpha:opacity];
[[self colorPanel] setColor:_cachedColor];
}
@@ -194,10 +194,10 @@
var hsb = [newColor hsbComponents];
[_hueSaturationView setPositionToColor:newColor];
[_brightnessSlider setFloatValue:hsb[2]];
[_hueSaturationView setWheelBrightness:hsb[2] / 100.0];
[_brightnessSlider setFloatValue:hsb[2] * 100.0];
[_hueSaturationView setWheelBrightness:hsb[2]];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hsb[0] saturation:hsb[1] brightness:100]];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hsb[0] saturation:hsb[1] brightness:1]];
}
- (CPImage)provideNewButtonImage
@@ -366,8 +366,8 @@
{
var hsb = [aColor hsbComponents],
bounds = [self bounds],
angle = [self degreesToRadians:hsb[0]],
distance = (hsb[1] / 100.0) * _radius;
angle = [self degreesToRadians:hsb[0] * 360.0],
distance = hsb[1] * _radius;
[self setAngle:angle distance:distance];
}
+12 -9
View File
@@ -146,7 +146,7 @@
[_hueLabel setTextColor:[CPColor blackColor]];
_hueSlider = [[CPSlider alloc] initWithFrame:CGRectMake(15, 143, aFrame.size.width - 70, 20)];
[_hueSlider setMaxValue:359.0];
[_hueSlider setMaxValue:0.999];
[_hueSlider setMinValue:0.0];
[_hueSlider setTarget:self];
[_hueSlider setAction:@selector(sliderChanged:)];
@@ -165,7 +165,7 @@
[_saturationLabel setTextColor:[CPColor blackColor]];
_saturationSlider = [[CPSlider alloc] initWithFrame:CGRectMake(15, 168, aFrame.size.width - 70, 20)];
[_saturationSlider setMaxValue:100.0];
[_saturationSlider setMaxValue:1.0];
[_saturationSlider setMinValue:0.0];
[_saturationSlider setTarget:self];
[_saturationSlider setAction:@selector(sliderChanged:)];
@@ -184,7 +184,7 @@
[_brightnessLabel setTextColor:[CPColor blackColor]];
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(15, 194, aFrame.size.width - 70, 20)];
[_brightnessSlider setMaxValue:100.0];
[_brightnessSlider setMaxValue:1.0];
[_brightnessSlider setMinValue:0.0];
[_brightnessSlider setTarget:self];
[_brightnessSlider setAction:@selector(sliderChanged:)];
@@ -282,6 +282,9 @@
- (void)setColor:(CPColor)aColor
{
if (!aColor)
[CPException raise:CPInvalidArgumentException reason:"aColor can't be nil"];
[self updateRGBSliders:aColor];
[self updateHSBSliders:aColor];
[self updateHex:aColor];
@@ -313,9 +316,9 @@
- (void)updateLabels
{
[_hueValue setStringValue:ROUND([_hueSlider floatValue])];
[_saturationValue setStringValue:ROUND([_saturationSlider floatValue])];
[_brightnessValue setStringValue:ROUND([_brightnessSlider floatValue])];
[_hueValue setStringValue:ROUND([_hueSlider floatValue] * 360.0)];
[_saturationValue setStringValue:ROUND([_saturationSlider floatValue] * 100.0)];
[_brightnessValue setStringValue:ROUND([_brightnessSlider floatValue] * 100.0)];
[_redValue setStringValue:ROUND([_redSlider floatValue] * 255)];
[_greenValue setStringValue:ROUND([_greenSlider floatValue] * 255)];
@@ -363,15 +366,15 @@
[self sliderChanged:_blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360), 0)];
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360) / 360.0, 0)];
[self sliderChanged:_hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100) / 100.0, 0)];
[self sliderChanged:_saturationSlider];
break;
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100) / 100.0, 0)];
[self sliderChanged:_brightnessSlider];
break;
}
+28 -1
View File
@@ -8,7 +8,7 @@
{
var colors = ['000000', '0099CC', '7E8EAB', 'FFFFFF'];
for (var i = 0; i < colors.length; ++i)
[self assert: colors[i] equals: [[CPColor colorWithHexString: colors[i]] hexString]];
[self assert:colors[i] equals:[[CPColor colorWithHexString:colors[i]] hexString]];
}
- (void)testColorWithCSSString
@@ -21,6 +21,33 @@
[self assert:128 equals:ROUND([rgbaColour alphaComponent] * 255) message:"alpha component"];
}
- (void)testColorWithHue_saturation_brightness_
{
var tests = [
[[0, 0, 0], [0, 0, 0]],
[[0, 0, 1], [1, 1, 1]],
[[0, 1, 1], [1, 0, 0]],
[[0.75, 1, 1], [0.5, 0, 1]],
[[0.5, 0.5, 0.5], [0.25, 0.5, 0.5]],
[[0.9, 0.8, 0.7], [0.7, 0.14, 0.476]]
];
for (var i = 0; i < tests.length; i++)
{
var test = tests[i],
input = test[0],
expected = test[1],
c = [CPColor colorWithCalibratedHue:input[0] saturation:input[1] brightness:input[2] alpha:0.5];
[self assert:expected equals:[Math.round([c redComponent] * 1000) / 1000, Math.round([c greenComponent] * 1000) / 1000, Math.round([c blueComponent] * 1000) / 1000] message:@"hue: " + input[0] + " saturation: " + input[1] + " brightness: " + input[2]];
}
var hsb = [[CPColor colorWithHue:0.9 saturation:0.8 brightness:0.7] hsbComponents];
[self assert:[0.9, 0.8, 0.7] equals:[Math.round(hsb[0] * 10) / 10, Math.round(hsb[1] * 10) / 10, Math.round(hsb[2] * 10) / 10]];
hsb = [[CPColor colorWithHue:0.999 saturation:0.8 brightness:0.7] hsbComponents];
[self assert:[0.999, 0.8, 0.7] equals:[Math.round(hsb[0] * 1000) / 1000, Math.round(hsb[1] * 10) / 10, Math.round(hsb[2] * 10) / 10]];
}
- (void)testIsEqual_
{
// Based on https://gist.github.com/e06f749362cb1166439f by spakanati.