@@ -21,15 +21,18 @@ #import "OFOnce.h" #import "OFString.h" #import "OFInvalidArgumentException.h" -@interface OFColor () -+ (instancetype)of_alloc; +@interface OFConcreteColor: OFColor +{ + float _red, _green, _blue, _alpha; + OF_RESERVE_IVARS(OFColor, 4) +} @end -@interface OFColorSingleton: OFColor +@interface OFColorSingleton: OFConcreteColor @end @interface OFColorPlaceholder: OFColorSingleton @end @@ -46,31 +49,10 @@ #ifdef OF_OBJFW_RUNTIME static int colorTag; #endif -@implementation OFColorSingleton -- (instancetype)autorelease -{ - return self; -} - -- (instancetype)retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} -@end - @implementation OFColorPlaceholder - (instancetype)initWithRed: (float)red green: (float)green blue: (float)blue alpha: (float)alpha @@ -90,14 +72,76 @@ if (ret != nil) return ret; } #endif - return (id)[[OFColor of_alloc] initWithRed: red - green: green - blue: blue - alpha: alpha]; + return (id)[[OFConcreteColor alloc] initWithRed: red + green: green + blue: blue + alpha: alpha]; +} +@end + +@implementation OFColorSingleton +- (instancetype)autorelease +{ + return self; +} + +- (instancetype)retain +{ + return self; +} + +- (void)release +{ +} + +- (unsigned int)retainCount +{ + return OFMaxRetainCount; +} +@end + +@implementation OFConcreteColor +- (instancetype)initWithRed: (float)red + green: (float)green + blue: (float)blue + alpha: (float)alpha +{ + self = [super init]; + + @try { + if (red < 0.0 || red > 1.0 || + green < 0.0 || green > 1.0 || + blue < 0.0 || blue > 1.0 || + alpha < 0.0 || alpha > 1.0) + @throw [OFInvalidArgumentException exception]; + + _red = red; + _green = green; + _blue = blue; + _alpha = alpha; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)getRed: (float *)red + green: (float *)green + blue: (float *)blue + alpha: (float *)alpha +{ + *red = _red; + *green = _green; + *blue = _blue; + + if (alpha != NULL) + *alpha = _alpha; } @end #ifdef OF_OBJFW_RUNTIME @implementation OFTaggedPointerColor @@ -129,15 +173,10 @@ colorTag = objc_registerTaggedPointerClass([OFTaggedPointerColor class]); #endif } -+ (instancetype)of_alloc -{ - return [super alloc]; -} - + (instancetype)alloc { if (self == [OFColor class]) return (id)&placeholder; @@ -196,75 +235,78 @@ - (instancetype)initWithRed: (float)red green: (float)green blue: (float)blue alpha: (float)alpha { - self = [super init]; - - @try { - if (red < 0.0 || red > 1.0 || - green < 0.0 || green > 1.0 || - blue < 0.0 || blue > 1.0 || - alpha < 0.0 || alpha > 1.0) - @throw [OFInvalidArgumentException exception]; - - _red = red; - _green = green; - _blue = blue; - _alpha = alpha; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; + if ([self isMemberOfClass: [OFColor class]]) { + @try { + [self doesNotRecognizeSelector: _cmd]; + } @catch (id e) { + [self release]; + @throw e; + } + + abort(); + } + + return [super init]; } - (bool)isEqual: (id)object { OFColor *other; + float red, green, blue, alpha; + float otherRed, otherGreen, otherBlue, otherAlpha; if (object == self) return true; if (![object isKindOfClass: [OFColor class]]) return false; other = object; - - if (other->_red != _red) - return false; - if (other->_green != _green) - return false; - if (other->_blue != _blue) - return false; - if (other->_alpha != _alpha) + [self getRed: &red green: &green blue: &blue alpha: &alpha]; + [other getRed: &otherRed + green: &otherGreen + blue: &otherBlue + alpha: &otherAlpha]; + + if (otherRed != red) + return false; + if (otherGreen != green) + return false; + if (otherBlue != blue) + return false; + if (otherAlpha != alpha) return false; return true; } - (unsigned long)hash { + float red, green, blue, alpha; unsigned long hash; float tmp; + [self getRed: &red green: &green blue: &blue alpha: &alpha]; + OFHashInit(&hash); - tmp = OFToLittleEndianFloat(_red); + tmp = OFToLittleEndianFloat(red); + for (uint_fast8_t i = 0; i < sizeof(float); i++) + OFHashAddByte(&hash, ((char *)&tmp)[i]); + + tmp = OFToLittleEndianFloat(green); for (uint_fast8_t i = 0; i < sizeof(float); i++) OFHashAddByte(&hash, ((char *)&tmp)[i]); - tmp = OFToLittleEndianFloat(_green); + tmp = OFToLittleEndianFloat(blue); for (uint_fast8_t i = 0; i < sizeof(float); i++) OFHashAddByte(&hash, ((char *)&tmp)[i]); - tmp = OFToLittleEndianFloat(_blue); - for (uint_fast8_t i = 0; i < sizeof(float); i++) - OFHashAddByte(&hash, ((char *)&tmp)[i]); - - tmp = OFToLittleEndianFloat(_alpha); + tmp = OFToLittleEndianFloat(alpha); for (uint_fast8_t i = 0; i < sizeof(float); i++) OFHashAddByte(&hash, ((char *)&tmp)[i]); OFHashFinalize(&hash); @@ -274,16 +316,11 @@ - (void)getRed: (float *)red green: (float *)green blue: (float *)blue alpha: (float *)alpha { - *red = _red; - *green = _green; - *blue = _blue; - - if (alpha != NULL) - *alpha = _alpha; + OF_UNRECOGNIZED_SELECTOR } - (OFString *)description { float red, green, blue, alpha;