diff options
Diffstat (limited to 'Build/source/texk/dvipsk/scanpage.c')
-rw-r--r-- | Build/source/texk/dvipsk/scanpage.c | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/scanpage.c b/Build/source/texk/dvipsk/scanpage.c new file mode 100644 index 00000000000..51ad3afb9c7 --- /dev/null +++ b/Build/source/texk/dvipsk/scanpage.c @@ -0,0 +1,310 @@ +/* + * 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 "dvips.h" /* The copyright notice in that file is included too! */ + +/* + * The external declarations: + */ +#include "protos.h" + +/* + * 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(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 (curfnt->resfont) { + thischar = PSCHARCOST; + cd->flags |= THISPAGE; + } else 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] * 256L + cras[4]) * + ((cras[1] * 256L + cras[2] + 7) >> 3); + else + thischar += ((long)(cras[2] * ((cras[1] + 7) >> 3))); + } + cd->flags |= THISPAGE; + } else + thischar = 0; + 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(fontdesctype *f) +{ + curfnt = f; + if (curfnt->loaded == 0 || curfnt->loaded == 3) { + 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(void) +{ + register shalfword cmd; + register chardesctype *cd; + register fontmaptype *cfnt = 0; + integer fnt; + integer mychar; + register frametype *frp = frames; + + if (firstboploc == 0) + firstboploc = ftell(dvifile); + pagecost = 0; +#ifdef DEBUG + if (dd(D_PAGE)) +#ifdef SHORTINT + fprintf(stderr,"Scanning page %ld\n", pagenum); +#else /* ~SHORTINT */ + fprintf(stderr,"Scanning page %d\n", pagenum); +#endif /* ~SHORTINT */ +#endif /* DEBUG */ + curfnt = NULL; + curpos = NULL; + + bopcolor(0); /* IBM: color - put current colorstack to bopstackdepth */ + + while (1) { + switch (cmd=dvibyte()) { +case 255: /* pTeX's dir or undefined */ + if (!noptex) { + dvibyte(); + break; + } +/* illegal commands */ +case 131: case 136: case 139: /* set4, put4, bop */ +case 247: case 248: case 249: /* pre, post, post_post */ +case 250: case 251: case 252: case 253: case 254: /* undefined */ + sprintf(errbuf, + "! DVI file contains unexpected command (%d)",cmd); + error(errbuf); +case 132: case 137: /* eight-byte commands setrule, putrule */ + dvibyte(); + dvibyte(); + dvibyte(); + dvibyte(); +case 146: case 151: case 156: case 160: case 165: case 170: + /* four-byte commands right4, w4, x4, down4, y4, z4 */ + dvibyte(); +case 145: case 150: case 155: case 159: case 164: case 169: + /* three-byte commands right3, w3, x3, down3, y3, z3 */ + dvibyte(); +case 144: case 149: case 154: case 158: case 163: case 168: + /* two-byte commands right2, w2, x2, down2, y2, z2 */ + dvibyte(); +case 143: case 148: case 153: case 157: case 162: case 167: + /* one-byte commands right1, w1, x1, down1, y1, z1 */ + dvibyte(); +case 147: case 152: case 161: case 166: /* w0, x0, y0, z0 */ +case 138: case 141: case 142: /* nop, push, pop */ + break; +case 130: case 135: /* set3, put3 */ + if (noptex) { + sprintf(errbuf, + "! DVI file contains unexpected pTeX command (%d)",cmd); + error(errbuf); + } + mychar = dvibyte(); mychar = (mychar << 8) + dvibyte(); + mychar = (mychar << 8) + dvibyte(); + goto dochar; +case 129: case 134: /* set2, put2 */ + if (noomega && noptex) { + sprintf(errbuf, + "! DVI file contains unexpected command (%d)",cmd); + error(errbuf); + } + mychar = dvibyte(); mychar = (mychar << 8) + dvibyte(); + goto dochar; +case 128: case 133: cmd = dvibyte(); /* set1, put1 commands drops through */ +default: /* these are commands 0 (setchar0) thru 127 (setchar 127) */ + mychar = cmd; +dochar: +/* + * 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 (mychar>=curfnt->maxchars) { + if (!noptex && mychar<0x1000000 && curfnt->loaded == 2 && curfnt->kind == VF_PTEX) { + /* fallback */ + } else { + sprintf(errbuf,"! [scanpage] invalid char %d from font %.500s", + mychar, curfnt->name); + error(errbuf); + } + } + if (curfnt->loaded == 2) { /* scanning a virtual font character */ + struct tft *ffont0; + frp->curp = curpos; + frp->curl = curlim; + frp->ff = ffont; + frp->curf = curfnt; + if (++frp == &frames[MAXFRAME] ) + error("! virtual recursion stack overflow"); + cd = curfnt->chardesc + mychar; + if (mychar>=curfnt->maxchars || cd->packptr == NULL) { + if (!noptex && mychar<0x1000000 && curfnt->kind == VF_PTEX) { /* fallback */ +#ifdef DEBUG + if (dd(D_FONTS)) + fprintf_str(stderr, + "We will fallback pTeX vf:%s to %s\n", + curfnt->name, curfnt->localfonts->desc->name); +#endif /* DEBUG */ + } else { + fprintf(stderr, "Wrong char code: %04X\n", mychar); + error("! a non-existent virtual character is being used; check vf/tfm files"); + } + ffont0 = curfnt->localfonts; + if (ffont0==NULL) + curfnt = NULL; + else if (!preselectfont(ffont0->desc)) + goto outofmem; + } else { + 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 (!prescanchar(curfnt->chardesc + mychar)) + 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(); + } + for (cfnt=ffont; cfnt; cfnt = cfnt->next) + if (cfnt->fontnum == fnt) goto fontfound; + printf("Font number %d not found\n", fnt); + error("! no font selected"); +fontfound: curfnt = cfnt->desc; + 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); + } /* IBM: color */ +#ifdef SHORTINT + fprintf(stderr, "Page %ld may be too complex to print\n", pagenum); +#else /* ~SHORTINT */ + 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; +} |