/*===========================================================================*/
/*                                                                           */
/* File    : ICODRAW.C                                                       */
/*                                                                           */
/* Purpose : Drawing routines for the IKE icon editor.                       */
/*                                                                           */
/* History :                                                                 */
/*                                                                           */
/* (C) Copyright 1991 Marc Adler/Magma Systems     All Rights Reserved       */
/*===========================================================================*/

#include <memory.h>
#include <string.h>
#include <windows.h>
#include "ico.h"

extern BYTE rgb[16][3];

HANDLE PASCAL AllocateDefaultBitmap(void);
int  FAR PASCAL DrawEllipse(HDC hMemDC);
int  FAR PASCAL DoFloodFill(HDC hMemDC);
VOID PASCAL DrawOnBitmap(HDC hDC, HANDLE hBits, HPEN hPen, HBRUSH hBrush, FARPROC lpfnDraw);


/****************************************************************************/
/*                                                                          */
/* Function : DisplayDIBitmap()                                             */
/*                                                                          */
/* Purpose  : Draws the bitmap which represents the icon                    */
/*                                                                          */
/* Returns  : Nothing.                                                      */
/*                                                                          */
/****************************************************************************/
VOID PASCAL DisplayDIBitmap(HWND hWnd, HDC hDC, HANDLE hBits)
{
  HANDLE       hbmi;
  LPBITMAPINFO lpbmi;
  RECT         rClient;
  LPSTR        lpBits;

  if ((lpBits = GlobalLock(hBits)) == NULL)
  {
    MessageBox(hWndMain, "Could not lock lpBits", "DisplayDIB", MB_OK);
    return;
  }

  hbmi = AllocateDefaultBitmap();
  lpbmi = (LPBITMAPINFO) GlobalLock(hbmi);

  /*
    Draw the bitmap on the screen
  */
  GetClientRect(hWnd, &rClient);
  StretchDIBits(hDC, 0, 0, rClient.right+1, rClient.bottom+1,
                0, 0, 
                (WORD)lpbmi->bmiHeader.biWidth, (WORD)lpbmi->bmiHeader.biHeight,
                lpBits, (LPBITMAPINFO) lpbmi, DIB_RGB_COLORS, SRCCOPY);

  /*
    Unlock all of the various memory handles
  */
  GlobalUnlock(hBits);
  GlobalUnlock(hbmi);
  GlobalFree(hbmi);
}


/****************************************************************************/
/*                                                                          */
/* Function : DrawCircleInBitmap()                                          */
/*                                                                          */
/* Purpose  : Draws a circle within the current pixmap.                     */
/*                                                                          */
/* Returns  : Nothing.                                                      */
/*                                                                          */
/****************************************************************************/
static RECT rEllipse;

VOID PASCAL
DrawCircleInBitmap(HWND hWnd,HDC hDC,HANDLE hBits,int x1,int y1,int x2,int y2)
{
  HPEN        hPen;
  HBRUSH      hBrush;

  hPen = CreatePen(PS_SOLID, 1, 
     RGB(rgb[CurrentColor][2], rgb[CurrentColor][1], rgb[CurrentColor][0]));

  hBrush = (iCurrentTool == ID_FILLCIRC) ? 
   CreateSolidBrush(
     RGB(rgb[CurrentColor][2], rgb[CurrentColor][1], rgb[CurrentColor][0])) :
       GetStockObject(NULL_BRUSH);

  SetRect((LPRECT) &rEllipse, x1, y1, x2, y2);

  DrawOnBitmap(hDC, hBits, hPen, hBrush, DrawEllipse);
}

int FAR PASCAL DrawEllipse(HDC hMemDC)
{
  return
  Ellipse(hMemDC, rEllipse.left, rEllipse.top, rEllipse.right, rEllipse.bottom);
}


/****************************************************************************/
/*                                                                          */
/* Function : FloodFillBitmap()                                             */
/*                                                                          */
/* Purpose  : Does a flood-fill within the current bitmap. Uses BLACK as    */
/*            the border color for the fill.                                */
/*                                                                          */
/* Returns  : Nothing.                                                      */
/*                                                                          */
/****************************************************************************/
static POINT ptFlood;

VOID PASCAL
FloodFillBitmap(HWND hWnd,HDC hDC,HANDLE hBits,int x1,int y1)
{
  HBRUSH      hBrush;

  hBrush = CreateSolidBrush(
    RGB(rgb[CurrentColor][2], rgb[CurrentColor][1], rgb[CurrentColor][0]));

  ptFlood.x = x1;
  ptFlood.y = y1;
  DrawOnBitmap(hDC, hBits, (HPEN) 0, hBrush, DoFloodFill);
}

int FAR PASCAL DoFloodFill(HDC hMemDC)
{
  return
  FloodFill(hMemDC, ptFlood.x, ptFlood.y, RGB(0, 0, 0));
}



