/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NCOLORFORMAT__
#define	__NCOLORFORMAT__


		#include "nstring/nstring.h"


namespace GS {

/// The color space for a pixel format.
enum	PixelColorSpace
{
		PixelColorSpace_NULL	= 0,
		PixelColorSpace_RGB			///< Standard RGB space.
};

/// Pixel format descriptor.
struct		PixelFormatDescription
{
		PixelColorSpace	space;
		/*!
			When working with integer values these are actual bit masks.
			However when working with real values they are byte sized offsets
			in the pixel packet to access a given component.
		*/
		uint			amask, rmask, gmask, bmask;
		uchar			bpp;
		bool			real;
};

/*!
	@short	Structure holding a picture pixel format.
	@note	This structure only works with continuous bit masks.
	@author Emmanuel Julien (ejulien@nworks.fr)
*/
struct	PixelFormat
{
		// Predefined pixel formats.
static	PixelFormatDescription	NONE;
static	PixelFormatDescription	BGRA8;
static	PixelFormatDescription	RGBA8;
static	PixelFormatDescription	ARGB8;
static	PixelFormatDescription	BGR8;
static	PixelFormatDescription	RGB8;
static	PixelFormatDescription	RGB555;
static	PixelFormatDescription	RGB565;
static	PixelFormatDescription	RGBA4444;
static	PixelFormatDescription	RGBF;
static	PixelFormatDescription	RGBAF;
static	PixelFormatDescription	YUYV;

		PixelFormatDescription	desc;

		uchar		ashift, rshift, bshift, gshift;
		uchar		acount, rcount, bcount, gcount;

		/// Get format name (only use for cosmetic purposes! This is not a reliable naming convention).
		String		GetName() const;

		/// Internal function to parse a bit mask.
		void		LoadMask(uint mask, uchar &shift, uchar &count)
		{
			shift = Memory::GetShiftCount(mask);
			count = Memory::GetBitCount(mask);
		}

		/// Compare a format descriptor to this format.
		bool		operator == (const PixelFormatDescription &fmt) const
		{
			if	(	(fmt.space != desc.space) || (fmt.bpp != desc.bpp) ||
					(fmt.amask != desc.amask) || (fmt.rmask != desc.rmask) ||
					(fmt.gmask != desc.gmask) || (fmt.bmask != desc.bmask) ||
					(fmt.real != desc.real)		)
				return false;
			return true;
		}
		/// Compare a format descriptor to this format.
		bool		operator != (const PixelFormatDescription &fmt) const
		{	return !(*this == fmt);		}

		/// Return the format bpp.
		uchar		GetBpp() const { return desc.bpp; }

		/// Is format using real or integer numbers.
		bool		IsReal() const { return desc.real; }

		/// Set the the pixel format from user provided data.
		void		Set
						(
							PixelColorSpace space = PixelColorSpace_RGB,
							uint amask = 0xff000000,
							uint rmask = 0x00ff0000,
							uint gmask = 0x0000ff00,
							uint bmask = 0x000000ff,
							uchar bpp = 32,
							bool real = false
						)
		{
			desc.amask = amask;
			desc.rmask = rmask;
			desc.gmask = gmask;
			desc.bmask = bmask;
			desc.bpp = bpp;
			desc.space = space;
			LoadMask(amask, ashift, acount);
			LoadMask(rmask, rshift, rcount);
			LoadMask(gmask, gshift, gcount);
			LoadMask(bmask, bshift, bcount);
			desc.real = real;
		}
		/// Set the the pixel format from a descriptor.
		void		Set(const PixelFormatDescription &fmt)
		{	Set(fmt.space, fmt.amask, fmt.rmask, fmt.gmask, fmt.bmask, fmt.bpp, fmt.real);	}

		/// Return a reference to the format descriptor.
		const PixelFormatDescription	&GetDesc() const { return desc; }

		/// Format a color for this color format.
		uint			Format(float r, float g, float b, float a = 1) const;

		/// Constructor.
		PixelFormat
						(
							PixelColorSpace space = PixelColorSpace_RGB,
							uint amask = 0xff000000,
							uint rmask = 0x00ff0000,
							uint gmask = 0x0000ff00,
							uint bmask = 0x000000ff,
							uchar bpp = 32,
							bool real = false
						)
		{	Set(space, amask, rmask, gmask, bmask, bpp, real);	}
		/// Constructor via a format descriptor.
		PixelFormat(const PixelFormatDescription &desc)
		{	Set(desc);	}
};

} // GS


#endif	// __NCOLORFORMAT__
