/////////////////////////////////////////////////////////////////
// rasterop.cpp

#include <string.h>

#include "rasterop.h"

static unsigned long lbits[32] =
{
	0xFFFFFFFF, 0xFFFFFF7F, 0xFFFFFF3F, 0xFFFFFF1F,
	0xFFFFFF0F, 0xFFFFFF07, 0xFFFFFF03, 0xFFFFFF01,
	0xFFFFFF00, 0xFFFF7F00, 0xFFFF3F00, 0xFFFF1F00,
	0xFFFF0F00, 0xFFFF0700, 0xFFFF0300, 0xFFFF0100,
	0xFFFF0000, 0xFF7F0000, 0xFF3F0000, 0xFF1F0000,
	0xFF0F0000, 0xFF070000, 0xFF030000, 0xFF010000,
	0xFF000000, 0x7F000000, 0x3F000000, 0x1F000000,
	0x0F000000, 0x07000000, 0x03000000, 0x01000000
};

static unsigned long rbits[32] =
{
	0xFFFFFFFF, 0xFEFFFFFF, 0xFCFFFFFF, 0xF8FFFFFF,
	0xF0FFFFFF, 0xE0FFFFFF, 0xC0FFFFFF, 0x80FFFFFF,
	0x00FFFFFF, 0x00FEFFFF, 0x00FCFFFF, 0x00F8FFFF,
	0x00F0FFFF, 0x00E0FFFF, 0x00C0FFFF, 0x0080FFFF,
	0x0000FFFF, 0x0000FEFF, 0x0000FCFF, 0x0000F8FF,
	0x0000F0FF, 0x0000E0FF, 0x0000C0FF, 0x000080FF,
	0x000000FF, 0x000000FE, 0x000000FC, 0x000000F8,
	0x000000F0, 0x000000E0, 0x000000C0, 0x00000080
};


int bit_set( unsigned char bits[3300][300], int x1, int y1, int x2, int y2 )
{
#if 0
	// make p1 top-left, p2 bottom right
	if( x1 > x2 )
		swap(int, x1, x2);
	if( y1 > y2 )
		swap(int, y1, y2);
#endif

	int li = x1 / 32;	// index of leftmost long
	int lj = x1 % 32;	// bit index of leftmost long
	int ri = x2 / 32;	// index of rightmost long
	int rj = x2 % 32;	// bit index of rightmost long
	unsigned long lmask, rmask;

	int n = ri - li + 1;	// number of affected long words

	// calculate number of wholly affecte long words (n)
	// and left and right masks

	if( lj )		// leftmost partialy affected
	{
		lmask = lbits[lj];
		n--;
	}

	if( rj != 31 )	// rightmost partialy affected
	{
		rmask = rbits[31-rj];
		n--;
	}

	if( n < 0 )
	{ // single long word masked on both sides
		lmask &= rmask;
	}

	unsigned long (*longbits)[75];
	longbits = (unsigned long(*)[75])bits;

	int v = y1;
	for( int y = y1; y <= y2; y++, v++ )
	{
		int i = li;

		if( lj )
			longbits[v][i++] |= lmask;

		for( int c = 0; c < n; c++ )
			longbits[v][i++] |= 0xFFFFFFFF;

		if( rj != 31 && n >= 0 )
			longbits[v][i] |= rmask;
	}
	return 0;
}

int bit_blt( unsigned char d[3300][300], int x, int y, unsigned char *s, int w, int h )
{
	int j = x % 8, v = y;

	x = x / 8;
	w = (w + 7) / 8;
	while( h-- > 0 )
	{
		if( v >= 0 && v < 3300 )
		{
			int i = x;
			for( int k = w; k; k--, s++ )
			{
				if( i >= 0 && i < 300 )
				{
					if( j )
					{
						d[v][i++] |= *s >> j;
						if( i < 300 )
							d[v][i] |= *s << (8-j);
					}
					else
						d[v][i++] |= *s;
				}
				else
					i++;
			}
		}
		else
			s += w;
		v++;
	}
	return 0;
}

int bit_neg( unsigned char *d, int n )
{
	unsigned long *p = (unsigned long *)d;
	for( int i = n/4; i--; p++ )
		*p = ~*p;

	d = (unsigned char *)p;
	for( n = n%4; n--; d++ )
		*d = ~*d;

	return 0;
}

int bit_res( unsigned char *d, int w1, int h1, int w2, int h2 )
{
	int sx = (w1 + w2 - 1)/w2;
	int sy = (h1 + h2 - 1)/h2;
	int bpl = (w1+7)/8;

	if( sy > 1 )
	{
		unsigned char *p = d;
		unsigned char *q = p;
		unsigned char *r0 = new unsigned char[bpl];
		unsigned char *r = r0;
		memset( r0, 0, bpl );

		int j = 0;
		for( int y = 0; y < h1; y++ )
		{
			for( int i = 0; i < bpl; i++ )
			{
				unsigned char data = *p;
				if( !j )
					*q = *r;

				for( unsigned char mask = 0x80; mask; mask = mask >> 1 )
				{
					if( *r & mask )
					{
						if( !(data & mask) )
							*q &= ~mask;
					}
					else
					{
						if( data & mask )
							*q |= mask;
					}
				}
				p++;
				q++;
				r++;
			}

			j++;
			if( j == sy )
			{
				j = 0;
				r = q - bpl;
			}
			else
			{
				q -= bpl;
				r -= bpl;
			}
		}
		delete r0;
	}

	if( sx > 1 )
	{
		for( int y = 0; y < h1; y++ )
		{
			unsigned char smask = 0x80;
			unsigned char dmask = 0x80;
			unsigned char *p = d + y * bpl;
			unsigned char *q = p;

			int j = sx;
			unsigned char ddata = 0;
			unsigned char sdata = *p++;
			unsigned char f = 0;

			for( int x = 0; x < w1; x++ )
			{
				if( f )
				{
					if( !(sdata & smask) )
						ddata &= ~dmask;
				}
				else
				{
					if( sdata & smask )
						ddata |= dmask;
				}

				smask = smask >> 1;
				if( !smask )
				{
					sdata = *p++;
					smask = 0x80;
				}

				if( !--j )
				{
					f = ddata & dmask;

					dmask = dmask >> 1;

					if( !dmask )
					{
						dmask = 0x80;
						*q++ = ddata;
						ddata = 0;
					}
					if( f )
						ddata |= dmask;

					j = sx;
				}
			}
		}
	}
	return 0;
}