#ifndef BITMAP_H
#define BITMAP_H

// blitMode constants
// (in canonical logic table order)
//
#define  BLT_CLEAR         0  // 0
#define  BLT_NOR           1  // ~(src | dst)
#define  BLT_NOTAND        2  // ~src & dst
#define  BLT_NOTCOPY       3  // ~src
#define  BLT_ANDNOT        4  // src & ~dst
#define  BLT_NOT           5  // ~dst
#define  BLT_XOR           6  // src ^ dst
#define  BLT_NAND          7  // ~(src & dst)
#define  BLT_AND           8  // src & dst
#define  BLT_NEXOR         9  // ~(src ^ dst)
#define  BLT_NOP          10  // dst
#define  BLT_NOTOR        11  // ~src | dst
#define  BLT_COPY         12  // src
#define  BLT_ORNOT        13  // src | ~dst
#define  BLT_OR           14  // (src | dst)
#define  BLT_SET          15  // 1

// DPI <-> PelsPerMeter conversion
//
#define  DPI2PPM(dpi)  ((100.0/2.54)*dpi)
#define  PPM2DPI(ppm)  ((ppm/(100.0/2.54))

// Green LCD theme
//
#define  BMP_BGCOLOR  0x96ff00
#define  BMP_FGCOLOR  0x182800

// Midnight Blue
//
//#define  BMP_BGCOLOR  0x000040
//#define  BMP_FGCOLOR  0xC0C0FF

// Black n' White
//
//#define  BMP_BGCOLOR  0xFFFFFF
//#define  BMP_FGCOLOR  0x000000


/**
 * Compound structure for Windows .bmp files. For simplicity,
 * this structure contains a BITMAPFILEHEADER, BITMAPINFOHEADER,
 * and 2 RGBQUADS to directly support 2 color uncompressed
 * bitmap files.
 * Check out a copy of the Windows Platform SDK for more info.
 *
 */
typedef struct
{
  // BITMAPFILEHEADER
  short   bfType;                 // 0x4D42, 'BM'
  long    bfSize;                 // bits + 62
  short   bfReserved1;
  short   bfReserved2;
  long    bfOffBits;              // 62

  // BITMAPINFOHEADER
  long    biSize;                 // 40 bytes
  long    biWidth, biHeight;
  short   biPlanes, biBitCount;
  long    biCompression;
  long    biSizeImage;
  long    biXPelsPerMeter;
  long    biYPelsPerMeter;
  long    biClrUsed;
  long    biClrImportant;

  // RGBQUADS
  unsigned long color0, color1;

} BitmapFileHeader;


/**
 * Structure for in-memory bitmaps.
 *
 * This structure is somewhat special, because the bmBits do
 * directly follow the width and height entries. So be careful,
 * and use BM_Alloc/Free to handle Bitmap structures.
 *
 * The reason behind this is, that the Bitmap structure and its
 * bmBits can be adressed by using a single segment register.
 *
 * bmBitsSize will will be set to the size of the bmBits part
 * by BM_Alloc() (and should always be a multiple of two).
 *
 */
typedef struct Bitmap {
  int       width, height;
  unsigned  bmBitsSize;
  char      bmBits[];
} Bitmap;


typedef (BM_BlitFunc)(
  char *dst,   int dstwidth,
  char *src,   int srcwidth,
  int   width, int pages,
  char  shift, char fbm, char lbm
);


extern "C" {
  BM_BlitFunc  BM_Blit_Copy,   BM_Blit_NotCopy;
  BM_BlitFunc  BM_Blit_And,    BM_Blit_Nand;
  BM_BlitFunc  BM_Blit_NotAnd, BM_Blit_AndNot;
  BM_BlitFunc  BM_Blit_Or,     BM_Blit_Nor;
  BM_BlitFunc  BM_Blit_NotOr,  BM_Blit_OrNot;
  BM_BlitFunc  BM_Blit_Xor,    BM_Blit_Nexor;
}


/**
 * Get the color of the pixel located at (x,y).
 *
 * \param   bm pointer to bitmap
 * \param   x  x coordinate
 * \param   y  y coordinate
 * \returns 0  if pixel is cleared, != 0 if set
 *
 */
inline char BM_GetPixel(Bitmap *bm, int x, int y)
{
  if (x<0 || x>=bm->width || y<0 || y>=bm->height)
    return 0;
  if (bm->bmBits[x+(y>>3)*bm->width] & (1<<(y&7)))
    return 1;
  else
    return 0;
}


/**
 * Set or clear a pixel located at (x,y).
 *
 * \param bm     pointer to bitmap
 * \param x      x coordinate
 * \param y      y coordinate
 * \param color  color of the pixel. Either 0 or 1
 *
 */
inline void BM_PutPixel(Bitmap *bm, int x, int y, char color)
{
  if (x<0 || x>=bm->width || y<0 || y>=bm->height)
    return;
  if (color)
    bm->bmBits[x+(y>>3)*bm->width] |= 1<<(y&7);
  else
    bm->bmBits[x+(y>>3)*bm->width] &= ~(1<<(y&7));
}


/**
 * \todo  implement some nice-to-have functions:
 *
 * BM_Rotate, BM_Mirror, BM_Scale..
 */

extern  Bitmap *BM_Alloc( int w, int h );
extern  void    BM_Free( Bitmap *bm );
extern  Bitmap *BM_Copy( Bitmap *bm );

extern  void    BM_Clear( Bitmap *bm, char pattern=0x00 );
extern  void    BM_Invert( Bitmap *bm );
extern  void    BM_Scroll( Bitmap *bm, int dx, int dy );

extern  Bitmap *BM_Load( char *fn );
extern  void    BM_Save( Bitmap *bm, char *fn );

extern  void    BM_Blit( Bitmap *dst, int x,    int y,
                         Bitmap *src, int u=0,  int v=0,
                         int w=-1,    int h=-1, int mode=BLT_COPY );

extern  void    BM_FastBlit( Bitmap *dst, int x,    int y,
                             Bitmap *src, int u=0,  int v=0,
                             int w=-1,    int h=-1, int mode=BLT_COPY );

#endif
