home *** CD-ROM | disk | FTP | other *** search
- head 1.1;
- access;
- symbols;
- locks; strict;
- comment @ * @;
-
-
- 1.1
- date 94.03.26.11.35.12; author peteric; state Exp;
- branches;
- next ;
-
-
- desc
- @original version of afm parser.
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @/*************************************************************************
- *
- * $RCSfile: afm.c,v $
- *
- * $Author: peteric $
- *
- * $Date: 1994/03/07 12:43:26 $
- *
- * $Revision: 1.1 $
- *
- * Purpose: Main routine for ftree family tree formatter.
- *
- * $Log: afm.c,v $
- * Revision 1.1 1994/03/07 12:43:26 peteric
- * Initial revision
- *
- *
- *
- *************************************************************************/
-
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "ftree.h"
-
- #define MAXFONTS 8
- #define EOS '\0'
- #ifdef TEST_AFM
- #define err(str) printf("%s",str)
- #else
- #define err(str) errmsg(str)
- #endif
-
- typedef struct
- {
- char name[64]; /* PostScript name of font */
- double ulpos; /* underline position */
- double ulthick; /* underline thickness */
- int nchars; /* number of characters in font */
- double width; /* if >= 0 monospaced font of given width */
- short *encoding; /* encoding array */
- double *cwidths; /* widths array */
- int nextchar;
- } fontd_t;
-
- fontd_t fonts[MAXFONTS] = {0};
-
- int skipspc(FILE *fp);
- int readword(FILE *fp, char *buf);
- int readnum(FILE *fp, char *buf);
- int readhexnum(FILE *fp, char *buf);
- int readtoeol(FILE *fp, char *buf);
- int readbool(FILE *fp, char *buf);
- int findword(char *word);
- int readcharmetrics(FILE *fp, fontd_t *font);
- int readkerndata(FILE *fp, fontd_t *font);
- int readnextline(FILE *fp, fontd_t *font);
- FILE *openfontfile(char *name);
- void loadfont(char *name);
- double stringwidth(char *font, char *string);
-
-
- #define T_ASCENDER 1
- #define T_CAPHEIGHT 2
- #define T_CHARWIDTH 3
- #define T_CHARACTERSET 4
- #define T_CHARACTERS 5
- #define T_COMMENT 6
- #define T_DESCENDER 7
- #define T_ENCODINGSCHEME 8
- #define T_ENDCHARMETRICS 9
- #define T_ENDDIRECTION 10
- #define T_ENDFONTMETRICS 11
- #define T_ENDKERNDATA 12
- #define T_ESCCHAR 13
- #define T_FAMILYNAME 14
- #define T_FONTBBOX 15
- #define T_FONTNAME 16
- #define T_FULLNAME 17
- #define T_ISBASEFONT 18
- #define T_ISFIXEDPITCH 19
- #define T_ISFIXEDV 20
- #define T_ITALICANGLE 21
- #define T_MAPPINGSCHEME 22
- #define T_METRICSSETS 23
- #define T_NOTICE 24
- #define T_STARTCHARMETRICS 25
- #define T_STARTDIRECTION 26
- #define T_STARTFONTMETRICS 27
- #define T_STARTKERNDATA 28
- #define T_UNDERLINEPOSITION 29
- #define T_UNDERLINETHICKNESS 30
- #define T_VVECTOR 31
- #define T_VERSION 32
- #define T_WEIGHT 33
- #define T_XHEIGHT 34
-
- struct token
- {
- char *name;
- int tok;
- }
- afmNames[] =
- {
- "Ascender", T_ASCENDER,
- "CapHeight", T_CAPHEIGHT,
- "CharWidth", T_CHARWIDTH,
- "CharacterSet", T_CHARACTERSET,
- "Characters", T_CHARACTERS,
- "Comment", T_COMMENT,
- "Descender", T_DESCENDER,
- "EncodingScheme", T_ENCODINGSCHEME,
- "EndCharMetrics", T_ENDCHARMETRICS,
- "EndDirection", T_ENDDIRECTION,
- "EndFontMetrics", T_ENDFONTMETRICS,
- "EndKernData", T_ENDKERNDATA,
- "EscChar", T_ESCCHAR,
- "FamilyName", T_FAMILYNAME,
- "FontBBox", T_FONTBBOX,
- "FontName", T_FONTNAME,
- "FullName", T_FULLNAME,
- "IsBaseFont", T_ISBASEFONT,
- "IsFixedPitch", T_ISFIXEDPITCH,
- "IsFixedV", T_ISFIXEDV,
- "ItalicAngle", T_ITALICANGLE,
- "MappingScheme", T_MAPPINGSCHEME,
- "MetricsSets", T_METRICSSETS,
- "Notice", T_NOTICE,
- "StartCharMetrics", T_STARTCHARMETRICS,
- "StartDirection", T_STARTDIRECTION,
- "StartFontMetrics", T_STARTFONTMETRICS,
- "StartKernData", T_STARTKERNDATA,
- "UnderlinePosition", T_UNDERLINEPOSITION,
- "UnderlineThickness", T_UNDERLINETHICKNESS,
- "VVector", T_VVECTOR,
- "Version", T_VERSION,
- "Weight", T_WEIGHT,
- "XHeight", T_XHEIGHT,
- NULL
- };
-
- int skipspc(FILE *fp)
- {
- int c;
-
- while((c = getc(fp)) != EOF && (c == ' ' || c == '\t'))
- ;
-
- if (c != EOF)
- {
- ungetc(c, fp);
- }
-
- return !feof(fp);
- }
-
- int readword(FILE *fp, char *buf)
- {
- int c, i;
-
- i = 0;
- while((c = getc(fp)) != EOF && isalnum(c))
- {
- buf[i++] = c;
- }
- ungetc(c, fp);
- buf[i] = EOS;
- return !feof(fp);
- }
-
- int readnum(FILE *fp, char *buf)
- {
- int c, i;
-
- i = 0;
- while((c = getc(fp)) != EOF && (isdigit(c) || c == '.' || c == '-'))
- {
- buf[i++] = c;
- }
- ungetc(c, fp);
- buf[i] = EOS;
- return !feof(fp);
- }
-
- int readhexnum(FILE *fp, char *buf)
- {
- int c, i;
-
- i = 0;
- while((c = getc(fp)) != EOF && (isdigit(c) || c == '.' || c == '-' ||
- (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ))
- {
- buf[i++] = c;
- }
- ungetc(c, fp);
- buf[i] = EOS;
- return !feof(fp);
- }
-
-
- int readtoeol(FILE *fp, char *buf)
- {
- int c, i;
-
- if (buf)
- {
- i = 0;
- while((c = getc(fp)) != EOF && c != '\n' && c != '\r')
- {
- buf[i++] = c;
- }
- buf[i] = EOS;
- }
- else
- {
- while((c = getc(fp)) != EOF && c != '\n' && c != '\r')
- ;
- }
- return !feof(fp);
- }
-
-
- int readbool(FILE *fp, char *buf)
- {
- if (readword(fp, buf))
- {
- if (strcmp(buf, "true") == 0)
- return 1;
- else if (strcmp(buf, "false") == 0)
- return 0;
- }
- return -1;
- }
-
- int findword(char *word)
- {
- int r, i;
-
- for (i = 0; afmNames[i].name != NULL; i++)
- {
- r = strcmp(word, afmNames[i].name);
- if (r == 0)
- {
- return afmNames[i].tok;
- }
- else if (r < 0)
- {
- break;
- }
- }
- return -1;
- }
-
- static int inFontMetrics;
- static int inCharMetrics;
- static int inKernData;
-
- int readcharmetrics(FILE *fp, fontd_t *font)
- {
- int eoln = FALSE;
- int c, code;
- double wx[2], wy[2], bb[4], vv[2];
- char ll[2][32];
- char buf[32], nm[32];
-
- wx[0] = wy[0] = 0;
- wx[1] = wy[1] = 0;
- vv[0] = vv[1] = 0;
- bb[0] = bb[1] = bb[2] = bb[3] = 0;
- ll[0][0] = ll[1][0] = EOS;
- code = -1;
-
- while(!eoln)
- {
- if (readword(fp, buf))
- {
- switch(buf[0])
- {
- case 'C':
- c = buf[1];
- skipspc(fp);
- if (c == 'H')
- {
- readhexnum(fp, buf);
- sscanf(buf, "%x", &code);
- }
- else
- {
- readnum(fp, buf);
- sscanf(buf, "%d", &code);
- }
-
- break;
- case 'W':
- if (buf[1] == EOS || (buf[1] == '0' && buf[2] == EOS))
- {
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &wx[0]);
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &wy[0]);
- }
- else if (buf[1] == '1' && buf[2] == EOS)
- {
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &wx[1]);
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &wy[1]);
- }
- else if ((buf[1] == 'X' && buf[2] == EOS) ||
- (buf[1] == '0' && buf[2] == 'X' && buf[3] == EOS))
- {
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &wx[0]);
- }
- else if ((buf[1] == 'Y' && buf[2] == EOS) ||
- (buf[1] == '0' && buf[2] == 'Y' && buf[3] == EOS))
- {
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &wy[0]);
- }
- else if (buf[1] == '1' && buf[2] == 'X' && buf[3] == EOS)
- {
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &wx[1]);
- }
- else if (buf[1] == '1' && buf[2] == 'Y' && buf[3] == EOS)
- {
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &wy[1]);
- }
- break;
-
- case 'B':
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &bb[0]);
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &bb[1]);
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &bb[2]);
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &bb[3]);
- break;
-
- case 'N':
- if (skipspc(fp))
- readword(fp, nm);
- break;
-
- case 'V':
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &vv[0]);
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &vv[1]);
- break;
-
- case 'L':
- if (skipspc(fp) && readword(fp, ll[0]))
- readword(fp, ll[1]);
- break;
-
- default:
- if (findword(buf) == T_ENDCHARMETRICS)
- inCharMetrics = FALSE;
- else
- err("unknown keyword in char metrics\n");
- }
- }
- /*
- * move on, setting eoln or skipping one or more
- * ';' characters to get to the next word.
- */
- if (skipspc(fp))
- {
- do
- {
- c = getc(fp);
- if (c == '\n' || c == '\r')
- eoln = TRUE;
- } while (c == ';' && skipspc(fp));
-
- if (!eoln)
- ungetc(c, fp);
- }
- }
- if (code != -1)
- {
- if (font->nextchar < font->nchars)
- {
- printf("read: code %d, nm %s, w %6.2f %6.2f %6.2f %6.2f, vv %6.2f %6.2f ll %s %s\n",
- code, nm, wx[0], wy[0], wx[1], wy[1], vv[0], vv[1], ll[0], ll[1]);
- font->cwidths[code] = wx[0];
- font->encoding[code] = font->nextchar++;
- }
- }
-
- return inCharMetrics && !feof(fp);
- }
-
- int readkerndata(FILE *fp, fontd_t *font)
- {
- char word[32];
- if (readword(fp, word))
- {
- readtoeol(fp, NULL);
- if (findword(word) == T_ENDKERNDATA)
- return 0;
- }
- return !feof(fp);
- }
-
- int readnextline(FILE *fp, fontd_t *font)
- {
- char buf[80], word[32];
- int b;
-
- if (readword(fp, word))
- {
- switch(findword(word))
- {
- case T_CHARWIDTH:
- if (skipspc(fp) && readnum(fp, buf))
- font->width = atoi(buf);
- else
- err("bad CHARWIDTH setting\n");
- break;
-
- case T_CHARACTERS:
- if (skipspc(fp) && readnum(fp, buf))
- {
- font->nchars = atoi(buf);
- if (font->nchars < 0 || font->nchars > 1024)
- err("bad number of chars in font!\n");
- else
- font->cwidths = malloc(font->nchars * sizeof(int));
- if (font->cwidths == NULL)
- err("can't alloc memory for character sizes");
- }
- else
- err("bad CHARACTERS setting\n");
- break;
-
- case T_ENDCHARMETRICS:
- err("unexpected ENDCHARMETRICS\n");
- break;
-
- case T_ENDFONTMETRICS:
- inFontMetrics = FALSE;
- break;
-
- case T_ENDKERNDATA:
- err("unexpected ENDKERNDATA\n");
- break;
-
- case T_ISBASEFONT:
- if (skipspc(fp) && (b = readbool(fp, buf)) != -1)
- {
- if (b == 0)
- err("Can't cope with composite fonts, sorry\n");
- }
- break;
-
- case T_ISFIXEDPITCH:
- if (skipspc(fp) && (b = readbool(fp, buf)) != -1)
- {
- if (b == 0)
- font->width = -1; /* width = -1 ==> prop font */
- else
- font->width = 0; /* width >= 0 ==> mono font */
- }
- break;
-
- case T_METRICSSETS:
- break;
-
- case T_STARTCHARMETRICS:
- if (skipspc(fp) && readnum(fp, buf))
- {
- if (font->cwidths)
- free(font->cwidths);
- font->nchars = atoi(buf);
- if (font->nchars < 0 || font->nchars > 1024)
- err("bad number of chars in font!\n");
- else
- font->cwidths = malloc(font->nchars * sizeof(*font->cwidths));
- if (font->cwidths == NULL)
- err("can't alloc memory for character sizes");
- else
- {
- int i;
- for (i = 0; i < font->nchars; i++)
- font->cwidths[i] = 0;
- }
- }
- else
- err("bad STARTCHARMETRICS setting\n");
- inCharMetrics = TRUE;
- readtoeol(fp, NULL);
- while(readcharmetrics(fp,font));
- break;
-
- case T_STARTFONTMETRICS:
- inFontMetrics = TRUE;
- break;
-
- case T_STARTKERNDATA:
- inKernData = TRUE;
- readtoeol(fp, NULL);
- while(readkerndata(fp,font));
- break;
-
- case T_UNDERLINEPOSITION:
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &font->ulpos);
- else
- err("bad UNDERLINEPOSITION setting\n");
- break;
-
- case T_UNDERLINETHICKNESS:
- if (skipspc(fp) && readnum(fp, buf))
- sscanf(buf, "%lf", &font->ulthick);
- else
- err("bad UNDERLINETHICKNESS setting\n");
- break;
-
- case T_ENCODINGSCHEME:
- if (skipspc(fp) && readword(fp, buf))
- printf("encoding: %s\n",buf);
- break;
-
- case T_FAMILYNAME:
- case T_ASCENDER:
- case T_CAPHEIGHT:
- case T_CHARACTERSET:
- case T_COMMENT:
- case T_DESCENDER:
- case T_ENDDIRECTION:
- case T_ESCCHAR:
- case T_ITALICANGLE:
- case T_FONTNAME:
- case T_FULLNAME:
- case T_FONTBBOX:
- case T_ISFIXEDV:
- case T_MAPPINGSCHEME:
- case T_NOTICE:
- case T_STARTDIRECTION:
- case T_VVECTOR:
- case T_VERSION:
- case T_WEIGHT:
- case T_XHEIGHT:
- /* dont need to know these */
- break;
-
- default:
- /* don't know this one, ignore it */
- break;
- }
- /*
- * read the newline (at least)
- */
- readtoeol(fp, NULL);
- }
-
- return !feof(fp);
- }
-
- FILE *openfontfile(char *name)
- {
- char filen[128];
-
- strcpy(filen, "afm/");
- strcat(filen, name);
- strcat(filen, ".afm");
- return fopen(filen, "r");
- }
-
- void loadfont(char *name)
- {
- FILE *fp;
- int i, j;
-
- for(i = 0; fonts[i].name[0] != '\0' && i < MAXFONTS; i++)
- {
- if (streq(fonts[i].name, name))
- return;
- }
-
- /*
- * Run out of space!
- */
- if (i == MAXFONTS)
- {
- err("ran out of space in fonts array\n");
- return;
- }
-
- /*
- * if we got here, the font isnt loaded yet and 'i' is
- * the index of a free font struct.
- */
- fp = openfontfile(name);
- if (fp == NULL)
- {
- err("cannot load font file\n");
- return;
- }
- strcpy(fonts[i].name, name);
- fonts[i].nchars = 0;
- fonts[i].nextchar = 0;
- fonts[i].ulpos = 0;
- fonts[i].ulthick = 0;
- fonts[i].width = -1;
- fonts[i].cwidths = NULL;
- fonts[i].encoding = malloc(255 * sizeof(short));
- for(j = 0; i < 255; j++)
- fonts[i].encoding[j] = 0;
-
- while(readnextline(fp, &fonts[i]));
-
- fclose(fp);
- }
-
- double stringwidth(char *name, char *string)
- {
- char *p;
- int i, ec;
- double w;
- fontd_t *font = NULL;
-
- for(i = 0; fonts[i].name[0] != '\0' && i < MAXFONTS; i++)
- {
- if (streq(fonts[i].name, name))
- {
- font = &fonts[i];
- break;
- }
- }
-
- if (font == NULL)
- {
- return -1;
- }
-
- /*
- * check for monospaced fonts.
- */
- if (font->width >= 0)
- {
- return (strlen(string) * font->width) / 1000;
- }
- else
- {
- p = string;
- w = 0.0;
- while(*p)
- {
- ec = font->encoding[(int)*p];
- printf("Char '%c' => %d w(%10.3f)\n", *p, ec, font->cwidths[ec]);
- w += font->cwidths[ec];
- p++;
- }
- return (w / 1000);
- }
- }
-
- #ifdef TEST_AFM
-
- int main(int argc, char *argv[])
- {
- int i;
- char *font = NULL;
- char *s1, *s2, *s3, *s4, *s5;
-
- s1 = "abcdefg";
- s2 = "ABCDEFG";
- s3 = "VAflffij";
- s4 = "The Rain in Spain falls Mainly on the Plain";
- s5 = "The Quick Brown Fox Jumped over the Lazy Dog";
-
- for(i = 1; i < argc; i++)
- {
- font = argv[i];
-
- printf("loading %s...\n", font);
- loadfont(font);
-
- printf("%s:\n", font);
- printf("%s width %6.2f\n", s1, stringwidth(font, s1));
- printf("%s width %6.2f\n", s2, stringwidth(font, s2));
- printf("%s width %6.2f\n", s3, stringwidth(font, s3));
- printf("%s width %6.2f\n", s4, stringwidth(font, s4));
- printf("%s width %6.2f\n", s5, stringwidth(font, s5));
- }
- }
-
- #endif
- @
-