/*
 * Bitmap.c - Bitmap support and what not, man this file is going to be ugly..
 * By: Odis
 */
#include <windows.h>
#include "main.h"

void clean_bitmaps(GAME *g)
{
   BMP *b = NULL;
   BMP *bnext = NULL;

   if ( g == NULL )
    return;
    
   for ( b = g->first_bmp; b != NULL; b = bnext )
   {
      bnext = b->next; /* b is going to die, we need to store this */
      UNLINK( b, g->first_bmp, g->last_bmp, next, prev );
      FreeBitmap(b);
   }
}

void FreeBitmap( BMP *Bitmap )
{
  if (Bitmap != NULL)
  {
   if (Bitmap->bitmap)
    DeleteObject(Bitmap->bitmap);
    
    DISPOSE( Bitmap->name );
    DISPOSE( Bitmap );
  }
}

/* create bitmap from file */
BMP *bitmap_from_file(HINSTANCE hInstance, LPCTSTR name)
{
  BMP *bitmap = NULL;
  HBITMAP bmp;
  SIZE sz;
  
  CREATE( bitmap, BMP, 1 );
  
  bmp = LoadImage(hInstance,
        name,
        IMAGE_BITMAP,
        0,
        0,
        LR_LOADFROMFILE);
  
  bitmap->bitmap = bmp;
  
  GetBitmapDimensionEx( bmp, &sz );
  
  bitmap->width = sz.cx;
  bitmap->height = sz.cy;
  bitmap->name = (char *)strdup( name );
  
  if ( bmp == NULL )
  {
    FreeBitmap( bitmap );
    return NULL;
  }
  
  /* link into list */
  LINK( bitmap, game->first_bmp, game->last_bmp, next, prev );
  
  /*everything ok, return */
  return bitmap;
}

/* create bitmap from a resource */
/*  ... for historical purposes
BMP *bitmap_from_resource(HINSTANCE hInstance, WORD resource)
{
  BMP *bitmap = NULL;
  HBITMAP bmp;

  CREATE( bitmap, BMP, 1 );

   bmp = LoadImage(hInstance,
        MAKEINTRESOURCE(resource),
        IMAGE_BITMAP,
        0,
        0,
        LR_DEFAULTCOLOR);
   bmp = LoadBitmap(hInstance, MAKEINTRESOURCE(resource));

  bitmap->bitmap = bmp;

  bitmap->width = PRG_WIDTH;
  bitmap->height = PRG_HEIGHT;

  if ( bmp == NULL )
  {
    FreeBitmap( bitmap );
    
    return NULL;
  }

  LINK( bitmap, game->first_bmp, game->last_bmp, next, prev );

  return bitmap;
}
*/

/* create a generic bitmap */
BMP *bitmap_from_generic(HDC hDC, int iWidth, int iHeight, COLORREF crColor, char *name, bool link)
{
  BMP *woof;

  CREATE( woof, BMP, 1 );
  
  /* Create a blank bitmap */
  woof->bitmap = CreateCompatibleBitmap(hDC, iWidth, iHeight);
  if (woof->bitmap == NULL)
    return NULL;

  /* Set the width and height */
  woof->width = iWidth;
  woof->height = iHeight;

  /* name? */
  woof->name = (char *)strdup(name);
  
  /* Create a memory device context to draw on the bitmap */
  HDC hMemDC = CreateCompatibleDC(hDC);

  /* Create a solid brush to fill the bitmap */
  HBRUSH hBrush = CreateSolidBrush(crColor);

  /* Select the bitmap into the device context */
  HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, woof->bitmap);

  /* Fill the bitmap with a solid color */
  RECT rcBitmap = { 0, 0, woof->width, woof->height };
  FillRect(hMemDC, &rcBitmap, hBrush);

  /* Cleanup */
  SelectObject(hMemDC, hOldBitmap);
  DeleteDC(hMemDC);
  DeleteObject(hBrush);

 if ( link == TRUE )
  LINK( woof, game->first_bmp, game->last_bmp, next, prev );

  return woof;
}

