1*23842Sslatteng /* ch2vft.c 1.6 85/07/03
216037Sslatteng *
317892Sslatteng * Font translation to vfont format from character format.
416064Sslatteng *
516305Sslatteng * Use: ch2vft [ -i -s ] charfile > vfontfile
616037Sslatteng *
716037Sslatteng * Takes input from charfile (which must be in the format written
817892Sslatteng * by one of the xxx2ch programs), converts to vfont format and writes it
917892Sslatteng * to stdout. If charfile is missing, stdin is read. The -i flag tells
1017892Sslatteng * ch2vft to ignore the character codes at the start of each glyph
1117892Sslatteng * definition, and pack the glyphs in consecutive code positions starting
1217892Sslatteng * with 0. The -s flag forces ch2vft to include the whole bit-map that
1317892Sslatteng * defines the glyph. Normally, it is trimmed of white space. This is
1417892Sslatteng * usefull for making stipple patterns of fixed size.
1516037Sslatteng */
1616037Sslatteng
1716037Sslatteng #include <stdio.h>
1816037Sslatteng #include <vfont.h>
1916037Sslatteng
2016037Sslatteng
21*23842Sslatteng #ifdef sun
22*23842Sslatteng #define RES 120 /* for SUN vfont, resolution is 120 */
23*23842Sslatteng #else
2416037Sslatteng #define RES 200 /* for vfont, resolution is 200 */
25*23842Sslatteng #endif
2616037Sslatteng #define MAXLINE 200
2716064Sslatteng #define GLYPHSPACE (MAXLINE * MAXLINE)
2816037Sslatteng #define MAGICNO 0436
2916037Sslatteng #define DIRSIZ 256 /* vfonts MUST have 256 entries */
3016037Sslatteng #define DIMLIMIT 128
3116037Sslatteng
3216037Sslatteng
3316037Sslatteng char * malloc();
3416037Sslatteng
3516037Sslatteng struct dispatch g[DIRSIZ]; /* directory of glyph definitions */
3616037Sslatteng struct header head; /* font file header */
3716037Sslatteng
3817892Sslatteng int code;
3916037Sslatteng int width, length, maxv, minv, maxh, minh, refv, refh;
4016037Sslatteng int fileaddr;
4116037Sslatteng
4216037Sslatteng int ignorecode = 0;
4316305Sslatteng int stipple = 0;
4416037Sslatteng FILE * filep;
4516037Sslatteng char ibuff[MAXLINE];
4616037Sslatteng char ebuff[MAXLINE];
4716037Sslatteng char * glyphs[DIRSIZ];
4816064Sslatteng char charbits[GLYPHSPACE]; /* place to store bits for a glyph */
4916037Sslatteng
5016037Sslatteng
main(argc,argv)5116037Sslatteng main(argc,argv)
5216037Sslatteng int argc;
5316037Sslatteng char **argv;
5416037Sslatteng {
5516037Sslatteng register int i;
5616037Sslatteng register int j;
5717892Sslatteng register int codeindex;
5816037Sslatteng register char *chp;
5916037Sslatteng register char *bitp;
6016037Sslatteng float par;
6116037Sslatteng
6217892Sslatteng
6316037Sslatteng head.magic = MAGICNO;
6416037Sslatteng head.maxx = head.maxy = head.xtend = 0;
6516037Sslatteng while (argc > 1 && argv[1][0] == '-') {
6616037Sslatteng switch(argv[1][1]) {
6716037Sslatteng case 'i':
6816037Sslatteng ignorecode = 1;
6916037Sslatteng break;
7016305Sslatteng
7116305Sslatteng case 's':
7216305Sslatteng stipple = 1;
7316305Sslatteng break;
7416037Sslatteng default:
7516037Sslatteng error("%s, unknown option flag", argv[1]);
7616037Sslatteng }
7716037Sslatteng argc--; argv++;
7816037Sslatteng }
7916037Sslatteng
8016037Sslatteng if (argc == 2) {
8116037Sslatteng if ((filep = fopen (argv[1], "r")) == NULL)
8216037Sslatteng error("can't open file \"%s\"", argv[1]);
8316037Sslatteng } else filep = stdin;
8416037Sslatteng
8516037Sslatteng codeindex = 0;
8616037Sslatteng for (i = 0; i < DIRSIZ; glyphs[i++] = (char *) 0);
8716037Sslatteng
8816037Sslatteng fgets(ibuff, MAXLINE, filep);
8916101Sslatteng if (strcmp(ibuff, "fontheader\n"))
9016037Sslatteng error("not a character font file");
9116037Sslatteng
9216037Sslatteng while (fgets(ibuff, MAXLINE, filep) != NULL) {
9316037Sslatteng if (index(ibuff, '\n') == 0)
9416037Sslatteng error("input line too long");
9516037Sslatteng
9616037Sslatteng if (ibuff[0] != ':') {
9716037Sslatteng sscanf (ibuff, "%s %f", ebuff, &par);
9817892Sslatteng if (strcmp(ebuff, "res") == 0) {
9916037Sslatteng if (((int) (par + 0.5)) != RES)
10016037Sslatteng fprintf(stderr, "ch2vft warning: wrong resolution (%d).\n",
10116037Sslatteng (int) (par + 0.5) );
10217892Sslatteng }
10316037Sslatteng } else {
10416037Sslatteng if (sscanf (ibuff, ":%d, width = %f", &code, &par) != 2)
10516037Sslatteng error("bad glyph header, %s", ibuff);
10617892Sslatteng if (ignorecode) codeindex++; else codeindex = code;
10717892Sslatteng if (codeindex < 0 || codeindex >= DIRSIZ)
10817892Sslatteng error("code (%d) out of range", codeindex);
10917892Sslatteng g[codeindex].width = par + 0.5;
11016037Sslatteng
11116037Sslatteng chp = &charbits[0];
11216037Sslatteng if (fgets(chp, MAXLINE, filep) == NULL)
11316037Sslatteng error("unexpected end of input");
11416037Sslatteng width = strlen(chp) - 1;
11516037Sslatteng minh = width;
11616037Sslatteng maxh = 0;
11716064Sslatteng refv = minv = -1;
11816037Sslatteng
11916037Sslatteng for (length = 0; *chp != '\n'; length++) {
12016064Sslatteng if ((length + 1) * width > GLYPHSPACE)
12116064Sslatteng error ("out of glyph space");
12217892Sslatteng for (i = 0; i < width; i++, chp++) {
12316037Sslatteng switch (*chp) {
12416037Sslatteng case '.':
12516037Sslatteng break;
12616037Sslatteng case 'x':
12717892Sslatteng refh = i;
12816037Sslatteng refv = length;
12916037Sslatteng *chp = '.';
13016037Sslatteng break;
13116037Sslatteng case 'X':
13217892Sslatteng refh = i;
13316037Sslatteng refv = length;
13416037Sslatteng case '@':
13516037Sslatteng case '*':
13616037Sslatteng maxv = length;
13716064Sslatteng if (minv < 0) minv = length;
13817892Sslatteng if (i < minh) minh = i;
13917892Sslatteng if (i > maxh) maxh = i;
14016037Sslatteng break;
14116037Sslatteng default:
14216037Sslatteng error("illegal character '%c' in map.", *chp);
14316037Sslatteng } /* switch */
14417892Sslatteng } /* for i */
14516037Sslatteng if (fgets(chp, MAXLINE, filep) == NULL)
14616037Sslatteng error("unexpected end of input");
14716037Sslatteng } /* for length */
14816064Sslatteng
14916305Sslatteng if (stipple) { /* force whole box if making stipples */
15016305Sslatteng minv = 0;
15116305Sslatteng minh = 0;
15216305Sslatteng maxv = length - 1;
15316305Sslatteng maxh = width - 1;
15416305Sslatteng }
15516305Sslatteng
15616064Sslatteng if (refv < 0) error("no reference point in glyph %d.", code);
15716064Sslatteng if (minv < 0) {
15816064Sslatteng minv = maxv = refv;
15916064Sslatteng minh = maxh = refh;
16016064Sslatteng }
16117892Sslatteng g[codeindex].up = bound(refv - minv);
16217892Sslatteng g[codeindex].down = bound(maxv + 1 - refv);
16317892Sslatteng g[codeindex].right = bound(maxh + 1 - refh);
16417892Sslatteng g[codeindex].left = bound(refh - minh);
165*23842Sslatteng #ifdef sun
166*23842Sslatteng g[codeindex].nbytes = (maxv+1-minv) * ((maxh+16-minh) / 16) * 2;
167*23842Sslatteng #else
16817892Sslatteng g[codeindex].nbytes = (maxv + 1 - minv) * ((maxh + 8 - minh) >> 3);
169*23842Sslatteng #endif
17016037Sslatteng
17116037Sslatteng /* convert from characters to bits */
17217892Sslatteng bitp = (glyphs[codeindex] = malloc(g[codeindex].nbytes)) - 1;
17317892Sslatteng for (i = minv; i <= maxv; i++) {
17416037Sslatteng register int bitwidth;
17516037Sslatteng
17617892Sslatteng chp = &charbits[0] + width * i + minh;
17716037Sslatteng bitwidth = 0;
17816037Sslatteng for (j = minh; j <= maxh; j++, chp++) {
17916037Sslatteng if (--bitwidth < 0) {
18016037Sslatteng *++bitp = '\0';
18116037Sslatteng bitwidth = 7;
18216037Sslatteng }
18316037Sslatteng if (*chp != '.') *bitp |= 1 << bitwidth;
18416037Sslatteng }
185*23842Sslatteng #ifdef sun
186*23842Sslatteng if (!((bitp - glyphs[codeindex]) & 1)) *++bitp = '\0';
187*23842Sslatteng #endif
18817892Sslatteng } /* for i */
18916037Sslatteng } /* else */
19016037Sslatteng } /* while */
19116037Sslatteng
19216037Sslatteng fileaddr = 0;
19316037Sslatteng for (i = 0; i < DIRSIZ; i++) {
19416037Sslatteng if (glyphs[i] == (char *) 0) {
19516037Sslatteng g[i].nbytes = 0;
19616037Sslatteng } else {
19716037Sslatteng g[i].addr = fileaddr;
19816037Sslatteng fileaddr += g[i].nbytes;
19916037Sslatteng if (g[i].up > head.maxy) head.maxy = g[i].up;
20016037Sslatteng if (g[i].down > head.xtend) head.xtend = g[i].down;
20116037Sslatteng if (((int) g[i].left + g[i].right) > head.maxx)
20216037Sslatteng head.maxx = g[i].left + (int) g[i].right;
20316037Sslatteng }
20416037Sslatteng }
20516037Sslatteng head.size = fileaddr;
20616037Sslatteng
20716037Sslatteng vwrite((char *) &head, sizeof(head));
20816037Sslatteng vwrite((char *) &(g[0]), sizeof(g));
20916037Sslatteng for (i = 0; i < DIRSIZ; i++)
21016037Sslatteng if (glyphs[i] != (char *) 0)
21116037Sslatteng vwrite(glyphs[i], g[i].nbytes);
21217892Sslatteng exit(0);
21316037Sslatteng }
21416037Sslatteng
21516037Sslatteng
21617892Sslatteng /*----------------------------------------------------------------------------*
21717892Sslatteng | Routine: bound (value)
21817892Sslatteng |
21917892Sslatteng | Results: checks to make sure that the dimensions of a glyph fit into
22017892Sslatteng | the vfont format's limitations. The up, down, right, and left
22117892Sslatteng | fields must fit into a byte!), but can be signed.
22217892Sslatteng *----------------------------------------------------------------------------*/
22317892Sslatteng
bound(i)22417892Sslatteng bound(i)
22517892Sslatteng {
22617892Sslatteng if(i < DIMLIMIT && i >= -DIMLIMIT) return i;
22717892Sslatteng error ("dimension out of range");
22817892Sslatteng }
22917892Sslatteng
23017892Sslatteng
23117892Sslatteng /*----------------------------------------------------------------------------*
23217892Sslatteng | Routine: vwrite (buffer, buffer_size)
23317892Sslatteng |
23417892Sslatteng | Results: writes out character array "buffer" of size "buffer_size"
23517892Sslatteng | to standard output in small enough chunks that a pipe could
23617892Sslatteng | handle them.
23717892Sslatteng |
23817892Sslatteng | Bugs: this routine shouldn't be needed
23917892Sslatteng *----------------------------------------------------------------------------*/
24017892Sslatteng
vwrite(buf,bufsize)24117892Sslatteng vwrite(buf, bufsize)
24216037Sslatteng char *buf;
24317892Sslatteng int bufsize;
24416037Sslatteng {
24516037Sslatteng int tsize = 0;
24616037Sslatteng
24717892Sslatteng while (bufsize) {
24816037Sslatteng buf += tsize;
24917892Sslatteng tsize = bufsize > BUFSIZ ? BUFSIZ : bufsize;
25016037Sslatteng if ((tsize = write(1, buf, tsize)) < 0) {
25116064Sslatteng perror("ch2vft: write failed");
25216037Sslatteng exit(-1);
25316037Sslatteng }
25417892Sslatteng bufsize -= tsize;
25516037Sslatteng }
25616037Sslatteng }
25716037Sslatteng
25816037Sslatteng
25917892Sslatteng /*----------------------------------------------------------------------------*
26017892Sslatteng | Routine: error (format_string, argument1, argument2.... )
26117892Sslatteng |
26217892Sslatteng | Results: fprints a message to standard error, then exits with error
26317892Sslatteng | code 1
26417892Sslatteng |
26517892Sslatteng | Side Efct: This routine does NOT return
26617892Sslatteng *----------------------------------------------------------------------------*/
26717892Sslatteng
26816037Sslatteng /*VARARGS1*/
error(string,a1,a2,a3,a4)26916037Sslatteng error(string, a1, a2, a3, a4)
27016037Sslatteng char *string;
27116037Sslatteng {
27216037Sslatteng fprintf(stderr, "ch2vft: ");
27316037Sslatteng fprintf(stderr, string, a1, a2, a3, a4);
27416037Sslatteng fprintf(stderr, "\n");
27517892Sslatteng exit(1);
27616037Sslatteng }
277