ObjFW  OFColor.m at [cbc09c6e26]

File src/OFColor.m artifact cc4d687d8e part of check-in cbc09c6e26


/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
 *               2018, 2019, 2020
 *   Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFColor.h"

#import "once.h"

#import "OFInvalidArgumentException.h"

@implementation OFColor
#define PREDEFINED_COLOR(name, r, g, b)					\
	static OFColor *name##Color = nil;				\
									\
	static void							\
	initPredefinedColor_##name(void)				\
	{								\
		name##Color = [[OFColor alloc] initWithRed: r		\
						     green: g		\
						      blue: b		\
						     alpha: 1];		\
	}								\
									\
	+ (OFColor *)name						\
	{								\
		static of_once_t onceControl = OF_ONCE_INIT;		\
		of_once(&onceControl, initPredefinedColor_##name);	\
									\
		return name##Color;					\
	}

PREDEFINED_COLOR(black,   0.00f, 0.00f, 0.00f)
PREDEFINED_COLOR(silver,  0.75f, 0.75f, 0.75f)
PREDEFINED_COLOR(grey,    0.50f, 0.50f, 0.50f)
PREDEFINED_COLOR(white,   1.00f, 1.00f, 1.00f)
PREDEFINED_COLOR(maroon,  0.50f, 0.00f, 0.00f)
PREDEFINED_COLOR(red,     1.00f, 0.00f, 0.00f)
PREDEFINED_COLOR(purple,  0.50f, 0.00f, 0.50f)
PREDEFINED_COLOR(fuchsia, 1.00f, 0.00f, 1.00f)
PREDEFINED_COLOR(green,   0.00f, 0.50f, 0.00f)
PREDEFINED_COLOR(lime,    0.00f, 1.00f, 0.00f)
PREDEFINED_COLOR(olive,   0.50f, 0.50f, 0.00f)
PREDEFINED_COLOR(yellow,  1.00f, 1.00f, 0.00f)
PREDEFINED_COLOR(navy,    0.00f, 0.00f, 0.50f)
PREDEFINED_COLOR(blue,    0.00f, 0.00f, 1.00f)
PREDEFINED_COLOR(teal,    0.00f, 0.50f, 0.50f)
PREDEFINED_COLOR(aqua,    0.00f, 1.00f, 1.00f)

+ (instancetype)colorWithRed: (float)red
		       green: (float)green
			blue: (float)blue
		       alpha: (float)alpha
{
	return [[[self alloc] initWithRed: red
				    green: green
				     blue: blue
				    alpha: alpha] autorelease];
}

- (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;
}

- (bool)isEqual: (id)object
{
	OFColor *other;

	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)
		return false;

	return true;
}

- (uint32_t)hash
{
	uint32_t hash;
	float tmp;

	OF_HASH_INIT(hash);

	tmp = OF_BSWAP_FLOAT_IF_LE(_red);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OF_HASH_ADD(hash, ((char *)&tmp)[i]);

	tmp = OF_BSWAP_FLOAT_IF_LE(_green);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OF_HASH_ADD(hash, ((char *)&tmp)[i]);

	tmp = OF_BSWAP_FLOAT_IF_LE(_blue);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OF_HASH_ADD(hash, ((char *)&tmp)[i]);

	tmp = OF_BSWAP_FLOAT_IF_LE(_alpha);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OF_HASH_ADD(hash, ((char *)&tmp)[i]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (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