V10/cmd/dimpress/oldrast.c

Compare this file to the similar file:
Show the results in this format:



/*
 *
 * The stuff in this file used to be part of di10.c. I've taken it out of
 * the main part of the post-processor because we're now accepting two
 * different formats for the raster files. The original raster files had
 * some rather severe limitations. They were machine dependent and used
 * shorts etc. quite extensively, especially as offsets to locate glyph
 * bitmaps. That put a limit on the point sizes that could be offered
 * even at 240 dots per inch, but at a resolution of 300 dots an inch
 * we probably wouldn't be able to access the bitmaps in a complete font
 * past size 24 or so. In addition nobody's supporting the old style
 * raster files or digitizing new characters for us. I've decided to
 * let the new post-processor read the old style raster files along with
 * the ones supplied by Imagen, although the old style won't be the
 * default.
 *
 *
 *
 *	The following things manage raster font information.
 *	The big problem is mapping desired font + size into
 *	available font + size.  For now, a file RASTERLIST
 *	contains entries like
 *		R 6 8 10 14 999
 *		I 8 10 12 999
 *		...
 *	This data is used to create an array "fontdata" that
 *	describes legal fonts and sizes, and pointers to any
 *	data from files that has actually been loaded.
 *
 */


#include <stdio.h>

#include "gen.h"			/* some general purpose definitions */
#include "ext.h"			/* external variable definitions */
#include "glyph.h"			/* raster file structures */
#include "impcodes.h"			/* Impress 2.0 opcode definitions */
#include "dimpress.h"			/* we'll need a few of these defs */


#define MAXFONT		60		/* max number of fonts forever */


struct fontdata {
	char	name[4];		/* e.g., "R" or "PA" */
	int	size[10];		/* e.g., 6 8 10 14 0 */
	struct	fontset	*fsp[10];	/* either NULL or block of data */
};



struct	Fontheader	fh;
struct	fontset {
	int	size;
	int	family;
	struct	Charparam *chp;
	unsigned char	*cdp;		/* char data pointer */
	unsigned char	*chused;	/* bit-indexed; 1 if char downloaded */
};


struct fontdata		fontdata[MAXFONT];
struct fontset		*fs;		/* current font+size */
int			maxfonts = 0;	/* number actually used */
int			nfamily = 0;	/* next available family number */
int			lastfam = -1;	/* last family we told Impress about */

extern int		res;		/* resolution assumed in input file */
extern int		pres;		/* printer resolution */
extern int		rres;		/* raster file resolution */
extern int		hpos;		/* troff's position variables */
extern int		vpos;
extern float		xfac;		/* scaling factors */
extern float		yfac;
extern int		xoffset;	/* hor and vert offsets in pixels */
extern int		yoffset;
extern int		font;		/* using font in this position */
extern int		size;		/* and want this point size */
extern int		lastfont;	/* got raster files for guy last */
extern int		lastsize;	/* and in this point size */
extern int		lastw;		/* width of the last character */
extern int		lastx;		/* Impress coordinates right now */
extern int		lasty;
extern int		center;		/* try and improve placement? */


/*****************************************************************************/


initfontdata()	/* read RASTERLIST information */
{
	char name[100];
	FILE *fp;
	int i, j, n;

	sprintf(name, "%s/RASTERLIST", rastdir);
	if ((fp = fopen(name, "r")) == NULL)
		error(FATAL, "can't open %s", name);
	maxfonts = 0;
	while (fscanf(fp, "%s", fontdata[maxfonts].name) != EOF) {
		i = 0;
		while (fscanf(fp, "%d", &n) != EOF && n < 100) {
			fontdata[maxfonts].size[i] = n;
			fontdata[maxfonts].fsp[i] = NULL;
			i++;
		}
		fontdata[maxfonts].size[i] = 999;
		if (++maxfonts > MAXFONT)
			error(FATAL, "Too many fonts in RASTERLIST");
	}
	fclose(fp);
	if (debug) {
		fprintf(stderr, "initfontdata():  maxfonts=%d", maxfonts);
		for (i = 0; i < maxfonts; i++) {
			fprintf(stderr, "%.4s ", fontdata[i].name);
			for (j = 0; fontdata[i].size[j] < 100; j++)
				fprintf(stderr, " %3d", fontdata[i].size[j]);
			fprintf(stderr, "\n");
		}
	}
}

