pdf: add splines
[neatpost.git] / font.c
blob3964d384b95f388590e4ed8e3fbf879d807a071b
1 /* font handling */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "post.h"
7 struct font {
8 char name[FNLEN];
9 char desc[1024];
10 char fontname[FNLEN];
11 char fontpath[1024];
12 int spacewid;
13 struct glyph *gl; /* glyphs present in the font */
14 int gl_n, gl_sz; /* number of glyphs in the font */
15 struct dict *gl_dict; /* mapping from gl[i].id to i */
16 struct dict *ch_dict; /* charset mapping */
17 struct dict *ch_map; /* character aliases */
20 /* find a glyph by its name */
21 struct glyph *font_find(struct font *fn, char *name)
23 int i = dict_get(fn->ch_dict, name);
24 if (i < 0) /* maybe a character alias */
25 i = dict_get(fn->ch_map, name);
26 return i >= 0 ? fn->gl + i : NULL;
29 /* find a glyph by its device-dependent identifier */
30 struct glyph *font_glyph(struct font *fn, char *id)
32 int i = dict_get(fn->gl_dict, id);
33 return i >= 0 ? &fn->gl[i] : NULL;
36 static int font_glyphput(struct font *fn, char *id, char *name, int type)
38 struct glyph *g;
39 if (fn->gl_n == fn->gl_sz) {
40 fn->gl_sz = fn->gl_sz + 1024;
41 fn->gl = mextend(fn->gl, fn->gl_n, fn->gl_sz, sizeof(fn->gl[0]));
43 g = &fn->gl[fn->gl_n];
44 snprintf(g->id, sizeof(g->id), "%s", id);
45 snprintf(g->name, sizeof(g->name), "%s", name);
46 g->type = type;
47 g->font = fn;
48 dict_put(fn->gl_dict, g->id, fn->gl_n);
49 return fn->gl_n++;
52 static void tilleol(FILE *fin, char *s)
54 int c = fgetc(fin);
55 while (c != EOF && c != '\n') {
56 *s++ = c;
57 c = fgetc(fin);
59 *s = '\0';
60 if (c != EOF)
61 ungetc(c, fin);
64 static int font_readchar(struct font *fn, FILE *fin, int *n, int *gid)
66 struct glyph *g;
67 char tok[128];
68 char name[GNLEN];
69 char id[GNLEN];
70 int type;
71 if (fscanf(fin, GNFMT " %127s", name, tok) != 2)
72 return 1;
73 if (!strcmp("---", name))
74 sprintf(name, "c%04d", *n);
75 if (strcmp("\"", tok)) {
76 if (fscanf(fin, "%d " GNFMT, &type, id) != 2)
77 return 1;
78 *gid = font_glyphput(fn, id, name, type);
79 g = &fn->gl[*gid];
80 sscanf(tok, "%d", &g->wid);
81 tilleol(fin, tok);
82 if (sscanf(tok, "%d", &g->pos) != 1)
83 g->pos = 0;
84 dict_put(fn->ch_dict, name, *gid);
85 (*n)++;
86 } else {
87 dict_put(fn->ch_map, name, *gid);
89 return 0;
92 static void skipline(FILE* filp)
94 int c;
95 do {
96 c = getc(filp);
97 } while (c != '\n' && c != EOF);
100 struct font *font_open(char *path)
102 struct font *fn;
103 int ch_g = -1; /* last glyph in the charset */
104 int ch_n = 0; /* number of glyphs in the charset */
105 char tok[128];
106 FILE *fin;
107 fin = fopen(path, "r");
108 if (!fin)
109 return NULL;
110 fn = malloc(sizeof(*fn));
111 if (!fn) {
112 fclose(fin);
113 return NULL;
115 memset(fn, 0, sizeof(*fn));
116 snprintf(fn->desc, sizeof(fn->desc), "%s", path);
117 fn->gl_dict = dict_make(-1, 1, 0);
118 fn->ch_dict = dict_make(-1, 1, 0);
119 fn->ch_map = dict_make(-1, 1, 0);
120 while (fscanf(fin, "%127s", tok) == 1) {
121 if (!strcmp("char", tok)) {
122 font_readchar(fn, fin, &ch_n, &ch_g);
123 } else if (!strcmp("spacewidth", tok)) {
124 fscanf(fin, "%d", &fn->spacewid);
125 } else if (!strcmp("name", tok)) {
126 fscanf(fin, "%s", fn->name);
127 } else if (!strcmp("fontname", tok)) {
128 fscanf(fin, "%s", fn->fontname);
129 } else if (!strcmp("fontpath", tok)) {
130 int c = fgetc(fin);
131 while (c == ' ')
132 c = fgetc(fin);
133 ungetc(c, fin);
134 tilleol(fin, fn->fontpath);
135 } else if (!strcmp("ligatures", tok)) {
136 while (fscanf(fin, "%s", tok) == 1)
137 if (!strcmp("0", tok))
138 break;
139 } else if (!strcmp("charset", tok)) {
140 while (!font_readchar(fn, fin, &ch_n, &ch_g))
142 break;
144 skipline(fin);
146 fclose(fin);
147 return fn;
150 void font_close(struct font *fn)
152 dict_free(fn->gl_dict);
153 dict_free(fn->ch_dict);
154 dict_free(fn->ch_map);
155 free(fn->gl);
156 free(fn);
159 /* return width w for the given font and size */
160 int font_wid(struct font *fn, int sz, int w)
162 return (w * sz + dev_uwid / 2) / dev_uwid;
165 /* space width for the give word space or sentence space */
166 int font_swid(struct font *fn, int sz)
168 return font_wid(fn, sz, fn->spacewid);
171 char *font_name(struct font *fn)
173 return fn->fontname[0] ? fn->fontname : fn->name;
176 char *font_path(struct font *fn)
178 return fn->fontpath;
181 int font_glnum(struct font *fn, struct glyph *g)
183 return g - fn->gl;
186 struct glyph *font_glget(struct font *fn, int id)
188 return id >= 0 && id < fn->gl_n ? &fn->gl[id] : NULL;
191 char *font_desc(struct font *fn)
193 return fn->desc;