/*
 * DEVICE dependent, TrueType font (FreeType2 lib)
 */

#include	"conf.h"
#if defined(FREETYPE) || defined(VFLIB)

#include	"defs.h"
#include	"emit.h"
#include	"global.h"
#include	"bifont.h"
#include	"rastfont.h"
#include	"ps.h"
#ifdef FREETYPE
#include	"freetype.h"
#endif /* FREETYPE */

static struct psbiops po;

#ifdef FREETYPE

/* tfm
 */
dev_ft_begfontdict(fe, maxc)
struct font_entry *fe;
int maxc;
{
    if (fe->ncdl == -1) {
	fe->k = dev_newdevfont();
	EMIT(outfp, "%.3f %d /%s NF\n",
	     1.0, maxc+1, psfname(fe->k));
	fe->ncdl = 0;
    }
    get_tfm_psbiops(fe, &po);
    return psgetfontsize(&po);
}

void
dev_ft_initfontdict(fe, tfmfi, i, w, h, xo, d, pixel)
struct font_entry *fe;
struct tfmfntinfo *tfmfi;
int i;
int w, h, xo, d;
char *pixel;
{
    struct tfmchar_entry *ce;
    int bw;

    end_string();

    ce = tfmfi->ch+i;
    ce->dev_font = fe->k;
    ce->dev_char = i;
    dev_setfont(ce->dev_font);

#ifdef DEBUG
    if (Debug)
	EMIT(outfp, "%% font: %s char: %x\n", fe->n, i);
#endif
    bw = (w+7)>>3;
    EMITC('[');
    if (!pscharbitmap(bw, bw, h, pixel)) {
	bw = 1;
	h = 1;
    }
    EMIT(outfp, "\n%d %d %d %d %.3f] %d D\n",
	 bw<<3, h, xo, d, ((float)ce->tfmw)/(float)hconv, ce->dev_char);
}

dev_fto_begfontdict(fe, famname, mark, maxc, remap)
struct font_entry *fe;
char *famname;
Boolean *mark;
int maxc;
unsigned char *remap;
{
    char dictname[STRSIZE];

    fe->k = dev_newdevfont();
    /* better name wanted */
    (void)sprintf(dictname, "%s-TT%d", fe->n, fe->k);
    fttobi(tfmfinfo(fe)->tfm_bf, dictname);
    get_tfm_psbiops(fe, &po);
    tt_type1_prologue1(dictname, famname);
    stdex_type1_encoding(mark, maxc, remap);
    tt_type1_prologue2();
    tt_type1_prologue3();
    return psgetfontsize(&po);
}

dev_fto_refontdict(fe)
struct font_entry *fe;
{
    fe->k = dev_newdevfont();
    get_tfm_psbiops(fe, &po);
    psfindfontop(psfname(fe->k), &po);
    fe->ncdl = 0;
}

void
dev_fto_initfontdict(i, outline, a)
int i;
FT_Outline *outline;
int a;
{
    PS_CharString(outline, stdex_type1_charname(i), a);
}

dev_fto_endfontdict(fe)
struct font_entry *fe;
{
    tt_type1_epilogue(500);
    psfindfontop(psfname(fe->k), &po);
}

#endif /* FREETYPE */

/* jfm
 */
dev_jft_begfontdict(fe)
struct font_entry *fe;
{
    get_jfm_psbiops(fe, &po);
    return psgetfontsize(&po);
}