getfontdata(f, s)	/* causes loading of font information if needed */
	char *f;
	int s;
{
	int fd, n, i, j;
	char name[100];
	static int first = 1;

	if (first) {
		initfontdata();
		first = 0;
	}

	for (i = 0; i < maxfonts; i++)
		if (strcmp(f, fontdata[i].name) == 0)
			break;
	if (i >= maxfonts)	/* the requested font wasn't there */
		i = 0;		/* use the first one (probably R) */

	s = (s * pres) / rres;	/* scale the requested point size */

	/* find the best approximation to size s */
	for (j = 1; s >= fontdata[i].size[j]; j++)
		;
	j--;

	/* open file if necessary */
	if (fontdata[i].fsp[j] == NULL) {
		fs = (struct fontset *) malloc(sizeof(struct fontset));
		fontdata[i].fsp[j] = fs;
		fs->chp = (struct Charparam *) malloc(256*sizeof(struct Charparam));
		sprintf(name, "%s/%s.%d", rastdir, f, fontdata[i].size[j]);
		fd = open(name, 0);
		if (fd == -1)
			error(FATAL, "can't open %s", name);
		read(fd, &fh, sizeof(struct Fontheader));
		read(fd, fs->chp, 256*sizeof(struct Charparam));
		fs->size = fontdata[i].size[j];
		fs->family = nfamily;
		nfamily += 2;	/* even-odd leaves room for big fonts */
		fs->cdp = (unsigned char *) malloc(fh.f_size);
		fs->chused = (unsigned char *) malloc(256/8);
		for (n = 0; n < 256/8; n++)
			fs->chused[n] = 0;
		n = read(fd, fs->cdp, fh.f_size);
		close(fd);
	}
	fs = fontdata[i].fsp[j];
}

xychar(c, f, s, chwid, tf)
	register int	c;		/* print this character */
	char		*f;		/* using this font */
	int		s;		/* and this point size */
	int		chwid;		/* use this as the char width? */
	FILE		*tf;		/* output written to this FILE */

{
	register unsigned char *p;
	register struct Charparam *par;
	register int x, y;
	char hold;
	int i, n, rwid, ht, fam;
	int	w;

	x = hpos * xfac + 0.5;
	x += xoffset;
	y = vpos * yfac + 0.5;
	y += yoffset;

	if (font != lastfont || size != lastsize) {
		getfontdata(f, s);
		lastsize = size;
		lastfont = font;
	}
	par = fs->chp + c;
	p = fs->cdp + par->c_addr;

	fam = fs->family;
	if (c > 127)
		fam++;
	if (fam != lastfam) {
		putc(ASF, tf);
		putc(lastfam = fam, tf);
	}

	/* first cut:  ship each glyph as needed. */
	/* ignore memory use, efficiency, etc. */

	if ( !checkbit(fs->chused, c) ) {	/* 1st use of this character */
		setbit(fs->chused, c);
		putc(ASGLY, tf);
		putint((fam << 7) | c, tf);
		par->c_width = (char)((lastw * pres) / res);
 		putc(par->c_width, tf);	/* character width */
		hold=(char) (w = CONVINT(par->c_left) + CONVINT(par->c_right) + 1);
		putc(hold,tf);
		if ( center )
			putc((w - CONVINT(par->c_width)) / 2, tf);
		else putc(par->c_left, tf);
  /* this nonsense fixes a bug in output produced by rec.c: */
  /* when up is < 0 (and = 0?) size is one too big */
		rwid = (1 + CONVINT(par->c_left) + CONVINT(par->c_right) + BYTE-1) / BYTE;
		ht = par->c_size / rwid;
		par->c_down = (char)(ht - CONVINT(par->c_up));
		hold=(char)(CONVINT(par->c_down) + CONVINT(par->c_up));
		putc(hold, tf);
		putc(par->c_up, tf);
		for (i = par->c_size; i--; )
			putc(*p++, tf);
	}

	if (y != lasty) {
		putc(ASETAV, tf);
		putint(y, tf);
		lasty = y;
	}

	if (ABS(x-lastx) > SLOP) {
		putc(ASETAH, tf);
		putint(x, tf);
		lastx = x + (par->c_width & BMASK);
	} else {
		lastx += (par->c_width & BMASK);
	}

	if (c <= 127)
		putc(c, tf);	/* fails if c > 127, probably disastrously */
	else
		putc(c-128, tf);
}