/* hamstuff.c   - routines to be given a set of colors. These will be plotted
		in ham mode. This is based on hamrtn.c */

#include <exec/types.h>
#include <stdio.h>
#include <intuition/intuition.h>

#include "globals.h"

extern UWORD colortable[];
extern UBYTE near[];
extern UWORD nearmc[];

/* near is 4096 long and is configured as a 16*16*16 array		*/
/* each byte gives the distance to the nearest colortable entry		*/
/* the high order nible is the index into the color table and the	*/
/* low order nible is the distance.					*/
/* color[16] - colormap containing rgb values fairly evenly */
/*             spread throughout 16x16x16 space.            */
/* near[4096] - table of distance. For each r,g,b           */
/*              address = (r<<8 | g<<4 | b) & 0xfff         */
/*              near>>4 gives the nearest color (index) and */
/*              near & 0x0f gives the distance.             */
/* nearmc[4096] - table of distance minus color             */
/*       This contains the nearest color ignoring a color   */
/*       (nearmc >> 8) & 0xf is for red,                    */
/*       (nearmc >> 4) & 0xf is for green,                  */
/*       and nearmc & 0xf is for blue                       */

#define INDEXNEAR(r,g,b) near[(((r)<<8) | ((g)<<4) | (b))&0xfff]

#define PLOTABS(x,y,color)     {mywritepixel(&ibitmap,x,y,color); \
				i = colortable[color];	\
				pr = i >> 8;		\
				pg = (i >> 4) & 0x0f;	\
				pb = i & 0x0f; 		\
				if (!exact)		\
				  mywritepixel(&ibitmap,ox,oy,near[oc]>>4);}


#define RED	0x20
#define GREEN	0x30
#define BLUE	0x10

extern struct RastPort *rp;

static short pr, pg, pb;
static int ox, oy, oc;

void
setcolor(xpos,ypos,yepos,r,b,g,exact)
int xpos,ypos,yepos,r,b,g,exact;
{
    short d1, dr, dg, db;
    int i;

    r &= 0x0f;
    b &= 0x0f;
    g &= 0x0f;

    if (bw) mywritepixel(&ibitmap,xpos,ypos,(r+b+g)/3);
    else {
	d1 = INDEXNEAR(r,g,b);
	if (((d1 & 0x0f) == 0) || (exact)) {	/* equals existing color */
		PLOTABS(xpos,ypos,(d1>>4));
		if (exact) mywritepixel(&ibitmap,xpos,yepos,d1>>4);
	} else {
		/* calculate nearest dist from prev */
		dr = r - pr;
		if (dr < 0) dr = -dr;
		dg = g - pg;
		if (dg < 0) dg = -dg;
		db = b - pb;
		if (db < 0) db = -db;
			if (dr > dg) {
		    if (dr > db) {
			/* dr is max */
			if ((d1 & 0x0f) < (dg+db)) {
				PLOTABS(xpos,ypos,(d1>>4));
			} else {
				mywritepixel(&ibitmap,xpos,ypos,RED | r);
				pr = r;
				mywritepixel(&ibitmap,ox,oy,(nearmc[oc]>>8));
			}
		    } else {	/* if (dr > db) . . . */
			/* db is max */
			if ((d1 & 0x0f) < (dg+dr)) {
				PLOTABS(xpos,ypos,(d1>>4));
			} else {
				mywritepixel(&ibitmap,xpos,ypos, BLUE | b);
				pb = b;
				mywritepixel(&ibitmap,ox,oy,(nearmc[oc] & 0xf));
			}
		    }
		} else {	/* if (dr > dg) . . . */
		    if (dg > db) {
			/* dg is max */
			if ((d1 & 0x0f) < (dr+db)) {
				PLOTABS(xpos,ypos,(d1>>4));
			} else {
				mywritepixel(&ibitmap,xpos,ypos,GREEN | g);
				pg = g;
				mywritepixel(&ibitmap,ox,oy,
						(nearmc[oc]>>4)& 0xf);
			}
		    } else {	/* if (dg > db) . . . */
			/* db is max */
			if ((d1 & 0x0f) < (dg+dr)) {
				PLOTABS(xpos,ypos,(d1>>4));
			} else {
				mywritepixel(&ibitmap,xpos,ypos,BLUE | b);
				pb = b;
				mywritepixel(&ibitmap,ox,oy,(nearmc[oc] & 0xf));
			}
		    }
		}	/* end if (dr > dg) */
	}		/* end else for if ((d1 & 0x0f) == 0) */
	oc = r<<8 | g<<4 | b;
	ox = xpos;
	oy = yepos;
    }
}				/* end setcolor */

void
dolast()
{
	if (!bw) mywritepixel(&ibitmap,ox,oy,near[oc]>>4);
}

int
match(r,g,b)
int r,g,b;
{
	if (bw) return(0.5 + ((float)(r + g + b)) / 3.0);
	else return(INDEXNEAR(r,g,b) >> 4);
}
