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