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