Back to index

tetex-bin  3.0
dopage.c
Go to the documentation of this file.
00001 /*
00002  *   Main page drawing procedure.  Interprets the page commands.  A simple
00003  *   (if lengthy) case statement interpreter.  
00004  */
00005 #include "dvips.h" /* The copyright notice in that file is included too! */
00006 #include <math.h>
00007 /*
00008  *   The external routines we use:
00009  */
00010 #include "protos.h"
00011 /*
00012  *   Now the external variables.
00013  */
00014 extern fontdesctype *curfnt ;
00015 extern fontmaptype *ffont ;
00016 extern quarterword *curpos, *curlim ;
00017 extern integer hh, vv ;
00018 extern integer hoff, voff ;
00019 extern Boolean noomega ;
00020 /*
00021  * CONVENTION:  conv -> horizontial converter
00022  *            vconv -> vertical converter
00023  */
00024 extern real conv ;
00025 extern real vconv ;
00026 
00027 extern FILE *bitfile ;
00028 extern int actualdpi ;
00029 extern int vactualdpi ;
00030 extern frametype frames[] ;
00031 extern int maxdrift ;
00032 extern int vmaxdrift ;
00033 
00034 #ifdef XENIX
00035 #define PixRound(x) ((integer)(x + (iconv >> 1)) / iconv)
00036 #define VPixRound(x) ((integer)(x + (viconv >> 1)) / viconv)
00037 #else
00038 #ifdef __THINK__
00039 #define  PixRound(x) ((integer)(x +  (iconv >> 1)) /  iconv)
00040 #define VPixRound(x) ((integer)(x + (viconv >> 1)) / viconv)
00041 #else
00042 #define PixRound(x) ((integer)(floor(((x) * conv) + 0.5)))
00043 #define VPixRound(x) ((integer)(floor(((x) * vconv) + 0.5)))
00044 #endif
00045 #endif
00046 /*
00047  *   Now we have the dopage procedure.
00048  *   Most error checking is suppressed because the prescan has already
00049  *   verified that the DVI data is OK....except for stack over/underflow.
00050  */
00051 struct dvistack {
00052   integer hh, vv ;
00053   integer h, v, w, x, y, z ;
00054 } stack[STACKSIZE] ;
00055 #ifdef HPS
00056 extern int pagecounter ;
00057 extern Boolean HPS_FLAG ;
00058 extern Boolean inHTMLregion ;
00059 integer vvmem, hhmem ;
00060 integer pushcount = 0 ;
00061 Boolean PAGEUS_INTERUPPTUS = 0 ;
00062 Boolean NEED_NEW_BOX = 0 ;
00063 extern integer HREF_COUNT ;
00064 extern int current_pushcount ;
00065 integer H_BREAK ; /* An empirical parameter for guessing line breaks; needs
00066                      dpi dependence */
00067 #endif 
00068 void
00069 dopage P1H(void)
00070 {
00071    register shalfword cmd ;
00072    register integer p ;
00073    register chardesctype *cd ;
00074    register integer h ;
00075    register fontmaptype *cfnt ;
00076    register frametype *frp = frames ;
00077    integer fnt ;
00078    integer mychar;
00079    int charmove ;
00080    struct dvistack *sp = stack ;
00081    integer v, w, x, y, z ;
00082    integer roundpos ;
00083    integer thinspace ;
00084    integer vertsmallspace ;
00085 #ifdef XENIX
00086    integer iconv ;
00087    integer viconv ;
00088 
00089    iconv = (integer)(1.0 / conv + 0.5) ;
00090    viconv = (integer)(1.0 / vconv + 0.5) ;
00091 #else
00092 #ifdef __THINK__
00093    integer  iconv ;
00094    integer viconv ;
00095 
00096     iconv = (integer)(1.0 /  conv + 0.5) ;
00097    viconv = (integer)(1.0 / vconv + 0.5) ;
00098 #endif
00099 #endif
00100 #ifdef EMTEX
00101    emclear() ;
00102 #endif
00103    pageinit() ;
00104    
00105    bopcolor(1) ;
00106    thinspace =  (integer)(0.025*DPI/conv) ; /* 0.025 inches */
00107    vertsmallspace = (integer)(0.025*VDPI/vconv) ; /* 0.025 inches */
00108 #ifdef HPS
00109    if (HPS_FLAG) pagecounter++ ;
00110    H_BREAK = (30 * DPI / 400 ) ; /* 30 seems to have worked well at 400 dpi */
00111 #endif 
00112    w = x = y = z = 0 ;
00113    h = (integer) (DPI / conv * hoff / 4736286.72) ;
00114    v = (integer) (DPI / conv * voff / 4736286.72) ;
00115    hh = PixRound(h) ;
00116    vv = PixRound(v) ;
00117    curfnt = NULL ;
00118    curpos = NULL ;
00119    charmove = 0 ;
00120 beginloop:
00121    switch (cmd=dvibyte()) {
00122 case 138: goto beginloop ; /* nop command does nuttin */
00123 /*
00124  *   For put1 commands, we subtract the width of the character before
00125  *   dropping through to the normal character setting routines.  This
00126  */
00127 case 134: /* put2 */
00128    if (noomega) error("! synch") ;
00129    mychar = dvibyte() ;
00130    mychar = (mychar << 8) + dvibyte() ;
00131    charmove = 0 ;
00132    goto dochar ;
00133 case 129: /* set2 */
00134    if (noomega) error("! synch") ;
00135    mychar = dvibyte() ;
00136    mychar = (mychar << 8) + dvibyte() ;
00137    charmove = 1 ;
00138    goto dochar ;
00139 case 133: /* put1 */
00140    mychar = dvibyte() ;
00141    charmove = 0 ;
00142    goto dochar ;
00143 case 128: cmd = dvibyte() ; /* set1 command drops through to setchar */
00144 default: /* these are commands 0 (setchar0) thru 127 (setchar127) */
00145    mychar = cmd ;
00146    charmove = 1 ;
00147 dochar:
00148 #ifdef HPS
00149    if (HPS_FLAG && PAGEUS_INTERUPPTUS) {
00150      HREF_COUNT-- ;
00151      start_new_box() ;
00152      PAGEUS_INTERUPPTUS = 0 ;
00153      }
00154    if (HPS_FLAG && NEED_NEW_BOX) {
00155        vertical_in_hps();
00156        NEED_NEW_BOX = 0;
00157        }
00158 #endif
00159    cd = &(curfnt->chardesc[mychar]) ;
00160    if (cd->flags & EXISTS) {
00161       if (curfnt->loaded == 2) { /* virtual character being typeset */
00162          if (charmove) {
00163             sp->hh = hh + cd->pixelwidth ;
00164             sp->h = h + cd->TFMwidth ;
00165          } else {
00166             sp->hh = hh ; sp->h = h ;
00167          }
00168          sp->vv = vv ; sp-> v = v ;
00169          sp->w = w ; sp->x = x ; sp->y = y ; sp->z = z ;
00170          if (++sp >= &stack[STACKSIZE]) error("! Out of stack space") ;
00171          w = x = y = z = 0 ; /* will be in relative units at new stack level */
00172          frp->curp = curpos ;
00173          frp->curl = curlim ;
00174          frp->ff = ffont ;
00175          frp->curf = curfnt ;
00176          if (++frp == &frames[MAXFRAME] )
00177             error("! virtual recursion stack overflow") ;
00178          curpos = cd->packptr + 2 ;
00179          curlim = curpos + (256*(long)(*cd->packptr)+(*(cd->packptr+1))) ;
00180          ffont = curfnt->localfonts ;
00181          if (ffont) {
00182             curfnt = ffont->desc ;
00183             thinspace = curfnt->thinspace ;
00184          } else {
00185             curfnt = NULL ;
00186             thinspace = vertsmallspace ;
00187          }
00188          goto beginloop ;
00189       }
00190       drawchar(cd, mychar) ;
00191    }
00192    if (charmove) {
00193       h += cd->TFMwidth ;
00194       hh += cd->pixelwidth ;
00195    }
00196    goto setmotion ;
00197 case 130: case 131: case 135: case 136: case 139: 
00198 case 247: case 248: case 249: case 250: case 251: case 252: case 253:
00199 case 254: case 255: /* unimplemented or illegal commands */
00200    error("! synch") ;
00201 case 132: case 137: /* rules */
00202  { integer ry, rx , rxx, ryy ;
00203    ry = signedquad() ; rx = signedquad() ;
00204    if (rx>0 && ry>0) {
00205       if (curpos) {
00206          rx = scalewidth(rx, (frp-1)->curf->scaledsize) ;
00207          ry = scalewidth(ry, (frp-1)->curf->scaledsize) ;
00208       }
00209       rxx = (int)(conv * rx + 0.9999999) ;
00210       ryy = (int)(vconv * ry + 0.9999999) ;
00211       drawrule(rxx, ryy) ;
00212    } else
00213       rxx = 0 ;
00214    if (cmd == 137) goto beginloop ;
00215    h += rx ; hh += rxx ;
00216    goto setmotion ;
00217  }
00218 case 141: /* push */
00219 #ifdef HPS
00220     if (HPS_FLAG) pushcount++ ;
00221   /*  if (HPS_FLAG && PAGEUS_INTERUPPTUS) {
00222       HREF_COUNT-- ;
00223       start_new_box() ;
00224       PAGEUS_INTERUPPTUS = 0 ;
00225      } */
00226     if (HPS_FLAG && NEED_NEW_BOX) {
00227        vertical_in_hps();
00228        NEED_NEW_BOX = 0;
00229        }
00230     /* printf("push %i, %i\n", pushcount, inHTMLregion) ; */
00231 #endif
00232    sp->hh = hh ; sp->vv = vv ; sp->h = h ; sp->v = v ;
00233    sp->w = w ; sp->x = x ; sp->y = y ; sp->z = z ;
00234    if (++sp >= &stack[STACKSIZE]) error("! Out of stack space") ;
00235    goto beginloop ;
00236 case 140: /* eop or end of virtual character */
00237    if (curpos == NULL) { /* eop */
00238 #ifdef HPS
00239      if (HPS_FLAG && inHTMLregion) PAGEUS_INTERUPPTUS = 1 ;
00240     /* printf("Page interrupted"); */
00241 #endif
00242      break;
00243    }
00244    --frp ;
00245    curfnt = frp->curf ;
00246    thinspace = (curfnt) ? curfnt->thinspace : vertsmallspace ;
00247    ffont = frp->ff ;
00248    curlim = frp->curl ;
00249    curpos = frp->curp ;
00250    if (hh < (sp-1)->hh+2 && hh > (sp-1)->hh-2)
00251       (sp-1)->hh = hh; /* retain `intelligence' of pixel width, if close */ 
00252    /* falls through */
00253 case 142: /* pop */
00254 #ifdef HPS
00255    pushcount-- ;
00256   /* printf("pop %i\n", pushcount) ; */
00257 #endif
00258    if (--sp < stack) error("! More pops than pushes") ;
00259 #ifdef HPS
00260    if (HPS_FLAG) {
00261       hhmem = hh ; vvmem = vv ; 
00262      }
00263 #endif
00264    hh = sp->hh ; vv = sp->vv ; h = sp->h ; v = sp->v ; 
00265    w = sp->w ; x = sp->x ; y = sp->y ; z = sp->z ;
00266 #ifdef HPS
00267    if (HPS_FLAG && inHTMLregion && (hhmem - hh > H_BREAK) && (pushcount > 0) &&
00268        (pushcount < current_pushcount)) 
00269      end_current_box() ;
00270 #endif
00271    goto beginloop ;
00272 case 143: /* right1 */
00273    p = signedbyte() ; goto horizontalmotion ;
00274 case 144: /* right2 */
00275    p = signedpair() ; goto horizontalmotion ;
00276 case 145: /* right3 */
00277    p = signedtrio() ; goto horizontalmotion ;
00278 case 146: /* right4 */
00279    p = signedquad() ; goto horizontalmotion ;
00280 case 147: /* w0 */
00281    p = w ; goto horizontalmotion ;
00282 case 148: /* w1 */
00283    p = w = signedbyte() ; goto horizontalmotion ;
00284 case 149: /* w2 */
00285    p = w = signedpair() ; goto horizontalmotion ;
00286 case 150: /* w3 */
00287    p = w = signedtrio() ; goto horizontalmotion ;
00288 case 151: /* w4 */
00289    p = w = signedquad() ; goto horizontalmotion ;
00290 case 152: /* x0 */
00291    p = x ; goto horizontalmotion ;
00292 case 153: /* x1 */
00293    p = x = signedbyte() ; goto horizontalmotion ;
00294 case 154: /* x2 */
00295    p = x = signedpair() ; goto horizontalmotion ;
00296 case 155: /* x3 */
00297    p = x = signedtrio() ; goto horizontalmotion ;
00298 case 156: /* x4 */
00299    p = x = signedquad() ; goto horizontalmotion ;
00300 case 157: /* down1 */
00301    p = signedbyte() ; goto verticalmotion ;
00302 case 158: /* down2 */
00303    p = signedpair() ; goto verticalmotion ;
00304 case 159: /* down3 */
00305    p = signedtrio() ; goto verticalmotion ;
00306 case 160: /* down4 */
00307    p = signedquad() ; goto verticalmotion ;
00308 case 161: /* y0 */
00309    p = y ; goto verticalmotion ;
00310 case 162: /* y1 */
00311    p = y = signedbyte() ; goto verticalmotion ;
00312 case 163: /* y2 */
00313    p = y = signedpair() ; goto verticalmotion ;
00314 case 164: /* y3 */
00315    p = y = signedtrio() ; goto verticalmotion ;
00316 case 165: /* y4 */
00317    p = y = signedquad() ; goto verticalmotion ;
00318 case 166: /* z0 */
00319    p = z ; goto verticalmotion ;
00320 case 167: /* z1 */
00321    p = z = signedbyte() ; goto verticalmotion ;
00322 case 168: /* z2 */
00323    p = z = signedpair() ; goto verticalmotion ;
00324 case 169: /* z3 */
00325    p = z = signedtrio() ; goto verticalmotion ;
00326 case 170: /* z4 */
00327    p = z = signedquad() ; goto verticalmotion ;
00328 case 171: case 172: case 173: case 174: case 175: case 176: case 177:
00329 case 178: case 179: case 180: case 181: case 182: case 183: case 184:
00330 case 185: case 186: case 187: case 188: case 189: case 190: case 191:
00331 case 192: case 193: case 194: case 195: case 196: case 197: case 198:
00332 case 199: case 200: case 201: case 202: case 203: case 204: case 205:
00333 case 206: case 207: case 208: case 209: case 210: case 211: case 212:
00334 case 213: case 214: case 215: case 216: case 217: case 218: case 219:
00335 case 220: case 221: case 222: case 223: case 224: case 225: case 226:
00336 case 227: case 228: case 229: case 230: case 231: case 232: case 233:
00337 case 234: case 235: case 236: case 237: case 238: /* font selection commands */
00338    if (cmd < 235) fnt = cmd - 171 ; /* fntnum0 thru fntnum63 */
00339    else {
00340       fnt = dvibyte() ;
00341       while (cmd-- > 235)
00342          fnt = (fnt << 8) + dvibyte() ;
00343    }
00344    for (cfnt=ffont; cfnt; cfnt = cfnt->next)
00345       if (cfnt->fontnum == fnt) break ;
00346    curfnt = cfnt->desc ;
00347    thinspace = curfnt->thinspace ;
00348    goto beginloop ;
00349 case 243: case 244: case 245: case 246: /*fntdef1 */
00350    skipover(cmd - 230) ;
00351    skipover(dvibyte() + dvibyte()) ;
00352    goto beginloop ;
00353 case 239: /* xxx1 */
00354    p = dvibyte() ;
00355    dospecial(p) ;
00356    goto beginloop ;
00357 case 240: /* xxx2 */
00358    p = twobytes() ;
00359    dospecial(p) ;
00360    goto beginloop ;
00361 case 241: /* xxx3 */
00362    p = threebytes() ;
00363    dospecial(p) ;
00364    goto beginloop ;
00365 case 242: /* xxx4 */
00366    p = signedquad() ;
00367    dospecial(p) ;
00368    goto beginloop ;
00369 
00370 /*
00371  *   The calculations here are crucial to the appearance of the document.
00372  *   If the motion is small, we round the amount of relative motion; otherwise,
00373  *   we update the position and round the new position.  Then we check to
00374  *   insure that the rounded position didn't accumulate an error that was
00375  *   greater than maxdrift.
00376  */
00377 verticalmotion:
00378 /* vertical motion cases */
00379       if (curpos)
00380          p = scalewidth(p, (frp-1)->curf->scaledsize) ;
00381       v += p ;
00382       if (p >= vertsmallspace) vv = VPixRound(v) ;
00383       else if (p <= -vertsmallspace) vv = VPixRound(v) ;
00384       else 
00385       { vv += VPixRound(p) ;
00386         roundpos = VPixRound(v) ;
00387         if (roundpos - vv > vmaxdrift) vv = roundpos - vmaxdrift ;
00388         else if (vv - roundpos > vmaxdrift) vv = roundpos + vmaxdrift ;
00389       }
00390 #ifdef HPS
00391    /* printf("Doing vertical motion: p = %i, v = %i, vv = %i\n",p,v,vv); */
00392               /* printf("inHTMLregion %i\n", inHTMLregion) ; */
00393      if (HPS_FLAG && inHTMLregion) NEED_NEW_BOX = 1 /* vertical_in_hps() */;
00394 #endif   
00395       goto beginloop ;
00396 /*
00397  *   Horizontal motion is analogous. We know the exact width of each
00398  *   character in pixels. Kerning is distinguished from space between
00399  *   words if it's less than a thinspace and not more negative than would
00400  *   occur when an accent is being positioned by backspacing.
00401  */
00402 horizontalmotion:
00403 /* horizontal motion cases */
00404       if (curpos)
00405          p = scalewidth(p, (frp-1)->curf->scaledsize) ;
00406       h += p ;
00407       if (p >= thinspace || p <= -6 * thinspace) {
00408          hh = PixRound(h) ; goto beginloop ;
00409       }
00410       else hh += PixRound(p) ;
00411 #ifdef HPS
00412     /* printf("Doing horizontal motion: p = %i, h = %i, hh = %i\n",p,h,hh); */
00413 #endif
00414 setmotion:
00415       roundpos = PixRound(h) ;
00416       if (roundpos - hh > maxdrift) { hh = roundpos - maxdrift ; }
00417       else if (hh - roundpos > maxdrift) { hh = roundpos + maxdrift ; }
00418 goto beginloop ;
00419 
00420    } /* end of the big switch */
00421    pageend() ;
00422 }