mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-09 12:17:13 +00:00
Merge branch 'refs/heads/slevenbits-cpcolor-hsb-fix'
This commit is contained in:
+87
-20
@@ -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:
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user