#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <setjmp.h>
#include <Arthur.h>
#include "defs.h"
#include "vars.h"

int cmaxx, cmaxy, cminx, cminy, ffflag;

int readnum(fd)
FILE *fd;
{
        unsigned char a, b;
        a = getc(fd);
        b = getc(fd);
        if (a < 128) return((int)(a*256+b));
        else return((int)(a*256+b)-65536);
}

void pointinfo(p, fd)
struct point *p;
FILE *fd;
{
        p->x = readnum(fd);
        p->y = readnum(fd);
}

void segmentinfo(seg, fd)
struct elem *seg;
FILE *fd;
{
        int n,c=0,t;
        t = readnum(fd);
        n = readnum(fd);
        switch(t) {
        case 1: numputs+=n;
                seg->type = DRAW;
                break;
        case 10: numputs+=32*n;
                 seg->type = CURVE;
                 break;
        default: seterror("Unrecognised segment type in font"); }
        seg->npoints = n;
        seg->points = (struct point *)calloc(n, sizeof(struct point));
        for (; c<n; c++) pointinfo(&seg->points[c], fd);
}

void subpathinfo(spb, fd)
struct subpath *spb;
FILE *fd;
{
        int n,c=0;
        n=readnum(fd); /* Number of segments */
        spb->length = n;
        spb->segments = (struct elem *)calloc(n, sizeof(struct elem));
        for (; c<n; c++) segmentinfo(&spb->segments[c], fd);
}

int pathinfos(new, fd)
struct charlist **new;
FILE *fd;
{
        int n, c=0;
        n = readnum(fd); /* Number of subpaths */
        if (n==0) return(0);
        (*new)->sub = (struct subpath *)calloc(n, sizeof(struct subpath));
        for (; c<n; c++) subpathinfo(&(*new)->sub[c], fd);
        return(n);
}

struct charlist **chardata(new, fd, c)
struct charlist **new;
FILE *fd;
int c;
{
        int m;
        *new=(struct charlist *)malloc(sizeof(struct charlist));
        (*new)->name=stenca->array[c].u.spname;
        (*new)->width = readnum(fd);
        m=readnum(fd); /* side-bearing - throw it away */
        m=readnum(fd);
        if (m<cminx && ffflag) cminx=m;
        m=readnum(fd);
        if (m<cminy && ffflag) cminy=m;
        m=readnum(fd);
        if (m>cmaxx && ffflag) cmaxx=m;
        m=readnum(fd);
        if (m>cmaxy && ffflag) cmaxy=m;
        numputs=0;
        (*new)->length = pathinfos(new, fd);
        (*new)->storage = numputs;
        (*new)->next = NULL;
        return(&(*new)->next);
}

struct charlist **charinfo(new, fd, c)
struct charlist **new;
FILE *fd;
int c;
{
        if (!c) ffflag=0;
        else ffflag=1;
        if (readnum(fd)) new=chardata(new, fd, c);
        return(new);
}

void charinfos(new, fd)
struct charlist **new;
FILE *fd;
{
        int c=0;
        for (; c<256; c++) new=charinfo(new, fd, c);
}

void fontinfo(new, fd)
struct fontdict *new;
FILE *fd;
{
        int c=0;
        readnum(fd); /* Throw away FileType */
        new->uniqueid = readnum(fd); /* UniqueID field (almost!) */
        new->encoding = stenca;
        new->fontheight = readnum(fd);
        new->fontbbox = createarray(4);
        for (; c<4; c++) {
                new->fontbbox->array[c].sort = NUMBER;
                new->fontbbox->array[c].u.number = (double)readnum(fd); }
        readnum(fd); /* Throw away Proportional */
        c=readnum(fd); /* FillType */
        new->painttype = c-(c==1);
}

struct fontdict *fontfile(path)
char *path;
{
        char inp[256];
        struct fontdict *new;
        FILE *fd;
        cmaxx=0; cmaxy=0; cminx=0; cminy=0;
        fd = fopen(path, "r");
        fgets(inp, 256, fd);
        fgets(inp, 256, fd);
        new = (struct fontdict *)malloc(sizeof(struct fontdict));
        fontinfo(new, fd);
        charinfos(&new->charstrings, fd);
        new->fontmatrix=createarray(6);
        setmat(new->fontmatrix, 1/(double)(cmaxx-cminx), 0.0, 0.0,
                                1/(double)(cmaxy-cminy), 0.0, 0.0);
        fclose(fd);
        return(new);
}
