
//
// Modifications History
//
//$ LB (13/06/2002)  : changed ObjBitmap management, according to the new ObjBitmap structure
//
//
//$LB (20/12/2002) : 16bits to 24bits
//




#include "layer.h"
#include "utils.h"
#include "bitmap.h"
#include "colors.h"


#define NO_TRANSPARENCY -1

#if DEBUG_LAYER
int Layer::ctr=0;
#endif

#if DEBUG_ALLOCATED	
int Layer::size_allocated=0;
int Layer::nb_obj=0;
#endif

extern mmachine mm;

Layer::Layer ( PtrObjBitmap rgb, PtrObjBitmap alpha, int transparency )
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::Layer");
#endif
//***********************************

	this->RGBbitmap = rgb;
	this->AlphaBitmap = alpha;

	this->Transparency = transparency;
	if ( rgb != NULL )
		this->sourceRect = Rect2D( 0, 0, rgb->TailleW, rgb->TailleH );
	else
		this->sourceRect = Rect2D( 0, 0, 0, 0 );

	this->Xdecal = 0;
	this->Ydecal = 0;

	this->allocated = 0;

	this->Next = NULL;


//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::Layer end");
#endif
//***********************************
#if DEBUG_LAYER
	MMechostr(MSKTRACE,"Layer:constructeur non alloue:nb Layer:%d\n",++ctr);
#endif
}










Layer::Layer ( int width, int height, int transparency, int withalpha )
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::Layer");
#endif
//***********************************
	this->AlphaBitmap = NULL;
	this->Transparency=transparency;
	this->RGBbitmap=(PtrObjBitmap)malloc(sizeof(ObjBitmap));
	this->RGBbitmap->TailleW=width;
	this->RGBbitmap->TailleH=height;
	this->RGBbitmap->BPP=24;
	ObjBitmap_NewDIBSection(this->RGBbitmap,NULL);
#if DEBUG_ALLOCATED
	size_allocated += this->RGBbitmap->TailleW * this->RGBbitmap->TailleH * this->RGBbitmap->BPP>>3;
	nb_obj++;
#endif
	if (withalpha)
	{
		this->AlphaBitmap=(PtrObjBitmap)malloc(sizeof(ObjBitmap));
		this->AlphaBitmap->TailleW=width;
		this->AlphaBitmap->TailleH=height;
		this->AlphaBitmap->BPP=8;
		ObjBitmap_NewDIBSection(this->AlphaBitmap,NULL);
		this->fillAlphaLayer( 255 );
#if DEBUG_ALLOCATED
		size_allocated+=this->AlphaBitmap->TailleW * this->AlphaBitmap->TailleH * this->AlphaBitmap->BPP>>3;
		nb_obj++;
#endif
	}

	this->sourceRect = Rect2D( 0, 0, width, height );
	this->allocated = 1;

	this->Xdecal = 0;
	this->Ydecal = 0;

	this->Next = NULL;

	if ( transparency != NO_TRANSPARENCY )
		this->fillLayer( transparency ); 

#if DEBUG_ALLOCATED
	MMechostr(MSKTRACE,"Layer allocated nb:%d  size:%d\n",nb_obj,size_allocated);
#endif
#if DEBUG_LAYER
	MMechostr(MSKTRACE,"Layer:constructeur alloue:nb Layer:%d\n",++ctr);
#endif
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::Layer end");
#endif
//***********************************

}

// FIN BOURRIN: TEMPORAIRE














Layer::~Layer ()
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::~Layer ");
#endif
//***********************************
	
	if ( this->allocated == 1 )
	{
		if ( this->RGBbitmap != NULL )
		{
#if DEBUG_ALLOCATED
	size_allocated-=this->RGBbitmap->TailleW*this->RGBbitmap->TailleH*this->RGBbitmap->BPP>>3;
	nb_obj--;
#endif
			DeleteObject( this->RGBbitmap->DIBhandler);
			free( this->RGBbitmap );
		}
		if ( this->AlphaBitmap != NULL ) 
		{
#if DEBUG_ALLOCATED
		size_allocated-=this->AlphaBitmap->TailleW*this->AlphaBitmap->TailleH*this->AlphaBitmap->BPP>>3;
		nb_obj--;
#endif
			DeleteObject( this->AlphaBitmap->DIBhandler);
			free( this->AlphaBitmap );
		}
#if DEBUG_ALLOCATED
	MMechostr(MSKTRACE,"Layer allocated nb:%d  size:%d\n",nb_obj,size_allocated);
#endif
#if DEBUG_LAYER
		MMechostr(MSKTRACE,"Layer:destructeur alloue:nb Layer:%d\n",--ctr);
#endif
	}
#if DEBUG_LAYER
	else
		MMechostr(MSKTRACE,"Layer:destructeur non alloue:nb Layer:%d\n",--ctr);
