/**********************************************************************
 *
 * ibmcols.h - internal color definition
 *
 * NOTE: arch. independence header
 * for more information, please see the readme file
 *
 **********************************************************************/


#ifndef __IBMCOLS_H__
#define __IBMCOLS_H__

#include "ibitmap.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif


/**********************************************************************
 * COLOR OPERATION MACRO
 **********************************************************************/
#ifndef __IBITMAP_COLOR_TYPES
#define __IBITMAP_COLOR_TYPES
typedef unsigned long ICOLORD;     /* RAW-COLOR INTEGER: DWORD */
typedef unsigned short ICOLORW;     /* RAW-COLOR INTEGER: WORD. */
typedef unsigned char ICOLORB;     /* RAW-COLOR INTEGER: BYTE. */
typedef unsigned long ICOLORV;	  /* COLOR VECTOR: 0xAARRGGBB */
#endif

typedef struct IRGB
{ 
	unsigned char r, g, b; 
	unsigned char reserved;
}	IRGB;


#define ICORDER_USEBGRA		1	/* color-bits order: B0:B B1:G G2:R */


extern long _ishift_endian;
extern long _ishift_endmag;

/* color integer shifting in R-G-B bits-order */
extern int _ishift_rgb_r_15;
extern int _ishift_rgb_g_15;
extern int _ishift_rgb_b_15;
extern int _ishift_rgb_r_16;
extern int _ishift_rgb_g_16;
extern int _ishift_rgb_b_16;
extern int _ishift_rgb_r_24;
extern int _ishift_rgb_g_24;
extern int _ishift_rgb_b_24;
extern int _ishift_rgb_r_32;
extern int _ishift_rgb_g_32;
extern int _ishift_rgb_b_32;
extern int _ishift_rgb_a_32;
extern int _ishift_rgb_r_4444;
extern int _ishift_rgb_g_4444;
extern int _ishift_rgb_b_4444;
extern int _ishift_rgb_a_4444;

/* bytes shift 24bits */
extern int _ishift_data_b1;
extern int _ishift_data_b2;
extern int _ishift_data_b3;

/* color scale 1/4/5/6 bits -> 8 bits lookup table */
extern int _iscale_rgb_1[];
extern int _iscale_rgb_4[];
extern int _iscale_rgb_5[];  
extern int _iscale_rgb_6[];

/* color converter 15/16 bits -> 32 bits lookup table */
extern ICOLORD _iconvert_rgb_15_32[];
extern ICOLORD _iconvert_rgb_16_32[];

/* color converter 15 bits <-> 16 bits lookup table */
extern ICOLORW _iconvert_rgb_15_16[];
extern ICOLORW _iconvert_rgb_16_15[];
extern ICOLORW _iconvert_rgb_15_15[];
extern ICOLORW _iconvert_rgb_16_16[];

/* color converter 1555 <-> 4444 <-> 8888 lookup table */
extern ICOLORW _iconvert_rgb_1555_4444[];
extern ICOLORW _iconvert_rgb_4444_1555[];
extern ICOLORD _iconvert_rgb_1555_8888[];
extern ICOLORD _iconvert_rgb_4444_8888[];

/* color difference lookup table */
extern long _ilookup_diff[];

/* abs[n | n = (-255)->(+255)] = _ilookup_abs[256 + n] */
extern unsigned char _ilookup_abs[];

/* global palette array */
extern IRGB _ipaletted[];
extern IRGB*_icolormap;
extern int _icolorconv;

#define _imcolor15(r, g, b) ((ICOLORD)( \
            (((ICOLORD)(r) >> 3) << _ishift_rgb_r_15) | \
            (((ICOLORD)(g) >> 3) << _ishift_rgb_g_15) | \
            (((ICOLORD)(b) >> 3) << _ishift_rgb_b_15)))

#define _imcolor16(r, g, b) ((ICOLORD)( \
            (((ICOLORD)(r) >> 3) << _ishift_rgb_r_16) | \
            (((ICOLORD)(g) >> 2) << _ishift_rgb_g_16) | \
            (((ICOLORD)(b) >> 3) << _ishift_rgb_b_16)))

#define _imcolor24(r, g, b) ((ICOLORD)( \
            ((ICOLORD)(r) << _ishift_rgb_r_24) | \
            ((ICOLORD)(g) << _ishift_rgb_g_24) | \
            ((ICOLORD)(b) << _ishift_rgb_b_24)))

#define _imcolora32(r, g, b, a) ((ICOLORD)( \
            ((ICOLORD)(r) << _ishift_rgb_r_32) | \
            ((ICOLORD)(g) << _ishift_rgb_g_32) | \
            ((ICOLORD)(b) << _ishift_rgb_b_32) | \
            ((ICOLORD)(a) << _ishift_rgb_a_32)))