void
dev_jft_initfontdict(fe, jftfi, i, jis, tw, w, h, xo, d, pixel)
struct font_entry *fe;
struct jftfntinfo *jftfi;
int i, jis;
int tw, w, h, xo, d;
char *pixel;
{
    struct jftchar_entry *ce;
    struct pdlist *pl;
    int bw;

    end_string();

    ce = jftfi->ch+i;
    /* open font dict before first char */
    if ((pl = getpdlist(CORRNORM))->pl_char == FIRSTPACKPSCHAR)
	EMIT(outfp, "%.3f %d /%s NF\n",
	     1.0, 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;
    dev_setfont(ce->dev_font);

#ifdef DEBUG
    if (Debug)
	EMIT(outfp, "%% font: %s char: %x\n", fe->n, jis);
#endif
    bw = (w+7)>>3;
    EMITC('[');
    if (!pscharbitmap(bw, bw, h, pixel)) {
	bw = 1;
	h = 1;
    }
    EMIT(outfp, "\n%d %d %d %d %.3f] %d D\n",
	 bw<<3, h, xo, d, ((float)tw)/(float)hconv, ce->dev_char);
}

#ifdef FREETYPE

static struct pd pd;
static char *jfntname, *jfamname;

dev_jfto_begfontdict(dictname, famname)
char *dictname, *famname;
{
    jfntname = dictname;
    jfamname = famname;
    initpd(pd);
}

void
dev_jfto_initfontdict(jftfi, i, nc, outline, a)
struct jftfntinfo *jftfi;
int i, nc;
FT_Outline *outline;
int a;
{
    struct jftchar_entry *ce;
    static char dictname[STRSIZE];

    end_string();

    ce = jftfi->ch+i;
    /* open font dict before first char */
    if (getpd(&pd)) {
	(void)sprintf(dictname, "%s-TC%d", jfntname, pd.pd_font);
	po.po_dev_name = dictname;
	jtt_type1_prologue1(dictname, jfamname);
	cnum_type1_encoding(nc >= NPACKPSCHARS ? NPACKPSCHARS : nc);
	jtt_type1_prologue2();
	tt_type1_prologue3();
    }
    ce->dev_font = pd.pd_font;
    ce->dev_char = pd.pd_char;
    PS_CharString(outline, cnum_type1_charname(pd.pd_char), a);
    if (lastpd(pd))
	jfto_endfontdict(pd.pd_font);
}

dev_jfto_endfontdict()
{
    if (!lastpd(pd))
	jfto_endfontdict(pd.pd_font);
}

jfto_endfontdict(pd_font)
int pd_font;
{
    tt_type1_epilogue(1000);
    psfindsubfop(psfname(pd_font), &po);
}

#endif /* FREETYPE */

void
dev_jft_initfe(fe)
struct font_entry *fe;
{
    DEV_FONT jft_fontdict();
    int jft_setchar(), jft_setstring();
    int jft_setchar_abs(), jft_setstring_abs();

    fe->dev_fontdict = jft_fontdict;
    if (bifpos_rel(jfmfinfo(fe)->jfm_bf)) {
	fe->dev_setchar = jft_setchar;
	fe->dev_setstring = jft_setstring;
    } else {
	fe->dev_setchar = jft_setchar_abs;
	fe->dev_setstring = jft_setstring_abs;
    }
}

jft_setchar(c)
int c;
{
    struct jftchar_entry *ce;
    int cw;

    ce = &(jftfinfo(curfontent)->ch[jis_to_idx94(c)]);
    begin_string();
    pschar(ce->dev_char);
    *ps_move += (cw = ce->tfmw);
    return cw;
}

/* ARGSUSED */
jft_setstring(s, len)
char *s;
int len;
{
    Fatal("%s implementation error: jft_setstring", G_progname);
}

jft_setchar_abs(c)
int c;
{
    int cw;

    cw = jft_setchar(c);
    dev_setposn_abs(ps_h, ps_v);
    return cw;
}

/* ARGSUSED */
jft_setstring_abs(s, len)
char *s;
int len;
{
    Fatal("%s implementation error: jft_setstring_abs", G_progname);
}


/* jstfm
 */
dev_jsft_begfontdict(fe)
struct font_entry *fe;
{
    get_jstfm_psbiops(fe, &po);
    return psgetfontsize(&po);
}

void
dev_jsft_initfe(fe)
struct font_entry *fe;
{
    DEV_FONT jsft_fontdict();
    int jsft_setchar(), jsft_setstring();
    int jsft_setchar_abs(), jsft_setstring_abs();

    fe->dev_fontdict = jsft_fontdict;
    if (bifpos_rel(jstfmfinfo(fe)->js_bf)) {
	fe->dev_setchar = jsft_setchar;
	fe->dev_setstring = jsft_setstring;
    } else {
	fe->dev_setchar = jsft_setchar_abs;
	fe->dev_setstring = jsft_setstring_abs;
    }
}

jsft_setchar(c)
int c;
{
    struct jstfmfntinfo *jsfi;
    int cw;

    jsfi = jstfmfinfo(curfontent);
    begin_string();
    pschar(jsftfinfo(jsfi)->ch[jsub_to_idx94(jsfi->jsubfont,c)].dev_char);
    *ps_move += (cw = jsfi->ch[c].tfmw);
    return cw;
}

/* ARGSUSED */
jsft_setstring(s, len)
char *s;
int len;
{
    char *sp;
    struct jstfmchar_entry *ce = jstfmfinfo(curfontent)->ch;
    struct jstfmfntinfo *jsfi;
    int cw;

    jsfi = jstfmfinfo(curfontent);
    begin_string();
    for (sp = s, cw = 0; sp < s+len; sp++) {
	pschar(jsftfinfo(jsfi)->ch[jsub_to_idx94(jsfi->jsubfont,*sp)].dev_char);
	cw += (ce+*sp)->tfmw;
    }
    *ps_move += cw;
    return cw;
}

jsft_setchar_abs(c)
int c;
{
    int cw;

    cw = jsft_setchar(c);
    dev_setposn_abs(ps_h, ps_v);
    return cw;
}

/* ARGSUSED */
jsft_setstring_abs(s, len)
char *s;
int len;
{
    char *sp;
    struct jstfmchar_entry *ce = jstfmfinfo(curfontent)->ch;
    struct jstfmfntinfo *jsfi;
    int cw, w;

    jsfi = jstfmfinfo(curfontent);
    for (sp = s, cw = 0; sp < s+len; sp++) {
	begin_string();
	pschar(jsftfinfo(jsfi)->ch[jsub_to_idx94(jsfi->jsubfont,*sp)].dev_char);
	end_string();
	cw += (w = (ce+*sp)->tfmw);
	*ps_move += w;
	dev_setposn_abs(ps_h, ps_v);
    }
    return cw;
}

#endif
