/*
	smooth.c

	戸田浩氏のスムース処理を解析するための一時ソース
*/

#include <stdlib.h>
#include <stdlib.h>

#include "ge.h"
#include "imageman.h"
#include "dispman.h"


#define	MYSpoint	EIMpoint


void commandSmooth()
{
	for (;;)
	{
		if (area_input(AREA_POLYGON) != 0)
			break;
		EIMbackup();
		smooth(28,0);
	}
}

#if 1
// 1993.6.12

smooth( rate, rnd )
int rate, rnd;
{
	int ax1, ay1, ax2, ay2, a, b, c, d, cmp;
	int start, mid, fine, mode, r, s, x, y;
	int k0, k1, k2;
	int mp[4];

	area_getboundxy(&ax1,&ay1,&ax2,&ay2);
	s = 32 - rate;			/* sharp rate */
	r = rnd;

	for( y=ay1+1 ; y<=ay2-1 ; y++ ){
		mode = 0;
		for( x=ax1+1 ; x<=ax2-1 ; x++ ){
			a = EIMpoint_back(x,y);		// a=WORD(bbuf+vadd+x*2);
			b = EIMpoint_back(x,y+1);	// b=WORD(bbuf+vadd+x*2+1024);
			c = EIMpoint_back(x+1,y);	// c=WORD(bbuf+vadd+x*2+2);
			d = EIMpoint_back(x+1,y-1);	// d=WORD(bbuf+vadd+x*2-1022);
			cmp = cmpdata( a, b, s );
			if( (mode == 0) && cmp ){
				mode = 1;
				start = x;
				k0 = 0;
			}
			if( (mode == 1) && (cmp == 0) )mode = 0;
			if( (mode == 2) && (cmpdata( a, d, s ) == 0) ){
				mode = 0;
				fine = x;
				smooth1( start, mid, fine, y, r );
				x = mid;
			}
			if( mode == 1 ){
			  k1 = katamuki( x, y );
			  if( cmpdata(a,c,s) ){
			    if( (k1 <= k0) && (k1 < 0) ){
			      k2 = katamuki( x+1, y );
			      if( (k1 <= k2) || (cmpdata(b,c,12) == 0) ){
					mode = 2;
					mid = x;
			      }
			    }
			  }
			  k0 = k1;
			}
			if( (mode == 2) && (cmpdata( c, d, s ) == 0) ){
				mode = 0;
				fine = x;
				smooth1( start, mid, fine, y, r );
				x = mid;
			}
		}
	}
	for( y=ay1+1 ; y<=ay2-1 ; y++ ){
		mode = 0;
		for( x=ax2-1 ; x>=ax1+1 ; x-- ){
			a = EIMpoint_back(x,y);		// a=WORD(bbuf+vadd+x*2);
			b = EIMpoint_back(x,y+1);	// b=WORD(bbuf+vadd+x*2+1024);
			c = EIMpoint_back(x-1,y);	// c=WORD(bbuf+vadd+x*2-2);
			d = EIMpoint_back(x-1,y-1);	// d=WORD(bbuf+vadd+x*2-1026);
			cmp = cmpdata( a, b, s );
			if( (mode == 0) && cmp ){
				mode = 1;
				start = x;
				k0 = 0;
			}
			if( (mode == 1) && (cmp == 0) )mode = 0;
			if( (mode == 2) && (cmpdata( a, d, s ) == 0) ){
				mode = 0;
				fine = x;
				smooth2( start, mid, fine, y, r );
				x = mid;
			}
			if( mode == 1 ){
			  k1 = katamuki( x, y );
			  if( cmpdata(a,c,s) ){
			    if( (k1 >= k0) && (k1 > 0) ){
			      k2 = katamuki( x-1, y );
			      if( (k1 >= k2) || (cmpdata(b,c,12) == 0) ){
				mode = 2;
				mid = x;
			      }
			    }
			  }
			  k0 = k1;
			}
			if( (mode == 2) && (cmpdata( c, d, s ) == 0) ){
				mode = 0;
				fine = x;
				smooth2( start, mid, fine, y, r );
				x = mid;
			}
		}
	}

	for( x=ax1+1 ; x<=ax2-1 ; x++ ){
		// vadd = x*2; mode = 0;
		mode = 0;
		for( y=ay1+1 ; y<=ay2-1 ; y++ ){
			a = EIMpoint_back(x,y);		// a=WORD(bbuf+vadd+y*1024);
			b = EIMpoint_back(x+1,y);	// b=WORD(bbuf+vadd+y*1024+2);
			c = EIMpoint_back(x,y+1);	// c=WORD(bbuf+vadd+y*1024+1024);
			d = EIMpoint_back(x-1,y+1);	// d=WORD(bbuf+vadd+y*1024+1022);
			cmp = cmpdata( a, b, s );
			if( (mode == 0) && cmp ){
				mode = 1;
				start = y;
				k0 = 0;
			}
			if( (mode == 1) && (cmp == 0) )mode = 0;
			if( (mode == 2) && (cmpdata( a, d, s ) == 0) ){
				mode = 0;
				fine = y;
				smooth3( start, mid, fine, x, r );
				y = mid;
			}
			if( mode == 1 ){
			  k1 = katamuki( x, y );
			  if( cmpdata(a,c,s) ){
			    if( (k1 <= k0) && (k1 < 0) ){
			      k2 = katamuki( x, y+1 );
			      if( (k1 <= k2) || (cmpdata(b,c,12) == 0) ){
				mode = 2;
				mid = y;
			      }
			    }
			  }
			  k0 = k1;
			}
			if( (mode == 2) && (cmpdata( c, d, s ) == 0) ){
				mode = 0;
				fine = y;
				smooth3( start, mid, fine, x, r );
				y = mid;
			}
		}
	}

	for( x=ax2-1 ; x>=ax1+1 ; x-- ){
		// vadd = x*2; mode = 0;
		mode = 0;
		for( y=ay1+1 ; y<=ay2-1 ; y++ ){
			a = EIMpoint_back(x,y);		// a=WORD(bbuf+vadd+y*1024);
			b = EIMpoint_back(x-1,y);	// b=WORD(bbuf+vadd+y*1024-2);
			c = EIMpoint_back(x,y+1);	// c=WORD(bbuf+vadd+y*1024+1024);
			d = EIMpoint_back(x+1,y+1);	// d=WORD(bbuf+vadd+y*1024+1026);
			cmp = cmpdata( a, b, s );
			if( (mode == 0) && cmp ){
				mode = 1;
				start = y;
				k0 = 0;
			}
			if( (mode == 1) && (cmp == 0) )mode = 0;
			if( (mode == 2) && (cmpdata( a, d, s ) == 0) ){
				mode = 0;
				fine = y;
				smooth4( start, mid, fine, x, r );
				y = mid;
			}
			if( mode == 1 ){
			  k1 = katamuki( x, y );
			  if( cmpdata(a,c,s) ){
			    if( (k1 >= k0) && (k1 > 0) ){
			      k2 = katamuki( x, y+1 );
			      if( (k1 >= k2) || (cmpdata(b,c,12) == 0) ){
				mode = 2;
				mid = y;
			      }
			    }
			  }
			  k0 = k1;
			}
			if( (mode == 2) && (cmpdata( c, d, s ) == 0) ){
				mode = 0;
				fine = y;
				smooth4( start, mid, fine, x, r );
				y = mid;
			}
		}
	}
}

