/*
	spray.c

	spray_init		モジュールの初期化
	commandSpray
*/

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "ge.h"
#include "dispman.h"
#include "imageman.h"

#if 0
	
	static char *sprayPat[] =
	{
		"000001111100000",
		"000111111111000",
		"001111222111100",
		"011122222221110",
		"011222444222110",
		"111224666422111",
		"1122468b8642211",
		"112246bbb642211",
		"1122468b8642211",
		"111224666422111",
		"011222444222110",
		"011122222221110",
		"001111222111100",
		"000111111111000",
		"000001111100000",
		NULL
	};
	
	
	static int sprdatnum = 0;
	static struct {signed char dx,dy} sprdat[16*16*16], *sprp;
	
	
	static int ctox(char c)
	{
		if ('0'<=c && c<='9')
			return c-'0';
		else if ('a'<=c && c<='f')
			return c-'a'+10;
		else if ('A'<=c && c<='F')
			return c-'A'+10;
		else
			return 0;
	}
	
	static void makeSprayData(char **data)
	{
		int xlen,ylen;
		xlen=0;
		for (ylen=0; *(data+ylen)!=NULL; ylen++)
			xlen = _max(strlen(*(data+ylen)),xlen);
		int i,j,k;
		sprdatnum=0;
		for (i=0; i<ylen; i++) {
			char *p;
			p = *(data+i);
			for (j=0; j<xlen && *(p+j)!=0; j++,p++) {
				for (k = ctox(*p);  k;  k--) {
					sprdat[sprdatnum].dx = j-xlen/2;
					sprdat[sprdatnum].dy = i-ylen/2;
					sprdatnum++;
				}
			}
		}
	}

#endif

/*--------------------------------------------------------*/
/*                   モジュールの初期化                   */
/*--------------------------------------------------------*/

typedef	int	ireal;

#if 0
	static ireal *sintbl = NULL, *costbl = NULL;
#endif

#define	ID(n)	((n)<<10)
#define	FD(n)	(int)((n)*1024.0)
#define	DI(n)	(((n)+512)>>10)
#define	ANGLESTEP	1024		/* ２πを何分割するか */

int spray_init(void)
{
#if 0
	if (sintbl == NULL)
	{
		if ((sintbl = (ireal*)malloc(sizeof(ireal)*((ANGLESTEP/8)+1)*2))
			== NULL)
			return -1;
		costbl = sintbl + ((ANGLESTEP/8)+1);
		int i;
		for (i=0; i<=ANGLESTEP/8; i++)
		{
			sintbl[i] = FD(sin(2*_PI*(double)i/ANGLESTEP));
			costbl[i] = FD(cos(2*_PI*(double)i/ANGLESTEP));
		}
	}
#endif
	return 0;
}

#if 0
void getsincos(int theta, ireal *sin, ireal *cos)
// theta : 0..ANGLESTEP の整数
{
	while (theta < 0)
		theta += ANGLESTEP;
	theta %= ANGLESTEP;
	int a,b,c,si,co;
	a = theta / (ANGLESTEP/4);			// a = 0,1,2,3 : 象限を表す
	b = theta % (ANGLESTEP/4);
	if (b > (ANGLESTEP/8))
		c = 1, b = ANGLESTEP/4 - b;
	else
		c = 0;
	if (c == 0)
		si = sintbl[b], co = costbl[b];
	else
		si = costbl[b], co = sintbl[b];
	switch(a)
	{
	case 1:		*sin = si, *cos = -co;	break;
	case 2:		*sin = -si, *cos = -co;	break;
	case 3:		*sin = -si, *cos = co;	break;
	default:	*sin = si, *cos = co;	break;
	}
}
#endif

/*--------------------------------------------------------*/
/*                   スプレーのプロット                   */
/*--------------------------------------------------------*/

static void xpset(int x,int y,int col)
{
	int col0,r,g,b,r0,g0,b0,rnd,i,rr,gr,br;
	col0 = EIMpoint(x,y);
	r = getR(col);		g = getG(col);		b = getB(col);
	r0 = getR(col0);	g0 = getG(col0);	b0 = getB(col0);
	for (i=0; i<2; i++) {
		rr = _abs(r-r0);	gr = _abs(g-g0);	br = _abs(b-b0);
		if (rr+gr+br == 0)
			break;
		rnd = rand() % (rr+gr+br);
		if (rnd < rr) {
			if (r > r0)			r0++;
			else if (r < r0)	r0--;
		} else if (rnd < rr+gr) {
			if (g > g0)			g0++;
			else if (g < g0)	g0--;
		} else {
			if (b > b0)			b0++;
			else if (b < b0)	b0--;
		}
	}
	EIMpset(x,y,GRB(g0,r0,b0),DrawNORMAL);
}


static void plot_spray(int x, int y, int r, int col)
{
	int mixr0,mixr;
	mixr0 = getmixrate();
	for (int i=0; i<10; i++) {
		int dx,dy;
		dx = rand() % (spray_r*2+1) - spray_r;
		dy = rand() % (spray_r*2+1) - spray_r;
		if (dx*dx+dy*dy > spray_r*spray_r)
			continue;
		int xx,yy;
		xx = x + dx;		yy = y + dy;
		if (0<=xx && xx<EIMgetxsize() && 0<=yy && yy<EIMgetysize())
		{
			if (spray_t == 0)
			{
				if (mixr0 == 256)
					xpset(xx,yy,col);
					// EIMgraypset(xx,yy,col,7);
				else
				{
					char *cp = cbuf_adrs(xx,yy);  int conc = 32;
					int t = cbuf_mix(cbuf2conc(*cp), conc, mixr0);
					*cp = conc2cbuf(t);
					EIMpset(xx,yy,
							mixcol(EIMpoint_back(xx,yy),col,t,NO),
							DrawNORMAL);
				}
			}
			else
				psetWithPen(xx,yy,col,getcurpen(),YES);
		}
	}
}

/*--------------------------------------------------------*/
/*                 スプレーコマンドの実行                 */
/*--------------------------------------------------------*/

static void spray()
{
	int x,y;
	x = DMimage_getx(ms.x);
	y = DMimage_gety(ms.y);
	int i;
	int xx,yy;
	plot_spray(x, y, 16, forecol);
}


void commandSpray()
{
	DEBUG_MSG("commandSpray begin");
	// sprintf(debugmsg, "scrmode: %d", scrmode);
	DEBUG_MSG(debugmsg);
	bool first;
	// if (sprdatnum == 0)
	// 	makeSprayData(sprayPat);
	first = YES;
	for (;;) {
		DMdispcsr(ms.x,ms.y);
		do {
			ms_get(&ms);
		} while (ms.dx==0 && ms.dy==0 && ms.btn1==OFF && ms.btn2==OFF &&
				 key_chk() == 0);
		DMerasecsr();
		scrollForCsr(1,1);
		if (ms.btn1 == OFFON) {
			first = NO;
			EIMbackup();
			cbuf_clear();
			spray();
		} else if (ms.btn1 == ON) {
			if (!first)
				spray();
		}
		if (ms.btn2 == OFFON)
			break;
	}
	DEBUG_MSG("commandSpray end");
}

// end of spray.c
