/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#define ___OVERLAY_C___

#include	<stdlib.h>
#include	<math.h>
#include	"memory_debug.h"
#include	"utils.h"
#include	"resource.h"

void ov_default();
void ovf_transparent();
/*
OVERLAY default_overlay = {
	{0,OVT_OVERWRAP,ov_default}
};
*/
OV_TRANSPARENT default_overlay 
	= {{0,OVT_TRANSPARENT,ovf_transparent},0.5};



OVERLAY * overlay_list;


int
ov_setup(OV_ARG * d,OV_ARG * s)
{
int x,y;
	*d = *s;
	if ( d->d_x >= d->d_w )
		return -1;
	if ( d->d_y >= d->d_h )
		return -1;
	if ( d->d_x < 0 ) {
		x = -d->d_x;
		d->d_x = 0;
		d->d_x_w -= x;
		if ( d->d_x_w <= 0 )
			return -1;
		d->s_x += x;
		if ( d->s_x >= d->s_w )
			return -1;
	}
	if ( d->d_y < 0 ) {
		y = -d->d_y;
		d->d_y = 0;
		d->d_y_h -= y;
		if ( d->d_y_h <= 0 )
			return -1;
		d->s_y += y;
		if ( d->s_y >= d->s_h )
			return -1;
	}
	if ( d->d_x + d->d_x_w > d->d_w ) {
		x = d->d_x + d->d_x_w - d->d_w;
		d->d_x_w -= x;
	}
	if ( d->d_y + d->d_y_h >= d->d_h ) {
		y = d->d_y + d->d_y_h - d->d_h;
		d->d_y_h -= y;
	}
	if ( d->s_x >= d->s_w )
		return -1;
	if ( d->s_y >= d->s_h )
		return -1;
	if ( d->s_x < 0 ) {
		x = - d->s_x;
		d->s_x = 0;
		d->d_x_w -= x;
		if ( d->d_x_w <= 0 )
			return -1;
		d->d_x += x;
		if ( d->d_x >= d->d_w )
			return -1;
	}
	if ( d->s_y < 0 ) {
		y = - d->s_y;
		d->s_y = 0;
		d->d_y_h -= y;
		if ( d->d_y_h <= 0 )
			return -1;
		d->d_y += y;
		if ( d->d_y >= d->d_h )
			return -1;
	}
	if ( d->s_x + d->d_x_w >= d->s_w ) {
		x = d->s_x + d->d_x_w - d->s_w;
		d->d_x_w -= x;
	}
	if ( d->s_y + d->d_y_h >= d->s_h ) {
		y = d->s_y + d->d_y_h - d->s_h;
		d->d_y_h -= y;
	}
	return 0;
}

void
ov_default(OVERLAY * ov,OV_ARG * aa)
{
OV_ARG b;
unsigned long * dp, * sp;
char * rp;
int ix;
int i;
int yy;
unsigned long cc;
int y_last,w;
int s_yy;

	if ( ov_setup(&b,aa) < 0 )
		return;
	y_last = b.d_y + b.d_y_h;
	w = b.d_x_w;
	yy = b.d_y;
	s_yy = b.s_y;

	for ( ; yy < y_last ; yy ++ , s_yy ++ ) {
		ix = yy*b.d_w + b.d_x;
		dp = &b.dest[ix];
		sp = &b.src[s_yy*b.s_w + b.s_x];
		rp = &b.redraw[ix];
		for ( i = 0 ; i < w ; i ++ ) {
			if ( !(*rp++) ) {
				dp ++;
				sp ++;
				continue;
			}
			cc = *sp++;
			if ( cc & C_TRANSPARENT ) {
				dp ++;
				continue;
			}
			*dp ++ = cc&
				(C_COLOR|C_TRANSPARENT);
		}
	}
}