katamuki( x, y )		/* return=(karamuki + or 0 or -) s=rate */
int x, y;
{
	int p[3][3];
	int ck;

	// vadd = y*1024;
	ck = 0;
	if (x-1<0 || y-1<0 || EIMgetxsize()<=x+1 || EIMgetysize()<=y+1)
		return 0;
	// if( (vadd+x*2-1026 < 0) || (vadd+x*2+1026 > 524286) )return 0;
	// 座標チェック！
	p[0][0] = EIMpoint_back(x-1,y-1);	// p[0][0]=WORD(bbuf+vadd+x*2-1026);
	p[0][1] = EIMpoint_back(x  ,y-1);	// p[0][1]=WORD(bbuf+vadd+x*2-1024);
	p[0][2] = EIMpoint_back(x+1,y-1);	// p[0][2]=WORD(bbuf+vadd+x*2-1022);
	p[1][0] = EIMpoint_back(x-1,y  );	// p[1][0]=WORD(bbuf+vadd+x*2-2);
	p[1][1] = EIMpoint_back(x  ,y  );	// p[1][1]=WORD(bbuf+vadd+x*2);
	p[1][2] = EIMpoint_back(x+1,y  );	// p[1][2]=WORD(bbuf+vadd+x*2+2);
	p[2][0] = EIMpoint_back(x-1,y+1);	// p[2][0]=WORD(bbuf+vadd+x*2+1022);
	p[2][1] = EIMpoint_back(x  ,y+1);	// p[2][1]=WORD(bbuf+vadd+x*2+1024);
	p[2][2] = EIMpoint_back(x+1,y+1);	// p[2][2]=WORD(bbuf+vadd+x*2+1026);

	ck = ck - kata_s( p[0][0], p[1][1] );
	ck = ck - kata_s( p[0][1], p[1][2] );
	ck = ck - kata_s( p[1][0], p[2][1] );
	ck = ck - kata_s( p[1][1], p[2][2] );

	ck = ck + kata_s( p[0][1], p[1][0] );
	ck = ck + kata_s( p[0][2], p[1][1] );
	ck = ck + kata_s( p[1][1], p[2][0] );
	ck = ck + kata_s( p[1][2], p[2][1] );

	return ck;
}

