pdf: a basic pdf post-processor
[neatpost.git] / font.c
blob3a315da70a922806e2313a36597a67364ca85de9
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 fontname[FNLEN];
10 char fontpath[1024];
11 int spacewid;
12 struct glyph *gl; /* glyphs present in the font */
13 int gl_n, gl_sz; /* number of glyphs in the font */
14 struct dict *gl_dict; /* mapping from gl[i].id to i */
15 struct dict *ch_dict; /* charset mapping */
16 struct dict *ch_map; /* character aliases */
19 /* find a glyph by its name */
20 struct glyph *font_find(struct font *fn, char *name)
22 int i = dict_get(fn->ch_dict, name);
23 if (i < 0) /* maybe a character alias */
24 i = dict_get(fn->ch_map, name);
25 return i >= 0 ? fn->gl + i : NULL;
28 /* find a glyph by its device-dependent identifier */
29 struct glyph *font_glyph(struct font *fn, char *id)
31 int i = dict_get(fn->gl_dict, id);
32 return i >= 0 ? &fn->gl[i] : NULL;
35 static int font_glyphput(struct font *fn, char *id, char *name, int type)
37 struct glyph *g;
38 if (fn->gl_n == fn->gl_sz) {
39 fn->gl_sz = fn->gl_sz + 1024;
40 fn->gl = mextend(fn->gl, fn->gl_n, fn->gl_sz, sizeof(fn->gl[0]));
42 g = &fn->gl[fn->gl_n];
43 strcpy(g->id, id);
44 strcpy(g->name, name);
45 g->type = type;
46 g->font = fn;
47 dict_put(fn->gl_dict, g->id, fn->gl_n);
48 return fn->gl_n++;
51 static void tilleol(FILE *fin, char *s)
53 int c = fgetc(fin);
54 while (c != EOF && c != '\n') {
55 *s++ = c;
56 c = fgetc(fin);
58 *s = '\0';
59 if (c != EOF)
60 ungetc(c, fin);
63 static int font_readchar(struct font *fn, FILE *fin, int *n, int *gid)
65 struct glyph *g;
66 char tok[ILNLEN];
67 char name[ILNLEN];
68 char id[ILNLEN];
69 int type;
70 if (fscanf(fin, "%s %s", name, tok) != 2)
71 return 1;
72 if (!strcmp("---", name))
73 sprintf(name, "c%04d", *n);
74 if (strcmp("\"", tok)) {
75 if (fscanf(fin, "%d %s", &type, id) != 2)
76 return 1;
77 *gid = dict_get(fn->gl_dict, id);
78 if (*gid < 0) {
79 *gid = font_glyphput(fn, id, name, type);
80 g = &fn->gl[*gid];
81 sscanf(tok, "%d", &g->wid);
82 tilleol(fin, tok);
83 if (sscanf(tok, "%d", &g->pos) != 1)
84 g->pos = 0;
86 dict_put(fn->ch_dict, name, *gid);
87 (*n)++;
88 } else {
89 dict_put(fn->ch_map, name, *gid);
91 return 0;
94 static void skipline(FILE* filp)
96 int c;
97 do {
98 c = getc(filp);
99 } while (c != '\n' && c != EOF);
102 struct font *font_open(char *path)
104 struct font *fn;
105 int ch_g = -1; /* last glyph in the charset */
106 int ch_n = 0; /* number of glyphs in the charset */
107 char tok[ILNLEN];
108 FILE *fin;
109 fin = fopen(path, "r");
110 if (!fin)
111 return NULL;
112 fn = malloc(sizeof(*fn));
113 if (!fn) {
114 fclose(fin);
115 return NULL;
117 memset(fn, 0, sizeof(*fn));
118 fn->gl_dict = dict_make(-1, 1);
119 fn->ch_dict = dict_make(-1, 1);
120 fn->ch_map = dict_make(-1, 1);
121 while (fscanf(fin, "%s", tok) == 1) {
122 if (!strcmp("char", tok)) {
123 font_readchar(fn, fin, &ch_n, &ch_g);
124 } else if (!strcmp("spacewidth", tok)) {
125 fscanf(fin, "%d", &fn->spacewid);
126 } else if (!strcmp("name", tok)) {
127 fscanf(fin, "%s", fn->name);
128 } else if (!strcmp("fontname", tok)) {
129 fscanf(fin, "%s", fn->fontname);
130 } else if (!strcmp("fontpath", tok)) {
131 int c = fgetc(fin);
132 while (c == ' ')
133 c = fgetc(fin);
134 ungetc(c, fin);
135 tilleol(fin, fn->fontpath);
136 } else if (!strcmp("ligatures", tok)) {
137 while (fscanf(fin, "%s", tok) == 1)
138 if (!strcmp("0", tok))
139 break;
140 } else if (!strcmp("charset", tok)) {
141 while (!font_readchar(fn, fin, &ch_n, &ch_g))
143 break;
145 skipline(fin);
147 fclose(fin);
148 return fn;
151 void font_close(struct font *fn)
153 dict_free(fn->gl_dict);
154 dict_free(fn->ch_dict);
155 dict_free(fn->ch_map);
156 free(fn->gl);
157 free(fn);
160 /* return width w for the given font and size */
161 int font_wid(struct font *fn, int sz, int w)
163 return (w * sz + dev_uwid / 2) / dev_uwid;
166 /* space width for the give word space or sentence space */
167 int font_swid(struct font *fn, int sz)
169 return font_wid(fn, sz, fn->spacewid);
172 char *font_name(struct font *fn)
174 return fn->fontname;
177 char *font_path(struct font *fn)
179 return fn->fontpath;
182 int font_glnum(struct font *fn, struct glyph *g)
184 return g - fn->gl;
187 struct glyph *font_glget(struct font *fn, int id)
189 return id >= 0 && id < fn->gl_n ? &fn->gl[id] : NULL;