/*
	Twilight Prophecy 3D/Multimedia SDK
	A multi-platform development system for virtual reality and multimedia.

	Copyright (C) 1997-2001 by Twilight 3D Finland Oy Ltd.
*/
#ifndef PRCORE_COLOR32_HPP
#define PRCORE_COLOR32_HPP



namespace prcore
{

	struct Color32
	{
		// members
		#ifdef PRCORE_LITTLE_ENDIAN
		uint8	b, g, r, a;
		#else
		uint8	a, r, g, b;
		#endif
		
		// constructors
inline	Color32() {}
inline	Color32(uint32 color);
inline	Color32(const Color32& color);
inline	Color32(uint8 r, uint8 g, uint8 b, uint8 a=0xff);

		// operators
inline	Color32			operator +  () const;
inline	Color32			operator -  () const;
inline	Color32			operator +  (const Color32& other) const;
inline	Color32			operator *  (const Color32& other) const;
inline	Color32			operator *	(const uint8 scale) const;
inline	void			operator =  (const uint32 color);
inline	void			operator =  (const Color32& other);
inline	bool			operator == (const Color32& other) const;
inline	bool			operator != (const Color32& other) const;
inline					operator uint32 () const;
	};


inline Color32::Color32(uint32 color)
{
	*this = color;
}

inline Color32::Color32(const Color32& color)
{
	*this = color;
}

inline Color32::Color32(uint8 red, uint8 green, uint8 blue, uint8 alpha)
{
	b = blue;
	g = green;
	r = red;
	a = alpha;
}

inline Color32 Color32::operator + () const
{
	return *this;
}

inline Color32 Color32::operator - () const
{
	const uint32& u = *this;
	return Color32( u ^ 0xffffffff );
}

inline Color32 Color32::operator + (const Color32& color) const
{
	// rgb components are saturated, a wraps around
	const uint32& u1 = *this;
	const uint32& u2 = color;
	uint32 x = (u1 & 0xfefefefe) + (u2 & 0xfefefefe);
	return Color32(x | ((x & 0x01010101) - ((x & 0x01010101) >> 8)));
}

inline Color32 Color32::operator * (const Color32& color) const
{
	return Color32(
		uint8((r * color.r) >> 8),
		uint8((g * color.g) >> 8),
		uint8((b * color.b) >> 8),
		uint8((a * color.a) >> 8) );
}

inline Color32 Color32::operator * (const uint8 scale) const
{
	const uint32& u = *this;
	uint32 lsb = (((u & 0x00ff00ff) * scale) >> 8) & 0x00ff00ff;
	uint32 msb = (((u & 0xff00ff00) >> 8) * scale) & 0xff00ff00;
	lsb |= msb;
	return (Color32&)lsb;
}

inline void Color32::operator = (const uint32 color)
{
	*(uint32*)this = color;
}

inline void Color32::operator = (const Color32& color)
{
	*(uint32*)this = (uint32&)color;
}

inline bool Color32::operator == (const Color32& color) const
{
	return (uint32&)*this == (uint32&)color;
}

inline bool Color32::operator != (const Color32& color) const
{
	return (uint32&)*this != (uint32&)color;
}

inline Color32::operator uint32 () const
{
	return (uint32&)*this;
}

inline Color32 Lerp(const Color32& c0, const Color32& c1, uint32 scale)
{
	const uint32& u0 = c0;
	const uint32& u1 = c1;
	uint32 vx = u0 & 0x00ff00ff;
	uint32 rb = vx + ((((u1 & 0x00ff00ff) - vx) * scale) >> 8) & 0x00ff00ff;
	vx = u0 & 0xff00ff00;
	return Color32( rb | (vx + ((((u1 >> 8) & 0x00ff00ff) - (vx >> 8)) * scale) & 0xff00ff00) );
}
	
} // namespace prcore



#endif