/* * * 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); }