/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
 *
 * This file is part of the TeX Font Tools package.
 *
 * Copyright  1997 Jakob Stoklund Olesen.
 *
 * $Id: TFTLib.h.Fontfile 4.1 1998/02/13 17:22:35 stoklund Stable $
 *
 * Reading and writing of RISC OS font files.
 * Outlines and IntMetrics. Always writes newest version.
 *
 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
#ifndef FONTFILE_H
#define FONTFILE_H

/* a 16-bit bounding box, used by both intmetrics and fontfile */
typedef struct box16_str {
  short           x0, y0;
  short           x1, y1;
}               Box16;

/* Expand box to contain point (x,y) */
void            Box16_UnionPoint(Box16 * a, int x, int y);
/* Expand box a to contain box b */
void            Box16_Union(Box16 * a, Box16 * b);
/* Expand box a to contain box b, offset (x,y) */
void            Box16_UnionOffset(Box16 * a, Box16 * b, int x, int y);

/* The struct to hold an IntMetrics file */
typedef struct intmetrics_str Intmetrics;
typedef struct intmetrics_kern_str Intmetrics_Kern;
typedef enum intmetrics_flags_enm Intmetrics_Flags;

struct intmetrics_str {
  /* fields from the file header: */
  char            name[40];	/* Name of font, '\r' padded */
  int             n;		/* # slots in tables */
  int             version;	/* Version no. (0 or 2) */
  Intmetrics_Flags flags;
  int             m;		/* Character map size (max char
                                 * code+1) */
  /* Pointers to tables */
  unsigned char  *map;		/* character map (NULL=no map) */
  Box16          *bbox;		/* BBox table (if flags:0 is clear) */
  short          *xoffset;	/* in 1/1000em (if flags:1 clear) */
  short          *yoffset;	/* in 1/1000em (if flags:2 clear) */
  /* the misc and kerning is only there if flags:3 is set */
  struct intmetrics_misc_str *misc;	/* Misc. data */
  Intmetrics_Kern **kern;	/* table of kern progs. */
  /* indexed by char code */
};

/* The flags are bitmapped */
enum intmetrics_flags_enm {
  imf_nobbox = 001,		/* no bbox table in file */
  imf_noxoffset = 002,		/* no x data in file [xoffset+kern] */
  imf_noyoffset = 004,		/* no y data in file [yoffset+kern] */
  imf_moredata = 010,		/* more data [misc+kern] */
  /* bit 4 reserved */
  imf_mapsize = 040,		/* mapsize in file (else 256) */
  imf_kern16 = 0100		/* kern chars are 16bit (else 8) */
  /* bit 7 reserved */
};

/* The optional miscellaneous data area, layout identical to file */
struct intmetrics_misc_str {
  Box16           maxbbox;	/* maximum bbox for entire font */
  short           xoffset, yoffset;	/* default offsets in
                                         * 1/1000em */
  short           hoffset;	/* italic angle per 1000em */
  signed char     ulpos;
  char            ulthick;	/* underline parameters 1/256em */
  short           capheight;	/* heigth of X in 1/1000em */
  short           xheight;	/* heigth of x in 1/1000em */
  short           descender, ascender;	/* in 1/1000em */
  int             reserved;
};

/*
 * A single kern step. Lefthand char is given by position in kern
 * table
 */
struct intmetrics_kern_str {
  int             rightchar;	/* righthand character code [8/16
                                 * bits in file] */
  short           xkern, ykern;	/* in 1/1000em. One may be absent (0) */
};

/*
 * Read IntMetrics file, and allocate necessary memory. Returns 0 on
 * failure
 */
int             Intmetrics_Read(Intmetrics * im, const char *file);

/* Allocate blank tables with room for size chars and flags */
void            Intmetrics_Create(Intmetrics * im, int n, Intmetrics_Flags flags);

/* Get the index in the table for char code cc. */
/* Index is 0..n-1 (negative if no char) */
/* The index can be used in the tables bbox, xoffset, yoffset */
/* NOTE: the kern table uses char code as first index */
int             Intmetrics_GetIndex(Intmetrics * im, int cc);

