/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2002/X/X - 2013/08/17
/// 
/// @brief  基本的なカラー定義
/// 
/// ****************************************************************************

#pragma once

#include "CPL_Core_Define.h"

namespace CPL {
namespace Core {
namespace Color {


// _____________________________________________________________________________
/// @brief 16bit color
///
/// r:5bit  g:5bit  b:5bit\n
/// ※ 各色の取得は8bit値に補正されて返る
///
// *****************************************************************************
union R5G5B5 {
protected:
  struct{
    U16 b : 5;
    U16 g : 5;
    U16 r : 5;
    U16 dummy : 1;
  }c15;
  U16  color;

public:
  U8    GetR() const { return static_cast<U8>((c15.r << 3) + (c15.r >> 2)); }
  U8    GetG() const { return static_cast<U8>((c15.g << 3) + (c15.g >> 2)); }
  U8    GetB() const { return static_cast<U8>((c15.b << 3) + (c15.b >> 2)); }
  U16   GetColor() const { return color; }
  U16   GetColorR5G6B5() const { return ((U16)c15.r<<11) + ((U16)c15.g<<6) + (U16)c15.b; }
  U32   GetColorR8G8B8() const { return ((U32)GetR()<<16) + ((U32)GetG()<<8) + ((U32)GetB()); }
  U32   GetColorA8R8G8B8() const { return 0xff000000 + ((U32)GetR()<<16) + ((U32)GetG()<<8) + ((U32)GetB()); }
  U32   GetColorA4R4G4B4() const { return 0xf000 + ((U32)GetR()<<8) + ((U32)GetG()<<4) + ((U32)GetB()); }
  void  SetR( U8 red   ){ c15.r = red   >> 3; }
  void  SetG( U8 green ){ c15.g = green >> 3; }
  void  SetB( U8 blue  ){ c15.b = blue  >> 3; }
  void  SetColor( U16 Color ){ color = Color; }

  operator U16(){ return color; }
//  bool operator ==( R5G5B5 rgb ){ return( color == rgb.color ); }

  R5G5B5(){ color = 0; }
  R5G5B5( R5G5B5& c ){ *this = c; }
  R5G5B5( U16 Color ){ color = Color; }
  R5G5B5( U8 r, U8 g, U8 b ){ SetR(r); SetG(g); SetB(b); }
  
  U32 GetColorRef(){
    return (U32)GetR() + (((U32)GetG())<<8) + (((U32)GetB())<<16);
  }
};


// _____________________________________________________________________________
/// @brief 16bit color
///
/// r:5bit  g:6bit  b:5bit
///
// *****************************************************************************
union R5G6B5 {
protected:
  struct{
    U16 b : 5;
    U16 g : 6;
    U16 r : 5;
  } c16;
  U16  color;

public:
  U8    GetR() const { return static_cast<U8>((c16.r << 3) + (c16.r >> 2)); }
  U8    GetG() const { return static_cast<U8>((c16.g << 2) + (c16.g >> 4)); }
  U8    GetB() const { return static_cast<U8>((c16.b << 3) + (c16.b >> 2)); }
  U16   GetColor() const { return color; }
  U16   GetColorR5G6B5() const { return R5G5B5(GetR(),GetG(),GetB()); }
  U32   GetColorR8G8B8() const { return ((U32)GetR()<<16) + ((U32)GetG()<<8) + ((U32)GetB()); }
  U32   GetColorA8R8G8B8() const { return 0xff000000 + ((U32)GetR()<<16) + ((U32)GetG()<<8) + ((U32)GetB()); }
  U32   GetColorA4R4G4B4() const { return 0xf000 + ((U32)GetR()<<8) + ((U32)GetG()<<4) + ((U32)GetB()); }
  void  SetR( U8 red   ){ c16.r = red>>3; }
  void  SetG( U8 green ){ c16.g = green>>2; }
  void  SetB( U8 blue  ){ c16.b = blue>>3; }
  void  SetColor( U16 Color ){ color = Color; }

  operator U16(){ return color; }
//  bool operator ==( R5G6B5 rgb ){ return( color == rgb.color ); }

  R5G6B5(){ color = 0; }
  R5G6B5( R5G6B5& c ){ *this = c; }
  R5G6B5( U16 Color ){ color = Color; }
  R5G6B5( U8 r, U8 g, U8 b ){ SetR(r); SetG(g); SetB(b); }
  
