1 /* ch2vft.c	1.4	84/04/07
2  *
3  * Font translation to vfonts (RST format) from character format.
4  *
5  *	Use:	ch2vft  [ -i  -s ]  charfile  > vfontfile
6  *
7  *		Takes input from charfile (which must be in the format written
8  *	by xxx2ch), converts to rst format and writes to stdout.  If charfile
9  *	is missing, stdin is read.  The -i flag tells ch2rst to ignore the
10  *	character codes at the start of each glyph definition, and pack the
11  *	glyphs in consecutive code positions starting with 0.  The -s flag
12  *	forces ch2vft to include the whole bit-map that defines the glyph.
13  *	Normally, it is trimmed of white space.  This is usefull for making
14  *	stipple patterns of fixed size.
15  */
16 
17 #include <stdio.h>
18 #include <ctype.h>
19 #include <vfont.h>
20 
21 
22 #define RES		200	/* for vfont, resolution is 200 */
23 #define MAXLINE		200
24 #define GLYPHSPACE	(MAXLINE * MAXLINE)
25 #define MAGICNO		0436
26 #define DIRSIZ		256	/* vfonts MUST have 256 entries */
27 #define DIMLIMIT	128
28 
29 
30 char *	rdchar();
31 char *	malloc();
32 
33 struct dispatch g[DIRSIZ];	/* directory of glyph definitions */
34 struct header	head;		/* font file header */
35 
36 int	code, codeindex;
37 int	width, length, maxv, minv, maxh, minh, refv, refh;
38 int	fileaddr;
39 
40 int	ignorecode = 0;
41 int	stipple = 0;
42 FILE *	filep;
43 char	ibuff[MAXLINE];
44 char	ebuff[MAXLINE];
45 char *	glyphs[DIRSIZ];
46 char	charbits[GLYPHSPACE];	/* place to store bits for a glyph */
47 
48 
49 main(argc,argv)
50 int argc;
51 char **argv;
52 {
53     register int i;
54     register int j;
55     register int k;
56     register char *chp;
57     register char *bitp;
58     float par;
59 
60     head.magic = MAGICNO;
61     head.maxx = head.maxy = head.xtend = 0;
62     while (argc > 1 && argv[1][0] == '-') {
63 	switch(argv[1][1]) {
64 	case 'i':
65 		ignorecode = 1;
66 		break;
67 
68 	case 's':
69 		stipple = 1;
70 		break;
71 	default:
72 		error("%s, unknown option flag", argv[1]);
73 	}
74 	argc--; argv++;
75     }
76 
77     if (argc == 2) {
78 	if ((filep = fopen (argv[1], "r")) == NULL)
79 	    error("can't open file \"%s\"", argv[1]);
80     } else filep = stdin;
81 
82     codeindex = 0;
83     for (i = 0; i < DIRSIZ; glyphs[i++] = (char *) 0);
84 
85     fgets(ibuff, MAXLINE, filep);
86     if (strcmp(ibuff, "fontheader\n"))
87 	error("not a character font file");
88 
89     while (fgets(ibuff, MAXLINE, filep) != NULL) {
90 	if (index(ibuff, '\n') == 0)
91 	    error("input line too long");
92 
93 	if (ibuff[0] != ':') {
94 	    sscanf (ibuff, "%s %f", ebuff, &par);
95 	    if (strcmp(ebuff, "size") == 0);
96 	    else if (strcmp(ebuff, "version") == 0) {
97 		if ((int) (par + 0.5))
98 		    error("wrong version (%d) for Font file.", (int)(par+0.5));
99 	    } else if (strcmp(ebuff, "mag") == 0);
100 	    else if (strcmp(ebuff, "desiz") == 0);  /*des_size = par/FIX + 0.5*/
101 	    else if (strcmp(ebuff, "linesp") == 0);
102 	    else if (strcmp(ebuff, "wordsp") == 0);
103 	    else if (strcmp(ebuff, "rot") == 0);
104 	    else if (strcmp(ebuff, "cadv") == 0);
105 	    else if (strcmp(ebuff, "ladv") == 0);
106 	    else if (strcmp(ebuff, "id") == 0);
107 	    else if (strcmp(ebuff, "res") == 0) {
108 		if (((int) (par + 0.5)) != RES)
109 		    fprintf(stderr, "ch2vft warning: wrong resolution (%d).\n",
110 			(int) (par + 0.5) );
111 	    } else
112 		error("unknown input descriptor, \"%s\"", ebuff);
113 	} else {
114 	    if (sscanf (ibuff, ":%d, width = %f", &code, &par) != 2)
115 		error("bad glyph header, %s", ibuff);
116 	    if (ignorecode) i = codeindex++; else i = code;
117 	    if (i < 0 || i >= DIRSIZ) error("code (%d) out of range", i);
118 	    g[i].width = par + 0.5;
119 
120 	    chp = &charbits[0];
121 	    if (fgets(chp, MAXLINE, filep) == NULL)
122 		error("unexpected end of input");
123 	    width = strlen(chp) - 1;
124 	    minh = width;
125 	    maxh = 0;
126 	    refv = minv = -1;
127 
128 	    for (length = 0; *chp != '\n'; length++) {
129 		if ((length + 1) * width > GLYPHSPACE)
130 		    error ("out of glyph space");
131 		for (j = 0; j < width; j++, chp++) {
132 		    switch (*chp) {
133 			case '.':
134 				break;
135 			case 'x':
136 				refh = j;
137 				refv = length;
138 				*chp = '.';
139 				break;
140 			case 'X':
141 				refh = j;
142 				refv = length;
143 			case '@':
144 			case '*':
145 				maxv = length;
146 				if (minv < 0) minv = length;
147 				if (j < minh) minh = j;
148 				if (j > maxh) maxh = j;
149 				break;
150 			default:
151 				error("illegal character '%c' in map.", *chp);
152 		    } /* switch */
153 		} /* for j */
154 		if (fgets(chp, MAXLINE, filep) == NULL)
155 			error("unexpected end of input");
156 	    } /* for length */
157 
158 	    if (stipple) {		/* force whole box if making stipples */
159 		minv = 0;
160 		minh = 0;
161 		maxv = length - 1;
162 		maxh = width - 1;
163 	    }
164 
165 	    if (refv < 0) error("no reference point in glyph %d.", code);
166 	    if (minv < 0) {
167 		minv = maxv = refv;
168 		minh = maxh = refh;
169 	    }
170 	    g[i].up = bound(refv - minv);
171 	    g[i].down = bound(maxv + 1 - refv);
172 	    g[i].right = bound(maxh + 1 - refh);
173 	    g[i].left = bound(refh - minh);
174 	    g[i].nbytes = (maxv + 1 - minv) * ((maxh + 8 - minh) >> 3);
175 
176 				/* convert from characters to bits */
177 	    bitp = (glyphs[i] = malloc(g[i].nbytes)) - 1;
178 	    for (k = minv; k <= maxv; k++) {
179 		register int bitwidth;
180 
181 		chp = &charbits[0] + width * k + minh;
182 		bitwidth = 0;
183 		for (j = minh; j <= maxh; j++, chp++) {
184 		    if (--bitwidth < 0) {
185 			*++bitp = '\0';
186 			bitwidth = 7;
187 		    }
188 		    if (*chp != '.') *bitp |= 1 << bitwidth;
189 		}
190 	    } /* for */
191 	} /* else */
192     } /* while */
193 
194     fileaddr = 0;
195     for (i = 0; i < DIRSIZ; i++) {
196 	if (glyphs[i] == (char *) 0) {
197 	    g[i].nbytes = 0;
198 	} else {
199 	    g[i].addr = fileaddr;
200 	    fileaddr += g[i].nbytes;
201 	    if (g[i].up > head.maxy) head.maxy = g[i].up;
202 	    if (g[i].down > head.xtend) head.xtend = g[i].down;
203 	    if (((int) g[i].left + g[i].right) > head.maxx)
204 		head.maxx = g[i].left + (int) g[i].right;
205 	}
206     }
207     head.size = fileaddr;
208 
209     vwrite((char *) &head, sizeof(head));
210     vwrite((char *) &(g[0]), sizeof(g));
211     for (i = 0; i < DIRSIZ; i++)
212 	if (glyphs[i] != (char *) 0)
213 	    vwrite(glyphs[i], g[i].nbytes);
214 }
215 
216 
217 vwrite(buf,usize)
218 char *buf;
219 int usize;
220 {
221 	int tsize = 0;
222 
223 	while (usize) {
224 		buf += tsize;
225 		tsize = usize > BUFSIZ ? BUFSIZ : usize;
226 		if ((tsize = write(1, buf, tsize)) < 0) {
227 			perror("ch2vft: write failed");
228 			exit(-1);
229 		}
230 		usize -= tsize;
231 	}
232 }
233 
234 
235 /*VARARGS1*/
236 error(string, a1, a2, a3, a4)
237 char *string;
238 {
239 	fprintf(stderr, "ch2vft: ");
240 	fprintf(stderr, string, a1, a2, a3, a4);
241 	fprintf(stderr, "\n");
242 	exit(8);
243 };
244 
245 bound(i)
246 {
247 	if(i < DIMLIMIT && i >= -DIMLIMIT) return i;
248 	error ("dimension out of range");
249 }
250