out: ignore invalid size requests
[neatpost.git] / font.c
blob372279e6c89e7329a2db731da5913acd4c3f6f97
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "post.h"
6 struct font {
7 char name[FNLEN];
8 char fontname[FNLEN];
9 int spacewid;
10 struct glyph gl[NGLYPHS]; /* font glyphs */
11 int gl_n; /* number of glyphs in gl[] */
12 /* charset mapping; ch[i] is mapped to glyph ch_g[i] */
13 char ch[NGLYPHS][GNLEN];
14 int ch_g[NGLYPHS];
15 int ch_n; /* number of characters in ch[] */
16 /* glyph table; lists per glyph identifier starting character */
17 int ghead[256]; /* glyph list head */
18 int gnext[NGLYPHS]; /* next item in glyph list */
19 /* charset table; lists per mapping starting character */
20 int chead[256]; /* charset list head */
21 int cnext[NGLYPHS]; /* next item in glyph list */
24 struct glyph *font_find(struct font *fn, char *name)
26 int i = fn->chead[(unsigned char) name[0]];
27 while (i >= 0) {
28 if (!strcmp(name, fn->ch[i]))
29 return fn->gl + fn->ch_g[i];
30 i = fn->cnext[i];
32 return NULL;
35 struct glyph *font_glyph(struct font *fn, char *id)
37 int i = fn->ghead[(unsigned char) id[0]];
38 while (i >= 0) {
39 if (!strcmp(fn->gl[i].id, id))
40 return &fn->gl[i];
41 i = fn->gnext[i];
43 return NULL;
46 static struct glyph *font_glyphput(struct font *fn, char *id,
47 char *name, int wid, int type)
49 int i = fn->gl_n++;
50 struct glyph *g;
51 g = &fn->gl[i];
52 strcpy(g->id, id);
53 strcpy(g->name, name);
54 g->wid = wid;
55 g->type = type;
56 g->font = fn;
57 fn->gnext[i] = fn->ghead[(unsigned char) id[0]];
58 fn->ghead[(unsigned char) id[0]] = i;
59 return g;
62 static void tilloel(FILE *fin, char *s)
64 int c = fgetc(fin);
65 while (c != EOF && c != '\n') {
66 *s++ = c;
67 c = fgetc(fin);
69 *s = '\0';
70 if (c != EOF)
71 ungetc(c, fin);
74 static int font_readchar(struct font *fn, FILE *fin)
76 char tok[ILNLEN];
77 char name[ILNLEN];
78 char id[ILNLEN];
79 struct glyph *glyph = NULL;
80 int wid, type;
81 if (fn->ch_n >= NGLYPHS)
82 return 1;
83 if (fscanf(fin, "%s %s", name, tok) != 2)
84 return 1;
85 if (!strcmp("---", name))
86 sprintf(name, "c%04d", fn->ch_n);
87 if (strcmp("\"", tok)) {
88 wid = atoi(tok);
89 if (fscanf(fin, "%d %s", &type, id) != 2)
90 return 1;
91 glyph = font_glyph(fn, id);
92 if (!glyph) {
93 glyph = font_glyphput(fn, id, name, wid, type);
94 tilloel(fin, tok);
95 if (sscanf(tok, "%d", &glyph->pos) < 1)
96 glyph->pos = 0;
98 } else {
99 glyph = fn->gl + fn->ch_g[fn->ch_n - 1];
101 strcpy(fn->ch[fn->ch_n], name);
102 fn->ch_g[fn->ch_n] = glyph - fn->gl;
103 fn->cnext[fn->ch_n] = fn->chead[(unsigned char) name[0]];
104 fn->chead[(unsigned char) name[0]] = fn->ch_n;
105 fn->ch_n++;
106 return 0;
109 static void skipline(FILE* filp)
111 int c;
112 do {
113 c = getc(filp);
114 } while (c != '\n' && c != EOF);
117 struct font *font_open(char *path)
119 struct font *fn;
120 char tok[ILNLEN];
121 FILE *fin;
122 int i;
123 fin = fopen(path, "r");
124 if (!fin)
125 return NULL;
126 fn = malloc(sizeof(*fn));
127 if (!fn) {
128 fclose(fin);
129 return NULL;
131 memset(fn, 0, sizeof(*fn));
132 for (i = 0; i < LEN(fn->ghead); i++)
133 fn->ghead[i] = -1;
134 for (i = 0; i < LEN(fn->chead); i++)
135 fn->chead[i] = -1;
136 while (fscanf(fin, "%s", tok) == 1) {
137 if (!strcmp("char", tok)) {
138 font_readchar(fn, fin);
139 } else if (!strcmp("spacewidth", tok)) {
140 fscanf(fin, "%d", &fn->spacewid);
141 } else if (!strcmp("name", tok)) {
142 fscanf(fin, "%s", fn->name);
143 } else if (!strcmp("fontname", tok)) {
144 fscanf(fin, "%s", fn->fontname);
145 } else if (!strcmp("ligatures", tok)) {
146 while (fscanf(fin, "%s", tok) == 1)
147 if (!strcmp("0", tok))
148 break;
149 } else if (!strcmp("charset", tok)) {
150 while (!font_readchar(fn, fin))
152 break;
154 skipline(fin);
156 fclose(fin);
157 return fn;
160 void font_close(struct font *fn)
162 free(fn);
165 int font_wid(struct font *fn, int sz, int w)
167 return (w * sz + dev_uwid / 2) / dev_uwid;
170 int font_swid(struct font *fn, int sz)
172 return font_wid(fn, sz, fn->spacewid);
175 char *font_name(struct font *fn)
177 return fn->fontname;