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