V10/cmd/dimpress/printrast.c
/*
*
* Reads the raster files listed as arguments and prints the glyphs, along
* with information about character widths and glyph numbers, on an Imagen
* printer. The output is written in Impress. If no glyphs are selected by
* using the -o option the entire file or files will be printed. An Impress
* document header is the first thing written to the output file provided
* want_header == TRUE. Use the -H option to force the header. The target
* printer is assumed to have a resolution of res dots per inch, which by
* default is set to RAST_RES (probably 300). If that's not the case use
* the -r option to select a new resolution. It's really only important
* in determining the pixel length of a page.
*
* Text in the printout is written using font *font in size list_size.
* By default it's resident font cour10. You can change the requested font
* and size using the -f and -s options respectively.
*
* All the raster files are assumed to be in directory *rastdir, which by
* default is set to ".". *rastdir can be changed by using the -R option.
* but in all cases the string "*rastdir/" is prepended to the raster file
* names to get the complete pathname.
*
* As an example the command line,
*
* printrast -R /usr/lib/raster/rasti300 -H -r 300 R.10 I.10 >xxx
*
* will write the Impress commands needed to print the glyphs in raster
* file /usr/lib/raster/rasti300/R.10 and /usr/lib/raster/rasti300/I.10 out
* to file xxx. The target printer is assumed to have a resolution of 300
* dots per inch. The output file xxx begins with a document header defining
* the language to be Impress and can therefore be set directly to an 8/300.
*
* A word of warning is in order here. Because I've written readrastfile()
* so it accepts two different raster file naming conventions there isn't
* a one to one mapping of file names to font name, size pairs. That means
* if you have two similiarly named raster files, differing only in the
* naming convention used, and you keep them in the same directory you'll
* always display glyphs from the preferred file no matter which file
* you list on the command line. I don't think it will cause any real
* problems so I'm not going to change any of this stuff.
*
*/
#include <stdio.h>
#include "gen.h" /* general purpose definitions */
#include "ext.h" /* external variable declarations */
#include "rast.h" /* raster file definitions */
#include "impcodes.h" /* Impress opcode definitions */
FILE *fp_out = stdout; /* output file - probably won't change */
char *font = "cour"; /* use this font for printing text */
int list_size = 10; /* and this point size */
float xoffset = .25; /* start this far from left edge */
float yoffset = .50; /* and this far down the page - inches */
int p_xoffset; /* same as last two but in pixels */
int p_yoffset;
float height = 10.50; /* height of the paper in inches */
float width = 8.75; /* same but for paper width */
int p_height; /* paper dimensions in pixels */
int p_width;
int res = RAST_RES; /* resolution of the target printer */
int hpos; /* current horizontal position - pixels */
int vpos; /* same but for vertical position */
int linesp; /* interline spacing */
int spacewid; /* interword spacing */
int want_header = FALSE; /* write document header first */
/*****************************************************************************/
main(agc, agv)
int agc;
char *agv[];
{
/*
*
* Reads Imagen formatted raster files and writes the Impress commands
* needed to print the glyphs, along with width and index data, to fp_out.
* Text is written using resident the resident font whose name is built
* by concatenating *font and list_size. By default the font is cour10,
* but both font and list_size can be changed by options. Individual glyphs
* in the raster files can be selected, rather than the whole file, by
* using the -o option (although I haven't tested this yet).
*
*/
argc = agc; /* other routines may want them */
argv = agv;
prog_name = argv[0]; /* really just for error messages */
rastdir = "."; /* current directory by default */
options(); /* first get command line options */
doc_header(); /* make sure this comes first */
initialize(); /* must be done after 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 = "DIFHR:o:x:y:r:h:w:s:";
extern char *optarg; /* used by getopt() */
extern int optind;
float atof();
/*
*
* Reads and processes the command line options. Right now the recognized
* options are,
*
*/
while ( (ch = getopt(argc, argv, names)) != EOF ) {
switch ( ch ) {
case 'r': /* target printer resolution */
res = atoi(optarg);
break;
case 'f': /* use this font (omit size) */
font = optarg;
break;
case 's': /* use this point size */
list_size = atoi(optarg);
break;
case 'h': /* set the paper height - inches */
height = atof(optarg);
break;
case 'w': /* same but for the width */
width = atof(optarg);
break;
case 'x': /* set the xoffset - inches */
xoffset = atof(optarg);
break;
case 'y': /* same but for yoffset */
yoffset = atof(optarg);
break;
case 'o': /* processing range list */
out_list(optarg);
break;
case 'H': /* want the document header */
want_header = TRUE;
break;
case 'F': /* new troff font directory */
fontdir = optarg;
break;
case 'R': /* set raster table directory */
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 */
/*****************************************************************************/
doc_header()
{
/*
*
* If want_header is TRUE we'll make sure a document header is the first
* thing written to the output file.
*
*/
if ( want_header == TRUE )
fprintf(fp_out, "@document(language impress)");
} /* End of doc_header */
/*****************************************************************************/
initialize()
{
/*
*
* Does the run time initialization of variables that depend on the target
* printer resolution. Also handles printer initialization of things like
* the space width and creating the listing font family table.
*
*/
p_xoffset = xoffset * res;
p_yoffset = yoffset * res;
p_height = height * res;
p_width = width * res;
spacewid = 2.2 * list_size; /* a reasonable value for spaces */
putc(ASETSP, fp_out);
putint(spacewid, fp_out);
putc(ACFT, fp_out); /* use resident font */
putc(MAXFAMILY, fp_out);
putc(1, fp_out);
putc(0, fp_out);
fprintf(fp_out, "%s%d", font, list_size);
putc('\0', fp_out);
} /* End of initialize */
/*****************************************************************************/
arguments()
{
char name[100]; /* make sure we can acces file */
char *font; /* name of the font we're dumping */
char *size; /* in this point size */
char *strtok();
/*
*
* All the remaining arguments are the names of raster files in *rastdir
* that we want to display. Because two raster file naming conventions
* are used in rast.c we can't be absolutely sure we're really displaying
* the raster file that the user wanted. That's why the pathname is built
* up in name[] and access to the file is checked. That's probably good
* enough for our purposes, but it still doesn't guarantee you get what
* you asked for. It shouldn't cause any real problems as long as you
* don't try and keep raster files with the two different naming conventions
* in the same directory.
*
*/
if ( argc < 1 )
error(FATAL, "can't read standard input");
else { /* have at least one argument */
while ( argc > 0 ) {
sprintf(name, "%s/%s", rastdir, *argv);
if ( access(name, 04) == -1 )
error(FATAL, "can't read file %s", name);
if ( (font = strtok(*argv, ".")) == NULL )
error(FATAL, "bad raster file name %s", *argv);
if ( *(size = font + strlen(font) + 1) == 'r' ) size++;
printrast(font, atoi(size));
argc--;
argv++;
} /* End while */
} /* End else */
} /* End of arguments */
/*****************************************************************************/
printrast(name, size)
char *name; /* name of the font */
int size; /* in this point size */
{
int start, stop; /* glyph number end points */
int i; /* loop index */
int cwid; /* character width */
int xref, yref; /* reference point for current glyph */
char buff[200]; /* text string buffer */
/*
*
* Prints glyphs from the raster file associated with font *name in point
* size 'size'. If no -o option was given all the glyphs will be printed.
* The listing for each new font begins on a new page.
*
*/
getrastdata(name, size); /* read the font's raster file */
start = getvalue(P_FIRSTGLY); /* first glyph number in the font */
stop = getvalue(P_LASTGLY); /* number of the last glyph */
linesp = ((MAX(size, list_size) + .2 * MAX(size, list_size)) / 72.27) * RAST_RES + 1.0;
newpage(); /* dump starts on a new page */
sprintf(buff, "FONT DUMP FOR %s: SIZE %d\n\n\n", name, size);
printstring(buff);
for ( i = start; i <= stop; i++ )
if ( in_olist(i) == ON ) {
printchar(i, name, size, -1, fp_out);
cwid = PIXEL_WIDTH(getvalue(G_CHWIDTH, i), rast_res);
xref = getvalue(G_XREF, i);
yref = getvalue(G_YREF, i);
hpos = 6 * spacewid + p_xoffset;
xymove();
sprintf(buff, "width = %d code = %d xref = %d yref = %d\n", cwid, i, xref, yref);
printstring(buff);
} /* End if */
} /* End of printrast */
/*****************************************************************************/
printchar(c, font, size, advance, fp)
int c; /* print glyph for this character */
char *font; /* in this font */
int size; /* and this point size */
int advance; /* using this as the advance width */
FILE *fp; /* Impress commands go here */
{
/*
*
* Does everything needed to get character c printed using the raster file
* for *font in point size 'size' and using advance as the character advance.
*
*/
if ( fam == NULL || fam->size != size || strcmp(font, fam->name) != 0 || fam->rst == NULL )
getrastdata(font, size);
putc(download(c, advance, ROT_0, fp), fp);
} /* End of printchar */
/*****************************************************************************/
newline()
{
/*
*
* Makes sure everything is properly set up to start a new line. If the
* vertical position on the page has gone past p_height (ie. the height
* of the paper in pixels) we'll start a new page.
*
*/
hpos = p_xoffset; /* left margin */
if ( (vpos += linesp) >= p_height )
newpage();
else xymove();
} /* End of newline */
/*****************************************************************************/
newpage()
{
/*
*
* Ends the previous page and makes sure we're positioned at the upper left
* corner of a new page. The way things are done results in a blank page at
* the beginning of every job - no big deal because the program isn't used
* much.
*
*/
putc(AENDP, fp_out);
hpos = p_xoffset;
vpos = p_yoffset;
xymove();
} /* End of newpage */
/*****************************************************************************/
xymove()
{
/*
*
* Makes sure the current position for Impress is set to (hpos, vpos).
*
*/
putc(ASETAH, fp_out);
putint(hpos, fp_out);
putc(ASETAV, fp_out);
putint(vpos, fp_out);
} /* End of xymove */
/*****************************************************************************/
printstring(str)
char *str; /* want to print this string */
{
/*
*
* Arranges to have string *str printed using the resident font that's been
* assigned the family number MAXFAMILY. Spaces and newlines are handled
* separately, although that probably isn't necessary for resident fonts.
*
* Some of the glyphs in the raster files we got from Imagen are bad. It
* didn't seem to matter much for version 1.9, but a glyph having 0 for its
* raster height hung version 2.0 and nothing was printed. Anyway I put a
* check in routine download() to make sure glyphs having no height weren't
* downloaded. At least that made sure the printer didn't crash. All we
* get for those glyphs is a harmless undefined glyph message and a
* special character got printed to mark where the problem occurred.
*
*/
if ( last_fam != MAXFAMILY ) { /* using this family for listing */
putc(ASF, fp_out); /* need to tell printer about it */
putc(MAXFAMILY, fp_out);
last_fam = MAXFAMILY;
} /* End if */
while ( *str != '\0' ) { /* print the whole string */
if ( *str == ' ' )
putc(ASP, fp_out);
else if ( *str == '\n' )
newline();
else putc(*str, fp_out);
str++;
} /* End while */
} /* End of printstring */
/*****************************************************************************/