/* draw function, to be used in game_paint */
void Draw(BMP *bitmap, HDC hDC, int x, int y, bool trans, bool stretch )
{
  if (bitmap == NULL || bitmap->bitmap == NULL)
  {
      char buf[100];
      RECT rect;
      
      GetClientRect( game->hWindow, &rect );

      sprintf(buf, "No Bitmap to Draw", 0 );
      
      rect.right = (rect.right/2)-(strlen(buf)/2);
      rect.bottom = (rect.bottom/2)-(1/2);
      
      TextOut(hDC, rect.right, rect.bottom, buf, strlen(buf)  );
  }
  else
  {
    COLORREF transparentcolor = RGB(255, 0, 254);

     if (trans == TRUE)
       DrawTransparentBitmap(hDC, bitmap->bitmap, x, y, 0, 0, bitmap->width, bitmap->height, transparentcolor);
     else
     {
        /* Create a memory device context for the bitmap */
        HDC hMemDC = CreateCompatibleDC(hDC);

        /* Select the bitmap into the device context */
        HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, bitmap->bitmap);

        /* Draw the bitmap to the destination device context */
        if ( stretch == TRUE )
        {
            /* stretch it */
            StretchBlt(hDC, 0, 0, PRG_WIDTH, PRG_HEIGHT, hMemDC, x, y, bitmap->width, bitmap->height, SRCCOPY);
        }
        else
            BitBlt(hDC, 0, 0, PRG_WIDTH, PRG_HEIGHT, hMemDC, x, y, SRCCOPY);

        /* Restore and delete the memory device context */
        SelectObject(hMemDC, hOldBitmap);
        DeleteDC(hMemDC);
     }
  }

}

/* from MSDN & modified*/
void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, int xStart, int yStart, int xpart, int ypart, int width, int height, COLORREF cTransparentColor)
{
   BITMAP     bm;
   COLORREF   cColor;
   HBITMAP    bmAndBack, bmAndObject, bmAndMem, bmSave;
   HBITMAP    bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
   HDC        hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
   POINT      ptSize;

   hdcTemp = CreateCompatibleDC(hdc);
   SelectObject(hdcTemp, hBitmap);

   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
   ptSize.x = bm.bmWidth;
   ptSize.y = bm.bmHeight;
   DPtoLP(hdcTemp, &ptSize, 1);

   hdcBack   = CreateCompatibleDC(hdc);
   hdcObject = CreateCompatibleDC(hdc);
   hdcMem    = CreateCompatibleDC(hdc);
   hdcSave   = CreateCompatibleDC(hdc);

   bmAndBack   = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);

   bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);

   bmAndMem    = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
   bmSave      = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);

   bmBackOld   = SelectObject(hdcBack, bmAndBack);
   bmObjectOld = SelectObject(hdcObject, bmAndObject);
   bmMemOld    = SelectObject(hdcMem, bmAndMem);
   bmSaveOld   = SelectObject(hdcSave, bmSave);

   SetMapMode(hdcTemp, GetMapMode(hdc));

   BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);

   cColor = SetBkColor(hdcTemp, cTransparentColor);

   BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
          SRCCOPY);

   SetBkColor(hdcTemp, cColor);

   BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,
          NOTSRCCOPY);

   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart-xpart, yStart-ypart,
          SRCCOPY);

   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);

   BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);

   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);

   BitBlt(hdc, xStart, yStart, width, height, hdcMem, xpart, ypart,
          SRCCOPY);

   BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);

   DeleteObject(SelectObject(hdcBack, bmBackOld));
   DeleteObject(SelectObject(hdcObject, bmObjectOld));
   DeleteObject(SelectObject(hdcMem, bmMemOld));
   DeleteObject(SelectObject(hdcSave, bmSaveOld));

   DeleteDC(hdcMem);
   DeleteDC(hdcBack);
   DeleteDC(hdcObject);
   DeleteDC(hdcSave);
   DeleteDC(hdcTemp);
}

/* get a bitmap via name */
BMP *get_bmp( char *name ) /* went global...*/
{
  BMP *loop = NULL;

  for ( loop = game->first_bmp; loop != NULL; loop = loop->next )
   if ( !stricmp( name, loop->name ) )
    return loop;

  return NULL;
}

/*from brian*/
/*
void DrawTransparentBitmap(HDC hDC, HBITMAP Imagetodraw, int destx, int desty, int width, int height, int srcx, int srcy, COLORREF col)
{
   HDC Mem = CreateCompatibleDC(hDC);
   HGDIOBJ Old;
   int x, y;

   Old = SelectObject(Mem, Imagetodraw);
   for(x = 0; x < width; x++ )
   {
      for(y = 0; y < height; y++)
      {
            if( GetPixel(Mem, srcx+x, srcy+y) != col)
            {
                SetPixel(hDC, destx+x, desty+y, GetPixel(Mem, srcx+x, srcy+y));
            }
      }
   }
   SelectObject(Mem, Old);
   DeleteDC(Mem);
}
*/