summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/dopage.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipsk/dopage.c')
-rw-r--r--Build/source/texk/dvipsk/dopage.c515
1 files changed, 515 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/dopage.c b/Build/source/texk/dvipsk/dopage.c
new file mode 100644
index 00000000000..5519b76e35f
--- /dev/null
+++ b/Build/source/texk/dvipsk/dopage.c
@@ -0,0 +1,515 @@
+/*
+ * Main page drawing procedure. Interprets the page commands. A simple
+ * (if lengthy) case statement interpreter.
+ */
+#include "dvips.h" /* The copyright notice in that file is included too! */
+#include <math.h>
+/*
+ * The external declarations:
+ */
+#include "protos_add.h"
+
+#if defined(XENIX) || defined(__THINK__)
+#define PixRound(x) ((integer)(x + (iconv >> 1)) / iconv)
+#define VPixRound(x) ((integer)(x + (viconv >> 1)) / viconv)
+#else
+#define PixRound(x) ((integer)(floor(((x) * conv) + 0.5)))
+#define VPixRound(x) ((integer)(floor(((x) * vconv) + 0.5)))
+#endif
+/*
+ * Now we have the dopage procedure.
+ * Most error checking is suppressed because the prescan has already
+ * verified that the DVI data is OK....except for stack over/underflow.
+ */
+struct dvistack stack[STACKSIZE];
+integer dir;
+#ifdef HPS
+integer hhmem, vvmem;
+integer pushcount = 0;
+Boolean PAGEUS_INTERUPPTUS = 0;
+Boolean NEED_NEW_BOX = 0;
+integer H_BREAK; /* An empirical parameter for guessing line breaks; needs
+ dpi dependence */
+#endif
+
+void
+dopage(void)
+{
+ register shalfword cmd;
+ register integer p;
+ register chardesctype *cd;
+ register integer h;
+ register fontmaptype *cfnt;
+ register frametype *frp = frames;
+ integer fnt;
+ integer mychar;
+ int charmove;
+ struct dvistack *sp = stack;
+ integer v, w, x, y, z;
+ integer roundpos;
+ integer thinspace;
+ integer vertsmallspace;
+#if defined(XENIX) || defined(__THINK__)
+ integer iconv;
+ integer viconv;
+
+ iconv = (integer)(1.0 / conv + 0.5);
+ viconv = (integer)(1.0 / vconv + 0.5);
+#endif
+#ifdef EMTEX
+ emclear();
+#endif
+ pageinit();
+
+ bopcolor(1);
+ thinspace = (integer)(0.025*DPI/conv); /* 0.025 inches */
+ vertsmallspace = (integer)(0.025*VDPI/vconv); /* 0.025 inches */
+#ifdef HPS
+ if (HPS_FLAG) pagecounter++;
+ H_BREAK = (30 * DPI / 400 ); /* 30 seems to have worked well at 400 dpi */
+#endif
+ w = x = y = z = dir = rdir = fdir = 0;
+ h = (integer) (DPI / conv * hoff / 4736286.72);
+ v = (integer) (DPI / conv * voff / 4736286.72);
+ hh = PixRound(h);
+ vv = PixRound(v);
+ curfnt = NULL;
+ curpos = NULL;
+ charmove = 0;
+beginloop:
+ switch (cmd=dvibyte()) {
+case 138: goto beginloop; /* nop command does nuttin */
+/*
+ * For put1 commands, we subtract the width of the character before
+ * dropping through to the normal character setting routines. This
+ */
+case 135: /* put3 */
+ if (noptex) error("! synch");
+ mychar = dvibyte();
+ mychar = (mychar << 8) + dvibyte();
+ mychar = (mychar << 8) + dvibyte();
+ charmove = 0;
+ goto dochar;
+case 130: /* set3 */
+ if (noptex) error("! synch");
+ mychar = dvibyte();
+ mychar = (mychar << 8) + dvibyte();
+ mychar = (mychar << 8) + dvibyte();
+ charmove = 1;
+ goto dochar;
+case 134: /* put2 */
+ if (noomega && noptex) error("! synch");
+ mychar = dvibyte();
+ mychar = (mychar << 8) + dvibyte();
+ charmove = 0;
+ goto dochar;
+case 129: /* set2 */
+ if (noomega && noptex) error("! synch");
+ mychar = dvibyte();
+ mychar = (mychar << 8) + dvibyte();
+ charmove = 1;
+ goto dochar;
+case 133: /* put1 */
+ mychar = dvibyte();
+ charmove = 0;
+ goto dochar;
+case 128: cmd = dvibyte(); /* set1 command drops through to setchar */
+default: /* these are commands 0 (setchar0) thru 127 (setchar127) */
+ mychar = cmd;
+ charmove = 1;
+dochar:
+#ifdef HPS
+ if (HPS_FLAG && PAGEUS_INTERUPPTUS) {
+ HREF_COUNT--;
+ start_new_box();
+ PAGEUS_INTERUPPTUS = 0;
+ }
+ if (HPS_FLAG && NEED_NEW_BOX) {
+ vertical_in_hps();
+ NEED_NEW_BOX = 0;
+ }
+#endif
+ if (mychar<curfnt->maxchars)
+ cd = &(curfnt->chardesc[mychar]);
+ if (!noptex && mychar<0x1000000 && curfnt->loaded == 2 && curfnt->kind == VF_PTEX) {
+ if (mychar>=curfnt->maxchars || !(cd->flags & EXISTS)) {
+ /* try fallback */
+#ifdef DEBUG
+ if (dd(D_FONTS))
+ fprintf_str(stderr,
+ "Fallback pTeX vf:%s char=%d(0x%06x) to %s\n",
+ curfnt->name, mychar, mychar, curfnt->localfonts->desc->name);
+#endif /* DEBUG */
+ cd = curfnt->localfonts->desc->chardesc;
+ if (charmove) {
+ if (!dir) {
+ sp->hh = hh + cd->pixelwidth;
+ sp->h = h + cd->TFMwidth;
+ } else {
+ sp->v = v + cd->TFMwidth;
+ sp->vv = PixRound(sp->v);
+ }
+ } else {
+ if (!dir) {
+ sp->hh = hh; sp->h = h;
+ } else {
+ sp->vv = vv; sp->v = v;
+ }
+ }
+ if (!dir) {
+ sp->vv = vv; sp->v = v;
+ } else {
+ sp->hh = hh; sp->h = h;
+ }
+ sp->w = w; sp->x = x; sp->y = y; sp->z = z; sp->dir = dir;
+ if (++sp >= &stack[STACKSIZE]) error("! Out of stack space");
+ w = x = y = z = 0; /* will be in relative units at new stack level */
+ frp->ff = ffont;
+ frp->curf = curfnt;
+ if (++frp == &frames[MAXFRAME] )
+ error("! virtual recursion stack overflow");
+ ffont = curfnt->localfonts;
+ if (ffont) {
+ curfnt = ffont->desc;
+ thinspace = curfnt->thinspace;
+ } else {
+ curfnt = NULL;
+ thinspace = vertsmallspace;
+ }
+ drawchar(cd, mychar);
+ goto end_of_vf;
+ }
+ }
+ if (cd->flags & EXISTS) {
+ if (curfnt->loaded == 2) { /* virtual character being typeset */
+ if (charmove) {
+ if (!dir) {
+ sp->hh = hh + cd->pixelwidth;
+ sp->h = h + cd->TFMwidth;
+ } else {
+ sp->v = v + cd->TFMwidth;
+ sp->vv = PixRound(sp->v);
+ }
+ } else {
+ if (!dir) {
+ sp->hh = hh; sp->h = h;
+ } else {
+ sp->vv = vv; sp->v = v;
+ }
+ }
+ if (!dir) {
+ sp->vv = vv; sp->v = v;
+ } else {
+ sp->hh = hh; sp->h = h;
+ }
+ sp->w = w; sp->x = x; sp->y = y; sp->z = z; sp->dir = dir;
+ if (++sp >= &stack[STACKSIZE]) error("! Out of stack space");
+ w = x = y = z = 0; /* will be in relative units at new stack level */
+ frp->curp = curpos;
+ frp->curl = curlim;
+ frp->ff = ffont;
+ frp->curf = curfnt;
+ if (++frp == &frames[MAXFRAME] )
+ error("! virtual recursion stack overflow");
+ curpos = cd->packptr + 2;
+ curlim = curpos + (256*(long)(*cd->packptr)+(*(cd->packptr+1)));
+ ffont = curfnt->localfonts;
+ if (ffont) {
+ curfnt = ffont->desc;
+ thinspace = curfnt->thinspace;
+ } else {
+ curfnt = NULL;
+ thinspace = vertsmallspace;
+ }
+ goto beginloop;
+ }
+ drawchar(cd, mychar);
+ }
+ if (charmove) {
+ if (!dir) {
+ h += cd->TFMwidth;
+ hh += cd->pixelwidth;
+ } else {
+ v += cd->TFMwidth;
+ vv += cd->pixelwidth;
+ }
+ }
+ goto setmotion;
+case 255: /* pTeX's dir or undefined */
+ if (!noptex) {
+ dir = dvibyte();
+ cmddir();
+ goto beginloop;
+ }
+/* illegal commands */
+case 131: case 136: case 139: /* set4, put4, bop */
+case 247: case 248: case 249: /* pre, post, post_post */
+case 250: case 251: case 252: case 253: case 254: /* undefined */
+ error("! synch");
+case 132: case 137: /* rules */
+ { integer ry, rx , rxx, ryy;
+ ry = signedquad(); rx = signedquad();
+ if (rx>0 && ry>0) {
+ if (curpos) {
+ rx = scalewidth(rx, (frp-1)->curf->scaledsize);
+ ry = scalewidth(ry, (frp-1)->curf->scaledsize);
+ }
+ if (!dir) {
+ rxx = (int)(conv * rx + 0.9999999);
+ ryy = (int)(vconv * ry + 0.9999999);
+ }
+ else {
+ rxx = (int)(vconv * rx + 0.9999999);
+ ryy = (int)(conv * ry + 0.9999999);
+ }
+ /* Heiko Oberdiek 2001/06/03: synchronisation added for vertical rules
+ because of alignment reasons.
+ */
+ if (ry > rx) {
+ hh = PixRound(h);
+ }
+ drawrule(rxx, ryy);
+ } else
+ rxx = 0;
+ if (cmd == 137) goto beginloop;
+ if (!dir) {
+ h += rx; hh += rxx;
+ }
+ else {
+ v += rx; vv += rxx;
+ }
+ goto setmotion;
+ }
+case 141: /* push */
+#ifdef HPS
+ if (HPS_FLAG) pushcount++;
+ /* if (HPS_FLAG && PAGEUS_INTERUPPTUS) {
+ HREF_COUNT--;
+ start_new_box();
+ PAGEUS_INTERUPPTUS = 0;
+ } */
+ if (HPS_FLAG && NEED_NEW_BOX) {
+ vertical_in_hps();
+ NEED_NEW_BOX = 0;
+ }
+ /* printf("push %i, %i\n", pushcount, inHTMLregion); */
+#endif
+ sp->hh = hh; sp->vv = vv; sp->h = h; sp->v = v;
+ sp->w = w; sp->x = x; sp->y = y; sp->z = z; sp->dir = dir;
+ if (++sp >= &stack[STACKSIZE]) error("! Out of stack space");
+ goto beginloop;
+case 140: /* eop or end of virtual character */
+ if (curpos == NULL) { /* eop */
+#ifdef HPS
+ if (HPS_FLAG && inHTMLregion) PAGEUS_INTERUPPTUS = 1;
+ /* printf("Page interrupted"); */
+#endif
+ break;
+ }
+end_of_vf:
+ --frp;
+ curfnt = frp->curf;
+ thinspace = (curfnt) ? curfnt->thinspace : vertsmallspace;
+ ffont = frp->ff;
+ curlim = frp->curl;
+ curpos = frp->curp;
+ if (hh < (sp-1)->hh+2 && hh > (sp-1)->hh-2)
+ (sp-1)->hh = hh; /* retain `intelligence' of pixel width, if close */
+ /* falls through */
+case 142: /* pop */
+#ifdef HPS
+ pushcount--;
+ /* printf("pop %i\n", pushcount); */
+#endif
+ if (--sp < stack) error("! More pops than pushes");
+#ifdef HPS
+ if (HPS_FLAG) {
+ hhmem = hh; vvmem = vv;
+ }
+#endif
+ hh = sp->hh; vv = sp->vv; h = sp->h; v = sp->v;
+ w = sp->w; x = sp->x; y = sp->y; z = sp->z; dir = sp->dir;
+#ifdef HPS
+ if (HPS_FLAG && inHTMLregion && (hhmem - hh > H_BREAK) && (pushcount > 0) &&
+ (pushcount < current_pushcount))
+ end_current_box();
+#endif
+ cmddir();
+ goto beginloop;
+case 143: /* right1 */
+ p = signedbyte(); goto horizontalmotion;
+case 144: /* right2 */
+ p = signedpair(); goto horizontalmotion;
+case 145: /* right3 */
+ p = signedtrio(); goto horizontalmotion;
+case 146: /* right4 */
+ p = signedquad(); goto horizontalmotion;
+case 147: /* w0 */
+ p = w; goto horizontalmotion;
+case 148: /* w1 */
+ p = w = signedbyte(); goto horizontalmotion;
+case 149: /* w2 */
+ p = w = signedpair(); goto horizontalmotion;
+case 150: /* w3 */
+ p = w = signedtrio(); goto horizontalmotion;
+case 151: /* w4 */
+ p = w = signedquad(); goto horizontalmotion;
+case 152: /* x0 */
+ p = x; goto horizontalmotion;
+case 153: /* x1 */
+ p = x = signedbyte(); goto horizontalmotion;
+case 154: /* x2 */
+ p = x = signedpair(); goto horizontalmotion;
+case 155: /* x3 */
+ p = x = signedtrio(); goto horizontalmotion;
+case 156: /* x4 */
+ p = x = signedquad(); goto horizontalmotion;
+case 157: /* down1 */
+ p = signedbyte(); goto verticalmotion;
+case 158: /* down2 */
+ p = signedpair(); goto verticalmotion;
+case 159: /* down3 */
+ p = signedtrio(); goto verticalmotion;
+case 160: /* down4 */
+ p = signedquad(); goto verticalmotion;
+case 161: /* y0 */
+ p = y; goto verticalmotion;
+case 162: /* y1 */
+ p = y = signedbyte(); goto verticalmotion;
+case 163: /* y2 */
+ p = y = signedpair(); goto verticalmotion;
+case 164: /* y3 */
+ p = y = signedtrio(); goto verticalmotion;
+case 165: /* y4 */
+ p = y = signedquad(); goto verticalmotion;
+case 166: /* z0 */
+ p = z; goto verticalmotion;
+case 167: /* z1 */
+ p = z = signedbyte(); goto verticalmotion;
+case 168: /* z2 */
+ p = z = signedpair(); goto verticalmotion;
+case 169: /* z3 */
+ p = z = signedtrio(); goto verticalmotion;
+case 170: /* z4 */
+ p = z = signedquad(); goto verticalmotion;
+case 171: case 172: case 173: case 174: case 175: case 176: case 177:
+case 178: case 179: case 180: case 181: case 182: case 183: case 184:
+case 185: case 186: case 187: case 188: case 189: case 190: case 191:
+case 192: case 193: case 194: case 195: case 196: case 197: case 198:
+case 199: case 200: case 201: case 202: case 203: case 204: case 205:
+case 206: case 207: case 208: case 209: case 210: case 211: case 212:
+case 213: case 214: case 215: case 216: case 217: case 218: case 219:
+case 220: case 221: case 222: case 223: case 224: case 225: case 226:
+case 227: case 228: case 229: case 230: case 231: case 232: case 233:
+case 234: case 235: case 236: case 237: case 238: /* font selection commands */
+ if (cmd < 235) fnt = cmd - 171; /* fntnum0 thru fntnum63 */
+ else {
+ fnt = dvibyte();
+ while (cmd-- > 235)
+ fnt = (fnt << 8) + dvibyte();
+ }
+ for (cfnt=ffont; cfnt; cfnt = cfnt->next)
+ if (cfnt->fontnum == fnt) break;
+ curfnt = cfnt->desc;
+ thinspace = curfnt->thinspace;
+ goto beginloop;
+case 243: case 244: case 245: case 246: /*fntdef1 */
+ skipover(cmd - 230);
+ skipover(dvibyte() + dvibyte());
+ goto beginloop;
+case 239: /* xxx1 */
+ p = dvibyte();
+ dospecial(p);
+ goto beginloop;
+case 240: /* xxx2 */
+ p = twobytes();
+ dospecial(p);
+ goto beginloop;
+case 241: /* xxx3 */
+ p = threebytes();
+ dospecial(p);
+ goto beginloop;
+case 242: /* xxx4 */
+ p = signedquad();
+ dospecial(p);
+ goto beginloop;
+
+/*
+ * The calculations here are crucial to the appearance of the document.
+ * If the motion is small, we round the amount of relative motion; otherwise,
+ * we update the position and round the new position. Then we check to
+ * insure that the rounded position didn't accumulate an error that was
+ * greater than maxdrift.
+ */
+verticalmotion:
+/* vertical motion cases */
+ if (curpos)
+ p = scalewidth(p, (frp-1)->curf->scaledsize);
+ if (!dir) {
+ v += p;
+ if (p >= vertsmallspace) vv = VPixRound(v);
+ else if (p <= -vertsmallspace) vv = VPixRound(v);
+ else
+ { vv += VPixRound(p);
+ roundpos = VPixRound(v);
+ if (roundpos - vv > vmaxdrift) vv = roundpos - vmaxdrift;
+ else if (vv - roundpos > vmaxdrift) vv = roundpos + vmaxdrift;
+ }
+ } else {
+ h -= p;
+ if (p >= vertsmallspace) hh = VPixRound(h);
+ else if (p <= -vertsmallspace) hh = VPixRound(h);
+ else
+ { hh -= VPixRound(p);
+ roundpos = VPixRound(h);
+ if (roundpos - hh > vmaxdrift) hh = roundpos - vmaxdrift;
+ else if (hh - roundpos > vmaxdrift) hh = roundpos + vmaxdrift;
+ }
+ }
+#ifdef HPS
+ /* printf("Doing vertical motion: p = %i, v = %i, vv = %i\n",p,v,vv); */
+ /* printf("inHTMLregion %i\n", inHTMLregion); */
+ if (HPS_FLAG && inHTMLregion) NEED_NEW_BOX = 1 /* vertical_in_hps() */;
+#endif
+ goto beginloop;
+/*
+ * Horizontal motion is analogous. We know the exact width of each
+ * character in pixels. Kerning is distinguished from space between
+ * words if it's less than a thinspace and not more negative than would
+ * occur when an accent is being positioned by backspacing.
+ */
+horizontalmotion:
+/* horizontal motion cases */
+ if (curpos)
+ p = scalewidth(p, (frp-1)->curf->scaledsize);
+ if (!dir) {
+ h += p;
+ if (p >= thinspace || p <= -6 * thinspace) {
+ hh = PixRound(h); goto beginloop;
+ }
+ else hh += PixRound(p);
+ } else {
+ v += p;
+ if (p >= thinspace || p <= -6 * thinspace) {
+ vv = PixRound(v); goto beginloop;
+ }
+ else vv += PixRound(p);
+ }
+#ifdef HPS
+ /* printf("Doing horizontal motion: p = %i, h = %i, hh = %i\n",p,h,hh); */
+#endif
+setmotion:
+ if (!dir) {
+ roundpos = PixRound(h);
+ if (roundpos - hh > maxdrift) { hh = roundpos - maxdrift; }
+ else if (hh - roundpos > maxdrift) { hh = roundpos + maxdrift; }
+ } else {
+ roundpos = PixRound(v);
+ if (roundpos - vv > maxdrift) { vv = roundpos - maxdrift; }
+ else if (vv - roundpos > maxdrift) { vv = roundpos + maxdrift; }
+ }
+goto beginloop;
+
+ } /* end of the big switch */
+ pageend();
+}