#endif

	this->allocated = 0;
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::~Layer  end");
#endif
//***********************************
}





void Layer::fillLayer ( int color )
{
	register int i, j;
	int dcx, dcy;
	int height, width;
	unsigned char r, g, b;


//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::fillLayer");
#endif
//***********************************

	if ( this->RGBbitmap != NULL )
	{
		height = this->RGBbitmap->TailleH;
		width  = this->RGBbitmap->TailleW;

		_COLOR_I_TO_BGR (color, &b, &g, &r);

		dcy = 0;
		for ( j = 0 ; j < height ; j ++ )
		{
			dcx = dcy ;
			for ( i = 0 ; i < width ; i ++ , dcx +=3 )
			{
				this->RGBbitmap->bits[ dcx   ] = b;
				this->RGBbitmap->bits[ dcx+1 ] = g;
				this->RGBbitmap->bits[ dcx+2 ] = r;
			}
			dcy += this->RGBbitmap->BPL;
		}
	}
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::fillLayer end");
#endif
//***********************************
}





void Layer::fillPartLayer ( int color, Rect2D rect )
{
	register int i, j;
	int dcx, dcy;
	unsigned char r, g, b;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::fillPartLayer");
#endif
//***********************************

	if ( this->RGBbitmap != NULL )
	{
		dcy = (rect.RctHG.iptY * this->RGBbitmap->BPL)  + (rect.RctHG.iptX * this->RGBbitmap->BytesPP) ;

		_COLOR_I_TO_BGR (color, &b, &g, &r);

		for ( j = rect.RctHG.iptY; j < rect.RctBD.iptY ; j ++ )
		{
			dcx = dcy ;
			for ( i = rect.RctHG.iptX; i < rect.RctBD.iptX ; i ++ , dcx +=3 )
			{
				this->RGBbitmap->bits[ dcx   ] = b;
				this->RGBbitmap->bits[ dcx+1 ] = g;
				this->RGBbitmap->bits[ dcx+2 ] = r;
			}
			dcy += this->RGBbitmap->BPL;
		}
	}
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::fillPartLayer end");
#endif
//***********************************
}





void GetBitmapPalette ( PtrObjBitmap B , PtrPalette P )
{
    RGBQUAD Pal [ 256 ] ;
    HDC dc ;
    int i ;
    HBITMAP OldBitmap ;


//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nGetBitmapPalette");
#endif
//***********************************

    dc = CreateCompatibleDC ( NULL ) ;
    OldBitmap = (HBITMAP)SelectObject ( dc , B->DIBhandler) ;
    i = GetDIBColorTable ( dc , 0 , 256 , Pal ) ;
    SelectObject ( dc , OldBitmap ) ;
    DeleteDC ( dc ) ;

    for ( i = 0 ; i < 256 ; i ++ )
    {
        GET_RED(P,i) = Pal[i].rgbRed ;
        GET_GREEN(P,i) = Pal[i].rgbGreen ;
        GET_BLUE(P,i) = Pal[i].rgbBlue ;
    
    }

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nGetBitmapPalette end");
#endif
//***********************************
}