#define _imcolor32(r, g, b)	_imcolora32(r, g, b, 0)


/**********************************************************************
 * COLOR READ/WRITE FUNCTION
 **********************************************************************/
#define _im_getr8(c) (_ipaletted[c].r)
#define _im_getg8(c) (_ipaletted[c].g)
#define _im_getb8(c) (_ipaletted[c].b)
#define _im_geta8(c) 255

#define _im_getr15(c) (_iscale_rgb_5[((c) >> _ishift_rgb_r_15) & 0x1F])
#define _im_getg15(c) (_iscale_rgb_5[((c) >> _ishift_rgb_g_15) & 0x1F])
#define _im_getb15(c) (_iscale_rgb_5[((c) >> _ishift_rgb_b_15) & 0x1F])
#define _im_geta15(c) 255

#define _im_getr16(c) (_iscale_rgb_5[((c) >> _ishift_rgb_r_16) & 0x1F])
#define _im_getg16(c) (_iscale_rgb_6[((c) >> _ishift_rgb_g_16) & 0x3F])
#define _im_getb16(c) (_iscale_rgb_5[((c) >> _ishift_rgb_b_16) & 0x1F])
#define _im_geta16(c) 255

#define _im_getr24(c) ( ((c) >> _ishift_rgb_r_24) & 0xFF )
#define _im_getg24(c) ( ((c) >> _ishift_rgb_g_24) & 0xFF )
#define _im_getb24(c) ( ((c) >> _ishift_rgb_b_24) & 0xFF )
#define _im_geta24(c) 255

#define _im_getr32(c) ( ((c) >> _ishift_rgb_r_32) & 0xFF )
#define _im_getg32(c) ( ((c) >> _ishift_rgb_g_32) & 0xFF )
#define _im_getb32(c) ( ((c) >> _ishift_rgb_b_32) & 0xFF )
#define _im_geta32(c) ( ((c) >> _ishift_rgb_a_32) & 0xFF )

#define _im_getr4444(c) (_iscale_rgb_4[((c) >> _ishift_rgb_r_4444) & 15])
#define _im_getg4444(c) (_iscale_rgb_4[((c) >> _ishift_rgb_g_4444) & 15])
#define _im_getb4444(c) (_iscale_rgb_4[((c) >> _ishift_rgb_b_4444) & 15])
#define _im_geta4444(c) (_iscale_rgb_4[((c) >> _ishift_rgb_a_4444) & 15])

#define _im_getr1555(c) (_iscale_rgb_4[((c) >> _ishift_rgb_r_1555) & 31])
#define _im_getg1555(c) (_iscale_rgb_4[((c) >> _ishift_rgb_g_1555) & 31])
#define _im_getb1555(c) (_iscale_rgb_4[((c) >> _ishift_rgb_b_1555) & 31])
#define _im_geta1555(c) (_iscale_rgb_1[((c) >> _ishift_rgb_a_1555) &  1])

#define _imcolor15i(r, g, b   ) _imcolor15(b, g, r   )
#define _imcolor16i(r, g, b   ) _imcolor16(b, g, r   )
#define _imcolor24i(r, g, b   ) _imcolor24(b, g, r   )
#define _imcolor32i(r, g, b, a) _imcolor32(b, b, r, a)

#define _im_getr15i(c) _im_getb15(c)
#define _im_getg15i(c) _im_getg15(c)
#define _im_getb15i(c) _im_getr15(c)
#define _im_getr16i(c) _im_getb16(c)
#define _im_getg16i(c) _im_getg16(c)
#define _im_getb16i(c) _im_getr16(c)
#define _im_getr24i(c) _im_getb24(c)
#define _im_getg24i(c) _im_getg24(c)
#define _im_getb24i(c) _im_getr24(c)
#define _im_getr32i(c) _im_getb32(c)
#define _im_getg32i(c) _im_getg32(c)
#define _im_getb32i(c) _im_getr32(c)
#define _im_geta32i(c) _im_geta32(c)
#define _im_getr4444i(c) _im_getb4444(c)
#define _im_getg4444i(c) _im_getg4444(c)
#define _im_getb4444i(c) _im_getr4444(c)
#define _im_geta4444i(c) _im_geta4444(c)
#define _im_getr1555i(c) _im_getb1555(c)
#define _im_getg1555i(c) _im_getg1555(c)
#define _im_getb1555i(c) _im_getr1555(c)
#define _im_geta1555i(c) _im_geta1555(c)


/* approximate color fetching */
#define _im_getir8(c) _im_getr8(c)
#define _im_getig8(c) _im_getg8(c)
#define _im_getib8(c) _im_getb8(c)
#define _im_getia8(c) 255

