/*
 * MKSoft Development Amiga ToolKit V1.0
 *
 * Copyright (c) 1985,86,87,88,89,90 by MKSoft Development
 *
 * $Id: renderinfo.c,v 1.3.1 90/06/13 09:53:22 mks Exp Locker: mks $
 *
 * $Source: Programming:MKSoft/MKS/RCS/renderinfo.c,v $
 *
 * $Date: 90/06/13 09:53:22 $
 *
 * $Revision: 1.3.1 $
 *
 * $Log:	renderinfo.c,v $
 * Revsison 1.3.1  90/06/13  09:53:22  mks
 * Special version for DevCon examples...  This is a RCS branch
 * and will not be part of the main tree...
 *
 * Revision 1.3  90/06/03  10:25:59  mks
 * Fixed the fact the bottom value was set wrong!
 *
 * Revision 1.2  90/05/20  12:17:03  mks
 * New functions to allocate and free RenderInfo structure.
 * These should be used insted of the old FillIn_RenderInfo...
 * Now has a TextAttr in the RenderInfo
 * Now has the screen Width/Height in RenderInfo
 * Now can be passed a screen pointer
 *
 * Revision 1.1  90/05/09  21:45:02  mks
 * Source now fully under RCS...
 *
 */

/*
 ************************************************************************
 *                                                                      *
 *                            DISCLAIMER                                *
 *                                                                      *
 *   THIS SOFTWARE IS PROVIDED "AS IS".                                 *
 *   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE      *
 *   ACCURACY, RELIABILITY, PERFORMANCE, CURRENTNESS, OR OPERATION      *
 *   OF THIS SOFTWARE, AND ALL USE IS AT YOUR OWN RISK.                 *
 *   NEITHER COMMODORE NOR THE AUTHORS ASSUME ANY RESPONSIBILITY OR     *
 *   LIABILITY WHATSOEVER WITH RESPECT TO YOUR USE OF THIS SOFTWARE.    *
 *                                                                      *
 ************************************************************************
 */

/*
 * This file contains the definition of the rendering information
 * for elements on the screen.  This information is used to generate
 * the correct pen colours for items on the screen...
 */

#include	<exec/types.h>
#include	<exec/memory.h>
#include	<graphics/view.h>
#include	<graphics/text.h>
#include	<intuition/intuition.h>
#include	<intuition/screens.h>

#include	<proto/exec.h>
#include	<proto/intuition.h>
#include	<proto/graphics.h>

#include	"renderInfo.h"

/*
 * The "default" font we might need...
 */
static char fontnam[11]="topaz.font";
static struct TextAttr TOPAZ80={fontnam,8,0,FPF_ROMFONT};

/*
 * These define the amount of Red, Green, and Blue scaling used
 * to help take into account the different visual impact of those
 * colours on the screen.
 */
#define	BLUE_SCALE	2
#define	GREEN_SCALE	6
#define	RED_SCALE	3

/*
 * This returns the colour difference hamming value...
 */
SHORT ColourDifference(UWORD rgb0, UWORD rgb1)
{
register	SHORT	level;
register	SHORT	tmp;

	tmp=(rgb0 & 15) - (rgb1 & 15);
	level=tmp*tmp*BLUE_SCALE;
	tmp=((rgb0>>4) & 15) - ((rgb1>>4) & 15);
	level+=tmp*tmp*GREEN_SCALE;
	tmp=((rgb0>>8) & 15) - ((rgb1>>8) & 15);
	level+=tmp*tmp*RED_SCALE;
	return(level);
}

/*
 * Calculate a rough brightness hamming value...
 */
SHORT ColourLevel(UWORD rgb)
{
	return(ColourDifference(rgb,0));
}

/*
 * Define the maximum colours to look at.
 * This is my way of making this work "everywhere" including HAM
 */
#define	MAX_COLOURS	16

/*
 * For new programs, this also opens fonts...
 */