/*
 * Force char code cc to be mapped to index idx or vacant slot if
 * idx<0.
 */
/* Returns the index allocated for cc */
int             Intmetrics_MapChar(Intmetrics * im, int cc, int idx);

/*
 * Change the number of available slots. If shortened, slots will be
 * lost
 */
/* Returns old size */
int             Intmetrics_SetSize(Intmetrics * im, int size);

/* Compact the file as much as possible by joining equal slots. */
/* A map is created if necessary, all indexes are invalidated. */
/* Returns new number of slots. */
int             Intmetrics_Compact(Intmetrics * im);

/* Calculate the bounding box of the font from the bbox table */
/* If there is no bbox table, bbox is untouched and */
/* 0 is returned, otherwise 1 */
int             Intmetrics_GetBBox(Intmetrics * im, Box16 * bbox);

/* Write the Intmetrics to file. */
/* Compaction should be done manually if necessary */
/* returns 0 on failure */
int             Intmetrics_Write(Intmetrics * im, const char *filename);

/* Now The Fontfile which covers the new font file formats i.e */
/* Outlines, f9999x9999 and b9999x9999 */
typedef struct fontfile_str Fontfile;
typedef struct fontfile_character_str Fontfile_Character;
typedef struct fontfile_scaffold_str Fontfile_Scaffold;

struct fontfile_str {
  char            name[40];	/* Name of font, 0 terminated */
  int             bpp;		/* 0=outlines */
  int             version;	/* 4--8, 8 written */
  int             designsize;	/* only outlines (design units per
                                 * em) */
  enum {
    fff_xsub = 0001,		/* horiz. subpixels */
    fff_ysub = 0002,		/* vert. subpixel */
    fff_chunkflag = 0100	/* Flag word before chunk index */
  } flags;			/* 0,1=subpix, 6=chunkindex */
  Box16           bbox;		/* maximum bbox for font */
  int             nchunks;	/* # chunks in file */
  int             ns;		/* # scaffold index entries ([0] is
                                 * unused) */
  enum {
    fff_scafbase16 = 0001,	/* all scaf. base chars are 16-bit */
    fff_noantialias = 0002	/* don't antialias the outlines */
  } scaffoldflags;		/* 0=base16, 1=no-antialias */
  int             threshold;	/* skeleton threshold pixelsize */

  /* If bpp>0, the file has bitmaps, and the table is 10 bytes */
  struct {
    unsigned short  xsize, xdpi;/* size is in 1/16th pt */
    unsigned short  ysize, ydpi;/* dpi is resolution */
  }               bmpsize;
  /*
   * If bpp==0, the file has outlines, and the table is scaffold
   * lines
   */
  Fontfile_Scaffold **scaffold;
  struct fontfile_chunk *chunk;	/* array of chunks [0..nchunks-1] */
};

/* The scaffold lines for a character looks like this */
struct fontfile_scaffold_str {
  unsigned short  basechar;	/* code of base char (0=none) */
  unsigned short  lines;	/* # local scaffold lines */
  /* Bits defines whether lines are defined in base char */
  unsigned char   basex, basey;	/* bit n set=> line n in base */
  unsigned char   localx, localy;	/* bit n => line n def.
                                         * locally */
  struct fontfile_scaffoldline_str {
    short           coord;	/* line's coordinate */
    unsigned        link:4;	/* link index (+8 for linear link) */
    unsigned        index:4;	/* line's index (+8 for y-lines) */
    unsigned        width:8;	/* 254=L, 255=R */
  }              *line;
};

/* each chunk in the fontfile holds 32 characters */
struct fontfile_chunk {
  unsigned        flags;	/* 0,1=subpix, 7=dependency, 31=1 */
  int             mult;		/* 1, 4 or 16, depending on subpix
                                 * values */
  Fontfile_Character *((*character)[32]);	/* array of chars (x4,
                                                 * x4 if subpix) */
  unsigned        dependency;	/* one bit per chunk, max 32 chunks
                                 * should be enough */
};