kata_s( a, b )		/* total abs(sub) */
int a, b;
{
	int data1, data2, subd, add;

	data1 = a & 0x1f; data2 = b & 0x1f;
	subd = data2 - data1; if( subd < 0 )subd = -subd;
	add = subd;
	data1 = (a >> 5) & 0x1f; data2 = (b >> 5) & 0x1f;
	subd = data2 - data1; if( subd < 0 )subd = -subd;
	add = add + subd;
	data1 = (a >> 10) & 0x1f; data2 = (b >> 10) & 0x1f;
	subd = data2 - data1; if( subd < 0 )subd = -subd;
	add = add + subd;
	return add;
}

cmpdata( a, b, rate )
int a, b, rate;
{
	int data1, data2, subd;

	data1 = a & 0x1f; data2 = b & 0x1f;
	subd = data2 - data1; if( subd < 0 )subd = -subd;
	if( subd > rate )return 1;
	data1 = (a >> 5) & 0x1f; data2 = (b >> 5) & 0x1f;
	subd = data2 - data1; if( subd < 0 )subd = -subd;
	if( subd > rate )return 1;
	data1 = (a >> 10) & 0x1f; data2 = (b >> 10) & 0x1f;
	subd = data2 - data1; if( subd < 0 )subd = -subd;
	if( subd > rate )return 1;
	return 0;
}

smooth1( st, md, fn, y, r )		/* r=random( 0-256 ) */
int st, md, fn, y, r;
{
	int x1, x2, x3;
	int i, n, top, rate, a, b, c;

	x1 = ( st + md ) >> 1;
	x2 = md;
	x3 = ( md + fn + 1 ) >> 1;
	top = y*1024;
	if( x1 == x2 )goto smoo1;
	rate = 128/(x2-x1+1);
	n = 1;
	for( i=x1 ; i<=x2-1 ; i++ ){
		a = EIMpoint_back(i,y+1); // a = WORD( bbuf+top+i*2+1024 );
		b = MYSpoint(i,y); // b = peekw( top+i*2, 0x10c );
		if( area_chkxy(i,y) /* && (b < 0x8000) マスク */ ){
			c = mix( a, b, n*rate, r );
			EIMpset( i,y, c, DrawNORMAL );
		}
		n++;
	}
	if( x2 == x3 )goto smoo2;
smoo1:	if( x2 == x3 )return 0;
	rate = 128/(x3-x2+1);
	n = 1;
	for( i=x2+1 ; i<=x3 ; i++ ){
		a = EIMpoint_back(i,y-1); // a = WORD( bbuf+top+i*2-1024 );
		b = MYSpoint(i,y); //  b = peekw( top+i*2, 0x10c );
		if( area_chkxy(i,y) /* && (b < 0x8000) */){
			c = mix( a, b, (128 - n*rate), r );
			EIMpset(i,y,c,DrawNORMAL);
		}
		n++;
	}
smoo2:
	a = MYSpoint(x2-1,y);	// a = peekw( top+x2*2-2, 0x10c );
	b = MYSpoint(x2+1,y);	// b = peekw( top+x2*2+2, 0x10c );
	if( area_chkxy(x2,y) /* && (b < 0x8000) */){
		c = mix( a, b, 128, r );
		EIMpset(x2,y,c,DrawNORMAL);  // pokew( top+x2*2, 0x10c, c );
	}
	return 0;
}