  U32 GetColorRef(){
    return (U32)GetR() + (((U32)GetG())<<8) + (((U32)GetB())<<16);
  }
};




// _____________________________________________________________________________
/// @brief 16bit color
///
/// a:4bit r:4bit  g:4bit  b:4bit
///
// *****************************************************************************
union A4R4G4B4 {
protected:
  struct{
    U16 b : 4;
    U16 g : 4;
    U16 r : 4;
    U16 a : 4;
  } c16;
  U16  color;

public:
  U8    GetA() const { return static_cast<U8>(c16.a * 17); }
  U8    GetR() const { return static_cast<U8>(c16.r * 17); }
  U8    GetG() const { return static_cast<U8>(c16.g * 17); }
  U8    GetB() const { return static_cast<U8>(c16.b * 17); }
  U16   GetColor() const { return color; }
  U16   GetColorR5G5B5() const { return R5G5B5(GetR(),GetG(),GetB()); }
  U16   GetColorR5G6B5() const { return R5G6B5(GetR(),GetG(),GetB()); }
  U32   GetColorR8G8B8() const { return ((U32)GetR()<<16) + ((U32)GetG()<<8) + ((U32)GetB()); }
  U32   GetColorA8R8G8B8() const { return 0xff000000 + ((U32)GetR()<<16) + ((U32)GetG()<<8) + ((U32)GetB()); }
  void  SetA( U8 alpha ){ c16.a = alpha >> 4; }
  void  SetR( U8 red   ){ c16.r = red   >> 4; }
  void  SetG( U8 green ){ c16.g = green >> 4; }
  void  SetB( U8 blue  ){ c16.b = blue  >> 4; }
  void  SetColor( U16 Color ){ color = Color; }

  operator U16(){ return color; }
//  bool operator ==( A4R4G4B4 rgb ){ return( color == rgb.color ); }

  A4R4G4B4(){ color = 0; }
  A4R4G4B4( A4R4G4B4& c ){ *this = c; }
  A4R4G4B4( short Color ){ color = Color; }
  A4R4G4B4( U8 a, U8 r, U8 g, U8 b ){ SetA(a); SetR(r); SetG(g); SetB(b); }
  
  U32 GetColorRef(){
    return (U32)GetR() + (((U32)GetG())<<8) + (((U32)GetB())<<16);
  }
};


// _____________________________________________________________________________
/// @brief 24bit color
///
/// メモリ配置は、BGRとなる。
///
// *****************************************************************************
union R8G8B8 {
protected:
  U8 m_clr_elm[3];
  unsigned m_color : 24;
  struct {
    U8 m_B, m_G, m_R;
  };

public:
  U8    GetR() const { return m_R; }
  U8    GetG() const { return m_G; }
  U8    GetB() const { return m_B; }
  U32   GetColor() const { return (U32)m_color; }
  U16   GetColorR5G5B5() const { return R5G5B5(m_R,m_G,m_B).GetColor(); }
  U16   GetColorR5G6B5() const { return R5G6B5(m_R,m_G,m_B).GetColor(); }
  U16   GetColorA4R4G4B4() const { return A4R4G4B4(255,m_R,m_G,m_B).GetColor(); }
  void  SetR( U8 red   ){ m_R = red;   }
  void  SetG( U8 green ){ m_G = green; }
  void  SetB( U8 blue  ){ m_B = blue;  }
  void  SetColor(U32 color_){ m_color = color_; }

  operator U32() const { return (U32)m_color; }
//  bool operator ==( R8G8B8 rgb ){ return (m_color == rgb.m_color); }

  R8G8B8(){ m_color = 0; }
  R8G8B8( R8G8B8 const& color_rgb ){ *this = color_rgb; }
  R8G8B8( U32 color_ ){ m_color = color_; }
  R8G8B8( U8 r, U8 g, U8 b ){ m_R = r; m_G = g; m_B = b; }