#if 1
/* however switching the '#if' abrove to 1 seems faster then 0 in GCC -O3 */
#define _im_getir15(c) ( (((c) >> 10) & 0x1F) << 3 )
#define _im_getig15(c) ( (((c) >> 5) & 0x1F) << 3 )
#define _im_getib15(c) ( (((c) >> 0) & 0x1F) << 3 )
#define _im_getia15(c) 255

#define _im_getir16(c) ( (((c) >> 11) & 0x1F) << 3 )
#define _im_getig16(c) ( (((c) >> 5) & 0x3F) << 2 )
#define _im_getib16(c) ( (((c) >> 0) & 0x1F) << 3 )
#define _im_getia16(c) 255

#else
/* strange why the implementation below is slower than abrove in GCC -O3 */
#define _im_getir15(c) ( (((c) >> 7) & 0xf8) )
#define _im_getig15(c) ( (((c) >> 2) & 0xf8) )
#define _im_getib15(c) ( (((c) << 3) & 0xf8) )
#define _im_getia15(c) 255

#define _im_getir16(c) ( (((c) >> 8) & 0xf8) )
#define _im_getig16(c) ( (((c) >> 3) & 0xfc) )
#define _im_getib16(c) ( (((c) << 3) & 0xf8) )
#define _im_getia16(c) 255

#endif

#define _im_getir24(c) ( (((c) >> 16) & 0xff) )
#define _im_getig24(c) ( (((c) >>  8) & 0xff) )
#define _im_getib24(c) ( (((c) >>  0) & 0xff) )
#define _im_getia24(c) 255

#define _im_getia32(c) ( (((c) >> 24) & 0xff) )
#define _im_getir32(c) ( (((c) >> 16) & 0xff) )
#define _im_getig32(c) ( (((c) >>  8) & 0xff) )
#define _im_getib32(c) ( (((c) >>  0) & 0xff) )

#define _im_getia1555(c) ( (((c) >> 15) & 0x1) << 7)
#define _im_getir1555(c) ( (((c) >> 10) & 0x1F) << 3 )
#define _im_getig1555(c) ( (((c) >> 5) & 0x1F) << 3 )
#define _im_getib1555(c) ( (((c) >> 0) & 0x1F) << 3 )

#define _im_getia4444(c) ( (((c) >>12) & 0xf) << 4 )
#define _im_getir4444(c) ( (((c) >> 8) & 0xf) << 4 )
#define _im_getig4444(c) ( (((c) >> 4) & 0xf) << 4 )
#define _im_getib4444(c) ( (((c) >> 0) & 0xf) << 4 )

#define _im_getia8888(c) _im_getia32(c)
#define _im_getir8888(c) _im_getir32(c)
#define _im_getig8888(c) _im_getig32(c)
#define _im_getib8888(c) _im_getib32(c)
#define _im_getia555(c) _im_getia15(c)
#define _im_getir555(c) _im_getir15(c)
#define _im_getig555(c) _im_getig15(c)
#define _im_getib555(c) _im_getib15(c)
#define _im_getia565(c) _im_getia16(c)
#define _im_getir565(c) _im_getir16(c)
#define _im_getig565(c) _im_getig16(c)
#define _im_getib565(c) _im_getib16(c)
#define _im_getia888(c) _im_getia24(c)
#define _im_getir888(c) _im_getir24(c)
#define _im_getig888(c) _im_getig24(c)
#define _im_getib888(c) _im_getib24(c)

#define _im_unpack_rgb(col, bpp, r, g, b)  \
		(r) = _im_getir##bpp(col), \
		(g) = _im_getig##bpp(col), \
		(b) = _im_getib##bpp(col)

#define _im_unpack_argb(col, bpp, a, r, g, b) \
		(a) = _im_getia##bpp(col), \
		(r) = _im_getir##bpp(col), \
		(g) = _im_getig##bpp(col), \
		(b) = _im_getib##bpp(col) 


#define _im_scale_rgb(col, bpp, r, g, b)  \
		(r) = _im_getr##bpp(col), \
		(g) = _im_getg##bpp(col), \
		(b) = _im_getb##bpp(col)

#define _im_scale_argb(col, bpp, a, r, g, b) \
		(a) = _im_geta##bpp(col), \
		(r) = _im_getr##bpp(col), \
		(g) = _im_getg##bpp(col), \
		(b) = _im_getb##bpp(col) 


#define IRGBV(r, g, b) ((ICOLORD)( \
            ((ICOLORD)(r) << 16) | \
            ((ICOLORD)(g) << 8) | \
            ((ICOLORD)(b) << 0)))

