/* gemfont.c - Raster Font stuff, draws text based on a blit and a font
   in a format that some day may approach Ventura Publisher, but currently
   looks much more like GEM on the ST with some Mac-like mutations. */

#include "common.h"
#include "memgfx.h"
#include "gemfont.h"

static char const rcsid[] = "$Id: gemfont.c,v 1.11 2010/04/06 00:58:56 kent Exp $";

typedef union
    {
    int  theInt;
    char bytes[2];
    } myInt;

void gfText(struct memGfx *screen, struct font_hdr *f, char *text, 
       int x, int y, Color color, TextBlit tblit, Color bcolor)
{
UBYTE *s = (UBYTE*)text;
UBYTE *ss;
int c, lo, hi;
int sx, imageWid;
WORD *off, wd, ht;
UBYTE *data;
myInt *OWtab, *iPtr;
int missChar;
int font_type;
int extraWidth = f->lft_ofst + f->rgt_ofst;

x += f->xOff;
y += f->yOff;
x += f->lft_ofst;
lo = f->ADE_lo;
hi = f->ADE_hi;
off = f->ch_ofst;
wd = f->frm_wdt;
ht = f->frm_hgt,
data = f->fnt_dta;
OWtab= (myInt *)(f->hz_ofst);
font_type = f->id;

while ((c = *s++)!=0)
    {
    /* If we don't have the character, just turn it into a space. */
    if (c > hi)
	{
	c = ' ';
	}
    c -= lo;
    if (c < 0)
	{
	c = ' ' - lo;
	}

    /* Mac prop font && its a missing char */
    if (font_type == MPROP && (*(OWtab+c)).theInt == -1) 
	{            
	c=hi-lo;                      /* last char is set */
	missChar=1;
	sx = off[c+1];
	imageWid= f->frm_wdt*8 - sx;  /* sort of a kludge */
	}
    else 
	{
	missChar=0;
	sx = off[c];
	imageWid = off[c+1]-sx;
	}
    (*tblit)(imageWid, ht, sx, 0, data, wd, screen, x, y, color, bcolor);
    switch (font_type)
	{
	case STPROP:
	    x += imageWid + extraWidth;
	    break;
	case MFIXED:
	    x += f->wchr_wdt + extraWidth;          
	    break;
	case MPROP:
	    iPtr=OWtab+c;  
	    if (!missChar)
		    /* -1 means its a missing character */
		{
		x += (int)((*iPtr).bytes[1]);
		ss=s;
		if ((c=*(ss++)) != 0)
			/* look to next char to determine amt to change x */
		    {
		    c-= lo;
		    iPtr=OWtab+c;
		    /* subtract kern Of Next char */
		    /* f->rgt_ofst is neg of Mac maxKern value */
		    if ((*iPtr).theInt!=-1)
		       x += (int)((*iPtr).bytes[0])+ f->rgt_ofst;  
		    }           
		}
	    else /* display the non print char */
		x+=imageWid + extraWidth;
	    break;
	}
    }
}

static int fchar_width(struct font_hdr *f,unsigned char *s)
/* How wide is this character? */
{
int c;
signed char *offsets;
int width;
int t;

c = *s++;
if (c > f->ADE_hi)
    c = ' ';
c -= f->ADE_lo;
if (c < 0)
    {
    c = ' ' - f->ADE_lo;
    }
switch (f->id)
    {
    case MFIXED:
	    return(f->wchr_wdt + f->lft_ofst + f->rgt_ofst);
    case STPROP:
	    return(f->ch_ofst[c+1] - f->ch_ofst[c] + f->lft_ofst + f->rgt_ofst);
    case MPROP:
	    offsets = f->hz_ofst+c*2;
	    if (offsets[0] == -1 && offsets[1] == -1)	/* missing char */
		{
		t = f->ADE_hi - f->ADE_lo;
		return( f->frm_wdt*8 - f->ch_ofst[t+1]);
		}
	    else
		{
		width = offsets[1];
		if ((c = *s++) != 0)
			{
			c -= f->ADE_lo;
			offsets = f->hz_ofst+c*2;
			width += offsets[0] + f->rgt_ofst;
			}
		return(width);
		}
    default:
         internalErr();
	 return 0;
    }
}

long fnstring_width(struct font_hdr *f, unsigned char *s, int n)
{
long acc = 0;

while (--n >= 0)
    {
    acc += fchar_width(f, s);
    s++;
    }
return(acc);
}

#if 0 /* unused */
static long fstring_width(struct font_hdr *f, unsigned char *s)
{
return(fnstring_width(f, s, strlen((char *)s)));
}
#endif


int fwidest_char(struct font_hdr *f)
{
unsigned char buf[2];
int i;
int c;
int widest = 1;
int w;

c = f->ADE_lo;
i = f->ADE_hi - c;
buf[1] = 0;
while (--i >= 0)
	{
	buf[0] = c++;
	w = fchar_width(f, buf);
	if (w > widest)
		widest = w;
	}
return(widest);
}

int font_cel_height(struct font_hdr *f)
/* How tall is font? */
{
return f->frm_hgt;
}

int font_line_height(struct font_hdr *f)
/* How far to next line. */
{
return f->lineHeight;
}
