home *** CD-ROM | disk | FTP | other *** search
- /*
- * This routine scans a page for font definitions and character usage.
- * It keeps an estimate of the memory remaining in the printer, and
- * returns false when that memory is exhausted, unless scanning the
- * first page. Otherwise it returns 1 if no problems were found,
- * or 2 if it thinks the first page of a section may overflow memory.
- */
- #include "structures.h" /* The copyright notice in that file is included too! */
- /*
- * These are the external routines we need.
- */
- extern shalfword dvibyte() ;
- extern halfword twobytes() ;
- extern integer threebytes() ;
- extern integer signedquad() ;
- extern shalfword signedbyte() ;
- extern shalfword signedpair() ;
- extern integer signedtrio() ;
- extern void skipover() ;
- extern void fontdef() ;
- extern void predospecial() ;
- extern Boolean residentfont() ;
- extern Boolean virtualfont() ;
- extern void loadfont() ;
- extern void error() ;
- extern long getlong() ;
- extern void repack() ;
- /*
- * And, of course, the globals it uses.
- */
- #ifdef DEBUG
- extern integer debug_flag;
- #endif /* DEBUG */
- extern fontdesctype *curfnt ;
- extern fontdesctype *baseFonts[] ;
- extern fontmaptype *ffont ;
- extern quarterword *curpos, *curlim ;
- extern integer fontmem ;
- extern integer pagecount ;
- extern integer pagenum ;
- extern Boolean compressed ;
- extern char errbuf[] ;
- extern frametype frames[] ;
- extern integer pagecost ;
- /*
- * Charge pagecost for the cost of showing the character that *cd refers to
- * and charge fontmem for the cost of downloading the character if necessary.
- * A zero result indicates that we have run out of memory.
- * If the character is small (a small packet), we save 43 bytes (since we
- * use a single string instead of an array with integers in the PostScript.)
- */
- Boolean
- prescanchar(cd)
- chardesctype *cd ;
- {
- register quarterword *cras ;
- register integer thischar ;
-
- if ((cd->flags & (PREVPAGE | THISPAGE)) == 0) {
- /* the character hasn't been used before in the current section */
- cras = cd->packptr ;
- if (cras != NULL) {
- thischar = CHARCOST ;
- if (cd->flags & BIGCHAR)
- thischar += 43 ;
- if (compressed) {
- if ((cd->flags & REPACKED) == 0) {
- repack(cd) ;
- cras = cd->packptr ;
- }
- if ((*cras & 4))
- if ((*cras & 7) == 7)
- thischar += getlong(cras + 17) ;
- else
- thischar += getlong(cras + 9) ;
- else
- thischar += getlong(cras + 5) ;
- } else {
- if ((*cras & 4))
- if ((*cras & 7) == 7)
- thischar += getlong(cras + 1)
- * ((getlong(cras + 5) + 7) >> 3) ;
- else
- thischar += (cras[3] * 256 + cras[4]) *
- ((cras[1] * 256 + cras[2] + 7) >> 3) ;
- else
- thischar += ((int)(cras[2] * ((cras[1] + 7) >> 3))) ;
- }
- cd->flags |= THISPAGE ;
- fontmem -= thischar ;
- if (fontmem <= pagecost) {
- if (pagecount > 0)
- return(0) ;
- }
- }
- }
- return(1) ;
- }
- /*
- * When a font is selected during the prescan, this routine makes sure that
- * the tfm or pk file is loaded and charges fontmem for the VM overhead in
- * creating the font. The result is true unless the section must be aborted
- * in order to keep this font from overflowing VM.
- */
- Boolean
- preselectfont(f)
- fontdesctype *f ;
- {
- curfnt = f ;
- if (curfnt->loaded == 0) {
- if (!residentfont(curfnt))
- if (!virtualfont(curfnt))
- loadfont(curfnt) ;
- }
- if (curfnt->psname == 0) {
- if (curfnt->loaded < 2) /* virtual font costs nothing (yet) */
- if (curfnt->resfont)
- fontmem -= PSFONTCOST ;
- else {
- fontmem -= FONTCOST + curfnt->maxchars ;
- if (curfnt->loadeddpi != curfnt->dpi)
- fontmem -= 48 ; /* for the new font matrix */
- }
- curfnt->psname = 1 ;
- if (fontmem <= pagecost) {
- if (pagecount > 0)
- return(0) ;
- }
- }
- return(1) ;
- }
- /*
- * Now our scanpage routine.
- */
- short
- scanpage()
- {
- register shalfword cmd ;
- register chardesctype *cd ;
- register fontmaptype *cfnt = 0 ;
- integer fnt ;
- register frametype *frp = frames ;
-
- pagecost = 0 ;
- #ifdef DEBUG
- if (dd(D_PAGE))
- #ifdef SHORTINT
- (void)fprintf(stderr,"Scanning page %ld\n", pagenum) ;
- #else /* ~SHORTINT */
- (void)fprintf(stderr,"Scanning page %d\n", pagenum) ;
- #endif /* ~SHORTINT */
- #endif /* DEBUG */
- curfnt = NULL ;
- curpos = NULL ;
- while (1) {
- switch (cmd=dvibyte()) {
- case 129: case 130: case 131: case 134: case 135: case 136: case 139:
- case 247: case 248: case 249: case 250: case 251: case 252: case 253:
- case 254: case 255: /* unimplemented or illegal commands */
- (void)sprintf(errbuf,
- "! DVI file contains unexpected command (%d)",cmd) ;
- error(errbuf) ;
- case 132: case 137: /* eight-byte commands setrule, putrule */
- (void)dvibyte() ;
- (void)dvibyte() ;
- (void)dvibyte() ;
- (void)dvibyte() ;
- case 146: case 151: case 156: case 160: case 165: case 170:
- /* four-byte commands right4, w4, x4, down4, y4, z4 */
- (void)dvibyte() ;
- case 145: case 150: case 155: case 159: case 164: case 169:
- /* three-byte commands right3, w3, x3, down3, y3, z3 */
- (void)dvibyte() ;
- case 144: case 149: case 154: case 158: case 163: case 168:
- /* two-byte commands right2, w2, x2, down2, y2, z2 */
- (void)dvibyte() ;
- case 143: case 148: case 153: case 157: case 162: case 167:
- /* one-byte commands right1, w1, x1, down1, y1, z1 */
- (void)dvibyte() ;
- case 147: case 152: case 161: case 166: /* w0, x0, y0, z0 */
- case 138: case 141: case 142: /* nop, push, pop */
- break ;
- case 133: case 128: cmd = dvibyte() ; /* set1 commands drops through */
- default: /* these are commands 0 (setchar0) thru 127 (setchar 127) */
- /*
- * We are going to approximate that each string of consecutive characters
- * requires (length of string) bytes of PostScript VM.
- */
- if (curfnt==NULL)
- error("! Bad DVI file: no font selected") ;
- if (curfnt->loaded == 2) { /* scanning a virtual font character */
- frp->curp = curpos ;
- frp->curl = curlim ;
- frp->ff = ffont ;
- frp->curf = curfnt ;
- if (++frp == &frames[MAXFRAME] )
- error("! virtual recursion stack overflow") ;
- cd = curfnt->chardesc + cmd ;
- curpos = cd->packptr + 2 ;
- curlim = curpos + (256*(long)(*cd->packptr)+(*(cd->packptr+1))) ;
- ffont = curfnt->localfonts ;
- if (ffont==NULL)
- curfnt = NULL ;
- else if (!preselectfont(ffont->desc))
- goto outofmem ;
- } else {
- pagecost++ ;
- if (curfnt->resfont == NULL) {
- if (!prescanchar(curfnt->chardesc + cmd))
- goto outofmem ;
- }
- }
- break ;
- case 171: case 172: case 173: case 174: case 175: case 176: case 177:
- case 178: case 179: case 180: case 181: case 182: case 183: case 184:
- case 185: case 186: case 187: case 188: case 189: case 190: case 191:
- case 192: case 193: case 194: case 195: case 196: case 197: case 198:
- case 199: case 200: case 201: case 202: case 203: case 204: case 205:
- case 206: case 207: case 208: case 209: case 210: case 211: case 212:
- case 213: case 214: case 215: case 216: case 217: case 218: case 219:
- case 220: case 221: case 222: case 223: case 224: case 225: case 226:
- case 227: case 228: case 229: case 230: case 231: case 232: case 233:
- case 234: case 235: case 236: case 237: case 238: /* font selection commands */
- if (cmd < 235) fnt = cmd - 171 ; /* fntnum0 thru fntnum63 */
- else {
- fnt = dvibyte() ; /* fnt1 */
- while (cmd-- > 235)
- fnt = (fnt << 8) + dvibyte() ;
- }
- if (curpos || fnt > 255) {
- for (cfnt=ffont; cfnt; cfnt = cfnt->next)
- if (cfnt->fontnum == fnt) goto fontfound ;
- } else
- if (curfnt = baseFonts[fnt])
- goto fontfound2 ;
- error("! no font selected") ;
- fontfound: curfnt = cfnt->desc ;
- fontfound2: if (!preselectfont(curfnt))
- goto outofmem ;
- break ;
- case 239: predospecial((integer)dvibyte(), 1) ; break ; /* xxx1 */
- case 240: predospecial((integer)twobytes(), 1) ; break ; /* xxx2 */
- case 241: predospecial(threebytes(), 1) ; break ; /* xxx3 */
- case 242: predospecial(signedquad(), 1) ; break ; /* xxx4 */
- case 243: case 244: case 245: case 246: fontdef(cmd-242) ; break ; /* fntdef1 */
- case 140: /* eop or end of virtual char */
- if (curpos) {
- --frp ;
- curfnt = frp->curf ;
- ffont = frp->ff ;
- curlim = frp->curl ;
- curpos = frp->curp ;
- break ;
- }
- goto endofpage ; /* eop */
- }
- }
- endofpage:
- if (fontmem > pagecost)
- return(1) ;
- if (pagecount > 0)
- return(0) ;
- #ifdef SHORTINT
- (void)fprintf(stderr, "Page %ld may be too complex to print\n", pagenum) ;
- #else /* ~SHORTINT */
- (void)fprintf(stderr, "Page %d may be too complex to print\n", pagenum) ;
- #endif /* ~SHORTINT */
- /*
- * This case should be rare indeed. Even with only 200K of virtual memory,
- * at 11 bytes per char, you can have 18K characters on a page.
- */
- return(2) ;
- outofmem:
- if (frp != frames) {
- curpos = frames->curp ;
- curlim = frames->curl ;
- ffont = frames->ff ;
- curfnt = frames->curf ;
- }
- return 0 ;
- }
-