#define IRGBA(r, g, b, a) ((ICOLORD)( \
            ((ICOLORD)(r) << 16) | \
            ((ICOLORD)(g) << 8) | \
            ((ICOLORD)(b) << 0) | \
            ((ICOLORD)(a) << 24)))

#define _im_pack_c15(r, g, b) ((ICOLORW)( \
			((ICOLORW)((r) & 0xf8) << 7) | \
			((ICOLORW)((g) & 0xf8) << 2) | \
			((ICOLORW)((b) & 0xf8) >> 3)))

#define _im_pack_c16(r, g, b) ((ICOLORW)( \
			((ICOLORW)((r) & 0xf8) << 8) | \
			((ICOLORW)((g) & 0xfc) << 3) | \
			((ICOLORW)((b) & 0xf8) >> 3)))

#define _im_pack_c8(r, g, b) ((ICOLORB)( \
			((ICOLORB)((r) & 0xe0) << 0) | \
			((ICOLORB)((g) & 0xe0) >> 3) | \
			((ICOLORB)((b) & 0xff) >> 6)))

#define _im_pack_c24(r, g, b) IRGBV(r, g, b)
#define _im_pack_c32(r, g, b) IRGBV(r, g, b)

#define _im_pack_a32(a, r, g, b) IRGBA(r, g, b, a)
#define _im_pack_a8888(a, r, g, b) _im_pack_a32(a, r, g, b)

#define _im_pack_a1555(a, r, g, b) (_im_pack_c15(r, g, b) | \
			((((ICOLORW)(a)) & 0x80) << 8))

#define _im_pack_a4444(a, r, g, b)  ((ICOLORW)( \
			((ICOLORW)((r) & 0xf0) << 4) | \
			((ICOLORW)((g) & 0xf0) << 0) | \
			((ICOLORW)((b) & 0xf0) >> 4) | \
			((ICOLORW)((a) & 0xf0) << 8)))

#define _im_pack_rgb(bpp, r, g, b) \
		_im_pack_c##bpp(r, g, b)

#define _im_pack_bgr(bpp, r, g, b) \
		_im_pack_rgb(bpp, b, g, r)

#define _im_pack_argb(bpp, a, r, g, b) \
		_im_pack_a##bpp(a, r, g, b)

#define _im_pack_rgba(bpp, a, r, g, b) \
		_im_pack_argb(bpp, r, g, b, a)

#define _im_pack_abgr(bpp, a, r, g, b) \
		_im_pack_argb(bpp, a, b, g, r)

#define _im_pack_bgra(bpp, a, r, g, b) \
		_im_pack_argb(bpp, b, g, r, a)


/* make raw-color value with rgb */
ICOLORD _im_color_raw(ICOLORV rgb, int bpp, int order, const IRGB *pal);

/* make rgb-color value with raw */
ICOLORV _im_color_rgb(ICOLORD raw, int bpp, int order, const IRGB *pal);


#define _im_get1b(p) (((ICOLORB*)(p))[0])
#define _im_get2b(p) (((ICOLORW*)(p))[0])
#define _im_get4b(p) (((ICOLORD*)(p))[0])

#define _im_put1b(p, c) (((ICOLORB*)(p))[0] = (ICOLORB)(c))
#define _im_put2b(p, c) (((ICOLORW*)(p))[0] = (ICOLORW)(c))
#define _im_put4b(p, c) (((ICOLORD*)(p))[0] = (ICOLORD)(c))

#define _im_get3bx(p, b1, b2, b3) ( \
		(((ICOLORD)((ICOLORB*)(p))[0]) << (b1)) | \
		(((ICOLORD)((ICOLORB*)(p))[1]) << (b2)) | \
		(((ICOLORD)((ICOLORB*)(p))[2]) << (b3)) )

#define _im_put3bx(p, c, b1, b2, b3) \
		((ICOLORB*)(p))[0] = (ICOLORB)(((c) >> b1) & 0xFF), \
		((ICOLORB*)(p))[1] = (ICOLORB)(((c) >> b2) & 0xFF), \
		((ICOLORB*)(p))[2] = (ICOLORB)(((c) >> b3) & 0xFF)

#define _im_get3b(p) ( \
        (((ICOLORD)((ICOLORB*)(p))[0]) << _ishift_data_b1) | \
		(((ICOLORD)((ICOLORB*)(p))[1]) << _ishift_data_b2) | \
		(((ICOLORD)((ICOLORB*)(p))[2]) << _ishift_data_b3) )

#define _im_put3b(p, c) do { \
		((ICOLORB*)(p))[0] = (ICOLORB)(((c) >> _ishift_data_b1) & 0xFF); \
		((ICOLORB*)(p))[1] = (ICOLORB)(((c) >> _ishift_data_b2) & 0xFF); \
		((ICOLORB*)(p))[2] = (ICOLORB)(((c) >> _ishift_data_b3) & 0xFF); \
}	while (0)


