/*
 * DEVICE dependent, raster font dependent
 */

#include	"defs.h"
#include	"emit.h"
#include	"global.h"
#include	"rastfont.h"
#include	"ps.h"


void getpackdict();
struct confop pdcop = {
    "packdict",
    getpackdict
};
void getdvidict();
struct confop ddcop = {
    "dvidict",
    getdvidict
};

struct packdict {
    char *pd_name;
    int pd_len;
    int pd_pack;
    struct packdict *pd_next;
};
struct packdict *packdicts = NULL;

void getdictstat();

void
getpackdict()
{
    getdictstat(PACK);
}

void
getdvidict()
{
    getdictstat(DVI);
}

void
getdictstat(p)
int p;
{
    char field[STRSIZE];
    struct packdict *pd;

    getfield(field);
    skipline();
    pd = NEW(struct packdict, "packdict");
    pd->pd_name = strsave(field);
    pd->pd_len = strlen(field);
    pd->pd_pack = p;
    pd->pd_next = packdicts;
    packdicts = pd;
}

dictform(name)
char *name;
{
    struct packdict *pd;

    for (pd = packdicts; pd != NULL; pd = pd->pd_next)
	if (strncmp(name, pd->pd_name, pd->pd_len) == 0)
	    return pd->pd_pack;
    return DVI;
}

static struct pdlist *pdlists = NULL;
static struct pdlist **nextpl = &pdlists;

struct pdlist *
getpdlist(corr)
int corr;
{
    struct pdlist *pl;

    for (pl = pdlists; pl != NULL; pl = pl->pl_next)
	if (corr == pl->pl_corr) {
	    if (pl->pl_char++ == LASTPACKPSCHAR) {
		pl->pl_font = dev_newdevfont();
		pl->pl_char = FIRSTPACKPSCHAR;
	    } else if (pl->pl_char == NPACKPSCHARS)
		pl->pl_char = 0;
	    return pl;
	}
    pl = NEW(struct pdlist, "pdlist");
    pl->pl_corr = corr;
    pl->pl_font = dev_newdevfont();
    pl->pl_char = FIRSTPACKPSCHAR;
    pl->pl_next = NULL;
    *nextpl = pl;
    nextpl = &(pl->pl_next);
    return pl;
}

void
dev_rast_initfontdict(fe, c)		/* output a character bitmap */
struct font_entry *fe;
int c;
{
    struct rastchar_entry *ce;
    struct rastfntinfo *rfi;
    struct pdlist *pl;
    int corr, bytewidth, i;
    float cf;
    int j;
    unsigned char *sl;
    int cc;
    float cw;	/* char width, in "dots"
		   - we rely on PostScript maintaining sufficient accuracy */
    
    end_string();

    ce = &((rfi = rastfinfo(fe))->ch[c]);
    /* open font dict before first char */
    if (rfi->dictform == PACK) {
	corr = (int)(rfi->corrfact*CORRNORM);
	cf = (float)corr/CORRNORM;
	if ((pl = getpdlist(corr))->pl_char == FIRSTPACKPSCHAR)
	    EMIT(outfp, "%.3f %d /%s NF\n",
		 cf, NPACKPSCHARS, psfname(pl->pl_font));
#ifdef STATS
	if (fe->ncdl == -1)
	    fe->ncdl = 0;
#endif
	ce->dev_font = pl->pl_font;
	ce->dev_char = pl->pl_char;
    } else /* if (rfi->dictform == DVI) */ {
	cf = rfi->corrfact;
	if (fe->ncdl == -1) {
	    fe->k = dev_newdevfont();
	    EMIT(outfp, "%.3f %d /%s NF\n",
		 cf, rfi->nfntchars, psfname(fe->k));
	    fe->ncdl = 0;
	}
	ce->dev_font = fe->k;
	ce->dev_char = c;
    }
    dev_setfont(ce->dev_font);	/* because this isn't done on pass 0 */
    
#ifdef DEBUG
    if (Debug)
	EMIT(outfp, "%% font: %s char: %x\n", fe->n, c);
#endif
    bytewidth = (unsigned short)(ce->width + 7) >> 3;
    EMITC('[');
    if (!pscharbitmap(bytewidth, ce->nbpl, ce->height, ce->where.pixptr)) {
	bytewidth = 1;
	ce->height = 1;
    }
    cw = (float)ce->tfmw / (float)hconv;
    EMIT(outfp, "\n%d %d %d %d %.3f] %d D\n", 
	 bytewidth<<3, ce->height,
	 ce->xoffset, (((int)ce->height)-ce->yoffset)-1, cw/cf,
	 ce->dev_char);
#ifdef STATS
    (fe->ncdl)++;
    Snbpxl += bytewidth*ce->height;
    fe->nbpxl += bytewidth*ce->height;
    Sonbpx += (unsigned short)(ce->width*ce->height + 7) >> 3;
    Sndc += 1;
#endif
}

/* Output in PostScript coord system (y +ive up, x +ive right)
   (0,0) of char bitmap at lower left.  Output scan lines
   from bottom to top */
pscharbitmap(bytewidth, nbpl, height, pixel)
int bytewidth, nbpl, height;
char *pixel;
{
    int i, j, cc;
    unsigned char *sl;

    EMITC('<');
    for (i = height-1, cc = 2;  i >= 0;  i--) {
	sl = (unsigned char *)(pixel + i*nbpl);
	for (j = 0;  j < bytewidth;  j++, sl++) {
	    if (cc > 72) {
		EMITS("\n  ");   cc = 2;
	    }
	    EMITH(*sl);
	    cc += 2;
	}
    }
    if (bytewidth == 0 || height == 0) {
	EMITS("00>");
	return FALSE;
    }
    EMITC('>');
    return TRUE;
}

void
dev_rast_initfe(fe)
struct font_entry *fe;
{
    int rast_setchar(), rast_setstring();

    fe->dev_fontdict = rast_fontdict;
    fe->dev_setchar = rast_setchar;
    fe->dev_setstring = rast_setstring;
    rastfinfo(fe)->dictform = dictform(fe->n);
}

rast_setchar(c)
int c;
{
    struct rastchar_entry *ce = &(rastfinfo(curfontent)->ch[c]);
    int cw;

    begin_string();
    pschar(ce->dev_char);
    *ps_move += (cw = ce->tfmw);
    return cw;
}

rast_setstring(s, len)
char *s;
int len;
{
    char *sp;
    struct rastchar_entry *ce = rastfinfo(curfontent)->ch;
    int cw = 0;

    begin_string();
    for (sp = s; sp < s+len; sp++) {
	pschar((ce+*sp)->dev_char);
	cw += (ce+*sp)->tfmw;
    }
    *ps_move += cw;
    return cw;
}
