post: draw all glyphs with glyphshow with -n option
[neatpost.git] / font.c
blob927faec8a3d4633a34f41215b062b194508f1f6c
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 int spacewid;
11 struct glyph *gl; /* glyphs present in the font */
12 int gl_n, gl_sz; /* number of glyphs in the font */
13 struct dict *gl_dict; /* mapping from gl[i].id to i */
14 struct dict *ch_dict; /* charset mapping */
17 /* find a glyph by its name */
18 struct glyph *font_find(struct font *fn, char *name)
20 int i = dict_get(fn->ch_dict, name);
21 return i >= 0 ? fn->gl + i : NULL;
24 /* find a glyph by its device-dependent identifier */
25 struct glyph *font_glyph(struct font *fn, char *id)
27 int i = dict_get(fn->gl_dict, id);
28 return i >= 0 ? &fn->gl[i] : NULL;
31 static int font_glyphput(struct font *fn, char *id, char *name, int type)
33 struct glyph *g;
34 if (fn->gl_n == fn->gl_sz) {
35 fn->gl_sz = fn->gl_sz + 1024;
36 fn->gl = mextend(fn->gl, fn->gl_n, fn->gl_sz, sizeof(fn->gl[0]));
38 g = &fn->gl[fn->gl_n];
39 strcpy(g->id, id);
40 strcpy(g->name, name);
41 g->type = type;
42 g->font = fn;
43 dict_put(fn->gl_dict, g->id, fn->gl_n);
44 return fn->gl_n++;
47 static void tilleol(FILE *fin, char *s)
49 int c = fgetc(fin);
50 while (c != EOF && c != '\n') {
51 *s++ = c;
52 c = fgetc(fin);
54 *s = '\0';
55 if (c != EOF)
56 ungetc(c, fin);
59 static int font_readchar(struct font *fn, FILE *fin, int *n, int *gid)
61 struct glyph *g;
62 char tok[ILNLEN];
63 char name[ILNLEN];
64 char id[ILNLEN];
65 int type;
66 if (fscanf(fin, "%s %s", name, tok) != 2)
67 return 1;
68 if (!strcmp("---", name))
69 sprintf(name, "c%04d", *n);
70 if (strcmp("\"", tok)) {
71 if (fscanf(fin, "%d %s", &type, id) != 2)
72 return 1;
73 *gid = dict_get(fn->gl_dict, id);
74 if (*gid < 0) {
75 *gid = font_glyphput(fn, id, name, type);
76 g = &fn->gl[*gid];
77 sscanf(tok, "%d", &g->wid);
78 tilleol(fin, tok);
79 if (sscanf(tok, "%d", &g->pos) != 1)
80 g->pos = 0;
83 dict_put(fn->ch_dict, name, *gid);
84 (*n)++;
85 return 0;
88 static void skipline(FILE* filp)
90 int c;
91 do {
92 c = getc(filp);
93 } while (c != '\n' && c != EOF);
96 struct font *font_open(char *path)
98 struct font *fn;
99 int ch_g = -1; /* last glyph in the charset */
100 int ch_n = 0; /* number of glyphs in the charset */
101 char tok[ILNLEN];
102 FILE *fin;
103 fin = fopen(path, "r");
104 if (!fin)
105 return NULL;
106 fn = xmalloc(sizeof(*fn));
107 if (!fn) {
108 fclose(fin);
109 return NULL;
111 memset(fn, 0, sizeof(*fn));
112 fn->gl_dict = dict_make(-1, 1);
113 fn->ch_dict = dict_make(-1, 1);
114 while (fscanf(fin, "%s", tok) == 1) {
115 if (!strcmp("char", tok)) {
116 font_readchar(fn, fin, &ch_n, &ch_g);
117 } else if (!strcmp("spacewidth", tok)) {
118 fscanf(fin, "%d", &fn->spacewid);
119 } else if (!strcmp("name", tok)) {
120 fscanf(fin, "%s", fn->name);
121 } else if (!strcmp("fontname", tok)) {
122 fscanf(fin, "%s", fn->fontname);
123 } else if (!strcmp("ligatures", tok)) {
124 while (fscanf(fin, "%s", tok) == 1)
125 if (!strcmp("0", tok))
126 break;
127 } else if (!strcmp("charset", tok)) {
128 while (!font_readchar(fn, fin, &ch_n, &ch_g))
130 break;
132 skipline(fin);
134 fclose(fin);
135 return fn;
138 void font_close(struct font *fn)
140 dict_free(fn->gl_dict);
141 dict_free(fn->ch_dict);
142 free(fn->gl);
143 free(fn);
146 /* return width w for the given font and size */
147 int font_wid(struct font *fn, int sz, int w)
149 return (w * sz + dev_uwid / 2) / dev_uwid;
152 /* space width for the give word space or sentence space */
153 int font_swid(struct font *fn, int sz)
155 return font_wid(fn, sz, fn->spacewid);
158 char *font_name(struct font *fn)
160 return fn->fontname;