/*
  License:
    This is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.
    
  Use:    
    Some usefull color code.
    
  Author:
    Unai Landa	(unai_landa#eresmas·com)

  Notes:
    My english is really bad, I allready now that so dont tell me.
    The original code was nice comented in spanish, but I translated this  "on the fly" so I hope you can understand :-)
    
*/

// --------------------------------------------------------------------------------------------------------------------
// Some 565 Color space defines.
// --------------------------------------------------------------------------------------------------------------------
enum
{
    COLORSPACE_565_RED_MASK             = (0xF800),
    COLORSPACE_565_GREEN_MASK           = (0x07E0),
    COLORSPACE_565_BLUE_MASK            = (0x001F),

    COLORSPACE_565_SATURATE_RED_BIT     = (0x10000),
    COLORSPACE_565_SATURATE_GREEN_BIT   = (0x0800),
    COLORSPACE_565_SATURATE_BLUE_BIT    = (0x0020),
};

//----------------------------------------------------------------------------
// Some more defines
//----------------------------------------------------------------------------
enum
{
  MAXIMO_NUM_BITS_COLOR   = 6   ,
  BITS_BAJOS              = 5   ,

  MASCARA_A               =(COLORSPACE_565_GREEN_MASK)                                        ,
  MASCARA_B               =(COLORSPACE_565_RED_MASK|COLORSPACE_565_BLUE_MASK)                 ,

  MASCARA_SAT_A           =(COLORSPACE_565_SATURATE_GREEN_BIT )                               ,
  MASCARA_SAT_B           =(COLORSPACE_565_SATURATE_RED_BIT|COLORSPACE_565_SATURATE_BLUE_BIT) ,

  MASCARA_A_TWICE         =( ((COLORSPACE_565_RED_MASK|COLORSPACE_565_BLUE_MASK)<<16)|(COLORSPACE_565_GREEN_MASK<<0 ))  ,
  MASCARA_B_TWICE         =( ((COLORSPACE_565_RED_MASK|COLORSPACE_565_BLUE_MASK)<<0 )|(COLORSPACE_565_GREEN_MASK<<16))  ,

  MASCARA_SAT_A_TWICE     =( ((COLORSPACE_565_SATURATE_RED_BIT|COLORSPACE_565_SATURATE_BLUE_BIT)<<(16-BITS_BAJOS))|(COLORSPACE_565_SATURATE_GREEN_BIT>>BITS_BAJOS) )                              ,
  MASCARA_SAT_B_TWICE     =((((COLORSPACE_565_SATURATE_RED_BIT|COLORSPACE_565_SATURATE_BLUE_BIT)                 )|(COLORSPACE_565_SATURATE_GREEN_BIT<<16))<<(MAXIMO_NUM_BITS_COLOR-BITS_BAJOS) )
};


//----------------------------------------------------------------------
//  Use:            Adds two 565 colours with saturation and no lose.
//  Returns:        The added colour.
//  Parameters:     Two colours.
//----------------------------------------------------------------------
__inline unsigned GE_AddColors565( const unsigned c1, const unsigned c2)
{
    //  Separacion:
    //  SetUp:
    unsigned  t1_a = (c1 & MASCARA_A);                              //  0000__g1__
    unsigned  t2_a = (c2 & MASCARA_A);                              //  0000__g2__

    unsigned  t1_b = (c1 & MASCARA_B);                              //  0000r1__b1
    unsigned  t2_b = (c2 & MASCARA_B);                              //  0000r2__b2

    //  Suma_A:
    //  Suma_B:                                                     
    t1_a  = t2_a = t1_a + t2_a;                                     //  00__gT__    * T means Total
    t1_b  = t2_b = t1_b + t2_b;                                     //  00rT__bT

    t2_a &= MASCARA_SAT_A;                                          //  00_1____    *** 1 appears ONLY where saturation happened.
    t2_b &= MASCARA_SAT_B;                                          //  01___1__    *** 1 appears ONLY where saturation happened.

    t2_a -= (t2_a>>MAXIMO_NUM_BITS_COLOR);                          //  00__11__    *** 1 appears ONLY where saturation happened.
    t2_b -= (t2_b>>BITS_BAJOS);                                     //  0011__11    *** 1 appears ONLY where saturation happened.

    t1_a |= t2_a;                                                   //  00__gS__    * S means Saturated
    t1_b |= t2_b;                                                   //  00rS__bS  

    //  Comoposicion:
    return(t1_a | t1_b);
}