  U32 GetColorRef() const
  {
    return (U32)m_R + (((U32)m_G)<<8) + (((U32)m_B)<<16);
  }
};


// _____________________________________________________________________________
/// @brief 32bit ARGB color
/// 
/// メモリ配置は、BGRAとなる。
///
// *****************************************************************************
union A8R8G8B8 {
protected:
  U8  m_clr_elm[4];
  U32 m_color32;
  struct {
    U8 m_B, m_G, m_R, m_A;
  };

public:
  U8    GetA() const { return m_A; }
  U8    GetR() const { return m_R; }
  U8    GetG() const { return m_G; }
  U8    GetB() const { return m_B; }
  U32   GetColor() const { return m_color32; }
  U32   GetColorR8G8B8() const { return R8G8B8(m_R,m_G,m_B).GetColor(); }
  U16   GetColorR5G5B5() const { return R5G5B5(m_R,m_G,m_B).GetColor(); }
  U16   GetColorR5G6B5() const { return R5G6B5(m_R,m_G,m_B).GetColor(); }
  U16   GetColorA4R4G4B4() const { return A4R4G4B4(m_A,m_R,m_G,m_B).GetColor(); }
  void  SetA( U8 alpha ){ m_A = alpha; }
  void  SetR( U8 red   ){ m_R = red;   }
  void  SetG( U8 green ){ m_G = green; }
  void  SetB( U8 blue  ){ m_B = blue;  }
  void  SetColor( U32 color_ ){ m_color32 = color_; }
  void  SetColor( U8 a_, U8 r_, U8 g_, U8 b_ ){ m_A = a_; m_R = r_; m_G = g_; m_B = b_; }

  operator U32() const { return m_color32; }
//  bool operator ==( A8R8G8B8 rgb ){ return( m_color32 == rgb.m_color32 ); }

  A8R8G8B8(){ m_color32 = 0; }
  A8R8G8B8( A8R8G8B8 const& color_argb ){ *this = color_argb; }
  A8R8G8B8( U32 color_ ){ m_color32 = color_; }
  A8R8G8B8( U8 a, U8 r, U8 g, U8 b ){ SetColor(a,r,g,b); }

  U32 GetColorRef() const
  {
    return (U32)m_R + (((U32)m_G)<<8) + (((U32)m_B)<<16);
  }
};

// _____________________________________________________________________________
/// @brief 32bit rgba color
/// 
/// メモリ配置はRGBAとなる。\
/// 標準？と逆の並び表現として、クラス名を各要素を小文字とした。
///
// *****************************************************************************
union r8g8b8a8 {
protected:
  U8  m_clr_elm[4];
  U32 m_color32;
  struct {
    U8 m_R, m_G, m_B, m_A;
  };

public:
  U8    GetA() const { return m_A; }
  U8    GetR() const { return m_R; }
  U8    GetG() const { return m_G; }
  U8    GetB() const { return m_B; }
  U32   GetColor() const { return m_color32; }
  U32   GetColorR8G8B8() const { return R8G8B8(m_R,m_G,m_B).GetColor(); }
  U16   GetColorR5G5B5() const { return R5G5B5(m_R,m_G,m_B).GetColor(); }
  U16   GetColorR5G6B5() const { return R5G6B5(m_R,m_G,m_B).GetColor(); }
  U16   GetColorA4R4G4B4() const { return A4R4G4B4(m_A,m_R,m_G,m_B).GetColor(); }
  void  SetA( U8 alpha ){ m_A = alpha; }
  void  SetR( U8 red   ){ m_R = red;   }
  void  SetG( U8 green ){ m_G = green; }
  void  SetB( U8 blue  ){ m_B = blue;  }
  void  SetColor( U32 color_ ){ m_color32 = color_; }
  void  SetColor( U8 a_, U8 r_, U8 g_, U8 b_ ){ m_A = a_; m_R = r_; m_G = g_; m_B = b_; }

  operator U32() const { return m_color32; }
//  bool operator ==( r8g8b8a8 rgb ){ return( m_color32 == rgb.m_color32 ); }

  r8g8b8a8(){ m_color32 = 0; }
  r8g8b8a8( r8g8b8a8 const& color_argb ){ *this = color_argb; }
  r8g8b8a8( U32 color_ ){ m_color32 = color_; }
  r8g8b8a8( U8 a, U8 r, U8 g, U8 b ){ SetColor(a,r,g,b); }

  U32 GetColorRef() const
  {
    return (U32)m_R + (((U32)m_G)<<8) + (((U32)m_B)<<16);
  }
};


} // namespace Color
} // namespace Core
} // namespace CPL
