home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / d / dvips551.zip / DVIPS.ZIP / SCANPAGE.C < prev    next >
C/C++ Source or Header  |  1993-01-30  |  10KB  |  296 lines

  1. /*
  2.  *   This routine scans a page for font definitions and character usage.
  3.  *   It keeps an estimate of the memory remaining in the printer, and
  4.  *   returns false when that memory is exhausted, unless scanning the
  5.  *   first page. Otherwise it returns 1 if no problems were found,
  6.  *   or 2 if it thinks the first page of a section may overflow memory.
  7.  */
  8. #include "dvips.h" /* The copyright notice in that file is included too! */
  9. /*
  10.  *   These are the external routines we need.
  11.  */
  12. extern shalfword dvibyte() ;
  13. extern halfword twobytes() ;
  14. extern integer threebytes() ;
  15. extern integer signedquad() ;
  16. extern shalfword signedbyte() ;
  17. extern shalfword signedpair() ;
  18. extern integer signedtrio() ;
  19. extern void skipover() ;
  20. extern void fontdef() ;
  21. extern void predospecial() ;
  22. extern int residentfont() ;
  23. extern Boolean virtualfont() ;
  24. extern void loadfont() ;
  25. extern void error() ;
  26. extern long getlong() ;
  27. extern void repack() ;
  28. extern void bopcolor() ;  /* IBM: color */
  29. extern integer firstboploc ;
  30. /*
  31.  *   And, of course, the globals it uses.
  32.  */
  33. #ifdef DEBUG
  34. extern integer debug_flag;
  35. #endif  /* DEBUG */
  36. extern fontdesctype *curfnt ;
  37. extern fontdesctype *baseFonts[] ;
  38. extern fontmaptype *ffont ;
  39. extern quarterword *curpos, *curlim ;
  40. extern integer fontmem ;
  41. extern integer pagecount ;
  42. extern integer pagenum ;
  43. extern Boolean compressed ;
  44. extern FILE *dvifile ;
  45. extern char errbuf[] ;
  46. extern frametype frames[] ;
  47. extern integer pagecost ;
  48. /*
  49.  * Charge pagecost for the cost of showing the character that *cd refers to
  50.  * and charge fontmem for the cost of downloading the character if necessary.
  51.  * A zero result indicates that we have run out of memory.
  52.  *   If the character is small (a small packet), we save 43 bytes (since we
  53.  *   use a single string instead of an array with integers in the PostScript.)
  54.  */
  55. Boolean
  56. prescanchar(cd)
  57. chardesctype *cd ;
  58. {
  59.    register quarterword *cras ;
  60.    register integer thischar ;
  61.  
  62.    if ((cd->flags & (PREVPAGE | THISPAGE)) == 0) {
  63.       /* the character hasn't been used before in the current section */
  64.       cras = cd->packptr ;
  65.       if (curfnt->resfont) {
  66.          thischar = PSCHARCOST ;
  67.          cd->flags |= THISPAGE ;
  68.       } else if (cras != NULL) {
  69.          thischar = CHARCOST ;
  70.          if (cd->flags & BIGCHAR)
  71.             thischar += 43 ;
  72.          if (compressed) {
  73.             if ((cd->flags & REPACKED) == 0) {
  74.                repack(cd) ;
  75.                cras = cd->packptr ;
  76.             }
  77.             if ((*cras & 4))
  78.                if ((*cras & 7) == 7)
  79.                   thischar += getlong(cras + 17) ;
  80.                else
  81.                   thischar += getlong(cras + 9) ;
  82.             else
  83.                thischar += getlong(cras + 5) ;
  84.          } else {
  85.             if ((*cras & 4))
  86.                if ((*cras & 7) == 7)
  87.                   thischar += getlong(cras + 1)
  88.                                           * ((getlong(cras + 5) + 7) >> 3) ;
  89.                else
  90.                   thischar += (cras[3] * 256L + cras[4]) *
  91.                                  ((cras[1] * 256L + cras[2] + 7) >> 3) ;
  92.             else
  93.                thischar += ((long)(cras[2] * ((cras[1] + 7) >> 3))) ;
  94.          }
  95.          cd->flags |= THISPAGE ;
  96.       } else
  97.          thischar = 0 ;
  98.       fontmem -= thischar ;
  99.       if (fontmem <= pagecost) {
  100.          if (pagecount > 0)
  101.             return(0) ;
  102.       }
  103.    }
  104.    return(1) ;
  105. }
  106. /*
  107.  * When a font is selected during the prescan, this routine makes sure that
  108.  * the tfm or pk file is loaded and charges fontmem for the VM overhead in
  109.  * creating the font.  The result is true unless the section must be aborted
  110.  * in order to keep this font from overflowing VM.
  111.  */
  112. Boolean
  113. preselectfont(f)
  114. fontdesctype *f ;
  115. {
  116.    curfnt = f ;
  117.    if (curfnt->loaded == 0 || curfnt->loaded == 3) {
  118.       if (!residentfont(curfnt))
  119.          if (!virtualfont(curfnt))
  120.             loadfont(curfnt) ;
  121.    }
  122.    if (curfnt->psname == 0) {
  123.       if (curfnt->loaded < 2) /* virtual font costs nothing (yet) */
  124.          if (curfnt->resfont)
  125.             fontmem -= PSFONTCOST ;
  126.          else {
  127.             fontmem -= FONTCOST + curfnt->maxchars ;
  128.             if (curfnt->loadeddpi != curfnt->dpi)
  129.                fontmem -= 48 ; /* for the new font matrix */
  130.          }
  131.       curfnt->psname = 1 ;
  132.       if (fontmem <= pagecost) {
  133.          if (pagecount > 0)
  134.             return(0) ;
  135.       }
  136.    }
  137.    return(1) ;
  138. }
  139. /*
  140.  *   Now our scanpage routine.
  141.  */
  142. short
  143. scanpage()
  144. {
  145.    register shalfword cmd ;
  146.    register chardesctype *cd ;
  147.    register fontmaptype *cfnt = 0 ;
  148.    integer fnt ;
  149.    register frametype *frp = frames ;
  150.  
  151.   if (firstboploc == 0)
  152.      firstboploc = ftell(dvifile) ;
  153.    pagecost = 0 ;
  154. #ifdef DEBUG
  155.    if (dd(D_PAGE))
  156. #ifdef SHORTINT
  157.    (void)fprintf(stderr,"Scanning page %ld\n", pagenum) ;
  158. #else   /* ~SHORTINT */
  159.    (void)fprintf(stderr,"Scanning page %d\n", pagenum) ;
  160. #endif  /* ~SHORTINT */
  161. #endif  /* DEBUG */
  162.    curfnt = NULL ;
  163.    curpos = NULL ;
  164.  
  165.    bopcolor(0) ; /* IBM: color - put current colorstack to bopstackdepth */
  166.  
  167.    while (1) {
  168.       switch (cmd=dvibyte()) {
  169. case 129: case 130: case 131: case 134: case 135: case 136: case 139:
  170. case 247: case 248: case 249: case 250: case 251: case 252: case 253:
  171. case 254: case 255: /* unimplemented or illegal commands */
  172.          (void)sprintf(errbuf,
  173.             "! DVI file contains unexpected command (%d)",cmd) ;
  174.          error(errbuf) ;
  175. case 132: case 137: /* eight-byte commands setrule, putrule */
  176.          (void)dvibyte() ;
  177.          (void)dvibyte() ;
  178.          (void)dvibyte() ;
  179.          (void)dvibyte() ;
  180. case 146: case 151: case 156: case 160: case 165: case 170:
  181.    /* four-byte commands right4, w4, x4, down4, y4, z4 */
  182.          (void)dvibyte() ;
  183. case 145: case 150: case 155: case 159: case 164: case 169:
  184.    /* three-byte commands right3, w3, x3, down3, y3, z3 */
  185.          (void)dvibyte() ;
  186. case 144: case 149: case 154: case 158: case 163: case 168:
  187.    /* two-byte commands right2, w2, x2, down2, y2, z2 */
  188.          (void)dvibyte() ;
  189. case 143: case 148: case 153: case 157: case 162: case 167:
  190.    /* one-byte commands right1, w1, x1, down1, y1, z1 */
  191.          (void)dvibyte() ;
  192. case 147: case 152: case 161: case 166: /* w0, x0, y0, z0 */
  193. case 138: case 141: case 142: /* nop, push, pop */
  194.          break ;
  195. case 133: case 128: cmd = dvibyte() ; /* set1 commands drops through */
  196. default:    /* these are commands 0 (setchar0) thru 127 (setchar 127) */
  197. /*
  198.  *   We are going to approximate that each string of consecutive characters
  199.  *   requires (length of string) bytes of PostScript VM.
  200.  */
  201.          if (curfnt==NULL)
  202.             error("! Bad DVI file: no font selected") ;
  203.          if (curfnt->loaded == 2) { /* scanning a virtual font character */
  204.             frp->curp = curpos ;
  205.             frp->curl = curlim ;
  206.             frp->ff = ffont ;
  207.             frp->curf = curfnt ;
  208.             if (++frp == &frames[MAXFRAME] )
  209.                error("! virtual recursion stack overflow") ;
  210.             cd = curfnt->chardesc + cmd ;
  211.             if (cd->packptr == 0)
  212.  error("! a non-existent virtual character is being used; check vf/tfm files") ;
  213.             curpos = cd->packptr + 2 ;
  214.             curlim = curpos + (256*(long)(*cd->packptr)+(*(cd->packptr+1))) ;
  215.             ffont = curfnt->localfonts ;
  216.             if (ffont==NULL)
  217.                curfnt = NULL ;
  218.             else if (!preselectfont(ffont->desc))
  219.                goto outofmem ;
  220.          } else {
  221.             pagecost++ ;
  222.             if (!prescanchar(curfnt->chardesc + cmd))
  223.                goto outofmem ;
  224.          }
  225.          break ;        
  226. case 171: case 172: case 173: case 174: case 175: case 176: case 177:
  227. case 178: case 179: case 180: case 181: case 182: case 183: case 184:
  228. case 185: case 186: case 187: case 188: case 189: case 190: case 191:
  229. case 192: case 193: case 194: case 195: case 196: case 197: case 198:
  230. case 199: case 200: case 201: case 202: case 203: case 204: case 205:
  231. case 206: case 207: case 208: case 209: case 210: case 211: case 212:
  232. case 213: case 214: case 215: case 216: case 217: case 218: case 219:
  233. case 220: case 221: case 222: case 223: case 224: case 225: case 226:
  234. case 227: case 228: case 229: case 230: case 231: case 232: case 233:
  235. case 234: case 235: case 236: case 237: case 238: /* font selection commands */
  236.          if (cmd < 235) fnt = cmd - 171 ; /* fntnum0 thru fntnum63 */
  237.          else {
  238.             fnt = dvibyte() ; /* fnt1 */
  239.             while (cmd-- > 235)
  240.                fnt = (fnt << 8) + dvibyte() ;
  241.          }
  242.          if (curpos || fnt > 255) {
  243.             for (cfnt=ffont; cfnt; cfnt = cfnt->next)
  244.                if (cfnt->fontnum == fnt) goto fontfound ;
  245.          } else
  246.             if (0 != (curfnt = baseFonts[fnt]))
  247.                goto fontfound2 ;
  248.  printf("Font number %d not found\n", fnt) ;
  249.             error("! no font selected") ;
  250. fontfound: curfnt = cfnt->desc ;
  251. fontfound2: if (!preselectfont(curfnt))
  252.               goto outofmem ;
  253.             break ;
  254. case 239: predospecial((integer)dvibyte(), 1) ; break ; /* xxx1 */
  255. case 240: predospecial((integer)twobytes(), 1) ; break ; /* xxx2 */
  256. case 241: predospecial(threebytes(), 1) ; break ; /* xxx3 */
  257. case 242: predospecial(signedquad(), 1) ; break ; /* xxx4 */
  258. case 243: case 244: case 245: case 246: fontdef(cmd-242) ; break ; /* fntdef1 */
  259. case 140: /* eop or end of virtual char */
  260.          if (curpos) {
  261.             --frp ;
  262.             curfnt = frp->curf ;
  263.             ffont = frp->ff ;
  264.             curlim = frp->curl ;
  265.             curpos = frp->curp ;
  266.             break ;
  267.          }
  268.          goto endofpage ; /* eop */
  269.       }
  270.    }
  271. endofpage:
  272.    if (fontmem > pagecost)
  273.       return(1) ;
  274.    if (pagecount > 0) {
  275.       return(0) ;
  276.     }  /* IBM: color */
  277. #ifdef SHORTINT
  278.       (void)fprintf(stderr, "Page %ld may be too complex to print\n", pagenum) ;
  279. #else   /* ~SHORTINT */
  280.       (void)fprintf(stderr, "Page %d may be too complex to print\n", pagenum) ;
  281. #endif  /* ~SHORTINT */
  282. /*
  283.  *   This case should be rare indeed.  Even with only 200K of virtual memory,
  284.  *   at 11 bytes per char, you can have 18K characters on a page.
  285.  */
  286.    return(2) ;
  287. outofmem:
  288.    if (frp != frames) {
  289.       curpos = frames->curp ;
  290.       curlim = frames->curl ;
  291.       ffont = frames->ff ;
  292.       curfnt = frames->curf ;
  293.    }
  294.    return 0 ;
  295. }
  296.