//----------------------------------------------------------------------
//  Use:            Adds two 565 colours TWICE with saturation and no lose.
//  Returns:        The two added colours.
//  Parameters:     Four 565 colours, The first parameter colurs are added to the second parameter colours..
//----------------------------------------------------------------------
__inline unsigned  GE_AddColors565Twice( const unsigned c1, const unsigned c2)
{
    //  Separacion:
    //  SetUp:
    unsigned  t1_a = (c1 & MASCARA_A_TWICE) >> BITS_BAJOS;                          //  __R1__B1__g1
    unsigned  t2_a = (c2 & MASCARA_A_TWICE) >> BITS_BAJOS;                          //  __R2__B2__g2

    unsigned  t1_b = (c1 & MASCARA_B_TWICE) << (MAXIMO_NUM_BITS_COLOR-BITS_BAJOS);  //  __G1__r1__b1
    unsigned  t2_b = (c2 & MASCARA_B_TWICE) << (MAXIMO_NUM_BITS_COLOR-BITS_BAJOS);  //  __G2__r2__b2

    //  Suma_A:
    //  Suma_B:                                                     
    t1_a  = t2_a = t1_a + t2_a;                                                     //  __RT__BT__gT  * T means Total
    t1_b  = t2_b = t1_b + t2_b;                                                     //  __GT__rT__bT
                                                                                    
    t2_a &= MASCARA_SAT_A_TWICE;                                                    //  _1___1___1__  *** 1 appears ONLY where saturation happened.
    t2_b &= MASCARA_SAT_B_TWICE;                                                    //  _1___1___1__  *** 1 appears ONLY where saturation happened.
                                                                                    
    t2_a -= (t2_a>>MAXIMO_NUM_BITS_COLOR);                                          //  __11__11__11  *** 1 appears ONLY where saturation happened.
    t2_b -= (t2_b>>MAXIMO_NUM_BITS_COLOR);                                          //  __11__11__11  *** 1 appears ONLY where saturation happened.
                                                                                    
    t1_a |= t2_a;                                                                   //  __RSxxBSxxgS  * S means Saturated
    t1_b |= t2_b;                                                                   //  __GSxxrSxxbS  * xx Garbage that appeared betwen the color components.
                                                                                    
    t1_a  = (t1_a<<BITS_BAJOS) & (MASCARA_A_TWICE);                                 //  11xx11xx11xx  * Moves all to its correct place.
                                                                                    //  11__11__11__  * Cleans the space betwen components.   
    t1_b  = (t1_b>>MAXIMO_NUM_BITS_COLOR-BITS_BAJOS) & (MASCARA_B_TWICE);           //  11xx11xx11xx  * Moves all to its correct place.
                                                                                    //  __11__11__11  * Cleans the space betwen components.   
    //  Comoposicion:
    return(t1_a | t1_b);
}

//----------------------------------------------------------------------
//  Use:            Subs two 565 colours with saturation and no lose.
//  Returns:        The Sub colour.
//  Parameters:     Two colours.
//----------------------------------------------------------------------
__inline  unsigned GE_SubColors565( unsigned c1, const unsigned c2)
{
    //  Separacion:
    unsigned  t1_a = (c1 &  MASCARA_A) | MASCARA_SAT_A;             //  0000_1g1__    //  I set the bit so later I can check underflow.
    unsigned  t2_a = (c2 &  MASCARA_A);                             //  0000__g2__

    unsigned  t1_b = (c1 &  MASCARA_B) | MASCARA_SAT_B;             //  0001r1_1b1    //  I set the bit so later I can check underflow.
    unsigned  t2_b = (c2 &  MASCARA_B);                             //  0000r2__b2

    //  Resta_A:
    //  Resta_B:                                                     
    t1_a  = t2_a = (t1_a - t2_a);                                   //  00__gT__    * T means Total
    t1_b  = t2_b = (t1_b - t2_b);                                   //  00rT__bT

    t2_a &= (MASCARA_SAT_A);                                        //  00_1____    I test sign change.
    t2_b &= (MASCARA_SAT_B);                                        //  01___1__    1 appears ONLY where no underflow happened.

    t2_a -= (t2_a>>MAXIMO_NUM_BITS_COLOR);                          //  00__11__    I create the 1filled mask on the colours the didn't underflow.
    t2_b -= (t2_b>>BITS_BAJOS);                                     //  0011__11 

    t1_a &= t2_a;                                                   //  00__gU__    * U means UnderFlow
    t1_b &= t2_b;                                                   //  00rU__bU  

    //  Comoposicion:
    return(t1_a | t1_b);
}