#define ICOLORCONV_MASK_TRANS	1
#define ICOLORCONV_KEEP_TRANS	2
#define ICOLORCONV_DITHER_BLIT	4


void _ishift_init(void);
int _igenerate_332_palette(IRGB *pal);


/**********************************************************************
 * PIXEL GET/PUT
 **********************************************************************/
#define _ipixel_get_8(ptr)   _im_get1b(ptr)
#define _ipixel_get_15(ptr)  _im_get2b(ptr)
#define _ipixel_get_16(ptr)  _im_get2b(ptr)
#define _ipixel_get_24(ptr)  _im_get3b(ptr)
#define _ipixel_get_32(ptr)  _im_get4b(ptr)

#define _ipixel_put_8(ptr, col)  _im_put1b(ptr, col)
#define _ipixel_put_15(ptr, col) _im_put2b(ptr, col)
#define _ipixel_put_16(ptr, col) _im_put2b(ptr, col)
#define _ipixel_put_24(ptr, col) _im_put3b(ptr, col)
#define _ipixel_put_32(ptr, col) _im_put4b(ptr, col)

#define _ipixel_get(bpp, ptr)      _ipixel_get_##bpp(ptr)
#define _ipixel_put(bpp, ptr, col) _ipixel_put_##bpp(ptr, col)


/**********************************************************************
 * BITMAP OPERATION MACRO
 **********************************************************************/

typedef struct IBITMAP IBITMAP;

#define IFLAG_USEBGR	1	/* Bitmap - inverse bytes order (b,g,r,a) */
#define IFLAG_MTLOCK	2	/* Bitmap - must lock the bitmap          */
#define IFLAG_HAVEALPHA	4	/* Bitmap - have alpha channel            */
#define IFLAG_ALPHALOW  8   /* Bitmap - alpha in low bit order        */

#define IBCLIP	1			/* BLIT - use area clip			*/
#define IBCKEY	2			/* BLIT - use source color key	*/

#define _ilineptr(bmp, y) ((unsigned char*)((bmp)->line[y]))

#define _iget8(bmp, x, y ) _im_get1b(_ilineptr(bmp, y) + (x))
#define _iget15(bmp, x, y) _im_get2b(_ilineptr(bmp, y) + (x) * 2)
#define _iget16(bmp, x, y) _im_get2b(_ilineptr(bmp, y) + (x) * 2)
#define _iget24(bmp, x, y) _im_get3b(_ilineptr(bmp, y) + (x) * 3)
#define _iget32(bmp, x, y) _im_get4b(_ilineptr(bmp, y) + (x) * 4)

#define _iput8(b, x, y, c ) _im_put1b(_ilineptr(b, y) + (x), c)
#define _iput15(b, x, y, c) _im_put2b(_ilineptr(b, y) + (x) * 2, c)
#define _iput16(b, x, y, c) _im_put2b(_ilineptr(b, y) + (x) * 2, c)
#define _iput24(b, x, y, c) _im_put3b(_ilineptr(b, y) + (x) * 3, c)
#define _iput32(b, x, y, c) _im_put4b(_ilineptr(b, y) + (x) * 4, c)

#define _ibitmap_w(bmp)      ((long)((bmp)->w))
#define _ibitmap_h(bmp)      ((long)((bmp)->h))
#define _ibitmap_bpp(bmp)    ((long)((bmp)->bpp))
#define _ibitmap_pitch(bmp)  ((long)((bmp)->pitch))

#define _ibitmap_mask(bmp)   ((bmp)->mask)
#define _ibitmap_colorkey(bmp) _ibitmap_mask(bmp)
#define _ibitmap_pnbytes(bmp)  ((_ibitmap_bpp(bmp) + 7) >> 3)

#define _ibitmap_mode(b) ((b)->mode)
#define _ibitmap_code(b) ((b)->code)

#define _ibitmap_flags(b, flag) (_ibitmap_mode(b) & flag)
#define _ibitmap_flags_chk(b, flag) _ibitmap_flags(b, flag)

#define _ibitmap_flags_set(b, flag) \
	_ibitmap_mode(b) = (_ibitmap_mode(b) | flag)
#define _ibitmap_flags_clr(b, flag) \
	_ibitmap_mode(b) = (_ibitmap_mode(b) & (~((ICOLORD)flag)))

#define _ibitmap_isbgr(b)    _ibitmap_flags(b, IFLAG_USEBGR)
#define _ibitmap_mustlock(b) _ibitmap_flags(b, IFLAG_MUSTLOCK)

