/*
**	Colour.c
**
**	Colour table support code
**
**	Copyright © 1990-1995 by Olaf `Olsen' Barthel
**		All Rights Reserved
**
**	:ts=4
*/

#include "termGlobal.h"

	/* ColourTablex12(const ColourTable *Table,UWORD *Dest12,WORD NumColours):
	 *
	 *	Convert colour table into 12 bit precision colours.
	 */

STATIC VOID __regargs
ColourTablex12(const ColourTable *Table,UWORD *Dest12,WORD NumColours)
{
	ULONG	r,g,b;
	WORD	i;

	for(i = 0 ; i < NumColours ; i++)
	{
		r = Table -> Entry[i] . Red		>> 28;
		g = Table -> Entry[i] . Green	>> 28;
		b = Table -> Entry[i] . Blue	>> 28;

		*Dest12++ = (r << 8) | (g << 4) | b;
	}
}

	/* Colour96xColourTable(const ULONG *Source96,ColourTable *Table,WORD NumColours):
	 *
	 *	Convert 96 bit precision colours for colour table.
	 */

VOID __regargs
Colour96xColourTable(const ULONG *Source96,ColourTable *Table,WORD NumColours)
{
	WORD i;

	for(i = 0 ; i < NumColours ; i++)
	{
		Table -> Entry[i] . Red		= *Source96++;
		Table -> Entry[i] . Green	= *Source96++;
		Table -> Entry[i] . Blue	= *Source96++;
	}
}

	/* Colour12xColourTable(const UWORD *Source12,ColourTable *Table,WORD NumColours):
	 *
	 *	Convert 12 bit precision colours for colour table.
	 */

VOID __regargs
Colour12xColourTable(const UWORD *Source12,ColourTable *Table,WORD NumColours)
{
	Colour12x96(Source12,(ULONG *)Table -> Entry,NumColours);
}

	/* Colour12x96(const UWORD *Source12,ULONG *Dest96,WORD NumColours):
	 *
	 *	Convert 12 bit precision colours into 96 bit colours.
	 */

VOID __regargs
Colour12x96(const UWORD *Source12,ULONG *Dest96,WORD NumColours)
{
	ULONG r,g,b;
	UWORD v;

	do
	{
		v = *Source12++;

		r = (v & 0xF00) >> 8;
		g = (v & 0x0F0) >> 4;
		b = (v & 0x00F);

		*Dest96++ = SPREAD((r << 4) | r);
		*Dest96++ = SPREAD((g << 4) | g);
		*Dest96++ = SPREAD((b << 4) | b);
	}
	while(--NumColours);
}

	/* Colour96x12(const UWORD *Source12,ULONG *Dest96,WORD NumColours):
	 *
	 *	Convert 96 bit precision colours into 12 bit colours.
	 */

VOID __regargs
Colour96x12(const ULONG *Source96,UWORD *Dest12,WORD NumColours)
{
	ULONG r,g,b;

	do
	{
		r = (*Source96++) >> 28;
		g = (*Source96++) >> 28;
		b = (*Source96++) >> 28;

		*Dest12++ = (r << 8) | (g << 4) | b;
	}
	while(--NumColours);
}

	/* CopyColourEntry(const ColourTable *Source,ColourTable *Destination,WORD From,WORD To):
	 *
	 *	Copy one colour register from one place to another.
	 */

VOID __regargs
CopyColourEntry(const ColourTable *Source,ColourTable *Destination,WORD From,WORD To)
{
	if(From >= 0 && To >= 0 && From < Source -> NumColours && To < Destination -> NumColours)
	{
		Destination -> Entry[To] . Red		= Source -> Entry[From] . Red;
		Destination -> Entry[To] . Green	= Source -> Entry[From] . Green;
		Destination -> Entry[To] . Blue		= Source -> Entry[From] . Blue;
	}
}

	/* ColourTablex96(const ColourTable *Table,ULONG *Dest96):
	 *
	 *	Convert colour table to 96 bit RGB palette.
	 */

VOID __regargs
ColourTablex96(const ColourTable *Table,ULONG *Dest96)
{
	WORD i;

	for(i = 0 ; i < Table -> NumColours ; i++)
	{
		*Dest96++ = Table -> Entry[i] . Red;
		*Dest96++ = Table -> Entry[i] . Green;
		*Dest96++ = Table -> Entry[i] . Blue;
	}
}

	/* DeleteColourTable(ColourTable *Table):
	 *
	 *	Delete a colour table.
	 */

VOID __regargs
DeleteColourTable(ColourTable *Table)
{
	FreeVecPooled(Table);
}

	/* CreateColourTable(WORD NumEntries,UWORD *Source12,ULONG *Source96):
	 *
	 *	Create a colour table and fill it with given data.
	 */

ColourTable * __regargs
CreateColourTable(WORD NumEntries,const UWORD *Source12,const ULONG *Source96)
{
	ColourTable *Record;

	if(Record = (ColourTable *)AllocVecPooled(sizeof(ColourTable) + NumEntries * sizeof(ColourEntry),MEMF_ANY | MEMF_CLEAR))
	{
		WORD i;

		Record -> NumColours = NumEntries;

		for(i = 0 ; i < NumEntries ; i++)
		{
			Record -> Entry[i] . One	= 1;
			Record -> Entry[i] . Which	= i;
		}

		Record -> Entry[NumEntries] . One = 0;

		if(Source12)
			Colour12x96(Source12,(ULONG *)Record -> Entry,NumEntries);

		if(Source96)
		{
			for(i = 0 ; i < NumEntries ; i++)
			{
				Record -> Entry[i] . Red	= *Source96++;
				Record -> Entry[i] . Green	= *Source96++;
				Record -> Entry[i] . Blue	= *Source96++;
			}
		}
	}

	return(Record);
}

	/* LoadColours(struct ViewPort *VPort,const ColourTable *Table,const UWORD *Colour12,WORD NumColours):
	 *
	 *	Load a colour table.
	 */

VOID __regargs
LoadColourTable(struct ViewPort *VPort,const ColourTable *Table,const UWORD *Colour12,WORD NumColours)
{
	if(GfxBase -> LibNode . lib_Version >= 39 && Table)
		LoadRGB32(VPort,(ULONG *)Table -> Entry);
	else
	{
		if(Colour12)
			LoadRGB4(VPort,(UWORD *)Colour12,NumColours);
	}
}

	/* SetColour12(struct ViewPort *VPort,WORD Number,UWORD r,UWORD g,UWORD b):
	 *
	 *	Load a single colour entry in 12 bit colour precision.
	 */

VOID __regargs
SetColour12(struct ViewPort *VPort,WORD Number,UWORD r,UWORD g,UWORD b)
{
	SetRGB4(VPort,Number,r,g,b);
}

	/* SetColour96(struct ViewPort *VPort,ULONG Number,ULONG r,ULONG g,ULONG b):
	 *
	 *	Load a single colour entry in 96 bit colour precision.
	 */

VOID __regargs
SetColour96(struct ViewPort *VPort,ULONG Number,ULONG r,ULONG g,ULONG b)
{
	if(GfxBase -> LibNode . lib_Version >= 39)
	{
		ULONG Table[5];

		Table[0] = (1L << 16) | Number;
		Table[1] = r;
		Table[2] = g;
		Table[3] = b;
		Table[4] = 0;

		LoadRGB32(VPort,Table);
	}
	else
		SetRGB4(VPort,Number,r >> 28,g >> 28,b >> 28);
}