//----------------------------------------------------------------------
//  Use:            Subs two 565 colours TWICE with saturation and no lose.
//  Returns:        The two added colours.
//  Parameters:     Four 565 colours, The second parameter colurs are sub from the first parameter colours..
//----------------------------------------------------------------------
__inline  unsigned GE_SubColors565Twice( unsigned c1, const unsigned c2)
{
    //  Separacion:
    //  SetUp:
    unsigned  t1_a = ((c1 & MASCARA_A_TWICE) >> BITS_BAJOS) | MASCARA_SAT_A_TWICE;                          //  _1R1_1B1_1g1
    unsigned  t2_a = ((c2 & MASCARA_A_TWICE) >> BITS_BAJOS);                                                //  __R2__B2__g2

    unsigned  t1_b = ((c1 & MASCARA_B_TWICE) << (MAXIMO_NUM_BITS_COLOR-BITS_BAJOS)) | MASCARA_SAT_B_TWICE;  //  _1G1_1r1_1b1
    unsigned  t2_b = ((c2 & MASCARA_B_TWICE) << (MAXIMO_NUM_BITS_COLOR-BITS_BAJOS));                        //  __G2__r2__b2

    //  Suma_A:
    //  Suma_B:                                                     
    t1_a  = t2_a = t1_a - t2_a;                                               //  __RT__BT__gT  * T means Total
    t1_b  = t2_b = t1_b - t2_b;                                               //  __GT__rT__bT
                                                                              
    t2_a &= MASCARA_SAT_A_TWICE;                                              //  _1___1___1__  *** 1 appears ONLY where no underflow happened.
    t2_b &= MASCARA_SAT_B_TWICE;                                              //  _1___1___1__  *** 1 appears ONLY where no underflow happened.
                                                                              
    t2_a -= (t2_a>>MAXIMO_NUM_BITS_COLOR);                                    //  __11__11__11  *** 1 appears ONLY where no underflow happened.
    t2_b -= (t2_b>>MAXIMO_NUM_BITS_COLOR);                                    //  __11__11__11  *** 1 appears ONLY where no underflow happened.
                                                                              
    t1_a &= t2_a;                                                             //  __RUxxBUxxgU  * U means Underflow
    t1_b &= t2_b;                                                             //  __GUxxrSxxbU  * xx Garbage that appeared betwen the color components.
                                                                              
    t1_a  = (t1_a<<BITS_BAJOS) & (MASCARA_A_TWICE);                           //  11xx11xx11xx  * Moves all to its correct place.
                                                                              //  11__11__11__  * Cleans the space betwen components.   
    t1_b  = (t1_b>>MAXIMO_NUM_BITS_COLOR-BITS_BAJOS) & (MASCARA_B_TWICE);     //  11xx11xx11xx  * Moves all to its correct place.
                                                                              //  __11__11__11  * Cleans the space betwen components.   
    //  Comoposicion:                                                         
    return(t1_a | t1_b);
}

//----------------------------------------------------------------------
//  Use:            Make a 32 levels alfa blend betwen two 565 colours.
//  Returns:        The blended colour.
//  Parameters:     iAlfa=0 Only c1 is set, iAlfa=32 only c2 is set
//----------------------------------------------------------------------
__inline unsigned GE_BlendColors565( const unsigned c1, const unsigned c2, int iAlfa)
{
  unsigned  ta = c1 & MASCARA_A;                                            //  0000__g1__
  unsigned  tb = c2 & MASCARA_B;                                            //  0000r2__b2
  
  ta *= (32-iAlfa);
  tb *= (   iAlfa);

  ta += (   iAlfa) *(c2 & MASCARA_A);                                            //  0000__g2__
  tb += (32-iAlfa) *(c1 & MASCARA_B);                                            //  0000r1__b1

  ta =  (ta>>BITS_BAJOS) & MASCARA_A;
  ta += (tb>>BITS_BAJOS) & MASCARA_B;

  return(ta);
}

//----------------------------------------------------------------------
//  Use:            Make a 32 levels alfa blend betwen two 565 colours TWICE
//  Returns:        The two blended colours.
//  Parameters:     iAlfa=0 Only c1 is set, iAlfa=32 only c2 is set
//		    c1; two 565 Colours thar will blend with c2 that contains anothe two 565 colours.
//----------------------------------------------------------------------
__inline unsigned  GE_BlendColors565Twice( const unsigned c1, const unsigned c2, int iAlfa)
{
  unsigned  ta = (c1 & MASCARA_A_TWICE)>>BITS_BAJOS;                          //  __R1__B1__g1
  unsigned  tb = (c1 & MASCARA_B_TWICE);                                      //  __G1__r1__b1

  ta *= (32-iAlfa);
  tb *= (32-iAlfa);
  
  ta += iAlfa *((c2 & MASCARA_A_TWICE)>>(BITS_BAJOS));                        //  __R2__B2__g2
  tb += iAlfa * (c2 & MASCARA_B_TWICE);                                       //  __G2__r2__b2

  ta &=                    MASCARA_A_TWICE;                                   //  R2__B2__g2__
  ta += (tb>>BITS_BAJOS) & MASCARA_B_TWICE;                                   //  __G2__r2__b2
  return(ta);
}