void CopyObjBitmapToObjBitmap(PtrObjBitmap BD,int dposx,int dposy,PtrObjBitmap BS,int sposx,int sposy,int taillew,int tailleh,int couleur)
{
	register OBJBITMAP_BUFFER BufS;
	register OBJBITMAP_BUFFER BufD ;       
    register int j ;
    struct Palette Pal ;       
	int i , dcx , dcy , scx , scy ;
	unsigned char r, g, b;
	int bgrColor;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCopyObjBitmapToObjBitmap");
#endif
//***********************************


	if ( ClipBlit ( BD->TailleW , BD->TailleH , BS->TailleW , BS->TailleH , &dposx , &dposy , &sposx , &sposy , &taillew , &tailleh ) )
    {      

			//
			// Copy 8bits ==> 8bits
			//
			if (( BD->BPP == 8 ) && ( BS->BPP == 8 ))
            {
                BufS = (OBJBITMAP_BUFFER) BS->bits;
                BufD = (OBJBITMAP_BUFFER) BD->bits;

                dcy = dposy * BD->BPL + dposx ;
                scy = sposy * BS->BPL + sposx ;
                if ( couleur == NIL )  for ( j = 0 ; j < tailleh ; j ++ )
                {                     
                   
                    CopyMemory(BufD + dcy , BufS + scy , taillew ) ;
                    dcy += BD->BPL ; scy += BS->BPL ;
                } else
                for ( j = 0 ; j < tailleh ; j ++ )
                {                     
                    dcx = dcy  ;
                    scx = scy ;
                    for ( i = 0 ; i < taillew ; i ++ )
                    {             
                        if ( BufS [scx ] != couleur ) BufD [ dcx ] = BufS [ scx ] ;
                        dcx ++ ;
                        scx ++ ;
                    }
                    dcy += BD->BPL ;
                    scy += BS->BPL ;
                }
            } 
			
			
			//
			// Copy 8bits ==> 24bits
			//
			else if (( BD->BPP == 24 ) && ( BS->BPP == 8 ))
            {
                BufS = (OBJBITMAP_BUFFER) BS->bits;
                dcy = dposy * BD->BPL  + (dposx * BD->BytesPP) ;
                scy = sposy * BS->BPL + sposx ;
                GetBitmapPalette ( BS , & Pal ) ;
                
                for ( j = 0 ; j < tailleh ; j ++ )
                {
                    dcx = dcy ;
                    scx = scy ;
                    for ( i = 0 ; i < taillew ; i ++)
                    {
						b = BufS [ scx   ];
						g = BufS [ scx+1 ];
						r = BufS [ scx+2 ];
						bgrColor = _COLOR_BGR_TO_I (b, g, r);

                        if ( bgrColor != couleur )
						{
							BD->bits[ dcx   ] =  GET_BLUE(&Pal,BufS [ scx ]);
                            BD->bits[ dcx+1 ] =  GET_GREEN ( &Pal,BufS[ scx ]);
                            BD->bits[ dcx+2 ] =  GET_RED ( &Pal , BufS [ scx ]);
						}

                        dcx +=3;
                        scx ++ ;
                    }
                    dcy += BD->BPL;
                    scy += BS->BPL ;
                }
            } 
			
			
			//
			// Copy 24bits ==> 24bits
			//
			else if (( BD->BPP == 24 ) && ( BS->BPP == 24 ))
            {
                dcy = dposy * BD->BPL + (dposx * BD->BytesPP) ;
                scy = sposy * BS->BPL + (sposx * BD->BytesPP) ;                           

                if ( couleur == NIL ) 
                {            
                    BufS = ((OBJBITMAP_BUFFER) BS->bits) + scy;
                    BufD = ((OBJBITMAP_BUFFER) BD->bits) + dcy;

                    for ( j = 0 ; j < tailleh ; j ++ )
                    {                 
                        memcpy( BufD,BufS, taillew * BD->BytesPP) ;                   
                        BufD += BD->BPL ;
                        BufS += BS->BPL ;
                    }
                }
                else 
                {
                    for ( j = 0 ; j < tailleh ; j ++ )
                    {
                        dcx = dcy ;
                        scx = scy ;
                        for ( i = 0 ; i < taillew ; i ++ , dcx +=3 , scx +=3 )
						{
							b = BS->bits[ scx   ];
							g = BS->bits[ scx+1 ];
							r = BS->bits[ scx+2 ];
							bgrColor = _COLOR_BGR_TO_I (b, g, r);

							if (bgrColor != couleur ) 
							{
								BD->bits[ dcx   ] = b;
								BD->bits[ dcx+1 ] = g;
								BD->bits[ dcx+2 ] = r;
							}
						}
                        dcy += BD->BPL;
                        scy += BS->BPL;
                    }
                }
            }
    }


//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCopyObjBitmapToObjBitmap end");
#endif
//***********************************
}



void Layer::copyLayer( Layer *src )
{

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::copyLayer");
#endif
//***********************************
	if (src->RGBbitmap!=NULL)
			CopyObjBitmapToObjBitmap(this->RGBbitmap,0,0,src->RGBbitmap,0,0,src->RGBbitmap->TailleW,src->RGBbitmap->TailleH,-1);
	if (src->AlphaBitmap!=NULL)
			CopyObjBitmapToObjBitmap(this->AlphaBitmap,0,0,src->AlphaBitmap,0,0,src->AlphaBitmap->TailleW,src->AlphaBitmap->TailleH,-1);
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::copyLayer end");
#endif
//***********************************
}




void Layer::copyPartLayer( Layer *src, Rect2D rect)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::copyPartLayer");
#endif
//***********************************
	if (src->RGBbitmap!=NULL)
			CopyObjBitmapToObjBitmap(this->RGBbitmap,rect.RctHG.iptX,rect.RctHG.iptY,src->RGBbitmap,rect.RctHG.iptX,rect.RctHG.iptY,rect.RctBD.iptX-rect.RctHG.iptX-1,rect.RctBD.iptY-rect.RctHG.iptY-1,-1);
	if (src->AlphaBitmap!=NULL)
			CopyObjBitmapToObjBitmap(this->AlphaBitmap,rect.RctHG.iptX,rect.RctHG.iptY,src->AlphaBitmap,rect.RctHG.iptX,rect.RctHG.iptY,rect.RctBD.iptX-rect.RctHG.iptX-1,rect.RctBD.iptY-rect.RctHG.iptY-1,-1);			
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::copyPartLayer end");
#endif
//***********************************
}





