Blob Blame Raw
#ifndef COLOR_H
#define COLOR_H


#include "real.h"


typedef Real ColorReal;


class Color {
public:
	union {
		struct { ColorReal channels[4]; };
		struct { ColorReal r, g, b, a; };
	};

	Color(): r(), g(), b(), a() { }

	explicit Color(
		const ColorReal r,
		const ColorReal g,
		const ColorReal b,
		const ColorReal a = 1
	):
		r(r), g(g), b(b), a(a) { }

	const Real& operator[] (int i) const { return channels[i]; }
	Real& operator[] (int i) { return channels[i]; }

	bool operator< (const Color &c) const {
		return less(r, c.r) ? true : less(c.r, r) ? false
			 : less(g, c.g) ? true : less(c.g, g) ? false
			 : less(b, c.b) ? true : less(c.b, b) ? false
			 : less(a, c.a);
	}
	bool operator== (const Color &c) const { return equal(r, c.r) && equal(g, c.g) && equal(b, c.b) && equal(a, c.a); }
	bool operator!= (const Color &c) const { return !(*this == c); }

	bool istransparent() const { return *this == Color(); }
	void reset() { *this = Color(); }
	
	Color withalpha(const ColorReal &a) const { return Color(r, g, b, a); }
	Color mulalpha(const ColorReal &a = 0.5) const { return Color(r, g, b, this->a*a); }

	Color blend(const Color &c, const ColorReal &value = 1) const {
		ColorReal asrc = c.a*value;
		ColorReal adst = a*(1 - asrc);
		ColorReal ares = asrc + adst;

		if (lesseq(ares, 0))
			return Color();

		ColorReal k = 1/ares;
		return Color(
			(r*asrc + c.r*adst)*k,
			(g*asrc + c.g*adst)*k,
			(b*asrc + c.b*adst)*k,
			ares );
	}

	Color mergecolor(const Color &c, const ColorReal &value = 0.5) const {
		ColorReal v = 1 - value;
		return Color(
			r*v + c.r*value,
			g*v + c.g*value,
			b*v + c.b*value,
			a );
	}

	Color merge(const Color &c, const ColorReal &value = 0.5) const
		{ return mergecolor(c, value).withalpha(a*(1 - value) + c.a*value); }
	
	static Color transparent() { return Color(); }
	static Color black()       { return Color(0, 0, 0); }
	static Color white()       { return Color(1, 1, 1); }
	static Color red()         { return Color(1, 0, 0); }
	static Color green()       { return Color(0, 1, 0); }
	static Color blue()        { return Color(0, 0, 1); }
	static Color yellow()      { return Color(1, 1, 0); }
	static Color cyan()        { return Color(0, 1, 1); }
	static Color magenta()     { return Color(1, 0, 1); }
	
	static Color gray(const ColorReal &value = 0.5) { return Color(value, value, value); }
};


#endif