/**************************************************************/
/**  C++ code Copyright (C) Nick V. King <nking@eworld.com>  **/
/**************************************************************/

#include <gf_mac.h>

#include <defines.h>
#include <gui_mac.h>

grey_font_mac::grey_font_mac(const uint16 width, const uint16 height) : grey_font(width, height)
{
	extern int dataColor;

	currentType = dataColor;
	if (currentType == 1)
		heap_check(macSquares = new Handle [width * height + 1]);
	else
		heap_check(macSquares = new Handle [101]);
	w = width;
	h = height;
	_generate_squares();

	font_number = ++fonts_created;
	index = 0;
}

int grey_font_mac::resize(const uint16 width, const uint16 height)
{
	if ((currentType == 1) && ((uint32)width * height > MAX_SIZE))
		fatal_error((DREstring)"Cannot resize grey_font with " +
		DREstring10((uint32)width * height) + (DREstring)" entries");

	return _rebuild(width, height);
}

uint16 grey_font_mac::_rebuild(const uint16 width, const uint16 height)
{
	extern int dataColor;

	if (currentType == 1)
		for (short level = 0; level <= w*h; level++)
			KillPicture((PicHandle)macSquares[level]);
	else
		for (level = 0; level <= 100; level++)
			DisposPixPat((PixPatHandle)macSquares[level]);
	destroy_array(macSquares);

	currentType = dataColor;
	if (currentType == 1)
		heap_check(macSquares = new Handle [width * height + 1]);
	else
		heap_check(macSquares = new Handle [101]);
	w = width;
	h = height;
	_generate_squares();

	font_number = ++fonts_created;
	index = 0;
	
	return(width * height);
}

uint32 grey_font_mac::max_character_number(const uint16 width, const uint16 height)
{
	extern int dataColor;

	return(dataColor == 1 ? width*height : 100);
}

void grey_font_mac::_generate_squares(void)
{
	if (currentType == 1)
	{
		RGBColor foregroundRGB, backgroundRGB;
		SaveColors(foregroundRGB, backgroundRGB);
		for (short level = 0; level <= w*h; level++)
			macSquares[level] = (Handle)_generate_square(level);
		RestoreColors(foregroundRGB, backgroundRGB);
	}
	else
	{
		for (short level = 0; level <= 100; level++)
		{
			RGBColor theColor;
			if (currentType == 2)
				theColor.red = theColor.green = theColor.blue = 65535-level*655;
			else
			{
				HSVColor theHSVColor;
				theHSVColor.hue = (SmallFract)(43605 - level*436);
				theHSVColor.saturation = theHSVColor.value = (SmallFract)65535;
				HSV2RGB(&theHSVColor, &theColor);
			}	
			macSquares[level] = (Handle)NewPixPat();
			MakeRGBPat((PixPatHandle)macSquares[level], &theColor);	
		}
	}
}

void* grey_font_mac::_generate_square(const uint16 n_black)
{
	yield();

	Rect theRect;
	SetRect(&theRect, 0, 0, w, h);
	PicHandle thePicture = OpenPicture(&theRect);
	extern RGBColor blackRGB, whiteRGB;
	RGBForeColor(&blackRGB);
	RGBBackColor(&whiteRGB);

	const int square_size = w*h;
	int n_to_do;
	if (n_black > square_size/2)
	{
		PaintRect(&theRect);
		n_to_do = square_size - n_black;
	}
	else
	{
		EraseRect(&theRect);
		n_to_do = n_black;
	}
	if (n_to_do)
	{
		PenMode(srcXor);
		Boolean* alreadyDone = new Boolean [square_size];
		for (short fill = 0; fill < square_size; fill++)
			alreadyDone[fill] = false;
		int n_marked = 0;
		for (int j = 1; n_marked < n_to_do; j++)
			for (int i = 0; (i < square_size) && (n_marked < n_to_do); i++)
				if (!alreadyDone[i] && ((rand() / (1.0 * RAND_MAX)) < (1.0 / (10.0 * w))))
				{
					MoveTo((short)(i % w), (short)(i / w));
					Line(0, 0);
					alreadyDone[i] = true;
					n_marked++;
				}
		destroy_array(alreadyDone);
		PenNormal();
	}
	ClosePicture();
	return thePicture;
}

void* grey_font_mac::memory_pattern(const int n)
{
	return(macSquares[n]);
}

/***********/
/**  End  **/
/***********/