Back to index

tetex-bin  3.0
scanpage.c
Go to the documentation of this file.
00001 /*
00002  *   This routine scans a page for font definitions and character usage.
00003  *   It keeps an estimate of the memory remaining in the printer, and
00004  *   returns false when that memory is exhausted, unless scanning the
00005  *   first page. Otherwise it returns 1 if no problems were found,
00006  *   or 2 if it thinks the first page of a section may overflow memory.
00007  */
00008 #include "dvips.h" /* The copyright notice in that file is included too! */
00009 
00010 /*
00011  *   These are the external routines we need.
00012  */
00013 #include "protos.h"
00014 
00015 extern integer firstboploc ;
00016 /*
00017  *   And, of course, the globals it uses.
00018  */
00019 #ifdef DEBUG
00020 extern integer debug_flag;
00021 #endif  /* DEBUG */
00022 extern fontdesctype *curfnt ;
00023 extern fontmaptype *ffont ;
00024 extern quarterword *curpos, *curlim ;
00025 extern integer fontmem ;
00026 extern integer pagecount ;
00027 extern integer pagenum ;
00028 extern Boolean compressed ;
00029 extern FILE *dvifile ;
00030 extern char errbuf[] ;
00031 extern frametype frames[] ;
00032 extern integer pagecost ;
00033 extern Boolean noomega ;
00034 /*
00035  * Charge pagecost for the cost of showing the character that *cd refers to
00036  * and charge fontmem for the cost of downloading the character if necessary.
00037  * A zero result indicates that we have run out of memory.
00038  *   If the character is small (a small packet), we save 43 bytes (since we
00039  *   use a single string instead of an array with integers in the PostScript.)
00040  */
00041 Boolean
00042 prescanchar P1C(chardesctype *, cd)
00043 {
00044    register quarterword *cras ;
00045    register integer thischar ;
00046 
00047    if ((cd->flags & (PREVPAGE | THISPAGE)) == 0) {
00048       /* the character hasn't been used before in the current section */
00049       cras = cd->packptr ;
00050       if (curfnt->resfont) {
00051          thischar = PSCHARCOST ;
00052          cd->flags |= THISPAGE ;
00053       } else if (cras != NULL) {
00054          thischar = CHARCOST ;
00055          if (cd->flags & BIGCHAR)
00056             thischar += 43 ;
00057          if (compressed) {
00058             if ((cd->flags & REPACKED) == 0) {
00059                repack(cd) ;
00060                cras = cd->packptr ;
00061             }
00062             if ((*cras & 4))
00063                if ((*cras & 7) == 7)
00064                   thischar += getlong(cras + 17) ;
00065                else
00066                   thischar += getlong(cras + 9) ;
00067             else
00068                thischar += getlong(cras + 5) ;
00069          } else {
00070             if ((*cras & 4))
00071                if ((*cras & 7) == 7)
00072                   thischar += getlong(cras + 1)
00073                                           * ((getlong(cras + 5) + 7) >> 3) ;
00074                else
00075                   thischar += (cras[3] * 256L + cras[4]) *
00076                                  ((cras[1] * 256L + cras[2] + 7) >> 3) ;
00077             else
00078                thischar += ((long)(cras[2] * ((cras[1] + 7) >> 3))) ;
00079          }
00080          cd->flags |= THISPAGE ;
00081       } else
00082          thischar = 0 ;
00083       fontmem -= thischar ;
00084       if (fontmem <= pagecost) {
00085          if (pagecount > 0)
00086             return(0) ;
00087       }
00088    }
00089    return(1) ;
00090 }
00091 /*
00092  * When a font is selected during the prescan, this routine makes sure that
00093  * the tfm or pk file is loaded and charges fontmem for the VM overhead in
00094  * creating the font.  The result is true unless the section must be aborted
00095  * in order to keep this font from overflowing VM.
00096  */
00097 Boolean
00098 preselectfont P1C(fontdesctype *, f)
00099 {
00100    curfnt = f ;
00101    if (curfnt->loaded == 0 || curfnt->loaded == 3) {
00102       if (!residentfont(curfnt))
00103          if (!virtualfont(curfnt))
00104             loadfont(curfnt) ;
00105    }
00106    if (curfnt->psname == 0) {
00107       if (curfnt->loaded < 2) /* virtual font costs nothing (yet) */
00108          if (curfnt->resfont)
00109             fontmem -= PSFONTCOST ;
00110          else {
00111             fontmem -= FONTCOST + curfnt->maxchars ;
00112             if (curfnt->loadeddpi != curfnt->dpi)
00113                fontmem -= 48 ; /* for the new font matrix */
00114          }
00115       curfnt->psname = 1 ;
00116       if (fontmem <= pagecost) {
00117          if (pagecount > 0)
00118             return(0) ;
00119       }
00120    }
00121    return(1) ;
00122 }
00123 /*
00124  *   Now our scanpage routine.
00125  */
00126 short
00127 scanpage P1H(void)
00128 {
00129    register shalfword cmd ;
00130    register chardesctype *cd ;
00131    register fontmaptype *cfnt = 0 ;
00132    integer fnt ;
00133    integer mychar ;
00134    register frametype *frp = frames ;
00135 
00136   if (firstboploc == 0)
00137      firstboploc = ftell(dvifile) ;
00138    pagecost = 0 ;
00139 #ifdef DEBUG
00140    if (dd(D_PAGE))
00141 #ifdef SHORTINT
00142    (void)fprintf(stderr,"Scanning page %ld\n", pagenum) ;
00143 #else   /* ~SHORTINT */
00144    (void)fprintf(stderr,"Scanning page %d\n", pagenum) ;
00145 #endif  /* ~SHORTINT */
00146 #endif  /* DEBUG */
00147    curfnt = NULL ;
00148    curpos = NULL ;
00149 
00150    bopcolor(0) ; /* IBM: color - put current colorstack to bopstackdepth */
00151  
00152    while (1) {
00153       switch (cmd=dvibyte()) {
00154 case 130: case 131: case 135: case 136: case 139:
00155 case 247: case 248: case 249: case 250: case 251: case 252: case 253:
00156 case 254: case 255: /* unimplemented or illegal commands */
00157          (void)sprintf(errbuf,
00158             "! DVI file contains unexpected command (%d)",cmd) ;
00159          error(errbuf) ;
00160 case 132: case 137: /* eight-byte commands setrule, putrule */
00161          (void)dvibyte() ;
00162          (void)dvibyte() ;
00163          (void)dvibyte() ;
00164          (void)dvibyte() ;
00165 case 146: case 151: case 156: case 160: case 165: case 170:
00166    /* four-byte commands right4, w4, x4, down4, y4, z4 */
00167          (void)dvibyte() ;
00168 case 145: case 150: case 155: case 159: case 164: case 169:
00169    /* three-byte commands right3, w3, x3, down3, y3, z3 */
00170          (void)dvibyte() ;
00171 case 144: case 149: case 154: case 158: case 163: case 168:
00172    /* two-byte commands right2, w2, x2, down2, y2, z2 */
00173          (void)dvibyte() ;
00174 case 143: case 148: case 153: case 157: case 162: case 167:
00175    /* one-byte commands right1, w1, x1, down1, y1, z1 */
00176          (void)dvibyte() ;
00177 case 147: case 152: case 161: case 166: /* w0, x0, y0, z0 */
00178 case 138: case 141: case 142: /* nop, push, pop */
00179          break ;
00180 case 134: case 129: /* set2, put2 */
00181          if (noomega) {
00182             (void)sprintf(errbuf,
00183                "! DVI file contains unexpected Omega command (%d)",cmd) ;
00184             error(errbuf) ;
00185          }
00186          mychar = dvibyte() ; mychar = (mychar << 8) + dvibyte() ;
00187          goto dochar ;
00188 case 133: case 128: cmd = dvibyte() ; /* set1 commands drops through */
00189 default:    /* these are commands 0 (setchar0) thru 127 (setchar 127) */
00190         mychar = cmd ;
00191 dochar:
00192 /*
00193  *   We are going to approximate that each string of consecutive characters
00194  *   requires (length of string) bytes of PostScript VM.
00195  */
00196          if (curfnt==NULL)
00197             error("! Bad DVI file: no font selected") ;
00198          if (mychar>=curfnt->maxchars) {
00199             (void)sprintf(errbuf,"! invalid char %d from font %s", mychar, curfnt->name) ;
00200             error(errbuf) ;
00201          }
00202          if (curfnt->loaded == 2) { /* scanning a virtual font character */
00203             frp->curp = curpos ;
00204             frp->curl = curlim ;
00205             frp->ff = ffont ;
00206             frp->curf = curfnt ;
00207             if (++frp == &frames[MAXFRAME] )
00208                error("! virtual recursion stack overflow") ;
00209             cd = curfnt->chardesc + mychar ;
00210             if (cd->packptr == 0)
00211  error("! a non-existent virtual character is being used; check vf/tfm files") ;
00212             curpos = cd->packptr + 2 ;
00213             curlim = curpos + (256*(long)(*cd->packptr)+(*(cd->packptr+1))) ;
00214             ffont = curfnt->localfonts ;
00215             if (ffont==NULL)
00216                curfnt = NULL ;
00217             else if (!preselectfont(ffont->desc))
00218                goto outofmem ;
00219          } else {
00220             pagecost++ ;
00221             if (!prescanchar(curfnt->chardesc + mychar))
00222                goto outofmem ;
00223          }
00224          break ;        
00225 case 171: case 172: case 173: case 174: case 175: case 176: case 177:
00226 case 178: case 179: case 180: case 181: case 182: case 183: case 184:
00227 case 185: case 186: case 187: case 188: case 189: case 190: case 191:
00228 case 192: case 193: case 194: case 195: case 196: case 197: case 198:
00229 case 199: case 200: case 201: case 202: case 203: case 204: case 205:
00230 case 206: case 207: case 208: case 209: case 210: case 211: case 212:
00231 case 213: case 214: case 215: case 216: case 217: case 218: case 219:
00232 case 220: case 221: case 222: case 223: case 224: case 225: case 226:
00233 case 227: case 228: case 229: case 230: case 231: case 232: case 233:
00234 case 234: case 235: case 236: case 237: case 238: /* font selection commands */
00235          if (cmd < 235) fnt = cmd - 171 ; /* fntnum0 thru fntnum63 */
00236          else {
00237             fnt = dvibyte() ; /* fnt1 */
00238             while (cmd-- > 235)
00239                fnt = (fnt << 8) + dvibyte() ;
00240          }
00241          for (cfnt=ffont; cfnt; cfnt = cfnt->next)
00242             if (cfnt->fontnum == fnt) goto fontfound ;
00243          printf("Font number %d not found\n", fnt) ;
00244          error("! no font selected") ;
00245 fontfound: curfnt = cfnt->desc ;
00246          if (!preselectfont(curfnt))
00247               goto outofmem ;
00248          break ;
00249 case 239: predospecial((integer)dvibyte(), 1) ; break ; /* xxx1 */
00250 case 240: predospecial((integer)twobytes(), 1) ; break ; /* xxx2 */
00251 case 241: predospecial(threebytes(), 1) ; break ; /* xxx3 */
00252 case 242: predospecial(signedquad(), 1) ; break ; /* xxx4 */
00253 case 243: case 244: case 245: case 246: fontdef(cmd-242) ; break ; /* fntdef1 */
00254 case 140: /* eop or end of virtual char */
00255          if (curpos) {
00256             --frp ;
00257             curfnt = frp->curf ;
00258             ffont = frp->ff ;
00259             curlim = frp->curl ;
00260             curpos = frp->curp ;
00261             break ;
00262          }
00263          goto endofpage ; /* eop */
00264       }
00265    }
00266 endofpage:
00267    if (fontmem > pagecost)
00268       return(1) ;
00269    if (pagecount > 0) {
00270       return(0) ;
00271     }  /* IBM: color */
00272 #ifdef SHORTINT
00273       (void)fprintf(stderr, "Page %ld may be too complex to print\n", pagenum) ;
00274 #else   /* ~SHORTINT */
00275       (void)fprintf(stderr, "Page %d may be too complex to print\n", pagenum) ;
00276 #endif  /* ~SHORTINT */
00277 /*
00278  *   This case should be rare indeed.  Even with only 200K of virtual memory,
00279  *   at 11 bytes per char, you can have 18K characters on a page.
00280  */
00281    return(2) ;
00282 outofmem:
00283    if (frp != frames) {
00284       curpos = frames->curp ;
00285       curlim = frames->curl ;
00286       ffont = frames->ff ;
00287       curfnt = frames->curf ;
00288    }
00289    return 0 ;
00290 }