static VOID NewFillIn_RenderInfo(struct RenderInfo *ri,struct Screen *TheScreen)
{
register	SHORT		numcolours;
register	SHORT		loop;
register	SHORT		loop1;
register	SHORT		backpen;
register	SHORT		tmp;
		SHORT		colours[16];
		SHORT		colourlevels[16];
		SHORT		pens[16];
	struct	Screen		screen;

	/*
	 * If no screen was passed we will used the old (1.2 compatible)
	 * way of getting at the screen...
	 */
	if (!TheScreen) GetScreenData((CPTR)(TheScreen=&screen),sizeof(struct Screen),WBENCHSCREEN,NULL);

	ri->WindowTop=TheScreen->WBorTop;
	ri->WindowLeft=TheScreen->WBorLeft;
	ri->WindowRight=TheScreen->WBorRight;
	ri->WindowBottom=TheScreen->WBorBottom;
	ri->WindowTitle=TheScreen->BarHeight-TheScreen->BarVBorder+TheScreen->WBorTop;

	ri->ScreenWidth=TheScreen->Width;
	ri->ScreenHeight=TheScreen->Height;

	/*
	 * If we can't open the font given for the screen we need
	 * to fall-back to Topaz...  *YUCK!*
	 */
	Forbid();
	if (TheScreen->Font) if (!(ri->TheFont=OpenFont(TheScreen->Font))) ri->TheFont=OpenFont(&TOPAZ80);
	Permit();

	if (ri->TheFont)
	{
		ri->TextAttr.ta_Name=ri->TheFont->tf_Message.mn_Node.ln_Name;
		ri->TextAttr.ta_YSize=ri->TheFont->tf_YSize;
		ri->TextAttr.ta_Style=ri->TheFont->tf_Style;
		ri->TextAttr.ta_Flags=ri->TheFont->tf_Flags;
	}
	else ri->TextAttr=TOPAZ80;

	ri->FontSize=ri->TextAttr.ta_YSize;

	numcolours=1 << (TheScreen->RastPort.BitMap->Depth);
	if (numcolours>16) numcolours=16;

	if (numcolours<3)
	{	/* Some silly person is running with 2 colours... */
		ri->BackPen=0;
		ri->Highlight=1;
		ri->Shadow=1;
		ri->TextPen=1;
	}
	else
	{
		Forbid();
		for (loop=0;loop<numcolours;loop++)
		{
			colours[loop]=GetRGB4(TheScreen->ViewPort.ColorMap,(LONG)loop);
			colourlevels[loop]=ColourLevel(colours[loop]);
			pens[loop]=loop;
		}
		Permit();

		/* Sort darkest to brightest... */
		for (loop=0;loop<(numcolours-1);loop++)
		 for (loop1=loop+1;loop1<numcolours;loop1++)
		 {
			if (colourlevels[loop]>colourlevels[loop1])
			{
				tmp=colourlevels[loop];
				colourlevels[loop]=colourlevels[loop1];
				colourlevels[loop1]=tmp;

				tmp=colours[loop];
				colours[loop]=colours[loop1];
				colours[loop1]=tmp;

				tmp=pens[loop];
				pens[loop]=pens[loop1];
				pens[loop1]=tmp;
			}
		 }

		/* Now, pick the pens... HightLight... */
		loop=numcolours-1;
		while (!(ri->Highlight=pens[loop--]));

		/* and Shadow... */
		loop=0;
		while (!(ri->Shadow=pens[loop++]));

		/* The BackGround pen... */
		if (!pens[loop]) loop++;
		ri->BackPen=pens[backpen=loop];

		loop1=0;
		for (loop=0;loop<numcolours;loop++)
		{
			tmp=ColourDifference(colours[loop],colours[backpen]);
			if (tmp>loop1)
			{
				loop1=tmp;
				ri->TextPen=pens[loop];
			}
		}
	}
}

/*
 * Close the font and free the memory...
 */
VOID CleanUp_RenderInfo(struct RenderInfo *ri)
{
	if (ri)
	{
		if (ri->TheFont) CloseFont(ri->TheFont);
		FreeMem(ri,sizeof(struct RenderInfo));
	}
}

/*
 * Use this screen for the render information.
 */
struct RenderInfo *Get_RenderInfo(struct Screen *TheScreen)
{
register	struct	RenderInfo	*ri;

	if (ri=AllocMem(sizeof(struct RenderInfo),MEMF_PUBLIC|MEMF_CLEAR))
	{
		NewFillIn_RenderInfo(ri,TheScreen);
	}
	return (ri);
}

