
//
// Modifications History
//
//$ LB (13/06/2002)  : changed ObjBitmap management, according to the new ObjBitmap structure
//
//$LB (20/12/2002) : 16bits to 24bits
//

#include "CObjBufferWindows.h"
#include "lib2Dconf.h"
#include "Macro.h"
#include "utils.h"




OBJBITMAP_BUFFER alphaBlit( OBJBITMAP_BUFFER bDest, OBJBITMAP_BUFFER bRGB, OBJBITMAP_BUFFER bA,
					  int DestBPL, int RGBBPL, int ABPL,
					  int destX, int destY, int srcX, int srcY, int width, int height,
					  int transparency);
OBJBITMAP_BUFFER classicBlit( OBJBITMAP_BUFFER bDest, OBJBITMAP_BUFFER bSrc,
					    int DestBPL, int SrcBPL,
					    int destX, int destY, int srcX, int srcY, int width, int height,
						int transparency);
					  
extern int OBJCONTAINER;
extern mmachine mm;

#ifdef USE_WINDOWS

CObjBufferWindows::CObjBufferWindows(int xsize,int ysize):CObjBuffer()
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjBufferWindows::CObjBufferWindows");
#endif
//***********************************
	
	DIBSECTION Info ;
    BITMAPINFO Bit ;
    HDC dc=NULL;
    
	WinSizeW=xsize;
	WinSizeH=ysize;
	
    Bit.bmiHeader.biSize = sizeof ( BITMAPINFOHEADER ) ;
    Bit.bmiHeader.biWidth = xsize ;
	Bit.bmiHeader.biHeight = - ysize ;
    
    Bit.bmiHeader.biPlanes = 1 ;
    Bit.bmiHeader.biBitCount = BITSPERPIXEL ;
    Bit.bmiHeader.biCompression = BI_RGB ;
    Bit.bmiHeader.biSizeImage = 0 ;
    Bit.bmiHeader.biXPelsPerMeter = 0 ;
    Bit.bmiHeader.biYPelsPerMeter = 0 ;
    Bit.bmiHeader.biClrUsed = 256 ;
    Bit.bmiHeader.biClrImportant = Bit.bmiHeader.biClrUsed ;

    WinHbmp=CreateDIBSection (dc ,(BITMAPINFO * ) & Bit , DIB_RGB_COLORS ,(void **) &WinBmp ,NULL , 0 ) ;
    if (WinHbmp == NULL )
	{
    LPVOID lpMsgBuf;

		FormatMessage( 
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM | 
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
			(LPTSTR) &lpMsgBuf,
			0,
			NULL );


		MMechostr ( 1 , "BITMAP ERROR 1 WIN32 Num %d : %s" , GetLastError (), lpMsgBuf);
		LocalFree( lpMsgBuf );
		return;
	}

	if (!GetObject ( WinHbmp , sizeof( DIBSECTION ) , &Info )) MMechostr ( 1 , "GETOBJECT ERROR Num %d" , GetLastError ());
  WinBmp = (OBJBITMAP_BUFFER)Info.dsBm.bmBits ;
	WinBmp[0]=0;
  WinBitsPerPixel = Info.dsBm.bmBitsPixel ;
  WinBitsBitmapLength = Info.dsBm.bmWidthBytes ;
  if (WinBitsBitmapLength % 4 != 0 ) WinBitsBitmapLength += 4 - ( WinBitsBitmapLength % 4 );
	WinFlags=Info.dsBmih.biHeight>0?1:0;
	Winhandler = OBJgetNewHandler();

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjBufferWindows::CObjBufferWindows end");
#endif
//***********************************

}


CObjBufferWindows::~CObjBufferWindows()
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjBufferWindows::~CObjBufferWindows");
#endif
//***********************************

	OBJdelTH(mm,OBJtypebyname ("OBJTYPBITMAP"),(int)Winhandler);
	
  //$BB big memory leak without that !!
  if (WinHbmp != 0)
    DeleteObject(WinHbmp);
  
	WinHbmp=NULL;
	WinBmp=NULL;

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjBufferWindows::~CObjBufferWindows end");
#endif
//***********************************
}



int CObjBufferWindows::GetId()
{
	return (int)WinHbmp;
}




