1*26450Sslatteng /*	ch2rst.c	1.7	86/03/04
216038Sslatteng  *
316065Sslatteng  * Font translation to Imagen-style fonts (RST format) from character format.
416065Sslatteng  *
516306Sslatteng  *	Use:	ch2rst  [ -i  -s ]  charfile  > rstfile
616038Sslatteng  *
716038Sslatteng  *		Takes input from charfile (which must be in the format written
817891Sslatteng  *	by one of the xxx2ch programs), converts to rst format and writes to
917891Sslatteng  *	stdout.  If charfile is missing, stdin is read.  The -i flag tells
1017891Sslatteng  *	ch2rst to ignore the character codes at the start of each glyph
1117891Sslatteng  *	definition, and pack the glyphs in consecutive code positions starting
1217891Sslatteng  *	with 0.  The -s flag forces ch2rst to NOT trim off any white space in
1317891Sslatteng  *	the glyph map.  This is usefull to make stipples of fixed size.
1416038Sslatteng  */
1516038Sslatteng 
1616038Sslatteng #include <stdio.h>
1716038Sslatteng #include "rst.h"
1816038Sslatteng 
1916038Sslatteng 
2016038Sslatteng #define PREAMBLE	44			/* size of preamble */
2116038Sslatteng #define STRINGS		2			/* length of strings at pre. */
2216038Sslatteng #define STARTGLYPH	PREAMBLE + STRINGS
2318011Sslatteng #define MAXLINE		300
2416065Sslatteng #define GLYPHSPACE	(MAXLINE * MAXLINE)
2516038Sslatteng #define wr1(x)		putchar(x)
2616038Sslatteng 
2716038Sslatteng 
2816038Sslatteng char *	malloc();
2916038Sslatteng 
3016038Sslatteng glyph_dir g[DIRSIZ];		/* directory of glyph definitions */
3116038Sslatteng preamble p;			/* set of variables for preamble */
3217891Sslatteng double widthtofix;		/* fix conversion factor */
33*26450Sslatteng double wordsptemp;		/* holds wordsp "fix" `til res. is known */
34*26450Sslatteng double linesptemp;		/* holds linesp "fix" `til res. is known */
3516038Sslatteng 
3618011Sslatteng int	code;			/* read in code for a glyph */
3718011Sslatteng int	width, length;		/* width and length of read-in matrix */
3818011Sslatteng int	maxv, minv, maxh, minh;	/* extent of "blackness" in glyph */
3918011Sslatteng int	refv, refh;		/* reference point in matrix */
4016038Sslatteng int	bitwidth;
4116038Sslatteng 
4218011Sslatteng int	ignorecode = 0;		/* flag: ignore the code number; successive */
4318011Sslatteng int	stipple = 0;		/* flag: don't eliminate white-space */
4416038Sslatteng FILE *	filep;
4516038Sslatteng char	ibuff[MAXLINE];
4616038Sslatteng char	ebuff[MAXLINE];
4716038Sslatteng char *	glyphs[DIRSIZ];
4816065Sslatteng char	charbits[GLYPHSPACE];	/* place to store bits for a glyph */
4916038Sslatteng 
5016038Sslatteng 
main(argc,argv)5117891Sslatteng main(argc, argv)
5216038Sslatteng int argc;
5316038Sslatteng char **argv;
5416038Sslatteng {
5516038Sslatteng     register int i;
5616038Sslatteng     register int j;
5717891Sslatteng     register int codeindex;
5816038Sslatteng     register char *chp;
5916038Sslatteng     register char *bitp;
6016038Sslatteng     float par;
6116038Sslatteng 
6216038Sslatteng     while (argc > 1 && argv[1][0] == '-') {
6316038Sslatteng 	switch(argv[1][1]) {
6416038Sslatteng 	case 'i':
6516038Sslatteng 		ignorecode = 1;
6616038Sslatteng 		break;
6716306Sslatteng 
6816306Sslatteng 	case 's':
6916306Sslatteng 		stipple = 1;
7016306Sslatteng 		break;
7116038Sslatteng 	default:
7216038Sslatteng 		error("%s, unknown option flag", argv[1]);
7316038Sslatteng 	}
7416038Sslatteng 	argc--; argv++;
7516038Sslatteng     }
7616038Sslatteng 
7718011Sslatteng     if (argc > 2)
7818011Sslatteng 	error("too many arguments");
7916038Sslatteng     if (argc == 2) {
8016038Sslatteng 	if ((filep = fopen (argv[1], "r")) == NULL)
8116038Sslatteng 	    error("can't open file \"%s\"", argv[1]);
8216038Sslatteng     } else filep = stdin;
8316038Sslatteng 
8416038Sslatteng     codeindex = 0;
8516038Sslatteng     for (i = 0; i < DIRSIZ; glyphs[i++] = (char *) 0);
8616038Sslatteng 
8716038Sslatteng     fgets(ibuff, MAXLINE, filep);
8816100Sslatteng     if (strcmp(ibuff, "fontheader\n"))
8916038Sslatteng 	error("not a character font file");
9016038Sslatteng 
9116038Sslatteng     while (fgets(ibuff, MAXLINE, filep) != NULL) {
9216038Sslatteng 	if (index(ibuff, '\n') == 0)
9316038Sslatteng 	    error("input line too long");
9416038Sslatteng 
9516038Sslatteng 	if (ibuff[0] != ':') {
9616038Sslatteng 	    sscanf (ibuff, "%s %f", ebuff, &par);
9716038Sslatteng 	    if (strcmp(ebuff, "size") == 0) p.p_size = par + 0.5;
9816038Sslatteng 	    else if (strcmp(ebuff, "version") == 0) {
9916038Sslatteng 		if (p.p_version = par + 0.5)
10016038Sslatteng 		    error("wrong version (%d) for Font file.", p.p_version);
101*26450Sslatteng 	    } else if (strcmp(ebuff, "mag") == 0) p.p_mag = par + 0.5;
102*26450Sslatteng 	    else if (strcmp(ebuff, "desiz") == 0) p.p_desiz = par / FIX + 0.5;
103*26450Sslatteng 	    else if (strcmp(ebuff, "linesp") == 0) linesptemp = par;
104*26450Sslatteng 	    else if (strcmp(ebuff, "wordsp") == 0) wordsptemp = par;
10516038Sslatteng 	    else if (strcmp(ebuff, "rot") == 0) p.p_rot = par + 0.5;
10616038Sslatteng 	    else if (strcmp(ebuff, "cadv") == 0) p.p_cadv = par + 0.5;
10716038Sslatteng 	    else if (strcmp(ebuff, "ladv") == 0) p.p_ladv = par + 0.5;
10816038Sslatteng 	    else if (strcmp(ebuff, "id") == 0) p.p_id = par + 0.5;
109*26450Sslatteng 	    else if (strcmp(ebuff, "res") == 0) p.p_res = par + 0.5;
110*26450Sslatteng 		/* ignore unrecognized fields */
11116038Sslatteng 	} else {
112*26450Sslatteng 			/* set up for real resolution of font file */
113*26450Sslatteng 	    if (p.p_mag)
114*26450Sslatteng 		widthtofix = 1000.0 / (FIXIN * p.p_res * p.p_mag);
115*26450Sslatteng 	    else
116*26450Sslatteng 		widthtofix = (1.0 / (FIXIN * p.p_res));
117*26450Sslatteng 	    p.p_wordsp = wordsptemp * widthtofix + 0.5;
118*26450Sslatteng 	    p.p_linesp = linesptemp * widthtofix + 0.5;
119*26450Sslatteng 
12016038Sslatteng 	    if (sscanf (ibuff, ":%d, width = %f", &code, &par) != 2)
12116038Sslatteng 		error("bad glyph header, %s", ibuff);
12217891Sslatteng 	    if (ignorecode) codeindex++; else codeindex = code;
12317891Sslatteng 	    g[codeindex].g_pwidth = par * widthtofix + 0.5;
12416038Sslatteng 
12516038Sslatteng 	    chp = &charbits[0];
12616038Sslatteng 	    if (fgets(chp, MAXLINE, filep) == NULL)
12716038Sslatteng 		error("unexpected end of input");
12816038Sslatteng 	    width = strlen(chp) - 1;
12916038Sslatteng 	    minh = width;
13016038Sslatteng 	    maxh = 0;
13116065Sslatteng 	    refv = minv = -1;
13216038Sslatteng 
13316038Sslatteng 	    for (length = 0; *chp != '\n'; length++) {
13416065Sslatteng 		if ((length + 1) * width > GLYPHSPACE)
13516065Sslatteng 		    error ("out of glyph space");
13617891Sslatteng 		for (i = 0; i < width; i++, chp++) {
13716038Sslatteng 		    switch (*chp) {
13816038Sslatteng 			case '.':
13916038Sslatteng 				break;
14016038Sslatteng 			case 'x':
14118011Sslatteng 				if (refv != -1)
14218011Sslatteng 				 error("two reference points in glyph %d",code);
14317891Sslatteng 				refh = i;
14416038Sslatteng 				refv = length;
14516038Sslatteng 				*chp = '.';
14616038Sslatteng 				break;
14716038Sslatteng 			case 'X':
14818011Sslatteng 				if (refv != -1)
14918011Sslatteng 				 error("two reference points in glyph %d",code);
15017891Sslatteng 				refh = i;
15116038Sslatteng 				refv = length;
15216038Sslatteng 			case '@':
15316065Sslatteng 			case '*':
15416038Sslatteng 				maxv = length;
15516065Sslatteng 				if (minv < 0) minv = length;
15617891Sslatteng 				if (i < minh) minh = i;
15717891Sslatteng 				if (i > maxh) maxh = i;
15816038Sslatteng 				break;
15916038Sslatteng 			default:
16016038Sslatteng 				error("illegal character '%c' in map.", *chp);
16116038Sslatteng 		    } /* switch */
16217891Sslatteng 		} /* for i */
16318011Sslatteng 		if (*chp != '\n')
16418011Sslatteng 		    error("not all lines equal length in glyph %d", code);
16516038Sslatteng 		if (fgets(chp, MAXLINE, filep) == NULL)
16616038Sslatteng 			error("unexpected end of input");
16716038Sslatteng 	    } /* for length */
16816065Sslatteng 
16916306Sslatteng 	    if (stipple) {		/* use the whole box to make a */
17016306Sslatteng 		minv = 0;		/* stipple pattern. */
17116306Sslatteng 		minh = 0;
17216306Sslatteng 		maxv = length - 1;
17316306Sslatteng 		maxh = width - 1;
17416306Sslatteng 	    }
17516306Sslatteng 
17616065Sslatteng 	    if (refv < 0) error("no reference point in glyph %d.", code);
17716065Sslatteng 	    if (minv < 0) {
17816065Sslatteng 		minv = maxv = refv;
17916065Sslatteng 		minh = maxh = refh;
18016065Sslatteng 	    }
18117891Sslatteng 	    g[codeindex].g_height = maxv + 1 - minv;
18217891Sslatteng 	    g[codeindex].g_width = maxh + 1 - minh;
18317891Sslatteng 	    g[codeindex].g_up = refv - minv;
18417891Sslatteng 	    g[codeindex].g_left = refh - minh;
18517891Sslatteng 	    g[codeindex].g_bitp =
18617891Sslatteng 		g[codeindex].g_height * ((g[codeindex].g_width + 7) / 8);
18716038Sslatteng 
18817891Sslatteng 	    bitp = (glyphs[codeindex] = malloc(g[codeindex].g_bitp)) - 1;
18918011Sslatteng 	    if (!glyphs[codeindex])
19018011Sslatteng 		error("out of memory");
19117891Sslatteng 	    for (i = minv; i <= maxv; i++) {
19217891Sslatteng 		chp = &charbits[0] + width * i + minh;
19316038Sslatteng 		bitwidth = 0;
19416038Sslatteng 		for (j = minh; j <= maxh; j++, chp++) {
19516038Sslatteng 		    if (--bitwidth < 0) {
19616038Sslatteng 			*++bitp = '\0';
19716038Sslatteng 			bitwidth = 7;
19816038Sslatteng 		    }
19916038Sslatteng 		    if (*chp != '.') *bitp |= 1 << bitwidth;
20016038Sslatteng 		}
20117891Sslatteng 	    } /* for i */
20216038Sslatteng 	} /* else */
20316038Sslatteng     } /* while */
20416038Sslatteng 
20516038Sslatteng     if (ignorecode) {
20617891Sslatteng 	p.p_last = codeindex - 1;
20716038Sslatteng 	p.p_first = 0;
20816038Sslatteng     } else {
20916038Sslatteng 	for (i = DIRSIZ - 1; glyphs[i] == (char *) 0; i--);
21016038Sslatteng 	p.p_last = i;
21117891Sslatteng 	for (i = 0; glyphs[i] == (char *) 0; i++);
21217891Sslatteng 	p.p_first = i;
21316038Sslatteng     }
21416038Sslatteng     bitwidth = STARTGLYPH + 15 * (1 + p.p_last - p.p_first);
21516038Sslatteng 
21616038Sslatteng     printf("Rast UCB");
21716038Sslatteng     wr2(p.p_size);	 wr1(p.p_version);	wr3(STARTGLYPH);
21816038Sslatteng     wr2(p.p_first);	 wr2(p.p_last);		wr4(p.p_mag);
21916038Sslatteng     wr4(p.p_desiz);	 wr4(p.p_linesp);	wr4(p.p_wordsp);
22016038Sslatteng     wr2(p.p_rot);	 wr1(p.p_cadv);		wr1(p.p_ladv);
22116038Sslatteng     wr4(p.p_id);	 wr2(p.p_res);
22216038Sslatteng     for (i = 0; i < STRINGS; i++) putchar('\0');
22316038Sslatteng 
22416038Sslatteng     for (i = p.p_first; i <= p.p_last; i++) {
22516038Sslatteng 	if (glyphs[i] == (char *) 0) {
22616038Sslatteng 	    for (j = 0; j < 15; j++) putchar('\0');
22716038Sslatteng 	} else {
22816038Sslatteng 	    wr2(g[i].g_height);
22916038Sslatteng 	    wr2(g[i].g_width);
23016038Sslatteng 	    wr2(g[i].g_up);
23116038Sslatteng 	    wr2(g[i].g_left);
23216038Sslatteng 	    wr4(g[i].g_pwidth);
23316038Sslatteng 	    wr3(bitwidth);
23416038Sslatteng 	    bitwidth += g[i].g_bitp;
23516038Sslatteng 	}
23617891Sslatteng     } /* for i */
23716038Sslatteng     fflush(stdout);
23816038Sslatteng 
23916038Sslatteng     for (i = p.p_first; i <= p.p_last; i++)
24016038Sslatteng 	if (glyphs[i] != (char *) 0)
24116038Sslatteng 	    vwrite(glyphs[i], g[i].g_bitp);
24217891Sslatteng     exit(0);
24316038Sslatteng }
24416038Sslatteng 
24516038Sslatteng 
24617891Sslatteng /*----------------------------------------------------------------------------*
24717891Sslatteng  | Routine:	vwrite (buffer, buffer_size)
24817891Sslatteng  |
24917891Sslatteng  | Results:	writes out character array "buffer" of size "buffer_size"
25017891Sslatteng  |		to standard output in small enough chunks that a pipe could
25117891Sslatteng  |		handle them.
25217891Sslatteng  |
25317891Sslatteng  | Bugs:	this routine shouldn't be needed
25417891Sslatteng  *----------------------------------------------------------------------------*/
25517891Sslatteng 
vwrite(buf,bufsize)25617891Sslatteng vwrite(buf, bufsize)
25716038Sslatteng char *buf;
25817891Sslatteng int bufsize;
25916038Sslatteng {
26016038Sslatteng 	int tsize = 0;
26116038Sslatteng 
26217891Sslatteng 	while (bufsize) {
26316038Sslatteng 		buf += tsize;
26417891Sslatteng 		tsize = bufsize > BUFSIZ ? BUFSIZ : bufsize;
26516038Sslatteng 		if ((tsize = write(1, buf, tsize)) < 0) {
26616038Sslatteng 			perror("ch2rst: write failed");
26716038Sslatteng 			exit(-1);
26816038Sslatteng 		}
26917891Sslatteng 		bufsize -= tsize;
27016038Sslatteng 	}
27116038Sslatteng }
27216038Sslatteng 
27316038Sslatteng 
27417891Sslatteng /*----------------------------------------------------------------------------*
27517891Sslatteng  | Routine:	error (format_string, argument1, argument2.... )
27617891Sslatteng  |
27717891Sslatteng  | Results:	fprints a message to standard error, then exits with error
27817891Sslatteng  |		code 1
27917891Sslatteng  |
28017891Sslatteng  | Side Efct:	This routine does NOT return
28117891Sslatteng  *----------------------------------------------------------------------------*/
28217891Sslatteng 
28316038Sslatteng /*VARARGS1*/
error(string,a1,a2,a3,a4)28416038Sslatteng error(string, a1, a2, a3, a4)
28516038Sslatteng char *string;
28616038Sslatteng {
28716038Sslatteng 	fprintf(stderr, "ch2rst: ");
28816038Sslatteng 	fprintf(stderr, string, a1, a2, a3, a4);
28916038Sslatteng 	fprintf(stderr, "\n");
29017891Sslatteng 	exit(1);
29117891Sslatteng }
29216038Sslatteng 
29316038Sslatteng 
29417891Sslatteng /*----------------------------------------------------------------------------*
29517891Sslatteng  | Routine:	wr2, wr3, wr4 (and wr1)
29617891Sslatteng  |
29717891Sslatteng  | Results:	writes out 2, 3, or 4 byte integers in RST byte order, using
29817891Sslatteng  |		the wr1() routine, which writes one byte to standard output.
29917891Sslatteng  *----------------------------------------------------------------------------*/
30017891Sslatteng 
wr2(i)30116038Sslatteng wr2(i)
30216038Sslatteng unsigned int i;
30316038Sslatteng {
30417891Sslatteng     wr1((i >> 8) & 255);
30517891Sslatteng     wr1(i & 255);
30616038Sslatteng }
30716038Sslatteng 
wr3(i)30816038Sslatteng wr3(i)
30916038Sslatteng unsigned int i;
31016038Sslatteng {
31117891Sslatteng     wr1((i >> 16) & 255);
31217891Sslatteng     wr1(( i >> 8) & 255);
31317891Sslatteng     wr1(i & 255);
31416038Sslatteng }
31516038Sslatteng 
wr4(i)31616038Sslatteng wr4(i)
31716038Sslatteng unsigned int i;
31816038Sslatteng {
31917891Sslatteng     wr1((i >> 24) & 255);
32017891Sslatteng     wr1((i >> 16) & 255);
32117891Sslatteng     wr1((i >> 8) & 255);
32217891Sslatteng     wr1(i & 255);
32316038Sslatteng }
324