pdf: embedding Type 1 fonts
[neatpost.git] / font.c
blob0dcefefbdf85d4c055cd066c3e8ef8a28afb334e
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 strcpy(g->id, id);
45 strcpy(g->name, 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[ILNLEN];
68 char name[ILNLEN];
69 char id[ILNLEN];
70 int type;
71 if (fscanf(fin, "%s %s", 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 %s", &type, id) != 2)
77 return 1;
78 *gid = dict_get(fn->gl_dict, id);
79 if (*gid < 0) {
80 *gid = font_glyphput(fn, id, name, type);
81 g = &fn->gl[*gid];
82 sscanf(tok, "%d", &g->wid);
83 tilleol(fin, tok);
84 if (sscanf(tok, "%d", &g->pos) != 1)
85 g->pos = 0;
87 dict_put(fn->ch_dict, name, *gid);
88 (*n)++;
89 } else {
90 dict_put(fn->ch_map, name, *gid);
92 return 0;
95 static void skipline(FILE* filp)
97 int c;
98 do {
99 c = getc(filp);
100 } while (c != '\n' && c != EOF);
103 struct font *font_open(char *path)
105 struct font *fn;
106 int ch_g = -1; /* last glyph in the charset */
107 int ch_n = 0; /* number of glyphs in the charset */
108 char tok[ILNLEN];
109 FILE *fin;
110 fin = fopen(path, "r");
111 if (!fin)
112 return NULL;
113 fn = malloc(sizeof(*fn));
114 if (!fn) {
115 fclose(fin);
116 return NULL;
118 memset(fn, 0, sizeof(*fn));
119 snprintf(fn->desc, sizeof(fn->desc), "%s", path);
120 fn->gl_dict = dict_make(-1, 1, 0);
121 fn->ch_dict = dict_make(-1, 1, 0);
122 fn->ch_map = dict_make(-1, 1, 0);
123 while (fscanf(fin, "%s", tok) == 1) {
124 if (!strcmp("char", tok)) {
125 font_readchar(fn, fin, &ch_n, &ch_g);
126 } else if (!strcmp("spacewidth", tok)) {
127 fscanf(fin, "%d", &fn->spacewid);
128 } else if (!strcmp("name", tok)) {
129 fscanf(fin, "%s", fn->name);
130 } else if (!strcmp("fontname", tok)) {
131 fscanf(fin, "%s", fn->fontname);
132 } else if (!strcmp("fontpath", tok)) {
133 int c = fgetc(fin);
134 while (c == ' ')
135 c = fgetc(fin);
136 ungetc(c, fin);
137 tilleol(fin, fn->fontpath);
138 } else if (!strcmp("ligatures", tok)) {
139 while (fscanf(fin, "%s", tok) == 1)
140 if (!strcmp("0", tok))
141 break;
142 } else if (!strcmp("charset", tok)) {
143 while (!font_readchar(fn, fin, &ch_n, &ch_g))
145 break;
147 skipline(fin);
149 fclose(fin);
150 return fn;
153 void font_close(struct font *fn)
155 dict_free(fn->gl_dict);
156 dict_free(fn->ch_dict);
157 dict_free(fn->ch_map);
158 free(fn->gl);
159 free(fn);
162 /* return width w for the given font and size */
163 int font_wid(struct font *fn, int sz, int w)
165 return (w * sz + dev_uwid / 2) / dev_uwid;
168 /* space width for the give word space or sentence space */
169 int font_swid(struct font *fn, int sz)
171 return font_wid(fn, sz, fn->spacewid);
174 char *font_name(struct font *fn)
176 return fn->fontname;
179 char *font_path(struct font *fn)
181 return fn->fontpath;
184 int font_glnum(struct font *fn, struct glyph *g)
186 return g - fn->gl;
189 struct glyph *font_glget(struct font *fn, int id)
191 return id >= 0 && id < fn->gl_n ? &fn->gl[id] : NULL;
194 char *font_desc(struct font *fn)
196 return fn->desc;