void CObjBufferWindows::Blit(int dx,int dy,Layer *source)
{
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjBufferWindows::Blit");
#endif
//***********************************
	
	if ( source != NULL )
	{
		PtrObjBitmap SrcRGB   = source->RGBbitmap;
		PtrObjBitmap SrcAlpha = source->AlphaBitmap;
		int transparency      = source->Transparency;
		int sx = source->sourceRect.RctHG.iptX;
		int sy = source->sourceRect.RctHG.iptY;
		int sw = source->sourceRect.RctBD.iptX - source->sourceRect.RctHG.iptX;
		int sh = source->sourceRect.RctBD.iptY - source->sourceRect.RctHG.iptY;

		if ( SrcRGB != NULL )
		{
			if ( SrcAlpha != NULL )
			{
				if ( ClipBlit( WinSizeW , WinSizeH ,
							   min(SrcRGB->TailleW, SrcAlpha->TailleW) , min(SrcRGB->TailleH, SrcAlpha->TailleH),
							   &dx , &dy , &sx , &sy , &sw , &sh ) )
					alphaBlit( WinBmp,
							   SrcRGB->bits, (OBJBITMAP_BUFFER)SrcAlpha->bits,
							   WinBitsBitmapLength,
							   SrcRGB->BPL, SrcAlpha->BPL,
							   dx, dy, sx, sy, sw, sh,
							   transparency );
			}
			else
				if ( ClipBlit( WinSizeW , WinSizeH ,
							   SrcRGB->TailleW, SrcRGB->TailleH,
							   &dx , &dy , &sx , &sy , &sw , &sh ) )
					classicBlit( WinBmp,
								 SrcRGB->bits,
								 WinBitsBitmapLength,
								 SrcRGB->BPL,
								 dx, dy, sx, sy, sw, sh,
								 transparency );
		}
		else
			MMechostr( MSKTRACE, "Blit: bitmap has already been destroyed.\n" );
	}

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "CObjBufferWindows::Blit end\n");
#endif
//***********************************

}





void CObjBufferWindows::Clear(int dx1,int dy1,int dx2,int dy2,int bckcolor)
{
	HDC Dcb;
    HBITMAP OldBitmap;
	RECT clearRect = { (long)dx1, (long)dy1, (long)dx2, (long)dy2 };

//$BLG
//MMechostr (0, "CObjBufferWindows::Clear - %i\n", bckcolor);
//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjBufferWindows::Clear");
#endif
//***********************************
	
    Dcb = CreateCompatibleDC ( NULL ) ;
    OldBitmap =(HBITMAP) SelectObject ( Dcb , WinHbmp ) ;
	HBRUSH bufbrush = CreateSolidBrush( bckcolor );

	FillRect( Dcb, &clearRect, bufbrush );

	DeleteObject( bufbrush );

    SelectObject( Dcb , OldBitmap );
    DeleteDC( Dcb );

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjBufferWindows::Clear end");
#endif
//***********************************
}




int  CObjBufferWindows::CreateScolBuffer(mmachine m,int ndxchannel,int idcont)
{
	int s , s2 , tmp_res;


//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjBufferWindows::CreateScolBuffer");
#endif
//***********************************
	
    if ( (s=MMmallocCLR (m,SIZE(struct ObjVoid),TYPETAB) 
		 )== NIL 
	   ) return MERRMEM ;
    
	if ( MMpush(m,PTOM(s))) 
		return MERRMEM;

    if ( (s2= MMmalloc ( m,SIZE(struct ObjBitmap),TYPEBUF )
		 ) == NIL 
	   ) return MERRMEM ;
    
	s = MMget(m,0) ;

    PtrObjVoid O = ( PtrObjVoid ) MMstart(m, MTOP(s) ) ;
    PtrObjBitmap B = ( PtrObjBitmap ) MMstart(m, s2 ) ;
 
    O->Buffer	= PTOM(s2);
    O->Tab		= NIL ;
    O->Father	= NIL ;
    O->Type		= ITOM(OBJ_TYPE_BITMAP);

    B->TailleH	= WinSizeH ;
    B->TailleW	= WinSizeW ;
    
	B->BPP		= WinBitsPerPixel ;
	B->BytesPP  = B->BPP >>3;
	B->DIBhandler	= WinHbmp;
	B->bits	= WinBmp;
	B->BPL		= WinBitsBitmapLength;
	B->Flags	= WinFlags;
	B->handler  = Winhandler;

    CHECK(MMpush(m,MMget(m,ndxchannel+1)));
	INVERT(m,0,1);

//***********************************
#if DEBUG_LIB2D
MMechostr (0, "\nCObjBufferWindows::CreateScolBuffer end");
#endif
//***********************************

	return OBJcreate(m,OBJtypebyname ("OBJTYPBITMAP"),(int)B->handler,OBJCONTAINER,idcont ) ;
}
#endif //USE_WINDOWS