#define _ibitmap_order(b) (_ibitmap_mode(b) >> 16)
#define _ibitmap_set_order(b, order) do { \
		_ibitmap_mode(b) = (_ibitmap_mode(b) & 0xffff) | \
		((order & 0x7fff) << 16); \
	}	while (0);


/**********************************************************************
 * LIN's LOOP UNROLL MACROs: 
 * Actually Duff's unroll macro isn't compatible with vc7 because
 * of non-standard usage of 'switch' & 'for' statement. 
 * the macros below are standard implementation of loop unroll
 **********************************************************************/
#define ILINS_LOOP_UNROLL(action, width) do { \
	unsigned long __width = (unsigned long)(width); \
	unsigned long __increment = __width >> 3; \
	for (; __increment > 0; __increment--) { \
		action; \
		action; \
		action; \
		action; \
		action; \
		action; \
		action; \
		action; \
	}	\
	switch (__width & 7) \
	{		\
	case 7: action; \
	case 6: action; \
	case 5: action; \
	case 4: action; \
	case 3: action; \
	case 2: action; \
	case 1: action; \
	case 0:	break;	\
	}		\
}	while (0)

#define ILINS_LOOP_DOUBLE(action, actionx2, width) do { \
	unsigned long __width = (unsigned long)(width); \
	unsigned long __increment = __width >> 2; \
	for (; __increment > 0; __increment--) { \
		actionx2;	\
		actionx2;	\
	}	\
	switch (__width & 3) { \
	case 2: actionx2; break; \
	case 3: actionx2; \
	case 1: action; break; \
	}	\
}	while (0)

#define ILINS_LOOP_QUATRO(action, actionx2, actionx4, width) do { \
	unsigned long __width = (unsigned long)(width);	\
	unsigned long __increment = __width >> 2; \
	for (; __increment > 0; __increment--) { \
		actionx4;	\
	}	\
	switch (__width & 3) { \
	case 2: actionx2; break; \
	case 3: actionx2; \
	case 1: action; break; \
	}	\
}	while (0)

#define ILINS_LOOP_ONCE(action, width) do { \
	unsigned long __width = (unsigned long)(width); \
	for (; __width > 0; __width--) { action; } \
}	while (0)

#define ILINS_LOOP_DOUBLE_SLOW(action, actionx2, width) do { \
	unsigned long __width = (unsigned long)(width); \
	unsigned long __increment = __width >> 1; \
	for (; __increment > 0; __increment--) { actionx2; } \
	if (__width & 1) { action; }  \
}	while (0)


/**********************************************************************
 * PLATFORM DEPEDENCE
 **********************************************************************/
#if (defined(__BORLANDC__) || defined(__WATCOMC__))
#if (defined(__BORLANDC__) && (!defined(__MSDOS__)))
#pragma warn -8002  
#pragma warn -8004  
#pragma warn -8008  
#pragma warn -8012
#pragma warn -8027
#pragma warn -8057  
#pragma warn -8066
#elif !defined(__BORLANDC__)
#pragma warn -533
#endif
#endif

#if (defined(BUILD_TINY) || defined(__MSDOS__))
#ifndef IDISABLE_CONVERT
#define IDISABLE_CONVERT
#endif
#ifndef IDISABLE_BLEND
#define IDISABLE_BLEND
#endif
#endif



/**********************************************************************
 * PALETTE OPERATION
 **********************************************************************/
#define _ilookup_diff_r(r1, r2) _ilookup_diff[(r1) - (r2) +  256]
#define _ilookup_diff_g(g1, g2) _ilookup_diff[(g1) - (g2) +  768]
#define _ilookup_diff_b(b1, b2) _ilookup_diff[(b1) - (b2) + 1280]

void _imake_lookup_diff(void);

int _ibestfit_color(IRGB *pal, int r, int g, int b, int palsize);


/**********************************************************************
 * BITMAP COLOR CONVERTION
 **********************************************************************/

/* skipping src-mask (src colorkey) when performancing converting,
   enable this flag will using color-shifting method (no matter
   wheather ICONV_SHIFT is set */
#define ICONV_MASK         IBLIT_MASK

/* ICONV_RGB2BGR / ICONV_BGR2RGB is needed when converting needs to swap 
   color order from RGB to BGR or from BGR to RGB. For example, when you 
   want to convert R8G8B8 to B8G8R8, R5B5G5 to B8G8R8, just enable it */
#define ICONV_RGB2BGR      32
#define ICONV_BGR2RGB      ICONV_RGB2BGR

/* when converting lowwer color bits to higher bits, 16bits -> 24bits etc,
   there are two way to do it: lookup-table (default) & bits-shifting
   lookup-table will not cause color losing and fast in most platform,
   bits-shifting will cause color losing, enable ICONV_SHIFT to use it */
