// HeightField.cpp: implementation of the HeightField class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "imagegrinder.h"
#include "HeightField.h"


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

HeightField::HeightField()
{
	
}

void HeightField::HFBlendBlt(HeightField &img,RECT dst,RECT &src,HFBLENDMODE bmode,int UserVal)
{
	int dr,db;
	int xd,yd;
	int ddx,ddy;
	ddx=dst.right-dst.left;
	ddy=dst.bottom-dst.top;
	xd=src.right-src.left;
	yd=src.bottom-src.top;
	
	dst.right-=xpos;
	dst.left-=xpos;
	dst.bottom-=ypos;
	dst.top-=ypos;
	
	
	if(src.left>=(img.xpos+img.xlen) || src.top>=(img.ypos+img.ylen) ||
		src.right<=img.xpos || src.bottom<img.ypos ) return;
	
	
	//left clip
	if(src.left<=img.xpos) //fix source move dest.
	{ dst.left+=(img.xpos-src.left)*ddx/xd; src.left=0;}
	else			   //fix destination move source
		src.left-=img.xpos;
	
	if(src.top<=img.ypos) //fix source move dest.
	{ dst.top+=(img.ypos-src.top)*ddy/yd; src.top=0; }
	else			   //fix destination move source
		src.top-=img.ypos;
	
	//right clip
	
	if(src.right>(img.xpos+img.xlen)) 
	{
		dst.right-=(src.right-(img.xpos+img.xlen))*ddx/xd;
		src.right=img.xlen;	
	}
	else
		src.right=img.xlen-((img.xlen+img.xpos)-src.right);	
	
	if(src.bottom>(img.ypos+img.ylen)) 
	{
		dst.bottom-=(src.bottom-(img.ypos+img.ylen))*ddy/yd;
		src.bottom=img.ylen;	
	}
	else
		src.bottom=img.ylen-((img.ylen+img.ypos)-src.bottom);	
	
	
	if(dst.left<0)  { src.left-=dst.left*img.xlen/ddx; dst.left=0; }
	if(dst.top<0)   { src.top-=dst.top*img.ylen/ddy;   dst.top=0;  }
	
	
	if(dst.right>xlen) { src.right=src.left+(xlen-dst.left)*xd/ddx; dr=xlen;}
	else {dr=dst.right; }
	
	if(dst.bottom>ylen){ src.bottom=src.top+(ylen-dst.top)*yd/ddy; db=ylen; }
	else {db=dst.bottom; }
	
	dst.right=dr;
	dst.bottom=db;
	
	
	if(src.right<=0 || src.bottom<=0 || 
		src.left>=img.xlen || src.top>=img.ylen) return;
	
	
	BYTE *dptS=img.Lock(),*dptD=Lock();
	
	if((dst.right-dst.left)==(src.right-src.left) && (dst.bottom-dst.top)==(src.bottom-src.top))
	{//Pure Copy
		int psizeS=(img.Bpp>>3),psizeD=(Bpp>>3);
		int sp=img.GetPitch()-(src.right-src.left)*psizeS,dp=GetPitch()-(dst.right-dst.left)*psizeD;
		int x,y;
		ImgRGBColor srccol,dstcol;
		RGBPixel *tptr;
		BYTE *tdptS=dptS+(src.left+src.top*img.GetWidth())*psizeS,*tdptD=dptD+(dst.left+dst.top*GetWidth())*psizeD;
		
		switch(bmode)
		{
		case HFB_COPY:
			for(y=dst.top;y<dst.bottom;y++,tdptS+=sp,tdptD+=dp)
				for(x=dst.left;x<dst.right;x++,tdptS+=psizeS,tdptD+=psizeD)
				{
					tptr=(RGBPixel *)(tdptS);
					srccol.Set(*tptr,img.Mask);
	
					tptr=(RGBPixel *)(tdptD);
					tptr->Set(srccol,Mask);
				}
				break;

		case HFB_ADD:
			for(y=dst.top;y<dst.bottom;y++,tdptS+=sp,tdptD+=dp)
				for(x=dst.left;x<dst.right;x++,tdptS+=psizeS,tdptD+=psizeD)
				{
					tptr=(RGBPixel *)(tdptS);
					srccol.Set(*tptr,img.Mask);
					
					tptr=(RGBPixel *)(tdptD);
					dstcol.Set(*tptr,Mask);
					dstcol+=srccol;
					dstcol.Bound();
					tptr->Set(dstcol,Mask);
				}
				break;

		case HFB_SUBTRACT:
			for(y=dst.top;y<dst.bottom;y++,tdptS+=sp,tdptD+=dp)
				for(x=dst.left;x<dst.right;x++,tdptS+=psizeS,tdptD+=psizeD)
				{
					tptr=(RGBPixel *)(tdptS);
					srccol.Set(*tptr,img.Mask);
					
					tptr=(RGBPixel *)(tdptD);
					dstcol.Set(*tptr,Mask);
					dstcol.SetBounded(dstcol.r-srccol.r,dstcol.g-srccol.g,dstcol.b-srccol.b);
					tptr->Set(dstcol,Mask);
				}
				break;

		case HFB_BLEND:
			for(y=dst.top;y<dst.bottom;y++,tdptS+=sp,tdptD+=dp)
				for(x=dst.left;x<dst.right;x++,tdptS+=psizeS,tdptD+=psizeD)
				{
					tptr=(RGBPixel *)(tdptS);
					srccol.Set(*tptr,img.Mask);
					
					tptr=(RGBPixel *)(tdptD);
					dstcol.Set(*tptr,Mask);
					dstcol.SetBounded(dstcol.r+(((srccol.r)*UserVal)>>8),
										dstcol.g+(((srccol.g)*UserVal)>>8),
										dstcol.b+(((srccol.b)*UserVal)>>8));
					tptr->Set(dstcol,Mask);
				}
				break;

		case HFB_INVBLEND:
			for(y=dst.top;y<dst.bottom;y++,tdptS+=sp,tdptD+=dp)
				for(x=dst.left;x<dst.right;x++,tdptS+=psizeS,tdptD+=psizeD)
				{
					tptr=(RGBPixel *)(tdptS);
					srccol.Set(*tptr,img.Mask);
					
					tptr=(RGBPixel *)(tdptD);
					dstcol.Set(*tptr,Mask);
					dstcol.SetBounded(  ((dstcol.r*(255-srccol.r))>>8)+(((srccol.r)*UserVal)>>8),
										((dstcol.g*(255-srccol.g))>>8)+(((srccol.g)*UserVal)>>8),
										((dstcol.b*(255-srccol.b))>>8)+(((srccol.b)*UserVal)>>8));
					tptr->Set(dstcol,Mask);
				}
				break;


		
		default:
			GENFERR("Unimplemented Blend Mode");
		}
		
	}
	else
	{
		GENFERR("Stretchy Blts not supported in HF's");
	}
	UnLock();
	img.UnLock();
}

HeightField::~HeightField()
{
	
}

