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