smooth2( st, md, fn, y, r )		/* r=random( 0-256 ) */
int st, md, fn, y, r;
{
	int x1, x2, x3;
	int i, n, top, rate, a, b, c;

	x1 = ( st + md + 1 ) >> 1;
	x2 = md;
	x3 = ( md + fn ) >> 1;
	top = y*1024;
	if( x1 == x2 )goto smoo1;
	rate = 128/(x1-x2+1);
	n = 1;
	for( i=x1 ; i>=x2+1 ; i-- ){
		a = EIMpoint_back(i,y+1);	// a = WORD( bbuf+top+i*2+1024 );
		b = MYSpoint(i,y);			// b = peekw( top+i*2, 0x10c );
		if( area_chkxy(i,y) /* && (b < 0x8000) */ ){
			c = mix( a, b, n*rate, r );
			EIMpset(i,y,c,DrawNORMAL);	// pokew( top+i*2, 0x10c, c );
		}
		n++;
	}
	if( x2 == x3 )goto smoo2;
smoo1:
	if( x2 == x3 )return 0;
	rate = 128/(x2-x3+1);
	n = 1;
	for( i=x2-1 ; i>=x3 ; i-- ){
		a = EIMpoint_back(i,y-1);	// a = WORD( bbuf+top+i*2-1024 );
		b = MYSpoint(i,y);	// b = peekw( top+i*2, 0x10c );
		if( area_chkxy(i,y) /* && (b < 0x8000) */){
			c = mix( a, b, (128 - n*rate), r );
			EIMpset(i,y,c,DrawNORMAL); // pokew( top+i*2, 0x10c, c );
		}
		n++;
	}
smoo2:
	a = MYSpoint(x2+1,y); // a = peekw( top+x2*2+2, 0x10c );
	b = MYSpoint(x2-1,y); // b = peekw( top+x2*2-2, 0x10c );
	if( area_chkxy(x2,y) /* && (b < 0x8000) */){
		c = mix( a, b, 128, r );
		EIMpset(x2,y,c,DrawNORMAL); // pokew( top+x2*2, 0x10c, c );
	}
	return 0;
}

smooth3( st, md, fn, x, r )
int st, md, fn, x, r;
{
	int y1, y2, y3;
	int i, n, top, rate, a, b, c;

	y1 = ( st + md ) >> 1;
	y2 = md;
	y3 = ( md + fn ) >> 1;
	top = x*2;
	if( y1 == y2 )goto smoo1;
	rate = 128/(y2-y1+1);
	n = 1;
	for( i=y1 ; i<=y2-1 ; i++ ){
		a = EIMpoint_back(x+1,i); // a = WORD( bbuf+top+i*1024+2 );
		b = MYSpoint(x,i); // b = peekw( top+i*1024, 0x10c );
		if( area_chkxy(x,i) /*  && (b < 0x8000) */ ){
			c = mix( a, b, n*rate, r );
			EIMpset(x,i,c,DrawNORMAL); // pokew( top+i*1024, 0x10c, c );
		}
		n++;
	}
	if( y2 == y3 )goto smoo2;
smoo1:
	if( y2 == y3 )return 0;
	rate = 128/(y3-y2+1);
	n = 1;
	for( i=y2+1 ; i<=y3 ; i++ ){
		a = EIMpoint_back(x-1,i); // a = WORD( bbuf+top+i*1024-2 );
		b = MYSpoint(x,i); // b = peekw( top+i*1024, 0x10c );
		if( area_chkxy(x,i) /* && (b < 0x8000) */ ){
			c = mix( a, b, (128 - n*rate), r );
			EIMpset(x,i,c,DrawNORMAL); // pokew( top+i*1024, 0x10c, c );
		}
		n++;
	}
smoo2:
	a = MYSpoint(x,y2+1); // a = peekw( top+y2*1024+1024, 0x10c );
	b = MYSpoint(x,y2-1); // b = peekw( top+y2*1024-1024, 0x10c );
	if( area_chkxy(x,y2) /*  && (b < 0x8000) */ ){
		c = mix( a, b, 128, r );
		EIMpset(x,y2,c,DrawNORMAL); // pokew( top+y2*1024, 0x10c, c );
	}
	return 0;
}

