1 /* ch2x.c 1.1 87/02/05
2 *
3 * Font translation to X format from character format.
4 *
5 * Use: ch2x [ -i -s ] charfile > xfontfile
6 *
7 * Takes input from charfile (which must be in the format written
8 * by one of the xxx2ch programs), converts to X format and writes it
9 * to stdout. If charfile is missing, stdin is read. The -i flag tells
10 * ch2x to ignore the character codes at the start of each glyph
11 * definition, and pack the glyphs in consecutive code positions starting
12 * with 0. Unlike other conversion programs, white space around a glyph
13 * is preserved. Therefore, the -s option is ignored.
14 */
15
16 #include <stdio.h>
17 #include "xfont.h"
18
19
20 #define RES 75 /* for xfont, resolution is 75 */
21 #define MAXLINE 300
22 #define GLYPHSPACE (MAXLINE * MAXLINE / 8)
23 #define DIRSIZ 256 /* maximum # of entries */
24
25
26 char * malloc();
27 char * index();
28
29 struct FontData FH; /* font file header */
30 struct GlyphData {
31 short up;
32 short down;
33 short left;
34 short right;
35 short nbytes;
36 short width;
37 char *ptr;
38 } g[DIRSIZ]; /* table of glyph definitions */
39 short leftarea[DIRSIZ];
40 char bitmap[GLYPHSPACE];
41 char * newbitmap;
42
43 int code;
44 int printwidth, width, length, refv, refh;
45 int totalwidth, maxleft, maxup, maxdown;
46
47 int ignorecode = 0;
48 FILE * filep;
49 char ibuff[MAXLINE];
50
51
main(argc,argv)52 main(argc,argv)
53 int argc;
54 char **argv;
55 {
56 register int i;
57 register int j;
58 register int codeindex;
59 register char *chp;
60 register char *bitp;
61 register int bit;
62 float par;
63
64
65 while (argc > 1 && argv[1][0] == '-') {
66 switch(argv[1][1]) {
67 case 'i':
68 ignorecode = 1;
69 break;
70
71 case 's':
72 break;
73 default:
74 error("%s, unknown option flag", argv[1]);
75 }
76 argc--; argv++;
77 }
78
79 if (argc == 2) {
80 if ((filep = fopen (argv[1], "r")) == NULL)
81 error("can't open file \"%s\"", argv[1]);
82 } else filep = stdin;
83
84 codeindex = 0;
85 totalwidth = 0;
86 maxleft = 0;
87 maxup = 0;
88 maxdown = 0;
89 FH.fixedWidth = -1;
90 for (i = 0; i < DIRSIZ; g[i++].ptr = (char *) 0);
91
92 if (fgets(ibuff, MAXLINE, filep) == NULL || strcmp(ibuff, "fontheader\n"))
93 error("not a character font file");
94
95 while (fgets(ibuff, MAXLINE, filep) != NULL) {
96 if (index(ibuff, '\n') == NULL)
97 error("input line too long");
98
99 if (ibuff[0] == ':') {
100 if (sscanf (ibuff, ":%d, width = %f", &code, &par) != 2)
101 error("bad glyph header \"%s\"", ibuff);
102 if (ignorecode) codeindex++; else codeindex = code;
103 if (codeindex < 0 || codeindex >= DIRSIZ)
104 error("code (%d) out of range", codeindex);
105 printwidth = par + 0.5;
106
107 chp = &ibuff[0];
108 bitp = &bitmap[-1];
109 if (fgets(chp, MAXLINE, filep) == NULL)
110 error("unexpected end of input");
111 width = strlen(chp) - 1;
112 refv = -1;
113
114 for (length = 0; *chp != '\n'; length++) {
115 bit = 0x100;
116 for (i = 0; i < width; i++, chp++) {
117 if (bit == 0x100) {
118 if (++bitp >= &bitmap[GLYPHSPACE])
119 error ("out of glyph space");
120 *bitp = 0;
121 bit = 1;
122 }
123 switch (*chp) {
124 case '.':
125 break;
126 case 'x':
127 refh = i;
128 refv = length;
129 break;
130 case 'X':
131 refh = i;
132 refv = length;
133 case '@':
134 case '*':
135 *bitp |= bit;
136 break;
137 default:
138 error("illegal character '%c' in map.", *chp);
139 } /* switch */
140 bit <<= 1;
141 } /* for i */
142 chp = &ibuff[0];
143 if (fgets(chp, MAXLINE, filep) == NULL)
144 error("unexpected end of input");
145 } /* for length */
146
147 if (refv < 0) error("no reference point in glyph %d.", code);
148
149 g[codeindex].up = refv;
150 g[codeindex].down = length - refv;
151 g[codeindex].right = width - refh;
152 if (g[codeindex].right > printwidth)
153 printwidth = g[codeindex].right;
154 g[codeindex].left = refh;
155 g[codeindex].nbytes = bitp - bitmap + 1;
156 g[codeindex].width = printwidth;
157 totalwidth += printwidth;
158 if (FH.fixedWidth == -1)
159 FH.fixedWidth = printwidth;
160 if (FH.fixedWidth != printwidth)
161 FH.fixedWidth = 0;
162 if (g[codeindex].left > maxleft) maxleft = g[codeindex].left;
163 if (g[codeindex].up > maxup) maxup = g[codeindex].up;
164 if (g[codeindex].down > maxdown) maxdown = g[codeindex].down;
165
166 /* copy the bits to private place */
167 if ((g[codeindex].ptr = malloc(g[codeindex].nbytes)) == NULL)
168 error("out of memory reading in file");
169 bcopy(bitmap, g[codeindex].ptr, g[codeindex].nbytes);
170 } /* if ibuff == : */
171 } /* while not EOF */
172
173 if (totalwidth == 0)
174 error("empty font");
175
176 /*
177 * Fill in the "fontData" header for this font. fixedWidth is already set.
178 */
179 FH.waste = 0;
180 FH.bitsPerPixel = 1;
181 FH.spaceIndex = 32; /* we can only guess */
182 for (i = 0; g[i].ptr == NULL; i++)
183 ;
184 FH.firstChar = i;
185 for (i = DIRSIZ - 1; g[i].ptr == NULL; i--)
186 ;
187 FH.lastChar = i;
188 FH.bmHeight = maxup + maxdown;
189 FH.baseline = maxup + 1;
190 FH.leftArray = sizeof (FH);
191 FH.bitmapPtr = FH.leftArray + (FH.lastChar-FH.firstChar+2) * sizeof(short);
192
193 /*
194 * calculate "leftarea" - the pointers for each glyph into the bitmap
195 */
196 leftarea[FH.firstChar] = 0;
197 for (i = FH.firstChar; i <= FH.lastChar; i++) {
198 if (g[i].ptr == NULL) {
199 FH.fixedWidth = 0;
200 leftarea[i + 1] = leftarea[i];
201 } else {
202 leftarea[i + 1] = leftarea[i] + g[i].width + maxleft;
203 totalwidth += maxleft;
204 }
205 }
206 FH.bmWidth = totalwidth;
207 width = ((totalwidth + 15) >> 3) & ~1;
208 newbitmap = bitmap;
209 if (width > GLYPHSPACE)
210 if ((newbitmap = malloc(width)) == NULL)
211 error("out of memory writing file");
212
213 vwrite(&FH, sizeof(FH));
214 vwrite(&leftarea[FH.firstChar],(FH.lastChar-FH.firstChar+2)*sizeof(short));
215 /*
216 * Calculate and write out the "strike" bitmap
217 */
218 for (length = 0; length < FH.bmHeight; length++) {
219 bitp = newbitmap;
220 *bitp = 0;
221 i = 1;
222 for (codeindex = FH.firstChar; codeindex <= FH.lastChar; codeindex++) {
223 if (g[codeindex].ptr != NULL) {
224 for (j = -maxleft; j < g[codeindex].width; j++) {
225 if (bitset(&g[codeindex], j, maxup)) {
226 *bitp |= i;
227 }
228 i <<= 1;
229 if (i == 0x100) {
230 *++bitp = 0;
231 i = 1;
232 }
233 }
234 }
235 }
236 vwrite(newbitmap, width);
237 maxup--;
238 }
239 exit(0);
240 }
241
242
243 /*----------------------------------------------------------------------------*
244 | Routine: vwrite (buffer, buffer_size)
245 |
246 | Results: writes out character array "buffer" of size "buffer_size"
247 | in sizes that "write" can handle
248 *----------------------------------------------------------------------------*/
249
vwrite(buf,bufsize)250 vwrite(buf, bufsize)
251 char *buf;
252 int bufsize;
253 {
254 int tsize = 0;
255
256 while (bufsize) {
257 buf += tsize;
258 if ((tsize = write(1, buf, bufsize)) < 0) {
259 perror("ch2x: write failed");
260 exit(-1);
261 }
262 bufsize -= tsize;
263 }
264 }
265
266
267 /*----------------------------------------------------------------------------*
268 | Routine: bitset (GlyphData_pointer, x_position, y_position)
269 |
270 | Results: Given a Glyph definition and an x,y position (relative to the
271 | reference point of the glyph) bitset returns non-zero if the
272 | glyph has a pixel set at that point.
273 *----------------------------------------------------------------------------*/
274
275 /*VARARGS1*/
bitset(g,x,y)276 bitset(g, x, y)
277 register struct GlyphData *g;
278 register int x;
279 register int y;
280 {
281 register char *p;
282
283 x += g->left;
284 y = g->up - y;
285 if (x < 0 || y < 0 || x >= (g->left+g->right) || y >= (g->up+g->down))
286 return(0);
287 p = g->ptr + (x >> 3) + y * ((g->left + g->right + 7) >> 3);
288 return( *p & (1 << (x&7)) );
289 }
290
291
292 /*----------------------------------------------------------------------------*
293 | Routine: error (format_string, argument1, argument2.... )
294 |
295 | Results: fprints a message to standard error, then exits with error
296 | code 1
297 |
298 | Side Efct: This routine does NOT return
299 *----------------------------------------------------------------------------*/
300
301 /*VARARGS1*/
error(string,a1,a2,a3,a4)302 error(string, a1, a2, a3, a4)
303 char *string;
304 {
305 fprintf(stderr, "ch2x: ");
306 fprintf(stderr, string, a1, a2, a3, a4);
307 fprintf(stderr, "\n");
308 exit(1);
309 }
310