#define ICONV_SHIFT        64

/* skipping src-mask (src colorkey) and replacing with the dest 
   color key */
#define ICONV_KEEPTRANS    128

#define ICONV_CLIP         IBLIT_CLIP
#define ICONV_HFLIP        IBLIT_HFLIP
#define ICONV_VFLIP        IBLIT_VFLIP


void _iconvert_blit(IBITMAP *dst, int dx, int dy, IBITMAP *src,
	int sx, int sy, int w, int h, IRGB *pal, int flags);


#ifndef IDISABLE_CONVERT
/**********************************************************************
 * FAST COLOR CONVERTION
 **********************************************************************/

/**
 * _iconvert_fast:
 *
 * color format converting routine, supports endian indepedance, 
 * mask color converting, lookup-table color scaling and color order
 * swapping. EACH converting is compiled into DIFFERENT-C-FUNCTION
 * to get the high performance.
 * 
 * parameters:
 * dst, dx, dy - destination bitmap and position
 * src, sx, sy - source bitmap and position
 * w, h        - size
 * pal         - palette (can be used when srcbpp/dstbpp is 8 bits
 * flags       - enable ICONV_RGB2BGR or ICONV_SHIFT or ICONV_MASK
*/
void _iconvert_fast(IBITMAP *dst, int dx, int dy, IBITMAP *src,
	int sx, int sy, int w, int h, IRGB *pal, int flags);



void _iconvert_argb(IBITMAP *dst, int dx, int dy, IBITMAP *src,
	int sx, int sy, int w, int h, IRGB *pal, int ismask);

#endif


/**********************************************************************
 * BITMAP BLIT EFFECT
 **********************************************************************/
void _iblit_fill(IBITMAP *dst, int dx, int dy, int w, int h, 
	unsigned long rawcol, int alpha);

#ifndef IDISABLE_BLEND
void _iblit_blend(IBITMAP *dst, int dx, int dy, IBITMAP *src,
	int sx, int sy, int w, int h, int ismask, int alpha);
#endif


/**********************************************************************
 * COLOR SHIFTING
 **********************************************************************/
#define _icshift_mask(c, s, m) (((c) >> (s)) & (m))

#define _icsr1_8(c) _icshift_mask(c, 1, 0x6d6d6d6d)	
#define _icsr2_8(c) _icshift_mask(c, 2, 0x24242424)	
#define _icsr3_8(c) _icshift_mask(c, 0, 0x00000000)	
#define _icsr4_8(c) _icshift_mask(c, 0, 0x00000000)

#define _icsr1_15(c) _icshift_mask(c, 1, 0x3def3def)	
#define _icsr2_15(c) _icshift_mask(c, 2, 0x1ce71ce7)	
#define _icsr3_15(c) _icshift_mask(c, 3, 0x0c630c63)	
#define _icsr4_15(c) _icshift_mask(c, 4, 0x04210421)

#define _icsr1_16(c) _icshift_mask(c, 1, 0x7bef7bef)
#define _icsr2_16(c) _icshift_mask(c, 2, 0x39e739e7)
#define _icsr3_16(c) _icshift_mask(c, 3, 0x18e318e3)
#define _icsr4_16(c) _icshift_mask(c, 4, 0x08610861)

#define _icsr1_24(c) _icshift_mask(c, 1, 0x7f7f7f)
#define _icsr2_24(c) _icshift_mask(c, 2, 0x3f3f3f)
#define _icsr3_24(c) _icshift_mask(c, 3, 0x1f1f1f)
#define _icsr4_24(c) _icshift_mask(c, 4, 0x0f0f0f)

#define _icsr1_32(c) _icshift_mask(c, 1, 0x7f7f7f7f)
#define _icsr2_32(c) _icshift_mask(c, 2, 0x3f3f3f3f)
#define _icsr3_32(c) _icshift_mask(c, 3, 0x1f1f1f1f)
#define _icsr4_32(c) _icshift_mask(c, 4, 0x0f0f0f0f)

