post: specify the title with -t
[neatpost.git] / font.c
blobded8feed047d4bb3900c29b793548fbfd09a7016
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 */
15 struct dict *ch_map; /* character aliases */
18 /* find a glyph by its name */
19 struct glyph *font_find(struct font *fn, char *name)
21 int i = dict_get(fn->ch_dict, name);
22 if (i < 0) /* maybe a character alias */
23 i = dict_get(fn->ch_map, name);
24 return i >= 0 ? fn->gl + i : NULL;
27 /* find a glyph by its device-dependent identifier */
28 struct glyph *font_glyph(struct font *fn, char *id)
30 int i = dict_get(fn->gl_dict, id);
31 return i >= 0 ? &fn->gl[i] : NULL;
34 static int font_glyphput(struct font *fn, char *id, char *name, int type)
36 struct glyph *g;
37 if (fn->gl_n == fn->gl_sz) {
38 fn->gl_sz = fn->gl_sz + 1024;
39 fn->gl = mextend(fn->gl, fn->gl_n, fn->gl_sz, sizeof(fn->gl[0]));
41 g = &fn->gl[fn->gl_n];
42 strcpy(g->id, id);
43 strcpy(g->name, name);
44 g->type = type;
45 g->font = fn;
46 dict_put(fn->gl_dict, g->id, fn->gl_n);
47 return fn->gl_n++;
50 static void tilleol(FILE *fin, char *s)
52 int c = fgetc(fin);
53 while (c != EOF && c != '\n') {
54 *s++ = c;
55 c = fgetc(fin);
57 *s = '\0';
58 if (c != EOF)
59 ungetc(c, fin);
62 static int font_readchar(struct font *fn, FILE *fin, int *n, int *gid)
64 struct glyph *g;
65 char tok[ILNLEN];
66 char name[ILNLEN];
67 char id[ILNLEN];
68 int type;
69 if (fscanf(fin, "%s %s", name, tok) != 2)
70 return 1;
71 if (!strcmp("---", name))
72 sprintf(name, "c%04d", *n);
73 if (strcmp("\"", tok)) {
74 if (fscanf(fin, "%d %s", &type, id) != 2)
75 return 1;
76 *gid = dict_get(fn->gl_dict, id);
77 if (*gid < 0) {
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;
85 dict_put(fn->ch_dict, name, *gid);
86 (*n)++;
87 } else {
88 dict_put(fn->ch_map, name, *gid);
90 return 0;
93 static void skipline(FILE* filp)
95 int c;
96 do {
97 c = getc(filp);
98 } while (c != '\n' && c != EOF);
101 struct font *font_open(char *path)
103 struct font *fn;
104 int ch_g = -1; /* last glyph in the charset */
105 int ch_n = 0; /* number of glyphs in the charset */
106 char tok[ILNLEN];
107 FILE *fin;
108 fin = fopen(path, "r");
109 if (!fin)
110 return NULL;
111 fn = xmalloc(sizeof(*fn));
112 if (!fn) {
113 fclose(fin);
114 return NULL;
116 memset(fn, 0, sizeof(*fn));
117 fn->gl_dict = dict_make(-1, 1);
118 fn->ch_dict = dict_make(-1, 1);
119 fn->ch_map = dict_make(-1, 1);
120 while (fscanf(fin, "%s", 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("ligatures", tok)) {
130 while (fscanf(fin, "%s", tok) == 1)
131 if (!strcmp("0", tok))
132 break;
133 } else if (!strcmp("charset", tok)) {
134 while (!font_readchar(fn, fin, &ch_n, &ch_g))
136 break;
138 skipline(fin);
140 fclose(fin);
141 return fn;
144 void font_close(struct font *fn)
146 dict_free(fn->gl_dict);
147 dict_free(fn->ch_dict);
148 dict_free(fn->ch_map);
149 free(fn->gl);
150 free(fn);
153 /* return width w for the given font and size */
154 int font_wid(struct font *fn, int sz, int w)
156 return (w * sz + dev_uwid / 2) / dev_uwid;
159 /* space width for the give word space or sentence space */
160 int font_swid(struct font *fn, int sz)
162 return font_wid(fn, sz, fn->spacewid);
165 char *font_name(struct font *fn)
167 return fn->fontname;