/* each character in a chunk looks like this */
struct fontfile_character_str {
  enum {
    fff_coord12 = 001,		/* 12-bit coords, else 8-bit */
    fff_1bpp = 002,		/* data is 1bpp, else 4bpp */
    fff_blackpixel = 004,	/* colour of first pixel */
    fff_outline = 010,		/* outlines, else bitmaps */
    fff_composite = 020,	/* comp. base char follows */
    fff_accent = 040,		/* comp. accent follows */
    fff_code16 = 0100		/* char codes are 16-bit (not
                                 * supported) */
  } flags;
  int             base;		/* 0 if no comp. base char */
  int             accent;	/* 0 if no comp. accent */
  int             accx, accy;	/* accent position */
  Box16           bbox;		/* bounding box for char */

  /* remaining data depends on bpp */
  unsigned       *data;		/* bpp!=0: raw data */
  int             datasize;	/* size of remaining raw data */
  /* bpp==0: outlines + extra composite char inclusions */
  int            *outline;	/* bpp=0: list of move,line, curves */
  struct fontfile_composite_str {	/* composite character
                                         * inclusions */
    int             code;	/* char code (0=end) */
    int             x, y;	/* position of inclusion */
  }              *composite;
};

/* The outlines in the outline array have the following format */
/* It is a sequence of variable length seqments. */
enum fontfile_outlinetype {
  /* bits 0,1 are the segment type */
  ol_terminate = 0,		/* bit2=stroke paths follow,
                                 * bit3=comp.chars */
  ol_move,			/* move to x,y */
  ol_line,			/* line to x,y */
  ol_curve,			/* curve to x1,y1,x2,y2,x3,y3 */

  /* in a terminator, bits 2 and 3 mean: */
  ol_stroke = 004,		/* stroke paths follow */
  ol_composite = 010,		/* composite character inclusions
                                 * follow */

  /* in move/line/curve segments there is scaffold links */
  ol_xbit = 2,			/* bits 2-4 = x-scaffold link */
  ol_ybit = 5			/* bits 5-7 = y-scaffold link */
};
/*
 * Coordinates following the type header are all 16-bit signed
 * (design units)
 */


/*
 * Initialise and read given fontfile from filename. Return 0 in
 * failure
 */
int             Fontfile_Read(Fontfile * ff, const char *filename);

/* Get the character data for cc, or NULL if undefined */
Fontfile_Character *Fontfile_GetCharacter(Fontfile * ff, int cc);

/*
 * Free all the data in a character definition AND the structure
 * itself
 */
void            Fontfile_FreeCharacter(Fontfile_Character * ch);

/* Get the scaffold lines for cc, NULL if none */
Fontfile_Scaffold *Fontfile_GetScaffold(Fontfile * ff, int cc);

/* Free the data in a scaffold structure AND the structure itself */
void            Fontfile_FreeScaffold(Fontfile_Scaffold * sc);

/* Create a blank Fontfile */
void            Fontfile_Create(Fontfile * ff, int bpp);

/* Set character data for cc, return old data or NULL */
/* The old data should be freed by user */
Fontfile_Character *
Fontfile_SetCharacter(Fontfile * ff, int cc,
                      Fontfile_Character * ch);

/* Set the scaffold lines for cc, NULL for none */
/* The old data should be freed by user */
Fontfile_Scaffold *
Fontfile_SetScaffold(Fontfile * ff, int cc,
                     Fontfile_Scaffold * sc);

/*
 * Compact the fontfile structure, by removing undefined characters,
 * chunks and scaffold entries. Also calculate char bboxes and font
 * bbox. Also set ff_coord12 flag and scaffoldflags:0
 */
void            Fontfile_Compact(Fontfile * ff);

/* Write Fontfile to disc */
/* Returns 0 on failure */
int             Fontfile_Write(Fontfile * ff, const char *filename);

/* Delete that data structures in the fontfile */
void            Fontfile_Delete(Fontfile * ff);

#endif
