|
|
1.1 root 1:
2:
3: /*
4: *
5: * Reads specially formatted ASCII files, called control files, and uses
6: * them to build raster and font files that can be used by troff and its
7: * post-processors. The program reads raster files in Imagen's format from
8: * directory *rastdir and uses them, along with the information in the
9: * the control files to build new raster files and also font and device
10: * files for troff. The ASCII control files must list a target device.
11: * The new raster files will be put in directory *nrastdir/"rast"*device
12: * and the new font files will go in *fontdir/"dev"*device.
13: *
14: * Individual fonts or sizes can be selected using the -f and -s options.
15: * If they're not used all the font 'build' sections in the ASCII control
16: * files will be processed for all the sizes listed under 'sizes'. ASCII
17: * files will only be built when the current size is equal to the value
18: * set in unitwidth.
19: *
20: * The raster source, new raster, and new font directories can be selected
21: * using options -S, -R, and -F respectively. By default they're all set to
22: * ".".
23: *
24: * As an example I used this program and the RASTi300 file to build the
25: * tables in this package. The command line was,
26: *
27: *
28: * buildrast -S /usr/spool/imagen_src/fonts/raster/300 RASTi300
29: *
30: *
31: * The original raster files that we got from Imagen were kept in directory
32: * /usr/spool/imagen_src/fonts/raster/300.
33: *
34: */
35:
36:
37: #include <stdio.h>
38: #include <ctype.h>
39: #include <fcntl.h>
40:
41: #include "gen.h" /* general purpose definitions */
42: #include "ext.h" /* external variable declarations */
43: #include "init.h" /* printer and system definitions */
44: #include "rast.h" /* raster file definitions */
45: #include "buildrast.h" /* definitions for building files */
46:
47:
48: char *nrastdir = "."; /* new raster files go here - sort of */
49:
50: FILE *fp_in; /* current ASCII control file */
51: char buff[100]; /* buffer for reads from fp_in */
52:
53: int dodesc = ON; /* build troff's DESC file? */
54: int gotspecial = FALSE; /* recorded all special characters */
55: int dofont = ON; /* same but for ASCII font files */
56:
57: char device[20] = ""; /* everything's built for this printer */
58:
59: Charset charset[256]; /* records all special character names */
60: char *fontlist[50]; /* only do stuff for these fonts */
61: int sizelist[50]; /* and these point sizes */
62: int unitwidth = -1; /* troff tables built from this size */
63: int res = -1; /* target device's resolution */
64: char ligatures[50]; /* ligatures strings stored here */
65: char comment[100]; /* comments for each font */
66: int internalname = 1; /* for troff's ASCII font files */
67: int isspecial = FALSE; /* is this a special font */
68: char ascender[10]; /* used to get ascender data */
69: char spacechar[10]; /* spacewidth = width of this character */
70: int spacewidth = -1; /* it's index in charinfo[] */
71:
72: int above; /* has an ascender if yref > above */
73: int below; /* used to set descender value */
74:
75: int charcount = 0; /* number of chars in charset[] */
76: int fontcount = 0; /* number of entries in fonts[] */
77: int sizecount = 0; /* same but for sizelist[] */
78:
79: int first = 1; /* glyph number endpoints */
80: int last = 0;
81:
82: int fontoutput; /* process current font if ON */
83:
84: char glyphdir[GLYDIR_SIZE]; /* new raster file glyph directory */
85: Charinfo charinfo[MAX_INDEX+1]; /* data about characters in new font */
86:
87:
88: /*****************************************************************************/
89:
90:
91: main(agc, agv)
92:
93:
94: int agc;
95: char *agv[];
96:
97:
98: {
99:
100:
101: /*
102: *
103: * Builds raster tables and troff's ASCII files from Imagen supplied raster
104: * files in directory *rastdir. All this stuff is done under the control of
105: * specially formatted ASCII files which are named as command line arguments.
106: * The source raster files are found in *rastdir, which can be changed using
107: * the -S option.
108: *
109: */
110:
111:
112: argc = agc; /* other routines may want them */
113: argv = agv;
114:
115: prog_name = argv[0]; /* really just for error messages */
116:
117: rastdir = "."; /* source raster file directory */
118: nrastdir = "."; /* new raster file directory */
119: fontdir = "."; /* font directory for new files */
120:
121: options(); /* first get command line options */
122: arguments(); /* then process non-option arguments */
123:
124: exit(x_stat); /* everything probably went OK */
125:
126: } /* End of main */
127:
128:
129: /*****************************************************************************/
130:
131:
132: options()
133:
134:
135: {
136:
137:
138: int ch; /* return value from getopt() */
139: char *names = "DIF:R:S:s:r:u:f:d";
140:
141: extern char *optarg; /* used by getopt() */
142: extern int optind;
143:
144:
145: /*
146: *
147: * Reads and processes the command line options. Right now the recognized
148: * options are,
149: *
150: */
151:
152:
153: while ( (ch = getopt(argc, argv, names)) != EOF ) {
154:
155: switch ( ch ) {
156:
157: case 'r': /* set device resolution */
158: res = atoi(optarg);
159: break;
160:
161: case 'u': /* font table unitwidth */
162: unitwidth = atoi(optarg);
163: break;
164:
165: case 's': /* do stuff for these sizes only */
166: get_sizes(optarg);
167: break;
168:
169: case 'f': /* and these fonts */
170: get_fonts(optarg);
171: break;
172:
173: case 'd': /* don't build troff's DESC file */
174: dodesc = OFF;
175: break;
176:
177: case 'F': /* new troff font directory */
178: fontdir = optarg;
179: break;
180:
181: case 'R': /* directory for new raster files */
182: nrastdir = optarg;
183: break;
184:
185: case 'S': /* source raster files found here */
186: rastdir = optarg;
187: break;
188:
189: case 'D': /* debug flag */
190: debug = ON;
191: break;
192:
193: case 'I': /* ignore FATAL errors */
194: ignore = ON;
195: break;
196:
197: case '?': /* don't understand the option */
198: error(FATAL, "");
199: break;
200:
201: default: /* don't know what to do for ch */
202: error(FATAL, "missing case for option %c\n", ch);
203: break;
204:
205: } /* End switch */
206:
207: } /* End while */
208:
209: argc -= optind; /* get ready for non-option args */
210: argv += optind;
211:
212: } /* End of options */
213:
214:
215: /*****************************************************************************/
216:
217:
218: get_sizes(str)
219:
220:
221: char *str; /* comma or blank spearated size list */
222:
223:
224: {
225:
226:
227: char *tok; /* next token in *str */
228:
229: char *strtok();
230:
231:
232: /*
233: *
234: * Converts a comma or blank separated list of point sizes to integers
235: * and stores the results in sizelist[]. Used to control how many of the
236: * raster files are built. If the -s options isn't used to select point
237: * sizes, raster files for all the sizes listed in the ASCII control files
238: * will be built.
239: *
240: */
241:
242:
243: while ( (tok = strtok(str, " ,")) != NULL ) {
244: sizelist[sizecount++] = atoi(tok);
245: str = NULL;
246: } /* End while */
247:
248: } /* End of get_sizes */
249:
250:
251: /*****************************************************************************/
252:
253:
254: get_fonts(str)
255:
256:
257: char *str; /* list of fonts to process */
258:
259:
260: {
261:
262:
263: char *tok; /* next font name from *str */
264:
265:
266: /*
267: *
268: * Called from options() to convert a comma or blank separated list of
269: * font names into pointers that can be stored in fontlist[]. Overrides
270: * the selection of fonts listed in the ASCII control files.
271: *
272: */
273:
274:
275: while ( (tok = strtok(str, " ,")) != NULL ) {
276: fontlist[fontcount++] = tok;
277: str = NULL;
278: } /* End while */
279:
280: } /* End of get_fonts */
281:
282:
283: /*****************************************************************************/
284:
285:
286: arguments()
287:
288:
289: {
290:
291:
292: /*
293: *
294: * All the rest of the comand line arguments are the names of ASCII control
295: * files. If there are no arguments left when we get here stdin will be
296: * read.
297: *
298: * Although the program accepts more than one control file name, I haven't
299: * really tested things using several control files. Probably needs more
300: * some more work.
301: *
302: */
303:
304:
305: if ( argc < 1 ) {
306: fp_in = stdin;
307: readcontrol();
308: } else {
309: while ( argc > 0 ) {
310: if ( (fp_in = fopen(*argv, "r")) == NULL )
311: error(FATAL, "can't open %s", *argv);
312: readcontrol();
313: fclose(fp_in);
314: argc--;
315: argv++;
316: } /* End while */
317: } /* End else */
318:
319: } /* End of arguments */
320:
321:
322: /*****************************************************************************/
323:
324:
325: readcontrol()
326:
327:
328: {
329:
330:
331: long pos; /* where build section starts in fp_in */
332: int i; /* loop index for sizelist[] */
333:
334:
335: /*
336: *
337: * Starts reading the ASCII description file fp_in. The stuff at the
338: * beginning is primarily for the DESC file and is just skipped, although
339: * the sizes, res, and unitwidth fields are used if the values haven't been
340: * set by options. Lines are read and processed by this routine until
341: * EOF is reached or the first build command is found. If we process the
342: * first part of the file and don't have res, unitwidth, and sizecount set
343: * an error message will be printed and we'll quit.
344: *
345: * After we break out of the first while loop, usually because a 'build'
346: * command was read, we record our position in file *fp_in and then enter
347: * a for loop that processes the rest of the file - once for each of the
348: * requested sizes. gotspecial controls whether we record special character
349: * names for the DESC file. We only need to do it on the first complete read
350: * of file *fp_in.
351: *
352: */
353:
354:
355: while ( fscanf(fp_in, "%s", buff) != EOF )
356: if ( sizecount <= 0 && strcmp(buff, "sizes") == 0 ) {
357: while ( fscanf(fp_in, "%d", &sizelist[sizecount]) == 1 && sizelist[sizecount] != 0 )
358: sizecount++;
359: } else if ( unitwidth <= 0 && strcmp(buff, "unitwidth") == 0 )
360: fscanf(fp_in, "%d", &unitwidth);
361: else if ( res <= 0 && strcmp(buff, "res") == 0 )
362: fscanf(fp_in, "%d", &res);
363: else if ( strcmp(buff, "device") == 0 )
364: fscanf(fp_in, "%s", device);
365: else if ( strcmp(buff, "build") == 0 )
366: break;
367: else skipline(fp_in);
368:
369: if ( res <= 0 || unitwidth <= 0 || sizecount <= 0 )
370: error(FATAL, "Missing res, unitwidth, or size specification");
371:
372: if ( device[0] == '\0' )
373: error(FATAL, "no device name given");
374:
375: pos = (long) ftell(fp_in); /* probably want to get back here */
376:
377: for ( i = 0; i < sizecount; i++ ) {
378: build(sizelist[i]);
379: fseek(fp_in, pos, 0);
380: gotspecial = TRUE;
381: } /* End for */
382:
383: builddesc();
384: rastdata();
385:
386: } /* End of readcontrol */
387:
388:
389: /*****************************************************************************/
390:
391:
392: build(size)
393:
394:
395: int size; /* building files for this size */
396:
397:
398: {
399:
400:
401: char name[40]; /* name of font we're building */
402: char *ptr; /* used to pick up font comment field */
403: int i, n; /* used for font size selection */
404: int lsize; /* last valid size in font size list */
405: int osize; /* original size - reset in the loop */
406:
407:
408: /*
409: *
410: * Called from readcontrol() when we want to build font and raster files. At the
411: * top of the main loop we've read a 'build' command but haven't processed the
412: * name of the font yet. Once we get the name we initialize some variables,
413: * throw out all raster files we may already have read, skip the rest of the
414: * current line in *fp_in, and then enter a loop that processes all the
415: * allowed commands in a build section. The most important of these commands
416: * is 'using', which allows us to select particular characters from named
417: * raster files. It's assumed that we're finished with the current build
418: * section when we return from using() or when we read another 'build'
419: * command. When we exit the inner loop we're ready to build the new
420: * raster file. If size == unitwidth we'll also want to construct an ASCII
421: * font file for font *name.
422: *
423: * Actually that's not quite right. I've added code, that's really not very
424: * clear, that handles fonts with less than a complete set of raster files.
425: * Although much of the stuff can be done by hand, I think it's important
426: * to have buildrast handle everything. Logos will usually come in only
427: * one size and we may eventually want to add more logos to the raster file.
428: * That in itself would be difficult to do by hand, and adding more font
429: * font positions isn't all that clean either. There are a bunch of other
430: * ways it could have been handled, but I think adding the code to buildrast
431: * was the best choice. Fonts that don't come in all the sizes are described
432: * in the 'build' section by a command that looks like,
433: *
434: * sizes 12 18 36 0
435: *
436: * This lists the point sizes that are available for building the font.
437: * All output will only be turned OFF unless the size that we're currently
438: * working on is in the list. The sizes can come in any order as long as
439: * the list is terminated by 0. The ASCII font files are built when the
440: * current size is equal to the first size in the list. Widths are properly
441: * scaled to the correct unitwidth. The ascender and descender stuff also
442: * had to be changed.
443: *
444: * Turning the output OFF when a given size wasn't available turned out
445: * to be tricky, and that's where lsize is used. If the size isn't available
446: * we'll still have work to do in addition to reading the file, especially
447: * the first time through. So all the stuff works properly I set size to
448: * lsize before going on to the 'using' section. It's a kludge but the
449: * raster files should be available in lsize even if we're not building
450: * any files. Anyway that's sort of what's happening in the new stuff.
451: *
452: */
453:
454:
455: osize = size; /* in case we change size */
456:
457: while ( fscanf(fp_in, "%s", name) != EOF ) {
458: fontoutput = wantfont(name);
459: size = osize;
460: first = 1;
461: last = 0;
462: comment[0] = '\0';
463: ligatures[0] = '\0';
464: ascender[0] = '\0';
465: spacechar[0] = '\0';
466: spacewidth = -1;
467: isspecial = FALSE;
468: dofont = (size == unitwidth) ? ON : OFF;
469: resetrast();
470: skipline(fp_in);
471: while ( fscanf(fp_in, "%s", buff) != EOF )
472: if ( strcmp(buff, "using") == 0 ) {
473: using(name, size);
474: break;
475: } else if ( strcmp(buff, "build") == 0 )
476: break;
477: else if ( strcmp(buff, "special") == 0 )
478: isspecial = TRUE;
479: else if ( strcmp(buff, "ascender") == 0 )
480: fscanf(fp_in, "%s", ascender);
481: else if ( strcmp(buff, "spacewidth") == 0 )
482: fscanf(fp_in, "%s", spacechar);
483: else if ( strcmp(buff, "start") == 0 ) {
484: fscanf(fp_in, "%d", &first);
485: last = first - 1;
486: } else if ( strcmp(buff, "sizes") == 0 ) {
487: for ( i = 0, lsize = 0; fscanf(fp_in, "%d", &n) == 1 && n != 0 && n != size; i++, lsize = n ) ;
488: lsize = (lsize == 0 ) ? n : lsize;
489: fontoutput = (fontoutput == ON && n == size) ? ON : OFF;
490: dofont = (fontoutput == ON && i == 0 ) ? ON : OFF;
491: size = (fontoutput == ON) ? size : lsize;
492: skipline(fp_in);
493: } else if ( strcmp(buff, "comment") == 0 ) {
494: for ( ptr = comment; (*ptr = getc(fp_in)) != '\n' && *ptr != EOF; ptr++ ) ;
495: *ptr = '\0';
496: } else if ( buff[0] == '#' )
497: skipline(fp_in);
498: else error(FATAL, "don't understand command %s", buff);
499: writerast(name, size);
500: buildfont(name, size);
501: } /* End while */
502:
503: } /* End of build */
504:
505:
506: /*****************************************************************************/
507:
508:
509: using(name, size)
510:
511:
512: char name[]; /* building things for this font */
513: int size; /* and in this size */
514:
515:
516: {
517:
518:
519: char chname[10]; /* special character name */
520:
521:
522: /*
523: *
524: * Called after we've read a 'using' command. The input file is read until
525: * we reach EOF of find another build command. The format of a 'using' command
526: * can be either,
527: *
528: * using name take ascii characters n to m
529: *
530: * or,
531: *
532: * using name take characters
533: * 12 fl
534: * 13 ff
535: * 103 *a
536: *
537: *
538: * where name refers to one of the raster files in *rastdir. It's assumed
539: * that the ascii characters n to m are in positions n to m in raster file
540: * name. If that's not the case the more general form given in the second
541: * example should be used. That's also the form that will be needed for troff's
542: * special characters.
543: *
544: * Synonyms are also allowed and can be specified by having the character
545: * '"' in the first index field as the following example illustrates.
546: *
547: * using name take characters
548: * 38 &
549: * 39 aa
550: * " '
551: * 119 14
552: * " 34
553: * " 12
554: * 91 [
555: *
556: * The list of synonyms for a particular character is recorded in the
557: * Charinfo structure for that character and is only used when we build the
558: * ASCII font files.
559: *
560: * There can be as many 'using' commands for a particular font as you want
561: * and you can intermix the two formats. We'll continue building the current
562: * raster file up until we find another 'build' command or reach EOF.
563: *
564: */
565:
566:
567: if ( fontoutput == ON )
568: fprintf(stdout, "Building tables for %s size %d\n", name, size);
569:
570: while ( fscanf(fp_in, "%s", buff) != EOF ) {
571: getrastdata(buff, size);
572:
573: if ( fscanf(fp_in, " take %s", buff) != 1 )
574: error(FATAL, "syntax error in using()");
575:
576: if ( strcmp(buff, "ascii") == 0 )
577: getascii();
578:
579: skipline(fp_in);
580: while ( fscanf(fp_in, "%s", buff) != EOF ) {
581: if ( isdigit(buff[0]) ) {
582: fscanf(fp_in, "%s", chname);
583: recordchar(chname, atoi(buff));
584: } else if ( buff[0] == '"' )
585: getsynonym();
586: else if ( strcmp(buff, "using") == 0 )
587: break;
588: else if ( strcmp(buff, "build") == 0 )
589: return;
590: else if ( strcmp(buff, "edit") == 0 ) {
591: skipline(fp_in);
592: edit(fp_in);
593: return;
594: } else if ( buff[0] == '#' )
595: skipline(fp_in);
596: else error(FATAL, "don't understand command %s", buff);
597: } /* End while */
598: } /* End while */
599:
600: } /* End of using */
601:
602:
603: /*****************************************************************************/
604:
605:
606: getascii()
607:
608:
609: {
610:
611:
612: int start; /* first character's ASCII code */
613: int stop; /* last character's code */
614: char name[2]; /* name of the character - string */
615:
616:
617: /*
618: *
619: * Called when we want to take a bunch of ASCII characters from the current
620: * raster file. As I mentioned before the expected format is,
621: *
622: * using name take ascii characters start to stop
623: *
624: * where name is the name of the raster file we want to use, while start
625: * and stop and the indices of the ASCII characters we want to steal from
626: * font name. Obviously start should be less than or equal to stop otherwise
627: * nothing will be done.
628: *
629: */
630:
631:
632: if ( fscanf(fp_in, "%*s %d to %d", &start, &stop) != 2 )
633: error(FATAL, "syntax error in getascii()");
634:
635: name[1] = '\0'; /* terminate the string */
636:
637: for ( ; start <= stop; start++ ) {
638: name[0] = start;
639: recordchar(name, start);
640: } /* End for */
641:
642: } /* End of getascii */
643:
644:
645: /*****************************************************************************/
646:
647:
648: recordchar(name, index)
649:
650:
651: char *name; /* name of the character */
652: int index; /* its glyph number in *fam */
653:
654:
655: {
656:
657:
658: char *gptr1, *gptr2; /* glyph directory pointers */
659: int height, width; /* of the bitmap */
660: int i; /* used to copy directory entry */
661:
662:
663: /*
664: *
665: * Called when we want to record information about character *name. Its
666: * number in the current raster file is index. Most of the information about
667: * the character is stored in charinfo[++last]. We'll need to remember its
668: * name, pointer to its bitmap, size of the bitmap, and pointer to the new
669: * glyph directory entry. Data about the bitmap comes directly from the glyph
670: * directory entry for character index. The pointer to the new glyph directory
671: * entry is figured out from the current values of first and last. Each entry
672: * in the directory is 15 bytes long, and all we do is copy index's entry
673: * over to the new character's entry. All that really has to be fixed up
674: * is the bitmap pointer, and this guy is figured out in writerast() when
675: * we're creating the new raster file.
676: *
677: */
678:
679:
680: if ( ++last > MAX_INDEX )
681: error(FATAL, "too many characters in current raster file");
682:
683: height = getvalue(G_HEIGHT, index);
684: width = getvalue(G_WIDTH, index);
685: gptr1 = fam->rst + GLYPH_PTR(index);
686: gptr2 = glyphdir + (15 * (last - first));
687:
688: strcpy(charinfo[last].name, name);
689: strcpy(charinfo[last].rastname, fam->name);
690: charinfo[last].index = index;
691: charinfo[last].mapsize = ((width + BYTE - 1) / BYTE) * height;
692: charinfo[last].map = fam->rst + getvalue(G_BPTR, index);
693: charinfo[last].glydir = gptr2;
694: charinfo[last].synonyms[0] = '\0';
695: charinfo[last].chwidth = -1;
696:
697: for ( i = 0; i < 15; i++, gptr1++, gptr2++ )
698: *gptr2 = *gptr1;
699:
700: if ( gotspecial == FALSE && dodesc == ON && name[1] != '\0' )
701: specialchar(name);
702:
703: if ( spacechar[0] != '\0' && strcmp(name, spacechar) == 0 )
704: spacewidth = last;
705:
706: } /* End of recordchar */
707:
708:
709: /*****************************************************************************/
710:
711:
712: getsynonym()
713:
714:
715: {
716:
717:
718: char chname[10]; /* character's name built up here */
719:
720:
721: /*
722: *
723: * Called from using() when we've found a '"' in the index field. The
724: * character named next in the input file is a synonym for the one we
725: * just defined (ie. charinfo[last]). We'll add the name to the list of
726: * synonyms for the character and use that list when we build the ASCII
727: * font file.
728: *
729: */
730:
731:
732: if ( last < first ) /* haven't defined anything yet */
733: error(FATAL, "bad synonym request - no characters defined");
734:
735: fscanf(fp_in, "%s", chname);
736:
737: strcat(strcat(charinfo[last].synonyms, " "), chname);
738:
739: if ( gotspecial == FALSE && dodesc == ON && chname[1] != '\0' )
740: specialchar(chname);
741:
742: } /* End of getsynonym */
743:
744:
745: /*****************************************************************************/
746:
747:
748: specialchar(name)
749:
750:
751: char *name; /* keep track of special characters */
752:
753:
754: {
755:
756:
757: int i; /* loop index */
758:
759:
760: /*
761: *
762: * Called to record the special characters we find in the charset[] array.
763: * It's used later on when we build the DESC file. We also keep track of
764: * the ligatures defined on this font (if any), and we'll use this info
765: * when we build the new ASCII font file.
766: *
767: */
768:
769:
770: for ( i = 0; i < charcount; i++ )
771: if ( strcmp(name, charset[i].name) == 0 )
772: break;
773:
774: if ( i >= charcount ) {
775: strcpy(charset[charcount++].name, name);
776: if ( strcmp(name, "fi") == 0 )
777: strcat(ligatures, " fi");
778: else if ( strcmp(name, "ff") == 0 )
779: strcat(ligatures, " ff");
780: else if ( strcmp(name, "fl") == 0 )
781: strcat(ligatures, " fl");
782: else if ( strcmp(name, "Fi") == 0 )
783: strcat(ligatures, " ffi");
784: else if ( strcmp(name, "Fl") == 0 )
785: strcat(ligatures, " ffl");
786: } /* End if */
787:
788: } /* End of specialchar */
789:
790:
791: /*****************************************************************************/
792:
793:
794: writerast(name, size)
795:
796:
797: char *name; /* name of the font */
798: int size; /* in this point size */
799:
800:
801: {
802:
803:
804: int fd; /* new raster file */
805: int presize; /* really preamble + file mark */
806: int dirsize; /* size of glyph directory */
807: int totsize; /* total size of preamble and direc */
808: char *ptr; /* used to change new directory */
809: int offset; /* adjust bitmap pointers */
810: int i; /* loop index */
811:
812:
813: /*
814: *
815: * All the raster file data for *name.size has been collected. This routine
816: * puts it all together and writes everything out to the new raster file.
817: *
818: */
819:
820:
821: if ( fontoutput == OFF ) return; /* not doing output for this font */
822:
823: fam = &fam_data[0];
824: cur_fam = 0;
825:
826: sprintf(buff, "%s/rast%s/%s.%d", nrastdir, device, name, size);
827: if ( (fd = creat(buff, 0644)) == -1)
828: error(FATAL, "can't open %s", buff);
829:
830: presize = 8 + rst[P_LENGTH].size + getvalue(P_LENGTH);
831: dirsize = (last - first + 1) * 15;
832: totsize = presize + dirsize;
833:
834: writevalue(first, P_FIRSTGLY, fam->rst + rst[P_FIRSTGLY].offset);
835: writevalue(last, P_LASTGLY, fam->rst + rst[P_LASTGLY].offset);
836: writevalue(presize, P_GLYDIR, fam->rst + rst[P_GLYDIR].offset);
837:
838: write(fd, fam->rst, presize);
839:
840: for ( ptr = glyphdir + rst[G_BPTR].offset, offset = 0, i = first; i <= last; i++, ptr += 15 ) {
841: writevalue(totsize + offset, G_BPTR, ptr);
842: offset += charinfo[i].mapsize;
843: } /* End for */
844:
845: write(fd, glyphdir, (last - first + 1) * 15);
846:
847: for ( i = first; i <= last; i++ )
848: write(fd, charinfo[i].map, charinfo[i].mapsize);
849:
850: close(fd);
851:
852: } /* End of writerast */
853:
854:
855: /*****************************************************************************/
856:
857:
858: buildfont(font, size)
859:
860:
861: char *font; /* name of troff's font file */
862: int size; /* have data for this point size */
863:
864:
865: {
866:
867:
868: FILE *fp; /* new font file */
869: int i; /* loop index */
870: int chwidth; /* next character's font table width */
871: char *ptr; /* the whole synonym string */
872: char *syn; /* next synonym for current character */
873:
874: char *strtok();
875:
876:
877: /*
878: *
879: * Called to build the ascii font file for the current font. Things are
880: * only done if if the current size is equal to unitwidth.
881: *
882: */
883:
884:
885: if ( fontoutput == OFF || dofont == OFF )
886: return;
887:
888: sprintf(buff, "%s/dev%s/%s", fontdir, device, font);
889: if ( (fp = fopen(buff, "w")) == NULL )
890: error(FATAL, "can't open font file %s", buff);
891:
892: if ( comment[0] != '\0' )
893: fprintf(fp, "#%s\n", comment);
894:
895: fprintf(fp, "name %s\n", font);
896: fprintf(fp, "internalname %d\n", internalname++);
897:
898: if ( isspecial == TRUE )
899: fprintf(fp, "special\n");
900:
901: if ( ligatures[0] != '\0' )
902: fprintf(fp, "ligatures %s 0\n", ligatures);
903:
904: fprintf(fp, "charset\n");
905:
906: if ( isspecial == FALSE ) {
907: fprintf(fp, "\\| %d 0 0\n", (res * unitwidth)/(72 * 6));
908: fprintf(fp, "\\^ %d 0 0\n", (res * unitwidth)/(72 * 12));
909: } /* End if */
910:
911: setascender(size);
912:
913: for ( i = first; i <= last; i++ ) {
914: if ( (chwidth = charinfo[i].chwidth) < 0 ) {
915: chwidth = readvalue(charinfo[i].glydir + rst[G_CHWIDTH].offset, rst[G_CHWIDTH].size, UNSIGNED);
916: chwidth = (PIXEL_WIDTH(chwidth, res) * unitwidth) / size;
917: } /* End if */
918: fprintf(fp, "%s %d %d %d\n", charinfo[i].name, chwidth, getascender(i), i);
919: ptr = charinfo[i].synonyms;
920: while ( (syn = strtok(ptr, " ")) != NULL ) {
921: fprintf(fp, "%s \"\n", syn);
922: ptr = NULL;
923: } /* End while */
924: } /* End for */
925:
926: fclose(fp);
927:
928: } /* End of buildfont */
929:
930:
931: /*****************************************************************************/
932:
933:
934: builddesc()
935:
936:
937: {
938:
939:
940: FILE *fp; /* new desc file */
941: int ch; /* for copying first part of fp_in */
942: int i; /* for loop index for copying charset */
943:
944:
945: /*
946: *
947: * Builds the new DESC file from the data contained in the first part of
948: * the ASCII control file *fp_in and the special characters saved in the
949: * charset[] array.
950: *
951: */
952:
953:
954: if ( dodesc == OFF ) /* don't build new DESC file */
955: return;
956:
957: sprintf(buff, "%s/dev%s/DESC", fontdir, device);
958: if ( (fp = fopen(buff, "w")) == NULL )
959: error(FATAL, "can't open file %s", buff);
960:
961: fseek(fp_in, 0L, 0); /* back to start of control file */
962:
963: while ( fscanf(fp_in, "%s", buff) != EOF )
964: if ( strcmp(buff, "build") == 0 )
965: break;
966: else if ( buff[0] == '#' || strcmp(buff, "device") == 0 )
967: skipline(fp_in);
968: else {
969: fprintf(fp, "%s", buff);
970: while ( (ch = putc(getc(fp_in), fp)) != '\n' && ch != EOF ) ;
971: } /* End else */
972:
973: fprintf(fp, "charset\n");
974: fprintf(fp, "\\| \\^");
975:
976: for ( i = 0; i < charcount; i++ )
977: fprintf(fp, "%c%s", (i % 15 == 13) ? '\n' : ' ', charset[i].name);
978: putc('\n', fp);
979:
980: fclose(fp);
981:
982: } /* End of builddesc */
983:
984:
985: /*****************************************************************************/
986:
987:
988: rastdata()
989:
990:
991: {
992:
993:
994: FILE *fp; /* "RASTDATA" file */
995:
996:
997: /*
998: *
999: * The post-processor and possibly others will need to know the resolution
1000: * and format of the raster files. It's looked for in file "RASTDATA", which
1001: * is defined in file init.h. Anyway this routine makes sure a reasonable
1002: * data file goes along with all the raster files we just built.
1003: *
1004: */
1005:
1006:
1007: sprintf(buff, "%s/rast%s/%s", nrastdir, device, RASTDATA);
1008: if ( (fp = fopen(buff, "w")) == NULL )
1009: error(FATAL, "can't write file %s", buff);
1010:
1011: fprintf(fp, "#\n# Format and resolution data\n#\n");
1012: fprintf(fp, "format new\nresolution %d\n", res);
1013:
1014: fclose(fp);
1015:
1016: } /* End of rastdata */
1017:
1018:
1019: /*****************************************************************************/
1020:
1021:
1022: setascender(size)
1023:
1024:
1025: int size; /* for this size - usually unitwidth */
1026:
1027:
1028: {
1029:
1030:
1031: int i; /* just a loop index */
1032:
1033:
1034: /*
1035: *
1036: * Called to set reasonable values for the ascender/descender values above
1037: * and below. If *ascender != '\0' we'll look the character up in charinfo[]
1038: * and use it's height and yref to set values for above and below. If we
1039: * don't find the character or it hasn't been set we'll use size and res
1040: * to pick reasonable values.
1041: *
1042: */
1043:
1044:
1045: for ( i = first; i <= last; i++ )
1046: if ( strcmp(ascender, charinfo[i].name) == 0 )
1047: break;
1048:
1049: if ( i > last )
1050: above = (size * res) / (72.27 * 2);
1051: else above = readvalue(charinfo[i].glydir + rst[G_YREF].offset, rst[G_YREF].size, INTEGER);
1052:
1053: above = above + .30 * above + .5;
1054: below = .20 * above + .5;
1055:
1056: } /* End of setascender */
1057:
1058:
1059: /*****************************************************************************/
1060:
1061:
1062: getascender(n)
1063:
1064:
1065: int n; /* character's index in charinfo[] */
1066:
1067:
1068: {
1069:
1070:
1071: int height; /* raster height of n's bitmap */
1072: int yref; /* y reference point */
1073: int value; /* ascender value for character n */
1074:
1075:
1076: /*
1077: *
1078: * Figures out an appropriate value for the ascender/descender field in
1079: * troff's ASCII font files for character n.
1080: *
1081: */
1082:
1083:
1084: value = 0;
1085:
1086: yref = readvalue(charinfo[n].glydir + rst[G_YREF].offset, rst[G_YREF].size, INTEGER);
1087: height = readvalue(charinfo[n].glydir + rst[G_HEIGHT].offset, rst[G_HEIGHT].size, UNSIGNED);
1088:
1089: if ( yref >= above )
1090: value |= 02;
1091:
1092: if ( height - yref > below )
1093: value |= 01;
1094:
1095: return(value);
1096:
1097: } /* End of getascender */
1098:
1099:
1100: /*****************************************************************************/
1101:
1102:
1103: skipline(fp)
1104:
1105:
1106: FILE *fp; /* skip rest of line in this file */
1107:
1108:
1109: {
1110:
1111:
1112: int ch; /* next character from *fp_in */
1113:
1114:
1115: /*
1116: *
1117: * Skips the rest of the current line in file *fp.
1118: *
1119: */
1120:
1121:
1122: while ( (ch = getc(fp)) != '\n' && ch != EOF ) ;
1123:
1124: } /* End of skipline */
1125:
1126:
1127: /*****************************************************************************/
1128:
1129:
1130: writevalue(val, field, p)
1131:
1132:
1133: unsigned val; /* write this value out */
1134: int field; /* as next rst[field].size bytes */
1135: char *p; /* starting right here */
1136:
1137:
1138: {
1139:
1140:
1141: int n; /* size in bytes of field */
1142: int i; /* just a loop index */
1143:
1144:
1145: /*
1146: *
1147: * Writes val out as the nextrst[field].sizebytes starting at address *p.
1148: * It's used to build entries in the preamble and glyph directory for the
1149: * new raster file we're currently working on.
1150: *
1151: */
1152:
1153:
1154: n = rst[field].size; /* number of bytes to write out */
1155:
1156: for ( i = 1; i <= n; i++, p++ )
1157: *p = (val >> (n - i) * BYTE) & BMASK;
1158:
1159: } /* End of writevalue */
1160:
1161:
1162: /*****************************************************************************/
1163:
1164:
1165: unsigned readvalue(p, n, kind)
1166:
1167:
1168: register char *p; /* start here */
1169: register int n; /* and get this many bytes */
1170: int kind; /* type of field - INTEGER or UNSIGNED */
1171:
1172:
1173: {
1174:
1175:
1176: register unsigned value; /* result after decoding the field */
1177:
1178:
1179: /*
1180: *
1181: * Does essentially the same thing as getvalue() in rast.c except that we
1182: * supply different information as parameters.
1183: *
1184: */
1185:
1186:
1187: value = (kind == INTEGER && (*p & 0200)) ? ~0 : 0;
1188:
1189: for ( ; n > 0; n--, p++ )
1190: value = (value << BYTE) | (*p & BMASK);
1191:
1192: return(value);
1193:
1194: } /* End of readvalue */
1195:
1196:
1197: /*****************************************************************************/
1198:
1199:
1200: wantfont(name)
1201:
1202:
1203: char *name; /* do work for this font? */
1204:
1205:
1206: {
1207:
1208:
1209: int i; /* loop index */
1210:
1211:
1212: /*
1213: *
1214: * If we've just asked to process a few fonts (using -f option) fontcount
1215: * will be non-zero and pointers to the requested font names will be stored
1216: * in array fontlist[]. This routine returns ON if *name is one of the
1217: * requested fonts or if fontcount is 0. Otherwise OFF will be returned to
1218: * the caller, which should stop all output for *name.
1219: *
1220: */
1221:
1222:
1223: if ( fontcount == 0 ) /* didn't ask for any fonts */
1224: return(ON);
1225:
1226: for ( i = 0; i < fontcount; i++ )
1227: if ( strcmp(name, fontlist[i]) == 0 )
1228: return(ON);
1229:
1230: return(OFF);
1231:
1232: } /* End of wantfont */
1233:
1234:
1235: /*****************************************************************************/
1236:
1237:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.