smooth4( st, md, fn, x, r )
int st, md, fn, x, r;
{
	int y1, y2, y3;
	int i, n, top, rate, a, b, c;

	y1 = ( st + md ) >> 1;
	y2 = md;
	y3 = ( md + fn ) >> 1;
	top = x*2;
	if( y1 == y2 )goto smoo1;
	rate = 128/(y2-y1+1);
	n = 1;
	for( i=y1 ; i<=y2-1 ; i++ ){
		a = EIMpoint_back(x-1,i); // a = WORD( bbuf+top+i*1024-2 );
		b = MYSpoint(x,i); // b = peekw( top+i*1024, 0x10c );
		if( area_chkxy(x,i) /* && (b < 0x8000) */ ){
			c = mix( a, b, n*rate, r );
			EIMpset(x,i,c,DrawNORMAL); // pokew( top+i*1024, 0x10c, c );
		}
		n++;
	}
	if( y2 == y3 )goto smoo2;
smoo1:	if( y2 == y3 )return 0;
	rate = 128/(y3-y2+1);
	n = 1;
	for( i=y2+1 ; i<=y3 ; i++ ){
		a = EIMpoint_back(x+1,i); // a = WORD( bbuf+top+i*1024+2 );
		b = MYSpoint(x,i); // b = peekw( top+i*1024, 0x10c );
		if( area_chkxy(x,i) /* && (b < 0x8000) */ ){
			c = mix( a, b, (128 - n*rate), r );
			EIMpset(x,i,c,DrawNORMAL); // pokew( top+i*1024, 0x10c, c );
		}
		n++;
	}
smoo2:
	a = MYSpoint(x,y2+1); // a = peekw( top+y2*1024+1024, 0x10c );
	b = MYSpoint(x,y2-1); // b = peekw( top+y2*1024-1024, 0x10c );
	if( area_chkxy(x,y2) /*  && (b < 0x8000) */ ){
		c = mix( a, b, 128, r );
		EIMpset(x,y2,c,DrawNORMAL); // pokew( top+y2*1024, 0x10c, c );
	}
	return 0;
}

#if 0

#endif


	/* 新しいrand()が合わなくなったんで自家製に切り換え 1993 3/6 */
static int my_rand()
{
	static unsigned int next = 1 ;

	next = next * 1103515245 + 12345 ;
	return (unsigned int)( next / 65536 ) % 32768 ;
}


static int mix( a, b, rate, r )	/* r = random rate ( 0-256 ) ( rate +-r ) */
int a, b, rate, r;
{
	int div, rate1, data, data1, data2, add;

	div = 32768/(r*2 + 1);

	rate1 = rate + my_rand()/div - r;
	if( rate1 < 0 )rate1 = 0;
	if( rate1 > 256 )rate1 = 256;
	data1 = a & 0x1f; data2 = b & 0x1f;
	add = ( data1*rate1 + data2*(256-rate1) + 0x80 ) >> 8;
	data = add;

	rate1 = rate + my_rand()/div - r;
	if( rate1 < 0 )rate1 = 0;
	if( rate1 > 256 )rate1 = 256;
	data1 = (a >> 5) & 0x1f; data2 = (b >> 5) & 0x1f;
	add = ( data1*rate1 + data2*(256-rate1) + 0x80 ) >> 8;
	data = data + ( add << 5 );

	rate1 = rate + my_rand()/div - r;
	if( rate1 < 0 )rate1 = 0;
	if( rate1 > 256 )rate1 = 256;
	data1 = (a >> 10) & 0x1f; data2 = (b >> 10) & 0x1f;
	add = ( data1*rate1 + data2*(256-rate1) + 0x80 ) >> 8;
	data = data + ( add << 10 );
	return data;
}






#endif