void Layer::fillAlphaLayer ( unsigned char coefficiency )
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::fillAlphaLayer");
#endif
//***********************************
	if ( this->AlphaBitmap != NULL )
		this->fillPartAlphaLayer( coefficiency, Rect2D( 0, 0, this->AlphaBitmap->TailleW, this->AlphaBitmap->TailleH ) );
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::fillAlphaLayer end");
#endif
//***********************************
}





void Layer::fillPartAlphaLayer(unsigned char coefficiency,Rect2D rect)
{
	register int i, j;
	int dcx, dcy;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::fillPartAlphaLayer");
#endif
//***********************************


	if ( this->AlphaBitmap != NULL )
	{
		dcy = (rect.RctHG.iptY * this->AlphaBitmap->BPL)   +   (rect.RctHG.iptX * this->AlphaBitmap->BytesPP);
		for ( j = 0; j < rect.RctBD.iptY - rect.RctHG.iptY ; j ++ )
		{
			dcx = dcy ;
			for ( i = 0; i < rect.RctBD.iptX - rect.RctHG.iptX ; i ++ , dcx ++ )
				((OBJBITMAP_BUFFER)this->AlphaBitmap->bits)[ dcx ] = coefficiency;
			dcy += this->AlphaBitmap->BPL;
		}
	}

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::fillPartAlphaLayer end");
#endif
//***********************************

}




void Layer::clearAlphaLayer(Rect2D rect)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::clearAlphaLayer");
#endif
//***********************************
	this->fillPartAlphaLayer( 0, rect );
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::clearAlphaLayer end");
#endif
//***********************************
}



void Layer::drawLine(int x1,int y1,int x2,int y2,int mode,int taille,int color)
{
	HDC Dc;
	HBITMAP OldBitmap;
	HPEN Pinceau , OldPen ;
	POINT Ligne [ 2 ] ;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::drawLine");
#endif
//***********************************

	// on ne dessine que sur le RGB
	Dc = CreateCompatibleDC ( NULL ) ;
    OldBitmap = (HBITMAP) SelectObject ( Dc ,RGBbitmap->DIBhandler) ;
    
    if ( mode == 0 || taille <= 0 )
        Pinceau = CreatePen ( PS_NULL  , taille , color ) ;
    else 
		Pinceau = CreatePen ( PS_SOLID , taille , color ) ;
    
	OldPen = (HPEN)SelectObject ( Dc , Pinceau ) ;
    

    Ligne [ 0 ] .x = x1 ;
    Ligne [ 0 ] .y = y1 ;
    Ligne [ 1 ] .x = x2 ;
    Ligne [ 1 ] .y = y2 ;

    if ( x1 == x2 && y1 == y2 ) SetPixel ( Dc , x1 , y1 , color ) ;
    else Polygon ( Dc , Ligne , 2 ) ;   
   
    OldPen = (HPEN)SelectObject ( Dc , OldPen ) ;
    SelectObject ( Dc , OldBitmap ) ;
    DeleteObject ( OldPen ) ;
	DeleteDC ( Dc ) ;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::drawLine end");
#endif
//***********************************
}




// manipulations de listes

Layer *Layer::addLayer( Layer *next )
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::addLayer");
#endif
//***********************************

	if ( next != NULL )
	{
		if ( this->Next != NULL )
			next->addLayer( this->Next );
		this->Next = next;
	}


//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nLayer::addLayer end");
#endif
//***********************************
	return this;
}




Layer *Layer::nextLayer()
{
	return this->Next;
}

Layer *Layer::removeNext()
{
	if (this->Next != NULL )
		this->Next = this->Next->Next;
	return this;
}

Layer *Layer::nulifyAllNext()
{
	if ( this != NULL )
	{
		this->Next->nulifyAllNext();
		this->Next = NULL;
	}
	return this;
}

Layer *Layer::nulifyNext()
{
	if ( this != NULL )
		this->Next = NULL;
	return this;
}

Layer *Layer::removeAllNext()
{
	if (this->Next != NULL )
	{
		this->Next->nulifyAllNext();
		this->Next=NULL;
	}
	return this;
}

void deleteLayers( Layer *first )
{
	if ( first != NULL )
	{
		deleteLayers( first->nextLayer() );
		delete first;
	}
}

int dsAlphaBitmap(mmachine m,int abmp)
{
	int tmp_res;
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\ndsAlphaBitmap");
#endif
//***********************************

	CHECK(MMpush(m,abmp));
	CHECK(MMpush(mm,Msearchinsyspak(mm,"_DSalphaBitmap")));
	Minterpreter(mm);
	MMpull(m);

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\ndsAlphaBitmap end");
#endif
//***********************************

	return 0;
}