void
ovf_transparent(OVERLAY * ov,OV_ARG * aa)
{
OV_ARG b;
unsigned long * dp, * sp;
char * rp;
int ix;
int i;
int yy;
unsigned long cc,dd;
int y_last,w;
int s_yy;
int c;
int d;
int j;
unsigned long ret;
int r1,r2;


	if ( ov_setup(&b,aa) < 0 )
		return;
	y_last = b.d_y + b.d_y_h;
	w = b.d_x_w;
	yy = b.d_y;
	s_yy = b.s_y;

	r1 = rint(ov->t.rate*0x1000);
	r2 = 0x1000 - r1;
	for ( ; yy < y_last ; yy ++ , s_yy ++ ) {
		ix = yy*b.d_w + b.d_x;
		dp = &b.dest[ix];
		sp = &b.src[s_yy*b.s_w + b.s_x];
		rp = &b.redraw[ix];
		for ( i = 0 ; i < w ; i ++ ) {
			if ( !(*rp++) ) {
				dp ++;
				sp ++;
				continue;
			}
			cc = *sp++;
			dd = *dp;
			if ( (cc & C_TRANSPARENT) ||
					ov->t.rate == 0  ) {
				dp ++;
				continue;
			}
			if ( (dd & C_TRANSPARENT) ||
					r1 >= 0xfff ) { 
				*dp ++ = cc&
					(C_COLOR|C_TRANSPARENT);
				continue;
			}
			ret = 0;
			for ( j = 0 ; j < 3 ; j ++ ) {
				c = (dd>>(COL_BIT*j))&COL_MASK;
				d = (cc>>(COL_BIT*j))&COL_MASK;
				d = d*r2 + c*r1;
				ret |= ((d>>12)&COL_MASK)
					<<(COL_BIT*j);
			}
			*dp ++  = ret;
		}
	}


}

unsigned long
ovf_csuperinpose(OVERLAY * ov,unsigned long b,unsigned long a)
{
long aa[3];
long bb[3];
unsigned long ret;
int i;
int f_in_key,f_dec_key;
int sb,sb1;
int R;
REAL1 rr2;
int c;
	if ( a == C_TRANSPARENT )
		return b;
	if ( b == C_TRANSPARENT )
		return a;
	if ( ov->cs.rate >= 0.9999 )
		return b;
	ret = 0;
	sb = 0;
	for ( i = 0 ; i < 3 ; i ++ ) {
		aa[i] = (a>>(COL_BIT*i))&COL_MASK;
		sb1 = IABS(aa[i]-ov->cs.key[i]);
		if ( sb < sb1 )
			sb = sb1;
		bb[i] = (b>>(COL_BIT*i))&COL_MASK;
	}
	if ( sb < ov->cs.key_radius )
		return b;
	if ( sb < ov->cs.inpose_radius ) {
		R = ov->cs.inpose_radius - ov->cs.key_radius;
		rr2 = (1-ov->cs.rate)/R*(sb-ov->cs.key_radius);
		ret = 0;
		for ( i = 0 ; i < 3 ; i ++ ) {
			c = rint(aa[i]*rr2 + bb[i]*(1-rr2));
			ret |= c<<(COL_BIT*i);
		}
		return ret;
	}
	for ( i = 0 ; i < 3 ; i ++ ) {
		c = rint(aa[i]*(1-ov->cs.rate) + bb[i]*ov->cs.rate);
		ret |= c<<(COL_BIT*i);
	}
	return ret;
}

OVERLAY * search_overlay(URL * u)
{
OVERLAY * ov;
	for ( ov = overlay_list; ov ; ov = ov->h.next )
		if ( url_cmp_str(&ov->h.url,u) == 0 )
			return ov;
	return ov;
}


OVERLAY *
new_overlay(int type,URL * u)
{
OVERLAY * ov;

	ov = search_overlay(u);
	if ( ov )
		return ov;
	ov = d_alloc(sizeof(OVERLAY));
	ov->h.type = type;
	ov->h.next = overlay_list;
	copy_url(&ov->h.url,u);
	overlay_list = ov;
	return ov;
}
