V10/cmd/dimpress/buildrast.c
/*
*
* Reads specially formatted ASCII files, called control files, and uses
* them to build raster and font files that can be used by troff and its
* post-processors. The program reads raster files in Imagen's format from
* directory *rastdir and uses them, along with the information in the
* the control files to build new raster files and also font and device
* files for troff. The ASCII control files must list a target device.
* The new raster files will be put in directory *nrastdir/"rast"*device
* and the new font files will go in *fontdir/"dev"*device.
*
* Individual fonts or sizes can be selected using the -f and -s options.
* If they're not used all the font 'build' sections in the ASCII control
* files will be processed for all the sizes listed under 'sizes'. ASCII
* files will only be built when the current size is equal to the value
* set in unitwidth.
*
* The raster source, new raster, and new font directories can be selected
* using options -S, -R, and -F respectively. By default they're all set to
* ".".
*
* As an example I used this program and the RASTi300 file to build the
* tables in this package. The command line was,
*
*
* buildrast -S /usr/spool/imagen_src/fonts/raster/300 RASTi300
*
*
* The original raster files that we got from Imagen were kept in directory
* /usr/spool/imagen_src/fonts/raster/300.
*
*/
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include "gen.h" /* general purpose definitions */
#include "ext.h" /* external variable declarations */
#include "init.h" /* printer and system definitions */
#include "rast.h" /* raster file definitions */
#include "buildrast.h" /* definitions for building files */
char *nrastdir = "."; /* new raster files go here - sort of */
FILE *fp_in; /* current ASCII control file */
char buff[100]; /* buffer for reads from fp_in */
int dodesc = ON; /* build troff's DESC file? */
int gotspecial = FALSE; /* recorded all special characters */
int dofont = ON; /* same but for ASCII font files */
char device[20] = ""; /* everything's built for this printer */
Charset charset[256]; /* records all special character names */
char *fontlist[50]; /* only do stuff for these fonts */
int sizelist[50]; /* and these point sizes */
int unitwidth = -1; /* troff tables built from this size */
int res = -1; /* target device's resolution */
char ligatures[50]; /* ligatures strings stored here */
char comment[100]; /* comments for each font */
int internalname = 1; /* for troff's ASCII font files */
int isspecial = FALSE; /* is this a special font */
char ascender[10]; /* used to get ascender data */
char spacechar[10]; /* spacewidth = width of this character */
int spacewidth = -1; /* it's index in charinfo[] */
int above; /* has an ascender if yref > above */
int below; /* used to set descender value */
int charcount = 0; /* number of chars in charset[] */
int fontcount = 0; /* number of entries in fonts[] */
int sizecount = 0; /* same but for sizelist[] */
int first = 1; /* glyph number endpoints */
int last = 0;
int fontoutput; /* process current font if ON */
char glyphdir[GLYDIR_SIZE]; /* new raster file glyph directory */
Charinfo charinfo[MAX_INDEX+1]; /* data about characters in new font */
/*****************************************************************************/
main(agc, agv)
int agc;
char *agv[];
{
/*
*
* Builds raster tables and troff's ASCII files from Imagen supplied raster
* files in directory *rastdir. All this stuff is done under the control of
* specially formatted ASCII files which are named as command line arguments.
* The source raster files are found in *rastdir, which can be changed using
* the -S option.
*
*/
argc = agc; /* other routines may want them */
argv = agv;
prog_name = argv[0]; /* really just for error messages */
rastdir = "."; /* source raster file directory */
nrastdir = "."; /* new raster file directory */
fontdir = "."; /* font directory for new files */
options(); /* first get command line options */
arguments(); /* then process non-option arguments */
exit(x_stat); /* everything probably went OK */
} /* End of main */
/*****************************************************************************/
options()
{
int ch; /* return value from getopt() */
char *names = "DIF:R:S:s:r:u:f:d";
extern char *optarg; /* used by getopt() */
extern int optind;
/*
*
* Reads and processes the command line options. Right now the recognized
* options are,
*
*/
while ( (ch = getopt(argc, argv, names)) != EOF ) {
switch ( ch ) {
case 'r': /* set device resolution */
res = atoi(optarg);
break;
case 'u': /* font table unitwidth */
unitwidth = atoi(optarg);
break;
case 's': /* do stuff for these sizes only */
get_sizes(optarg);
break;
case 'f': /* and these fonts */
get_fonts(optarg);
break;
case 'd': /* don't build troff's DESC file */
dodesc = OFF;
break;
case 'F': /* new troff font directory */
fontdir = optarg;
break;
case 'R': /* directory for new raster files */
nrastdir = optarg;
break;
case 'S': /* source raster files found here */
rastdir = optarg;
break;
case 'D': /* debug flag */
debug = ON;
break;
case 'I': /* ignore FATAL errors */
ignore = ON;
break;
case '?': /* don't understand the option */
error(FATAL, "");
break;
default: /* don't know what to do for ch */
error(FATAL, "missing case for option %c\n", ch);
break;
} /* End switch */
} /* End while */
argc -= optind; /* get ready for non-option args */
argv += optind;
} /* End of options */
/*****************************************************************************/
get_sizes(str)
char *str; /* comma or blank spearated size list */
{
char *tok; /* next token in *str */
char *strtok();
/*
*
* Converts a comma or blank separated list of point sizes to integers
* and stores the results in sizelist[]. Used to control how many of the
* raster files are built. If the -s options isn't used to select point
* sizes, raster files for all the sizes listed in the ASCII control files
* will be built.
*
*/
while ( (tok = strtok(str, " ,")) != NULL ) {
sizelist[sizecount++] = atoi(tok);
str = NULL;
} /* End while */
} /* End of get_sizes */
/*****************************************************************************/
get_fonts(str)
char *str; /* list of fonts to process */
{
char *tok; /* next font name from *str */
/*
*
* Called from options() to convert a comma or blank separated list of
* font names into pointers that can be stored in fontlist[]. Overrides
* the selection of fonts listed in the ASCII control files.
*
*/
while ( (tok = strtok(str, " ,")) != NULL ) {
fontlist[fontcount++] = tok;
str = NULL;
} /* End while */
} /* End of get_fonts */
/*****************************************************************************/
arguments()
{
/*
*
* All the rest of the comand line arguments are the names of ASCII control
* files. If there are no arguments left when we get here stdin will be
* read.
*
* Although the program accepts more than one control file name, I haven't
* really tested things using several control files. Probably needs more
* some more work.
*
*/
if ( argc < 1 ) {
fp_in = stdin;
readcontrol();
} else {
while ( argc > 0 ) {
if ( (fp_in = fopen(*argv, "r")) == NULL )
error(FATAL, "can't open %s", *argv);
readcontrol();
fclose(fp_in);
argc--;
argv++;
} /* End while */
} /* End else */
} /* End of arguments */
/*****************************************************************************/
readcontrol()
{
long pos; /* where build section starts in fp_in */
int i; /* loop index for sizelist[] */
/*
*
* Starts reading the ASCII description file fp_in. The stuff at the
* beginning is primarily for the DESC file and is just skipped, although
* the sizes, res, and unitwidth fields are used if the values haven't been
* set by options. Lines are read and processed by this routine until
* EOF is reached or the first build command is found. If we process the
* first part of the file and don't have res, unitwidth, and sizecount set
* an error message will be printed and we'll quit.
*
* After we break out of the first while loop, usually because a 'build'
* command was read, we record our position in file *fp_in and then enter
* a for loop that processes the rest of the file - once for each of the
* requested sizes. gotspecial controls whether we record special character
* names for the DESC file. We only need to do it on the first complete read
* of file *fp_in.
*
*/
while ( fscanf(fp_in, "%s", buff) != EOF )
if ( sizecount <= 0 && strcmp(buff, "sizes") == 0 ) {
while ( fscanf(fp_in, "%d", &sizelist[sizecount]) == 1 && sizelist[sizecount] != 0 )
sizecount++;
} else if ( unitwidth <= 0 && strcmp(buff, "unitwidth") == 0 )
fscanf(fp_in, "%d", &unitwidth);
else if ( res <= 0 && strcmp(buff, "res") == 0 )
fscanf(fp_in, "%d", &res);
else if ( strcmp(buff, "device") == 0 )
fscanf(fp_in, "%s", device);
else if ( strcmp(buff, "build") == 0 )
break;
else skipline(fp_in);
if ( res <= 0 || unitwidth <= 0 || sizecount <= 0 )
error(FATAL, "Missing res, unitwidth, or size specification");
if ( device[0] == '\0' )
error(FATAL, "no device name given");
pos = (long) ftell(fp_in); /* probably want to get back here */
for ( i = 0; i < sizecount; i++ ) {
build(sizelist[i]);
fseek(fp_in, pos, 0);
gotspecial = TRUE;
} /* End for */
builddesc();
rastdata();
} /* End of readcontrol */
/*****************************************************************************/
build(size)
int size; /* building files for this size */
{
char name[40]; /* name of font we're building */
char *ptr; /* used to pick up font comment field */
int i, n; /* used for font size selection */
int lsize; /* last valid size in font size list */
int osize; /* original size - reset in the loop */
/*
*
* Called from readcontrol() when we want to build font and raster files. At the
* top of the main loop we've read a 'build' command but haven't processed the
* name of the font yet. Once we get the name we initialize some variables,
* throw out all raster files we may already have read, skip the rest of the
* current line in *fp_in, and then enter a loop that processes all the
* allowed commands in a build section. The most important of these commands
* is 'using', which allows us to select particular characters from named
* raster files. It's assumed that we're finished with the current build
* section when we return from using() or when we read another 'build'
* command. When we exit the inner loop we're ready to build the new
* raster file. If size == unitwidth we'll also want to construct an ASCII
* font file for font *name.
*
* Actually that's not quite right. I've added code, that's really not very
* clear, that handles fonts with less than a complete set of raster files.
* Although much of the stuff can be done by hand, I think it's important
* to have buildrast handle everything. Logos will usually come in only
* one size and we may eventually want to add more logos to the raster file.
* That in itself would be difficult to do by hand, and adding more font
* font positions isn't all that clean either. There are a bunch of other
* ways it could have been handled, but I think adding the code to buildrast
* was the best choice. Fonts that don't come in all the sizes are described
* in the 'build' section by a command that looks like,
*
* sizes 12 18 36 0
*
* This lists the point sizes that are available for building the font.
* All output will only be turned OFF unless the size that we're currently
* working on is in the list. The sizes can come in any order as long as
* the list is terminated by 0. The ASCII font files are built when the
* current size is equal to the first size in the list. Widths are properly
* scaled to the correct unitwidth. The ascender and descender stuff also
* had to be changed.
*
* Turning the output OFF when a given size wasn't available turned out
* to be tricky, and that's where lsize is used. If the size isn't available
* we'll still have work to do in addition to reading the file, especially
* the first time through. So all the stuff works properly I set size to
* lsize before going on to the 'using' section. It's a kludge but the
* raster files should be available in lsize even if we're not building
* any files. Anyway that's sort of what's happening in the new stuff.
*
*/
osize = size; /* in case we change size */
while ( fscanf(fp_in, "%s", name) != EOF ) {
fontoutput = wantfont(name);
size = osize;
first = 1;
last = 0;
comment[0] = '\0';
ligatures[0] = '\0';
ascender[0] = '\0';
spacechar[0] = '\0';
spacewidth = -1;
isspecial = FALSE;
dofont = (size == unitwidth) ? ON : OFF;
resetrast();
skipline(fp_in);
while ( fscanf(fp_in, "%s", buff) != EOF )
if ( strcmp(buff, "using") == 0 ) {
using(name, size);
break;
} else if ( strcmp(buff, "build") == 0 )
break;
else if ( strcmp(buff, "special") == 0 )
isspecial = TRUE;
else if ( strcmp(buff, "ascender") == 0 )
fscanf(fp_in, "%s", ascender);
else if ( strcmp(buff, "spacewidth") == 0 )
fscanf(fp_in, "%s", spacechar);
else if ( strcmp(buff, "start") == 0 ) {
fscanf(fp_in, "%d", &first);
last = first - 1;
} else if ( strcmp(buff, "sizes") == 0 ) {
for ( i = 0, lsize = 0; fscanf(fp_in, "%d", &n) == 1 && n != 0 && n != size; i++, lsize = n ) ;
lsize = (lsize == 0 ) ? n : lsize;
fontoutput = (fontoutput == ON && n == size) ? ON : OFF;
dofont = (fontoutput == ON && i == 0 ) ? ON : OFF;
size = (fontoutput == ON) ? size : lsize;
skipline(fp_in);
} else if ( strcmp(buff, "comment") == 0 ) {
for ( ptr = comment; (*ptr = getc(fp_in)) != '\n' && *ptr != EOF; ptr++ ) ;
*ptr = '\0';
} else if ( buff[0] == '#' )
skipline(fp_in);
else error(FATAL, "don't understand command %s", buff);
writerast(name, size);
buildfont(name, size);
} /* End while */
} /* End of build */
/*****************************************************************************/
using(name, size)
char name[]; /* building things for this font */
int size; /* and in this size */
{
char chname[10]; /* special character name */
/*
*
* Called after we've read a 'using' command. The input file is read until
* we reach EOF of find another build command. The format of a 'using' command
* can be either,
*
* using name take ascii characters n to m
*
* or,
*
* using name take characters
* 12 fl
* 13 ff
* 103 *a
*
*
* where name refers to one of the raster files in *rastdir. It's assumed
* that the ascii characters n to m are in positions n to m in raster file
* name. If that's not the case the more general form given in the second
* example should be used. That's also the form that will be needed for troff's
* special characters.
*
* Synonyms are also allowed and can be specified by having the character
* '"' in the first index field as the following example illustrates.
*
* using name take characters
* 38 &
* 39 aa
* " '
* 119 14
* " 34
* " 12
* 91 [
*
* The list of synonyms for a particular character is recorded in the
* Charinfo structure for that character and is only used when we build the
* ASCII font files.
*
* There can be as many 'using' commands for a particular font as you want
* and you can intermix the two formats. We'll continue building the current
* raster file up until we find another 'build' command or reach EOF.
*
*/
if ( fontoutput == ON )
fprintf(stdout, "Building tables for %s size %d\n", name, size);
while ( fscanf(fp_in, "%s", buff) != EOF ) {
getrastdata(buff, size);
if ( fscanf(fp_in, " take %s", buff) != 1 )
error(FATAL, "syntax error in using()");
if ( strcmp(buff, "ascii") == 0 )
getascii();
skipline(fp_in);
while ( fscanf(fp_in, "%s", buff) != EOF ) {
if ( isdigit(buff[0]) ) {
fscanf(fp_in, "%s", chname);
recordchar(chname, atoi(buff));
} else if ( buff[0] == '"' )
getsynonym();
else if ( strcmp(buff, "using") == 0 )
break;
else if ( strcmp(buff, "build") == 0 )
return;
else if ( strcmp(buff, "edit") == 0 ) {
skipline(fp_in);
edit(fp_in);
return;
} else if ( buff[0] == '#' )
skipline(fp_in);
else error(FATAL, "don't understand command %s", buff);
} /* End while */
} /* End while */
} /* End of using */
/*****************************************************************************/
getascii()
{
int start; /* first character's ASCII code */
int stop; /* last character's code */
char name[2]; /* name of the character - string */
/*
*
* Called when we want to take a bunch of ASCII characters from the current
* raster file. As I mentioned before the expected format is,
*
* using name take ascii characters start to stop
*
* where name is the name of the raster file we want to use, while start
* and stop and the indices of the ASCII characters we want to steal from
* font name. Obviously start should be less than or equal to stop otherwise
* nothing will be done.
*
*/
if ( fscanf(fp_in, "%*s %d to %d", &start, &stop) != 2 )
error(FATAL, "syntax error in getascii()");
name[1] = '\0'; /* terminate the string */
for ( ; start <= stop; start++ ) {
name[0] = start;
recordchar(name, start);
} /* End for */
} /* End of getascii */
/*****************************************************************************/
recordchar(name, index)
char *name; /* name of the character */
int index; /* its glyph number in *fam */
{
char *gptr1, *gptr2; /* glyph directory pointers */
int height, width; /* of the bitmap */
int i; /* used to copy directory entry */
/*
*
* Called when we want to record information about character *name. Its
* number in the current raster file is index. Most of the information about
* the character is stored in charinfo[++last]. We'll need to remember its
* name, pointer to its bitmap, size of the bitmap, and pointer to the new
* glyph directory entry. Data about the bitmap comes directly from the glyph
* directory entry for character index. The pointer to the new glyph directory
* entry is figured out from the current values of first and last. Each entry
* in the directory is 15 bytes long, and all we do is copy index's entry
* over to the new character's entry. All that really has to be fixed up
* is the bitmap pointer, and this guy is figured out in writerast() when
* we're creating the new raster file.
*
*/
if ( ++last > MAX_INDEX )
error(FATAL, "too many characters in current raster file");
height = getvalue(G_HEIGHT, index);
width = getvalue(G_WIDTH, index);
gptr1 = fam->rst + GLYPH_PTR(index);
gptr2 = glyphdir + (15 * (last - first));
strcpy(charinfo[last].name, name);
strcpy(charinfo[last].rastname, fam->name);
charinfo[last].index = index;
charinfo[last].mapsize = ((width + BYTE - 1) / BYTE) * height;
charinfo[last].map = fam->rst + getvalue(G_BPTR, index);
charinfo[last].glydir = gptr2;
charinfo[last].synonyms[0] = '\0';
charinfo[last].chwidth = -1;
for ( i = 0; i < 15; i++, gptr1++, gptr2++ )
*gptr2 = *gptr1;
if ( gotspecial == FALSE && dodesc == ON && name[1] != '\0' )
specialchar(name);
if ( spacechar[0] != '\0' && strcmp(name, spacechar) == 0 )
spacewidth = last;
} /* End of recordchar */
/*****************************************************************************/
getsynonym()
{
char chname[10]; /* character's name built up here */
/*
*
* Called from using() when we've found a '"' in the index field. The
* character named next in the input file is a synonym for the one we
* just defined (ie. charinfo[last]). We'll add the name to the list of
* synonyms for the character and use that list when we build the ASCII
* font file.
*
*/
if ( last < first ) /* haven't defined anything yet */
error(FATAL, "bad synonym request - no characters defined");
fscanf(fp_in, "%s", chname);
strcat(strcat(charinfo[last].synonyms, " "), chname);
if ( gotspecial == FALSE && dodesc == ON && chname[1] != '\0' )
specialchar(chname);
} /* End of getsynonym */
/*****************************************************************************/
specialchar(name)
char *name; /* keep track of special characters */
{
int i; /* loop index */
/*
*
* Called to record the special characters we find in the charset[] array.
* It's used later on when we build the DESC file. We also keep track of
* the ligatures defined on this font (if any), and we'll use this info
* when we build the new ASCII font file.
*
*/
for ( i = 0; i < charcount; i++ )
if ( strcmp(name, charset[i].name) == 0 )
break;
if ( i >= charcount ) {
strcpy(charset[charcount++].name, name);
if ( strcmp(name, "fi") == 0 )
strcat(ligatures, " fi");
else if ( strcmp(name, "ff") == 0 )
strcat(ligatures, " ff");
else if ( strcmp(name, "fl") == 0 )
strcat(ligatures, " fl");
else if ( strcmp(name, "Fi") == 0 )
strcat(ligatures, " ffi");
else if ( strcmp(name, "Fl") == 0 )
strcat(ligatures, " ffl");
} /* End if */
} /* End of specialchar */
/*****************************************************************************/
writerast(name, size)
char *name; /* name of the font */
int size; /* in this point size */
{
int fd; /* new raster file */
int presize; /* really preamble + file mark */
int dirsize; /* size of glyph directory */
int totsize; /* total size of preamble and direc */
char *ptr; /* used to change new directory */
int offset; /* adjust bitmap pointers */
int i; /* loop index */
/*
*
* All the raster file data for *name.size has been collected. This routine
* puts it all together and writes everything out to the new raster file.
*
*/
if ( fontoutput == OFF ) return; /* not doing output for this font */
fam = &fam_data[0];
cur_fam = 0;
sprintf(buff, "%s/rast%s/%s.%d", nrastdir, device, name, size);
if ( (fd = creat(buff, 0644)) == -1)
error(FATAL, "can't open %s", buff);
presize = 8 + rst[P_LENGTH].size + getvalue(P_LENGTH);
dirsize = (last - first + 1) * 15;
totsize = presize + dirsize;
writevalue(first, P_FIRSTGLY, fam->rst + rst[P_FIRSTGLY].offset);
writevalue(last, P_LASTGLY, fam->rst + rst[P_LASTGLY].offset);
writevalue(presize, P_GLYDIR, fam->rst + rst[P_GLYDIR].offset);
write(fd, fam->rst, presize);
for ( ptr = glyphdir + rst[G_BPTR].offset, offset = 0, i = first; i <= last; i++, ptr += 15 ) {
writevalue(totsize + offset, G_BPTR, ptr);
offset += charinfo[i].mapsize;
} /* End for */
write(fd, glyphdir, (last - first + 1) * 15);
for ( i = first; i <= last; i++ )
write(fd, charinfo[i].map, charinfo[i].mapsize);
close(fd);
} /* End of writerast */
/*****************************************************************************/
buildfont(font, size)
char *font; /* name of troff's font file */
int size; /* have data for this point size */
{
FILE *fp; /* new font file */
int i; /* loop index */
int chwidth; /* next character's font table width */
char *ptr; /* the whole synonym string */
char *syn; /* next synonym for current character */
char *strtok();
/*
*
* Called to build the ascii font file for the current font. Things are
* only done if if the current size is equal to unitwidth.
*
*/
if ( fontoutput == OFF || dofont == OFF )
return;
sprintf(buff, "%s/dev%s/%s", fontdir, device, font);
if ( (fp = fopen(buff, "w")) == NULL )
error(FATAL, "can't open font file %s", buff);
if ( comment[0] != '\0' )
fprintf(fp, "#%s\n", comment);
fprintf(fp, "name %s\n", font);
fprintf(fp, "internalname %d\n", internalname++);
if ( isspecial == TRUE )
fprintf(fp, "special\n");
if ( ligatures[0] != '\0' )
fprintf(fp, "ligatures %s 0\n", ligatures);
fprintf(fp, "charset\n");
if ( isspecial == FALSE ) {
fprintf(fp, "\\| %d 0 0\n", (res * unitwidth)/(72 * 6));
fprintf(fp, "\\^ %d 0 0\n", (res * unitwidth)/(72 * 12));
} /* End if */
setascender(size);
for ( i = first; i <= last; i++ ) {
if ( (chwidth = charinfo[i].chwidth) < 0 ) {
chwidth = readvalue(charinfo[i].glydir + rst[G_CHWIDTH].offset, rst[G_CHWIDTH].size, UNSIGNED);
chwidth = (PIXEL_WIDTH(chwidth, res) * unitwidth) / size;
} /* End if */
fprintf(fp, "%s %d %d %d\n", charinfo[i].name, chwidth, getascender(i), i);
ptr = charinfo[i].synonyms;
while ( (syn = strtok(ptr, " ")) != NULL ) {
fprintf(fp, "%s \"\n", syn);
ptr = NULL;
} /* End while */
} /* End for */
fclose(fp);
} /* End of buildfont */
/*****************************************************************************/
builddesc()
{
FILE *fp; /* new desc file */
int ch; /* for copying first part of fp_in */
int i; /* for loop index for copying charset */
/*
*
* Builds the new DESC file from the data contained in the first part of
* the ASCII control file *fp_in and the special characters saved in the
* charset[] array.
*
*/
if ( dodesc == OFF ) /* don't build new DESC file */
return;
sprintf(buff, "%s/dev%s/DESC", fontdir, device);
if ( (fp = fopen(buff, "w")) == NULL )
error(FATAL, "can't open file %s", buff);
fseek(fp_in, 0L, 0); /* back to start of control file */
while ( fscanf(fp_in, "%s", buff) != EOF )
if ( strcmp(buff, "build") == 0 )
break;
else if ( buff[0] == '#' || strcmp(buff, "device") == 0 )
skipline(fp_in);
else {
fprintf(fp, "%s", buff);
while ( (ch = putc(getc(fp_in), fp)) != '\n' && ch != EOF ) ;
} /* End else */
fprintf(fp, "charset\n");
fprintf(fp, "\\| \\^");
for ( i = 0; i < charcount; i++ )
fprintf(fp, "%c%s", (i % 15 == 13) ? '\n' : ' ', charset[i].name);
putc('\n', fp);
fclose(fp);
} /* End of builddesc */
/*****************************************************************************/
rastdata()
{
FILE *fp; /* "RASTDATA" file */
/*
*
* The post-processor and possibly others will need to know the resolution
* and format of the raster files. It's looked for in file "RASTDATA", which
* is defined in file init.h. Anyway this routine makes sure a reasonable
* data file goes along with all the raster files we just built.
*
*/
sprintf(buff, "%s/rast%s/%s", nrastdir, device, RASTDATA);
if ( (fp = fopen(buff, "w")) == NULL )
error(FATAL, "can't write file %s", buff);
fprintf(fp, "#\n# Format and resolution data\n#\n");
fprintf(fp, "format new\nresolution %d\n", res);
fclose(fp);
} /* End of rastdata */
/*****************************************************************************/
setascender(size)
int size; /* for this size - usually unitwidth */
{
int i; /* just a loop index */
/*
*
* Called to set reasonable values for the ascender/descender values above
* and below. If *ascender != '\0' we'll look the character up in charinfo[]
* and use it's height and yref to set values for above and below. If we
* don't find the character or it hasn't been set we'll use size and res
* to pick reasonable values.
*
*/
for ( i = first; i <= last; i++ )
if ( strcmp(ascender, charinfo[i].name) == 0 )
break;
if ( i > last )
above = (size * res) / (72.27 * 2);
else above = readvalue(charinfo[i].glydir + rst[G_YREF].offset, rst[G_YREF].size, INTEGER);
above = above + .30 * above + .5;
below = .20 * above + .5;
} /* End of setascender */
/*****************************************************************************/
getascender(n)
int n; /* character's index in charinfo[] */
{
int height; /* raster height of n's bitmap */
int yref; /* y reference point */
int value; /* ascender value for character n */
/*
*
* Figures out an appropriate value for the ascender/descender field in
* troff's ASCII font files for character n.
*
*/
value = 0;
yref = readvalue(charinfo[n].glydir + rst[G_YREF].offset, rst[G_YREF].size, INTEGER);
height = readvalue(charinfo[n].glydir + rst[G_HEIGHT].offset, rst[G_HEIGHT].size, UNSIGNED);
if ( yref >= above )
value |= 02;
if ( height - yref > below )
value |= 01;
return(value);
} /* End of getascender */
/*****************************************************************************/
skipline(fp)
FILE *fp; /* skip rest of line in this file */
{
int ch; /* next character from *fp_in */
/*
*
* Skips the rest of the current line in file *fp.
*
*/
while ( (ch = getc(fp)) != '\n' && ch != EOF ) ;
} /* End of skipline */
/*****************************************************************************/
writevalue(val, field, p)
unsigned val; /* write this value out */
int field; /* as next rst[field].size bytes */
char *p; /* starting right here */
{
int n; /* size in bytes of field */
int i; /* just a loop index */
/*
*
* Writes val out as the nextrst[field].sizebytes starting at address *p.
* It's used to build entries in the preamble and glyph directory for the
* new raster file we're currently working on.
*
*/
n = rst[field].size; /* number of bytes to write out */
for ( i = 1; i <= n; i++, p++ )
*p = (val >> (n - i) * BYTE) & BMASK;
} /* End of writevalue */
/*****************************************************************************/
unsigned readvalue(p, n, kind)
register char *p; /* start here */
register int n; /* and get this many bytes */
int kind; /* type of field - INTEGER or UNSIGNED */
{
register unsigned value; /* result after decoding the field */
/*
*
* Does essentially the same thing as getvalue() in rast.c except that we
* supply different information as parameters.
*
*/
value = (kind == INTEGER && (*p & 0200)) ? ~0 : 0;
for ( ; n > 0; n--, p++ )
value = (value << BYTE) | (*p & BMASK);
return(value);
} /* End of readvalue */
/*****************************************************************************/
wantfont(name)
char *name; /* do work for this font? */
{
int i; /* loop index */
/*
*
* If we've just asked to process a few fonts (using -f option) fontcount
* will be non-zero and pointers to the requested font names will be stored
* in array fontlist[]. This routine returns ON if *name is one of the
* requested fonts or if fontcount is 0. Otherwise OFF will be returned to
* the caller, which should stop all output for *name.
*
*/
if ( fontcount == 0 ) /* didn't ask for any fonts */
return(ON);
for ( i = 0; i < fontcount; i++ )
if ( strcmp(name, fontlist[i]) == 0 )
return(ON);
return(OFF);
} /* End of wantfont */
/*****************************************************************************/