/****************************************************************************/
/*                                                                          */
/* Function : AllocateDefaultBitmap()                                       */
/*                                                                          */
/* Purpose  : Creates an empty device independent bitmap.                   */
/*                                                                          */
/* Returns  : A handle to the bitmap.                                       */
/*                                                                          */
/****************************************************************************/
HANDLE PASCAL AllocateDefaultBitmap(void)
{
  HANDLE       hbmi;
  LPBITMAPINFO lpbmi;

  hbmi = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, 
       (DWORD) sizeof(BITMAPINFOHEADER) + IconDir.ColorCount*sizeof(RGBQUAD));
  lpbmi = (LPBITMAPINFO) GlobalLock(hbmi);

  lpbmi->bmiHeader.biSize          = (long) sizeof(BITMAPINFOHEADER);
  lpbmi->bmiHeader.biWidth         = IconDir.Width;
  lpbmi->bmiHeader.biHeight        = IconDir.Height;
  lpbmi->bmiHeader.biPlanes        = 1;
  lpbmi->bmiHeader.biBitCount      = ColorCountToPlanes(IconDir.ColorCount);
  lpbmi->bmiHeader.biCompression   = BI_RGB;
  lpbmi->bmiHeader.biSizeImage     = 512L;
  lpbmi->bmiHeader.biXPelsPerMeter = 0;
  lpbmi->bmiHeader.biYPelsPerMeter = 0;
  lpbmi->bmiHeader.biClrUsed       = 0;
  lpbmi->bmiHeader.biClrImportant  = 0;

  /*
    Initialize the colors
  */
  if (IconDir.ColorCount == 2)
  {
    _fmemcpy(&lpbmi->bmiColors[0], rgb[0], 3);
    _fmemcpy(&lpbmi->bmiColors[1], rgb[7], 3);
  }
  else
  {
    int i;
    for (i = 0;  i < 16;  i++)
      _fmemcpy(&lpbmi->bmiColors[i], rgb[i], 3);
  }

  GlobalUnlock(hbmi);
  return hbmi;
}


/****************************************************************************/
/*                                                                          */
/* Function : DrawOnBitmap()                                                */
/*                                                                          */
/* Purpose  : Takes a bitmap, a pen, a brush, and a callback function, and  */
/*            does most of the grunt work for drawing a graphical object    */
/*            on a bitmap.                                                  */
/*                                                                          */
/* Returns  : Nothing.                                                      */
/*                                                                          */
/****************************************************************************/
VOID PASCAL DrawOnBitmap(HDC hDC, HANDLE hBits, HPEN hPen, HBRUSH hBrush, FARPROC lpfnDraw)
{
  HANDLE      hbmi;
  LPBITMAPINFO lpbmi;
  HBITMAP     hOldBitmap, hBitmap;
  HPEN        hOldPen;
  HBRUSH      hOldBrush;
  LPSTR       lpBits;
  HDC         hMemDC;

  hMemDC = CreateCompatibleDC(hDC);

  hbmi = AllocateDefaultBitmap();
  lpbmi = (LPBITMAPINFO) GlobalLock(hbmi);

  if ((lpBits = GlobalLock(hBits)) == NULL)
  {
    MessageBox(hWndMain, "Could not lock lpBits", "DrawOnBitmap", MB_OK);
    return;
  }

  /*
    Create the bitmap given the above structure.
  */
  hBitmap = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER) &lpbmi->bmiHeader,
                           CBM_INIT, (LPSTR) lpBits, (LPBITMAPINFO) lpbmi,
                           DIB_RGB_COLORS);
  if (hBitmap == NULL)
  {
    MessageBox(hWndMain, "Couldn't create the Bitmap", NULL, MB_OK);
    return;
  }

  /*
    Save the old objects
  */
  hOldBitmap = SelectObject(hMemDC, hBitmap);
  if (hPen)
    hOldPen = SelectObject(hMemDC, hPen);
  if (hBrush)
    hOldBrush = SelectObject(hMemDC, hBrush);

  StretchDIBits(hMemDC, 0, 0, 32, 32,
                        0, 0, 32, 32,
                        lpBits, lpbmi,
                        DIB_RGB_COLORS, SRCCOPY);

  (*lpfnDraw)(hMemDC);

  GetDIBits(hMemDC, hBitmap, 0,32, lpBits, lpbmi, DIB_RGB_COLORS);

  SelectObject(hMemDC, hOldBitmap);
  if (hPen)
    SelectObject(hMemDC, hOldPen);
  if (hBrush)
    SelectObject(hMemDC, hOldBrush);

  GlobalUnlock(hBits);
  DeleteDC(hMemDC);
  DeleteObject(hBitmap);
  if (hPen)
    DeleteObject(hPen);
  if (hBrush)
    DeleteObject(hBrush);

  GlobalUnlock(hbmi);
  GlobalFree(hbmi);
}

