Back to index

tetex-bin  3.0
bbox.c
Go to the documentation of this file.
00001 /*
00002  *   Calculates the bounding box for a one-page .dvi file.
00003  *   Based on a lot of other dvips stuff.  Requires a total re-scan
00004  *   of the page.
00005  *
00006  *   If you request an EPSF file and specify -a, you may end up
00007  *   processing a single page four times!
00008  */
00009 #include "dvips.h"
00010 #include <math.h>
00011 #include "protos.h"
00012 
00013 extern char *nextstring, errbuf[] ;
00014 extern FILE *tfmfile, *dvifile ;
00015 extern fontmaptype *ffont ;
00016 extern integer firstboploc, num, den ;
00017 extern double mag ;
00018 extern integer hoff, voff ;
00019 extern Boolean noomega ;
00020 
00021 typedef struct {
00022   integer llx, lly, urx, ury ;
00023 } bbchardesctype ;
00024 typedef struct {
00025   bbchardesctype *bbchardesc ;
00026 } bbfontdesctype ;
00027 typedef struct bbtft {
00028    integer fontnum ;
00029    bbfontdesctype *desc ;
00030    struct bbtft *next ;
00031 } bbfontmaptype ;
00032 
00033 static bbfontmaptype *bbffont ;
00034 
00035 void bbtfmload P1C(register fontdesctype *, curfnt)
00036 {
00037    register integer i, j ;
00038    register integer li, cd = 0 ;
00039    integer scaledsize ;
00040    integer nw, nh, nd, ns, hd ;
00041    integer bc, ec ;
00042    integer nco = 0, ncw = 0, npc = 0, no_repeats = 0 ;
00043    integer *scaled ;
00044    integer *chardat ;
00045    int font_level;
00046    integer pretend_no_chars;
00047    integer slant = 0 ;
00048    bbchardesctype *cc ;
00049    register bbfontdesctype *bbcurfnt =
00050       (bbfontdesctype *)mymalloc(sizeof(bbfontdesctype)) ;
00051 
00052    bbffont->desc = bbcurfnt ;
00053    tfmopen(curfnt) ;
00054 /*
00055  *   Next, we read the font data from the tfm file, and store it in
00056  *   our own arrays.
00057  */
00058    li = tfm16() ;
00059    if (li!=0) {
00060       font_level = -1;
00061       hd = tfm16() ;
00062       bc = tfm16() ; ec = tfm16() ;
00063       nw = tfm16() ; nh = tfm16(); nd = tfm16();
00064       ns = tfm16() ;
00065       ns += tfm16() ;
00066       ns += tfm16() ;
00067       ns += tfm16() ;
00068       li = tfm16() ;
00069       if (hd<2 || bc>ec+1 || ec>255 || nw>256 || nh>16 || nd>16)
00070          badtfm("header") ;
00071    } else {  /* In an .ofm file */
00072       if (noomega) badtfm("length") ;
00073       font_level = tfm16();
00074       li = tfm32() ;
00075       hd = tfm32() ;
00076       bc = tfm32() ; ec = tfm32() ;
00077       nw = tfm32() ; nh = tfm32() ; nd = tfm32();
00078       ns = tfm32() ;
00079       ns += tfm32() ;
00080       ns += tfm32() ;
00081       ns += tfm32() ;
00082       li = tfm32() ;
00083       li = tfm32() ;
00084       if (font_level>1 || hd<2 || bc<0 || ec<0 || nw<2 || nh<1 || nd<1 || ns<1
00085                        || bc>ec+1 || ec>65535 || nw>65536 || nh>256 || nd>256)
00086          badtfm("header") ;
00087       if (font_level==1) {
00088         nco = tfm32() ;
00089         ncw = tfm32() ;
00090         npc = tfm32() ;
00091         for (i=0; i<12; i++) li=tfm32();
00092       }
00093    }
00094    li = tfm32() ;
00095    check_checksum (li, curfnt->checksum, curfnt->name);
00096 
00097    li = tfm32() ;
00098    pretend_no_chars=ec+1;
00099    if (pretend_no_chars<256) pretend_no_chars=256;
00100    bbcurfnt->bbchardesc = (bbchardesctype *)
00101                           xmalloc(pretend_no_chars*sizeof(bbchardesctype));
00102    for (i=2; i<((font_level==1)?nco-29:hd); i++)
00103       li = tfm32() ;
00104    chardat = (integer *) xmalloc(pretend_no_chars*sizeof(integer)) ;
00105    for (i=0; i<pretend_no_chars; i++)
00106       chardat[i] = -1 ;
00107    for (i=bc; i<=ec; i++) {
00108       if (no_repeats>0) {
00109          no_repeats-- ;
00110       } else if (font_level>=0) {
00111          cd = tfm32() ;
00112          li = tfm32() ;
00113          if (font_level==1) {
00114             no_repeats = tfm16() ;
00115             for (j=0; j<(npc|1); j++) tfm16() ;
00116             ncw -= 3 + npc/2 ;
00117          }
00118       } else {
00119          cd = tfm16() ;
00120          li = tfm16() ;
00121       }
00122       if (cd) chardat[i] = cd ;
00123    }
00124    if (font_level==1&&ncw!=0) {
00125       sprintf(errbuf, "Table size mismatch in %s", curfnt->name) ;
00126       error(errbuf) ;
00127    }
00128    scaledsize = curfnt->scaledsize ;
00129    scaled = (integer *) xmalloc((nh + nd)*sizeof(integer)) ;
00130    for (i=0; i<nw; i++)
00131       tfm32() ;
00132    for (i=0; i<nh + nd; i++)
00133       scaled[i] = scalewidth(tfm32(), scaledsize) ;
00134    for (i=0; i<ns; i++)
00135       tfm32() ;
00136    slant = tfm32() ;
00137    (void)fclose(tfmfile) ;
00138    for (i=0; i<pretend_no_chars; i++) {
00139       cc = &(bbcurfnt->bbchardesc[i]) ;
00140       if (chardat[i] != -1) {
00141          halfword iw ;
00142          int ih, id ;
00143          if (font_level>=0) {
00144             iw = chardat[i] >> 16 ;
00145             ih = (chardat[i] >> 8) & 255 ;
00146             id = chardat[i] & 255 ;
00147          } else {
00148             iw = chardat[i] >> 8 ;
00149             ih = (chardat[i] >> 4) & 15 ;
00150             id = chardat[i] & 15 ;
00151          }
00152          if (iw>=nw || ih>=nh || id>=nd) badtfm("char info") ;
00153          cc->ury = scaled[ih] ;
00154          cc->lly = - scaled[nh + id] ;
00155          cc->llx = 0 ;
00156          cc->urx = curfnt->chardesc[i].TFMwidth ;
00157       } else {
00158          cc->llx = cc->lly = cc->urx = cc->ury = 0 ;
00159       }
00160    }
00161    if (slant) {
00162       for (i=0; i<pretend_no_chars; i++) {
00163          cc = &(bbcurfnt->bbchardesc[i]) ;
00164          li = scalewidth(cc->lly, slant) ;
00165          if (slant > 0) cc->llx += li ;
00166          else cc->urx += li ;
00167          li = scalewidth(cc->ury, slant) ;
00168          if (slant > 0) cc->urx += li ;
00169          else cc->llx += li ;
00170       }
00171    }
00172    free(chardat) ;
00173    free(scaled) ;
00174 }
00175 extern struct dvistack {
00176   integer hh, vv ;
00177   integer h, v, w, x, y, z ;
00178 } stack[] ;
00179 static integer llx, lly, urx, ury ;
00180 void bbspecial P3C(integer, h, integer, v, int, nbytes)
00181 {
00182    float *r = bbdospecial(nbytes) ;
00183    if (r) {
00184       /* convert from magnified PostScript units back to scaled points */
00185       real conv = 72.0 * (real)num / (real)den * (real)mag / 254000000.0 ;
00186       if (llx > h + r[0] / conv)
00187          llx = (integer) (h + r[0] / conv) ;
00188       if (lly > v - r[3] / conv)
00189          lly = (integer) (v - r[3] / conv) ;
00190       if (urx < h + r[2] / conv)
00191          urx = (integer) (h + r[2] / conv) ;
00192       if (ury < v - r[1] / conv)
00193          ury = (integer) (v - r[1] / conv) ;
00194    }
00195 }
00196 void bbdopage()
00197 {
00198    register shalfword cmd ;
00199    register bbchardesctype *bcd ;
00200    register chardesctype *cd ;
00201    register integer h ;
00202    register fontmaptype *cfnt ;
00203    bbfontmaptype *bbcfnt ;
00204    integer fnt ;
00205     integer mychar ;
00206    int charmove ;
00207    struct dvistack *sp = stack ;
00208    integer v, w, x, y, z ;
00209    register fontdesctype *curfnt = 0 ;
00210    register bbfontdesctype *bbcurfnt = 0 ;
00211 
00212    w = x = y = z = 0 ;
00213    h = 0 ; v = 0 ;
00214    llx = lly = 1000000000 ;
00215    urx = ury = -1000000000 ;
00216    charmove = 0 ;
00217    while (1) {
00218       switch (cmd=dvibyte()) {
00219 case 138: break ;
00220 case 134: /* put2 */
00221          if (noomega) error("! synch") ;
00222          mychar = dvibyte() ;
00223          mychar = (mychar << 8) + dvibyte() ;
00224          charmove = 0 ;
00225          goto dochar ;
00226 case 129: /* set2 */
00227          if (noomega) error("! synch") ;
00228          mychar = dvibyte() ;
00229          mychar = (mychar << 8) + dvibyte() ;
00230          charmove = 1;
00231          goto dochar ;
00232 case 133: /* put1 */
00233          mychar = dvibyte() ;
00234          charmove = 0 ;
00235          goto dochar ;
00236 case 128: cmd = dvibyte() ; /* set1 command drops through to setchar */
00237 default: /* these are commands 0 (setchar0) thru 127 (setchar127) */
00238          mychar = cmd ;
00239          charmove = 1 ;
00240 dochar:
00241          cd = &(curfnt->chardesc[mychar]) ;
00242          bcd = &(bbcurfnt->bbchardesc[mychar]) ;
00243          if (h + bcd->llx < llx) llx = h + bcd->llx ;
00244          if (h + bcd->urx > urx) urx = h + bcd->urx ;
00245          if (v - bcd->ury < lly) lly = v - bcd->ury ;
00246          if (v - bcd->lly > ury) ury = v - bcd->lly ;
00247          if (charmove)
00248             h += cd->TFMwidth ;
00249          break ;
00250 case 130: case 131: case 135: case 136: case 139: 
00251 case 247: case 248: case 249: case 250: case 251: case 252: case 253:
00252 case 254: case 255: /* unimplemented or illegal commands */
00253          error("! synch") ;
00254 case 132: case 137: /* rules */
00255          {  integer ry, rx ;
00256             ry = signedquad() ; rx = signedquad() ;
00257             if (rx>0 && ry>0) {
00258                if (h < llx) llx = h ;
00259                if (v - ry < lly) lly = v - ry ;
00260                if (h + rx > urx) urx = h + rx ;
00261                if (v > ury) ury = v ;
00262             } else
00263                rx = 0 ;
00264             if (cmd != 137)
00265                h += rx ;
00266             break ;
00267          }
00268 case 141: /* push */
00269          sp->h = h ; sp->v = v ;
00270          sp->w = w ; sp->x = x ; sp->y = y ; sp->z = z ;
00271          if (++sp >= &stack[STACKSIZE]) error("! Out of stack space") ;
00272          break ;
00273 case 140: /* eop or end of virtual character */
00274          return ;
00275 case 142: /* pop */
00276          if (--sp < stack) error("! More pops than pushes") ;
00277          h = sp->h ; v = sp->v ;
00278          w = sp->w ; x = sp->x ; y = sp->y ; z = sp->z ;
00279          break ;
00280 case 143: h += signedbyte() ; break ;
00281 case 144: h += signedpair() ; break ;
00282 case 145: h += signedtrio() ; break ;
00283 case 146: h += signedquad() ; break ;
00284 case 147: h += w ; break ;
00285 case 148: h += (w = signedbyte()) ; break ;
00286 case 149: h += (w = signedpair()) ; break ;
00287 case 150: h += (w = signedtrio()) ; break ;
00288 case 151: h += (w = signedquad()) ; break ;
00289 case 152: h += x ; break ;
00290 case 153: h += (x = signedbyte()) ; break ;
00291 case 154: h += (x = signedpair()) ; break ;
00292 case 155: h += (x = signedtrio()) ; break ;
00293 case 156: h += (x = signedquad()) ; break ;
00294 case 157: v += signedbyte() ; break ;
00295 case 158: v += signedpair() ; break ;
00296 case 159: v += signedtrio() ; break ;
00297 case 160: v += signedquad() ; break ;
00298 case 161: v += y ; break ;
00299 case 162: v += (y = signedbyte()) ; break ;
00300 case 163: v += (y = signedpair()) ; break ;
00301 case 164: v += (y = signedtrio()) ; break ;
00302 case 165: v += (y = signedquad()) ; break ;
00303 case 166: v += z ; break ;
00304 case 167: v += (z = signedbyte()) ; break ;
00305 case 168: v += (z = signedpair()) ; break ;
00306 case 169: v += (z = signedtrio()) ; break ;
00307 case 170: v += (z = signedquad()) ; break ;
00308 case 171: case 172: case 173: case 174: case 175: case 176: case 177:
00309 case 178: case 179: case 180: case 181: case 182: case 183: case 184:
00310 case 185: case 186: case 187: case 188: case 189: case 190: case 191:
00311 case 192: case 193: case 194: case 195: case 196: case 197: case 198:
00312 case 199: case 200: case 201: case 202: case 203: case 204: case 205:
00313 case 206: case 207: case 208: case 209: case 210: case 211: case 212:
00314 case 213: case 214: case 215: case 216: case 217: case 218: case 219:
00315 case 220: case 221: case 222: case 223: case 224: case 225: case 226:
00316 case 227: case 228: case 229: case 230: case 231: case 232: case 233:
00317 case 234: case 235: case 236: case 237: case 238: /* font selection commands */
00318          if (cmd < 235) fnt = cmd - 171 ; /* fntnum0 thru fntnum63 */
00319          else {
00320             fnt = dvibyte() ;
00321             while (cmd-- > 235)
00322                fnt = (fnt << 8) + dvibyte() ;
00323          }
00324          for (cfnt=ffont; cfnt; cfnt = cfnt->next)
00325             if (cfnt->fontnum == fnt) break ;
00326          curfnt = cfnt->desc ;
00327          for (bbcfnt=bbffont; bbcfnt; bbcfnt = bbcfnt->next)
00328             if (bbcfnt->fontnum == fnt) goto fontfound ;
00329          bbcfnt = (bbfontmaptype *)mymalloc(sizeof(bbfontmaptype)) ;
00330          bbcfnt->fontnum = fnt ;
00331          bbcfnt->next = bbffont ;
00332          bbffont = bbcfnt ;
00333          bbtfmload(curfnt) ;
00334 fontfound: bbcurfnt = bbcfnt->desc ;
00335          break ;
00336 case 243: case 244: case 245: case 246: /*fntdef1 */
00337          skipover(cmd - 230) ;
00338          skipover(dvibyte() + dvibyte()) ;
00339          break ;
00340 case 239: bbspecial(h, v, (int)dvibyte()) ; break ;
00341 case 240: bbspecial(h, v, (int)twobytes()) ; break ;
00342 case 241: bbspecial(h, v, (int)threebytes()) ; break ;
00343 case 242: bbspecial(h, v, (int)signedquad()) ; break ;
00344       }
00345    }
00346 }
00347 void findbb P1C(integer, bop)
00348 {
00349    integer curpos = ftell(dvifile) ;
00350    real conv = 72.0 * (real)num / (real)den * (real)mag / 254000000.0 ;
00351    real off = 72.0 / conv ;
00352    real margin = 1.0 / conv ;
00353    real vsize = 792.0 / conv ;
00354    real hadj = -72.0 * hoff / 4736286.72 ;
00355    real vadj = 72.0 * voff / 4736286.72 ;
00356 
00357    fseek(dvifile, bop, 0) ;
00358    bbdopage() ;
00359    fseek(dvifile, curpos, 0) ;
00360    lly = (int) (vsize - 2 * off - lly) ;
00361    ury = (int) (vsize - 2 * off - ury) ;
00362    llx = (int)floor((llx + off - margin) * conv - hadj + 0.5) ;
00363    lly = (int)floor((lly + off + margin) * conv - vadj + 0.5) ;
00364    urx = (int)floor((urx + off + margin) * conv - hadj + 0.5) ;
00365    ury = (int)floor((ury + off - margin) * conv - vadj + 0.5) ;
00366 /* no marks on the page? */
00367    if (llx >= urx || lly <= ury)
00368       llx = lly = urx = ury = 72 ;
00369 #ifdef SHORTINT
00370    sprintf(nextstring, "%ld %ld %ld %ld", llx, ury, urx, lly) ;
00371 #else
00372    sprintf(nextstring, "%d %d %d %d", llx, ury, urx, lly) ;
00373 #endif
00374 }