
#include "samplepattern.h"


static const int TABLE_SIZE = 1;

static const unsigned int TABLE[TABLE_SIZE][2] = {
	{	0x01011010, 0x01011010 }, // middle of checkerboard
};


SamplePattern::SamplePattern() {

	_pattern = NULL;
	_multiplier = NULL;
	_xsize = _ysize = _size = 0;
	_inited = _updated = 0;
}

SamplePattern::~SamplePattern() {

	delete [] _pattern;
	delete [] _multiplier;
}

SamplePattern& SamplePattern::CopyFrom(const SamplePattern&) {

	cerr << "SamplePattern::CopyFrom() not implemented" << endl;

	return *this;
}

void SamplePattern::SampleEveryPixel() {

	for (int i=0; i<_size; i++) {
		_pattern[i] = 0;
		_multiplier[i] = 1;
	}

	_inited = _updated = 1;
}

void SamplePattern::SetSamplePattern(int p, int x1, int x2, int y1, int y2) {

	int x, y;

	if (x2 < 0) x2 = _xsize-x2-1;
	if (y2 < 0) y2 = _ysize-y2-1;

	switch (p) {
		case SAMPLE_PATTERN_EVERY_PIXEL:
			for (y=y1; y<y2; y++)
				for (x=x1; x<x2; x++)
					_pattern[y*_xsize +x] = 0;
			break;

		case SAMPLE_PATTERN_ALMOST_EVERY_PIXEL:
			for (y=y1; y<y2; y++)
				for (x=x1; x<x2; x++)
					_pattern[y*_xsize +x] = !((x%3) || (y%3));
			break;

		case SAMPLE_PATTERN_MOST_PIXELS:
			for (y=y1; y<y2; y++)
				for (x=x1; x<x2; x++)
					_pattern[y*_xsize +x] = ((x & y) & 1);
			break;

		case SAMPLE_PATTERN_CHECKERBOARD:
			for (y=y1; y<y2; y++)
				for (x=x1; x<x2; x++)
					_pattern[y*_xsize +x] = ((x ^ y) & 1);
			break;

		case SAMPLE_PATTERN_SPARSE:
			for (y=y1; y<y2; y++)
				for (x=x1; x<x2; x++)
					_pattern[y*_xsize +x] = !((x & y) & 1);
			break;

		case SAMPLE_PATTERN_VERY_SPARSE:
			for (y=y1; y<y2; y++)
				for (x=x1; x<x2; x++)
					_pattern[y*_xsize +x] = !!((x%3) || (y%3));
			break;

		default:
			cerr << "error in SamplePattern::SetSamplePattern(): "
				 << "undefined sample pattern: " << p << endl;
			exit(-1);
	}

	_inited = 1;
	_updated = 0;
}

void SamplePattern::NewSize(int x, int y) {

	delete [] _pattern;
	delete [] _multiplier;

	_xsize = x;
	_ysize = y;
	_size = x*y;

	_pattern = new unsigned int[_size];
	_multiplier = new float[_size];

	_inited = _updated = 0;
}

void SamplePattern::Update() {

	if (_updated)
		return;

	if (!_inited) {
		cerr << "Error: SamplePattern not initialized" << endl;
		exit(-1);
	}

	int t, b, l, r, tl, tr, bl, br;
	int p;

	for (int y=0; y<_ysize; y++)
		for (int x=0; x<_xsize; x++)

			if (!_pattern[y*_xsize + x]) {
				_multiplier[y*_xsize + x] = 1;
			}

			else {
				if (x>0) {
					tl = (y>0)			? !_pattern[(y-1)*_xsize + x-1] : 0;
					l  = !_pattern[y*_xsize + x-1];
					bl = (y<(_ysize-1)) ? !_pattern[(y+1)*_xsize + x-1] : 0;
				}
				else
					tl = l = bl = 0;
				if (x<(_xsize-1)) {
					tr = (y>0)			? !_pattern[(y-1)*_xsize + x+1] : 0;
					r  = !_pattern[y*_xsize + x+1];
					br = (y<(_ysize-1)) ? !_pattern[(y+1)*_xsize + x+1] : 0;
				}
				else
					tr = r = br = 0;
				t = (y>0)		   ? !_pattern[(y-1)*_xsize + x] : 0;
				b = (y<(_ysize-1)) ? !_pattern[(y+1)*_xsize + x] : 0;

				p = (tl << 0) |
					(t  << 4) |
					(tr << 8) |
					(l  << 12) |
					(r  << 16) |
					(bl << 20) |
					(b  << 24) |
					(br << 28);

				int i;

				for (i=0; i<TABLE_SIZE; i++)
					if (p == TABLE[i][0]) {
						p = TABLE[i][1];
						i = TABLE_SIZE;
					}

				_pattern[y*_xsize + x] = p;

				int total=0;
				for (i=0; i<8; i++) {
					total += (p & 0x0F);
					p >>= 4;
				}

				_multiplier[y*_xsize + x] = 1.0f / float(total);
			}

	_updated = 1;
}
