// Copyright 1994 Brad Pitzel
//
// Feel free to use/distribute/modify as long as credit/copyrights for myself 
// are included.


#include "Bitmap.h"

void Bitmap::copy( const Bitmap& b ) 
	{ 
        allocMem( b.width(), b.height() );
        		       
        if (Vmap!=NULL)   memcpy(Vmap, b.Vmap, Vsize);
	}

// copy with scaling	
void Bitmap::copy( const Bitmap& b, int w, int h )
	{
	// check if scale factor=1
	if ( (b.width()==w) && (b.height()==h) )
		{
		copy( b );
		}
	else	{
		allocMem(w,h);
		
		if (Vmap!=NULL)
			{
			gl_scalebox( b.width(), b.height(), 
			             (unsigned char *)b.map(),
				     w, h, Vmap);
			}
		}
	}
				
// rotate 90 degress counter-clockwise
void Bitmap::rotcc90()
	{
	// only works on square bitmaps
	if (width()==height())
		{
		int x,y;
		unsigned char *ul,*ur,*ll,*lr,swap;

		for( y=0; y<(height()>>1); y++)
			for( x=y; x<(width()-y-1); x++)
				{
				ul = (Vmap + offset(x,y));
				ur = (Vmap + offset(width()-1-y,x));
				ll = (Vmap + offset(y,height()-1-x));
				lr = (Vmap + offset(width()-1-x,height()-1-y));
				
				swap = *ur;
				*ur = *lr;
				*lr = *ll;
				*ll = *ul;
				*ul = swap;
				}
		}
	}
	
// rotate 90 degress clockwise
void Bitmap::rotc90()
	{
	// only works on square bitmaps
	if (width()==height())
		{
		int x,y;
		unsigned char *ul,*ur,*ll,*lr,swap;

		for( y=0; y<(height()>>1); y++)
			for( x=y; x<(width()-y-1); x++)
				{
				ul = (Vmap + offset(x,y));
				ur = (Vmap + offset(width()-1-y,x));
				ll = (Vmap + offset(y,height()-1-x));
				lr = (Vmap + offset(width()-1-x,height()-1-y));
				
				swap = *ul;
				*ul = *ll;
				*ll = *lr;
				*lr = *ur;
				*ur = swap;
				}
		}
	}

// Simple/dumb rotate bitmap routine.
// width() and height() do not change, therefore
// parts of the bitmap could be rotated 'out'.
void Bitmap::rot(int degrees)
	{
	unsigned char *buf = new unsigned char[size()];

	if (buf==NULL) 
		{
		cerr << "Bitmap::rot(), unable to allocated memory.\n";
		return;
		}

	int x,y,x1,y1;
	double xo,yo;
	unsigned char c;
	
	// middle of bitmap
	xo = (double)( width() >> 1  );
	yo = (double)( height() >> 1 );
	
	// loop through each pixel in new buffer, and rotate *backwards*
	// into the bitmap to see what color it should have.
	// This method avoids getting holes in the bitmap
	for(y=0; y<height(); y++)
		for(x=0; x<width(); x++)
			{
			x1 = (int) ( xo + ((double)x-xo)*FastMath::cos(-degrees) -
					  ((double)y-yo)*FastMath::sin(-degrees));

			y1 = (int) ( yo + ((double)x-xo)*FastMath::sin(-degrees) +
					  ((double)y-yo)*FastMath::cos(-degrees));


			if ( (x1<0) || (x1>=width()) ||
			     (y1<0) || (y1>=height()) )
			     	{
			     	c = 0;
			     	}
			else	{
				c = *(Vmap + offset( x1,y1 ) ); 
				}
				     	
			*(buf + offset((int)x, (int)y) ) = c;

			}
	// delete original- if we had allocated the mem ourselves
	if (Valloc) delete [] Vmap;
	
	Valloc = 1;

	// set bitmap to new rotated bitmap
	Vmap = buf;

	}

	
// allocate memory for the bitmap
void Bitmap::allocMem( int w, int h )
	{
	if (Valloc==1) 
		{
		// if new size same as old, just reuse mem
		if ( (width()==w) && (height()==h) )
			{
			return;
			}
		delete [] Vmap;
		}
	
	Vmap = new unsigned char[w*h];
	
	// determine if 'new' succeeded, set Valloc
	// accordingly
	if (Vmap!=NULL)
		{
		Valloc = 1;
		Vwidth = w;
		Vheight= h;
		Vsize  = w*h;
		}
	else	{
		Valloc = 0;
		Vwidth = 0;
		Vheight= 0;
		Vsize  = 0;
		}
	}
