/*****************************************************************************
 * $Id: gfx_rgb.hh,v 1.32 2006/08/01 23:14:02 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	RGB color definitions.
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#ifndef GFX_RGB_HH
#define GFX_RGB_HH 1

namespace gfx {

////////////////////////////////////////////////////////////////////////////////
/// RGBA class.
/// Based on uint8[4].  Can output/convert to fp[4].
class RGBA
{
public:
	RGBA( void ) { }
	explicit RGBA( const uint8 rgba[4] )
	{
		*reinterpret_cast<uint32*>( mRgba ) = *reinterpret_cast<const uint32*>( rgba );
	}
	RGBA( fp r, fp g, fp b, fp a )
	{
		Set( r, g, b, a );
	}
	explicit RGBA( const fp* rgba )
	{
		Set( rgba[0], rgba[1], rgba[2], rgba[3] );
	}
	RGBA( const RGBA& src ) // copy constructor
	{
		*reinterpret_cast<uint32*>( mRgba ) = *reinterpret_cast<const uint32*>( src.mRgba );
	}
	void Set( const uint8 rgba[4] )
	{
		*reinterpret_cast<uint32*>( mRgba ) = *reinterpret_cast<const uint32*>( rgba );
	}
	void Set( fp r, fp g, fp b, fp a )
	{
		mRgba[0] = ClampFF( uint(r * 256) );
		mRgba[1] = ClampFF( uint(g * 256) );
		mRgba[2] = ClampFF( uint(b * 256) );
		mRgba[3] = ClampFF( uint(a * 256) );
	}
	const uint8* Get( void ) const
	{
		return mRgba;
	}
	// Return fp[4] from private uint8[4].  Slow but rarely called.
	const fp* Getfv( void ) const
	{
		static fp rgba[4];
		rgba[0] = mRgba[0] / 256.0;
		rgba[1] = mRgba[1] / 256.0;
		rgba[2] = mRgba[2] / 256.0;
		rgba[3] = mRgba[3] / 256.0;
		return rgba;
	}
	// RGBA object --> uint[4]
	void Copy( uint8 rgbaDest[4]/*OUT*/ ) const
	{
		*reinterpret_cast<uint32*>( rgbaDest ) = *reinterpret_cast<const uint32*>( mRgba );
	}
	RGBA& operator=( const RGBA& src )
	{
		*reinterpret_cast<uint32*>( mRgba ) = *reinterpret_cast<const uint32*>( src.mRgba );
		return *this;
	}
	bool operator==( const RGBA& src ) const
	{
		return *reinterpret_cast<const uint32*>( mRgba ) == *reinterpret_cast<const uint32*>( src.mRgba );
	}
	bool LessThan( const RGBA& src ) const
	{
		return *reinterpret_cast<const uint32*>( mRgba ) < *reinterpret_cast<const uint32*>( src.mRgba );
	}
	uint8& operator[]( uint i )
	{
		ASSERT2( i < 4 );
		return mRgba[i];
	}
	const uint8& operator[]( uint i ) const	// compiled when object is const
	{
		ASSERT2( i < 4 );
		return mRgba[i];
	}

private:
	uint8	mRgba[4];
};

/*****************************************************************************
 * operator<() as a function (for STL).
 * FYI: operator<() as a class method doesn't work with STL.
 *****************************************************************************/
static inline bool
operator<( const RGBA src1, const RGBA src2 )
{
	// Call class method which can access private members.
	return src1.LessThan( src2 );
}

/*****************************************************************************
 * operator<<()
 *****************************************************************************/
static inline ostream&
operator<<( ostream& strm, const RGBA rgba )
{
	ios::fmtflags savedFlags = strm.flags();
    strm << '('
         << GFX_OMANIP_FIELD(4) << uint(rgba[0]) << ','  // print numbers, not chars
         << GFX_OMANIP_FIELD(4) << uint(rgba[1]) << ','  // (uint8 is uchar)
         << GFX_OMANIP_FIELD(4) << uint(rgba[2]) << ','
         << GFX_OMANIP_FIELD(4) << uint(rgba[3]) << ')';
	strm.flags(savedFlags);
	return strm;
}

#define RGB_BROWN		0.7,	0.35,	0.2
#define RGB_GRAY		0.55,	0.55,	0.55
#define RGB_GREEN		0.05,	0.9,	0.05
#define RGB_DARK_GREEN	0.05,	0.5,	0.05
#define RGB_DARK_GREEN2	0.05,	0.45,	0.05
#define RGB_PURPLE		0.6,	0.1,	0.6
#define RGB_RED			0.8,	0.1,	0.1
#define RGB_BLUE		0.1,	0.1,	0.8
#define RGB_SKYBLUE		0.2,	0.6,	0.99
#define RGB_SHADOW		0.35,	0.35,	0.35
#define RGB_WHITE		0.95,	0.95,	0.95
#define RGB_YELLOW		1.0,    1.0,    0.0

} // namespace gfx

#endif // GFX_RGB_HH