#define _icmd_0(bpp, c) ( 0 )
#define _icmd_1(bpp, c) ( _icsr4_##bpp(c) )
#define _icmd_2(bpp, c) ( _icsr3_##bpp(c) )
#define _icmd_3(bpp, c) ( _icmd_2(bpp, c) + _icmd_1(bpp, c) )
#define _icmd_4(bpp, c) ( _icsr2_##bpp(c) )
#define _icmd_5(bpp, c) ( _icmd_4(bpp, c) + _icmd_1(bpp, c) )
#define _icmd_6(bpp, c) ( _icmd_4(bpp, c) + _icmd_2(bpp, c) )
#define _icmd_7(bpp, c) ( _icmd_4(bpp, c) + _icmd_3(bpp, c) )
#define _icmd_8(bpp, c) ( _icsr1_##bpp(c) )
#define _icmd_9(bpp, c) ( _icmd_8(bpp, c) + _icmd_1(bpp, c) )
#define _icmd_10(bpp,c) ( _icmd_8(bpp, c) + _icmd_2(bpp, c) )
#define _icmd_11(bpp,c) ( _icmd_8(bpp, c) + _icmd_3(bpp, c) )
#define _icmd_12(bpp,c) ( _icmd_8(bpp, c) + _icmd_4(bpp, c) )
#define _icmd_13(bpp,c) ( _icmd_8(bpp, c) + _icmd_5(bpp, c) )
#define _icmd_14(bpp,c) ( _icmd_8(bpp, c) + _icmd_6(bpp, c) )
#define _icmd_15(bpp,c) ( _icmd_8(bpp, c) + _icmd_7(bpp, c) )
#define _icmd_16(bpp,c) ( c )

#define _iblend_color(bpp, c1, d1, c2, d2) \
		(_icmd_##d1(bpp, c1) + _icmd_##d2(bpp, c2))

#define _iblend_0(bpp, c1, c2) _iblend_color(bpp, c1, 0, c2, 16)
#define _iblend_1(bpp, c1, c2) _iblend_color(bpp, c1, 1, c2, 15)
#define _iblend_2(bpp, c1, c2) _iblend_color(bpp, c1, 2, c2, 14)
#define _iblend_3(bpp, c1, c2) _iblend_color(bpp, c1, 3, c2, 13)
#define _iblend_4(bpp, c1, c2) _iblend_color(bpp, c1, 4, c2, 12)
#define _iblend_5(bpp, c1, c2) _iblend_color(bpp, c1, 5, c2, 11)
#define _iblend_6(bpp, c1, c2) _iblend_color(bpp, c1, 6, c2, 10)
#define _iblend_7(bpp, c1, c2) _iblend_color(bpp, c1, 7, c2, 9)
#define _iblend_8(bpp, c1, c2) _iblend_color(bpp, c1, 8, c2, 8)
#define _iblend_9(bpp, c1, c2) _iblend_color(bpp, c1, 9, c2, 7)
#define _iblend_10(bpp, c1, c2) _iblend_color(bpp, c1, 10, c2, 6)
#define _iblend_11(bpp, c1, c2) _iblend_color(bpp, c1, 11, c2, 5)
#define _iblend_12(bpp, c1, c2) _iblend_color(bpp, c1, 12, c2, 4)
#define _iblend_13(bpp, c1, c2) _iblend_color(bpp, c1, 13, c2, 3)
#define _iblend_14(bpp, c1, c2) _iblend_color(bpp, c1, 14, c2, 2)
#define _iblend_15(bpp, c1, c2) _iblend_color(bpp, c1, 15, c2, 1)
#define _iblend_16(bpp, c1, c2) _iblend_color(bpp, c1, 16, c2, 0)

#define _iblend_fast(bpp, alpha, c1, c2) _iblend_##alpha(bpp, c1, c2)
#define _iblend_alpha(alpha) (((alpha) + 1) * 16 / 255)

#define _iblend_pixel_ex(ptr, dbits, dsize, col, alpha) { \
			unsigned long cc = _im_get##dsize##b(ptr); \
			cc = _iblend_fast(dbits, alpha, col, cc); \
			_im_put##dsize##b(ptr, cc); \
		}

#define _iblend_pixel_8(ptr, cc, aa)  _iblend_pixel_ex(ptr,  8, 1, cc, aa)
#define _iblend_pixel_15(ptr, cc, aa) _iblend_pixel_ex(ptr, 15, 2, cc, aa)
#define _iblend_pixel_16(ptr, cc, aa) _iblend_pixel_ex(ptr, 16, 2, cc, aa)
#define _iblend_pixel_24(ptr, cc, aa) _iblend_pixel_ex(ptr, 24, 3, cc, aa)
#define _iblend_pixel_32(ptr, cc, aa) _iblend_pixel_ex(ptr, 32, 4, cc, aa)

#define _ipixel_blend(bpp, ptr, c, a) _iblend_pixel_##bpp(ptr, c, a)

#define _icolor_gray_0(R, G, B) ((R) * 0.3 + (G) * 0.59 + (B) * 0.11)
#define _icolor_gray_1(R, G, B) (((R) * 77 + (G) * 151 + (B) * 28) >> 8)


/**********************************************************************
 * HANDLERS
 **********************************************************************/



#ifdef __cplusplus
}
#endif


#endif


