#include "defs.h" #include "globals.h" static ScaledPts dviBBlx, dviBBrx; /* Bounding box of figure in DVI space */ static ScaledPts dviBBby, dviBBty; static int32 prevfont; /* * to keep track of prev font before the PUSH and expansion of the special */ static int32 ourpushdepth = 0; /* depth of internal pushes */ static int32 origTexfont = -1; /* number of TeX font in use before tyling */ static void IPUSH() { if (ourpushdepth == 0) /* first push --> start tyling */ origTexfont = font[curfont].num; else prevfont = ourfontnum; /* store the internal font number in use at this time */ cmd1byte(NOP); cmd1byte(NOP); /* our greeting */ cmd1byte(PUSH); ourpushdepth++; } static void IPOP() { cmd1byte(POP); cmd1byte(NOP); cmd1byte(NOP); /* our signature */ ourpushdepth--; if (ourpushdepth < 0) { complain(ERRREALBAD); fprintf(logfile, "Error: too many internal pops\n"); } if (ourpushdepth == 0) { /* we are totally done with tyling for now */ if (nf > 0) /* only if it is valid */ isetfont(origTexfont); } else { if (prevfont >= 0) /* restore that internal font previously in use */ isetfont(prevfont); } } char * xmalloc(size) unsigned int size; { char *p; char *malloc PP((unsigned)); void exit PP((int)); if ((p = malloc(size)) == 0) { fprintf(stderr, "Out of memory!\n"); exit(1); } return (p); } /*---------------------------------------------*/ Item * NewItem(what) int what; { Item *i; Figure *f; if ((i = (Item *) xmalloc(sizeof(Item))) == 0) i->nextitem = NULL; i->BBlx = 0; i->BBby = 0; i->BBrx = 0; i->BBty = 0; i->itemthick = LoVThick; i->itemvec = (unsigned) VKCirc; i->itempatt = (unsigned) solid; i->kind = what; switch (what) { /* give defaults */ case Aline: /* blank case */ break; case Aspline: i->UU.U2.nsplknots = 0; i->UU.U2.dosmarks = 0; i->UU.U2.sclosed = false; i->UU.U2.spltype = (unsigned) BSPL; break; case Attspline: i->UU.U3.nttknots = 0; i->UU.U3.dottmarks = 0; i->UU.U3.tspltype = (unsigned) BSPL; i->UU.U3.tclosed = false; break; case Abeam: /* blank case */ break; case Atieslur: i->UU.U5.ntknots = 0; break; case Aarc: i->UU.U6.narcknots = 0; break; case Alabel: i->UU.U7.fontstyle = -1; /* undefined */ i->UU.U7.labeltext[0] = '\0'; break; case Afigure: i->UU.U8.figtheta = 0.0; i->UU.U8.fsx = 1.0; i->UU.U8.fsy = 1.0; i->UU.U8.fdx = 0; i->UU.U8.fdy = 0; i->UU.U8.preWid = 0; i->UU.U8.preHt = 0; i->UU.U8.postWid = 0; i->UU.U8.postHt = 0; i->UU.U8.depthnumber = 0; /* for now */ f = (Figure *) xmalloc(sizeof(Figure)); /* a new figure */ i->UU.U8.body = f; i->UU.U8.body->things = NULL; break; } /* case */ /* with */ return i; } /* NewItem */ /*-----------------------------------------------------*/ static void TylBeam(fromx, fromy, tox, toy, staffsize, kind) int32 fromx, fromy, tox, toy, staffsize; BeamKind kind; { /* * fromx, fromy, tox, toy: ScaledPts; staffsize : integer; kind : BeamKind */ } /* TylBeam */ /* Local variables for TylLine: */ struct LOC_TylLine { VThickness thickness; }; /*-------------------------------------------------------*/ static void TylLine(xl, yb, xr, yt, thickness_, vec, patt) int32 xl, yb, xr, yt; VThickness thickness_; VectKind vec; LineStyle patt; { /* * xl, yb, xr, yt: ScaledPoints; thickness: VThickness; vec: VectKind; patt : LineStyle */ struct LOC_TylLine V; VecIndex findex; V.thickness = thickness_; /* * p2c: x.p, line 6596: Note: Taking & of possibly promoted param thickness [324] */ clampthickness(&V.thickness); findex = GetVectFont(V.thickness, vec); layline(xl, yb, xr, yt, findex, patt, false); } /*-----------------------------------------------------*/ static void TylThickThinSpline(thetype, isclosed, KnotArray, ThikThinAry, numknots, vec, patt, domarks) SplineKind thetype; int isclosed; int32(*KnotArray)[2]; VThickness *ThikThinAry; int32 numknots; VectKind vec; LineStyle patt; int32 domarks; { /* * thetype : SplineKind; isclosed : boolean; var KnotArray: ControlPoints; var ThikThinAry: ThickAryType; numknots: * integer; vec: VectKind; patt : LineStyle; domarks : integer */ layNspline(thetype, isclosed, false, domarks, KnotArray, numknots, ThikThinAry, vec, patt); } /*----------------------------------------------------*/ static void TylSpline(thetype, isclosed, KnotArray, numknots, thick, vec, patt, domarks) SplineKind thetype; int isclosed; int32(*KnotArray)[2]; int32 numknots; VThickness thick; VectKind vec; LineStyle patt; int32 domarks; { /* * thetype : SplineKind; isclosed : boolean; var KnotArray: ControlPoints; numknots: integer; thick: VThickness; vec: * VectKind; patt : LineStyle; domarks : integer */ layAspline(thetype, isclosed, false, domarks, KnotArray, numknots, thick, vec, patt); } #define ItsASlur true #define NotClosed false /* Local variables for TylTieSlur: */ struct LOC_TylTieSlur { VThickness minthick, maxthick; }; /*-----------------------------------------------------*/ static void TylTieSlur(KnotArray, numknots, minthick_, maxthick_) int32(*KnotArray)[2]; int32 numknots; VThickness minthick_, maxthick_; { /* * KnotArray: ControlPoints; numknots: integer; minthick, maxthick: VThickness */ struct LOC_TylTieSlur V; ThickAryType ourttarray; double one7th; VThickness val; V.minthick = minthick_; V.maxthick = maxthick_; /* * p2c: x.p, line 6636: Note: Taking & of possibly promoted param minthick [324] */ clampthickness(&V.minthick); /* * p2c: x.p, line 6637: Note: Taking & of possibly promoted param maxthick [324] */ clampthickness(&V.maxthick); if (numknots != 5) fprintf(logfile, "TieSlur needs 5 control points\n"); one7th = 1.0 / 7.0; val = (int32) floor(one7th * (V.maxthick - V.minthick) + 0.5); ourttarray[1] = V.minthick; ourttarray[2] = V.minthick + val; ourttarray[3] = V.maxthick; ourttarray[4] = V.minthick + val; ourttarray[5] = V.minthick; layNspline(CATROM, NotClosed, ItsASlur, 0, KnotArray, numknots, ourttarray, VKCirc, solid); } #undef ItsASlur #undef NotClosed #define ItsAnArc true /*-------------------------------------------------------*/ static void doTylArc(iscircle, apts, numknots, thick, vec, patt) int iscircle; int32(*apts)[2]; int32 numknots; VThickness thick; VectKind vec; LineStyle patt; { /* * iscircle : boolean; var apts : ControlPoints; numknots : integer; thick : VThickness; vec : VectKind; patt : * LineStyle */ layAspline(BSPL, iscircle, ItsAnArc, 0, apts, numknots, thick, vec, patt); } #undef ItsAnArc /*-----------------------------------------------------------*/ static void TylArc(radius, centx, centy, firstangle, secondangle, thick, vec, patt) int32 radius, centx, centy, firstangle, secondangle; VThickness thick; VectKind vec; LineStyle patt; { /* * radius : ScaledPts; centx, centy : ScaledPts; firstangle, secondangle : integer; thick : VThickness; vec : VectKind; * patt : LineStyle */ ControlPoints apts; int32 numknots; int iscircle; iscircle = (firstangle == secondangle); if (iscircle) { /* * maxspan := round ((360.0 / 16.0) * DEGTORAD * radius); { */ defineCircleCpts(radius, centx, centy, apts, &numknots); } else { /* * maxspan := round ((abs (secondangle - firstangle) / 16.0) * DEGTORAD * radius); { */ definearcpts(radius, centx, centy, firstangle, secondangle, apts, &numknots); } doTylArc(iscircle, apts, numknots, thick, vec, patt); } /*-----------------------------------------------------------*/ static void TylLabel(xpos, ypos, fontstyle, phrase, phraselen) int32 xpos, ypos, fontstyle; char *phrase; int32 phraselen; { /* * xpos, ypos : ScaledPts; fontstyle : integer; phrase : charstring; phraselen : integer */ int32 findex, c, spaceover; if (fontstyle < 1 || fontstyle > MAXLABELFONTS) { complain(ERRREALBAD); fprintf(logfile, "Unexpected bad fontstyle in TylLabel: %d?\n", fontstyle); jumpout(); } findex = GetLabFont(fontstyle); isetpos(xpos, ypos); IPUSH(); isetfont(LFontTable[findex - 1]->DVIFontNum); spaceover = LFontTable[findex - 1]->spacewidth; for (c = 0; c < phraselen; c++) { if (phrase[c] != ' ') { cmd1byte(SET1); cmd1byte(phrase[c]); } else { /* move over */ cmd1byte(RIGHTLEFT + 2); /* assume distance is less than 3 bytes */ cmdSigned(spaceover, 3); } } IPOP(); } /* &&module TeXtyl */ /*----------------------------------------------------------------*/ /* rotate a (x,y) point about mx, my */ static void ptrotate(x, y, mx, my, angle) int32 *x, *y, mx, my; double angle; { int32 tmpx, tmpy; double cosa, sina; tmpx = *x - mx; tmpy = *y - my; cosa = cos(angle * DEGTORAD); sina = sin(angle * DEGTORAD); *x = (int32) floor(tmpx * cosa - tmpy * sina + 0.5) + mx; *y = (int32) floor(tmpx * sina + tmpy * cosa + 0.5) + my; } /*----------------------------------------------------------------*/ /* * transform two line points: scale, rotate and translate */ static void xfmlinepts(x1, y1, x2, y2, offh, offv, midx, midy, scalefact, theta, dx, dy, sx, sy) int32 *x1, *y1, *x2, *y2, offh, offv, midx, midy; double scalefact, theta; int32 dx, dy; double sx, sy; { if (sx == 0.0 || sy == 0.0) { complain(ERRBAD); fprintf(logfile, "?? Some scale factor is Zero... continuing anyway\n"); } /* scale about center of item */ if (sx != 1.0 || sy != 1.0) { *x1 = (int32) floor((*x1 - midx) * sx + 0.5) + midx; *x2 = (int32) floor((*x2 - midx) * sx + 0.5) + midx; *y1 = (int32) floor((*y1 - midy) * sy + 0.5) + midy; *y2 = (int32) floor((*y2 - midy) * sy + 0.5) + midy; } /* rotate if necessary */ if (theta != 0.0) { /* rotate about the midpoint */ ptrotate(x1, y1, midx, midy, theta); ptrotate(x2, y2, midx, midy, theta); } /* translate */ *x1 += (int32) floor(dx * scalefact + 0.5) + offh; *x2 += (int32) floor(dx * scalefact + 0.5) + offh; *y1 += (int32) floor(dy * scalefact + 0.5) + offv; *y2 += (int32) floor(dy * scalefact + 0.5) + offv; } /* xfmlinepts */ /*----------------------------------------------------------------*/ static void xfmcontpts(xpts, xknots, offh, offv, midx, midy, scalefact, theta, dx, dy, sx, sy) int32(*xpts)[2]; int32 xknots, offh, offv, midx, midy; double scalefact, theta; int32 dx, dy; double sx, sy; { int32 i; /* scale about center of item */ if (sx != 1.0 || sy != 1.0) { for (i = 0; i <= xknots; i++) { xpts[i][0] = (int32) floor((xpts[i][0] - midx) * sx + 0.5) + midx; xpts[i][1] = (int32) floor((xpts[i][1] - midy) * sy + 0.5) + midy; } } if (theta != 0.0) { /* rotate about center */ for (i = 0; i <= xknots; i++) ptrotate(xpts[i], &xpts[i][1], midx, midy, theta); } /* translate */ for (i = 0; i <= xknots; i++) { xpts[i][0] += (int32) floor(dx * scalefact + 0.5) + offh; xpts[i][1] += (int32) floor(dy * scalefact + 0.5) + offv; } } /* xfmcontpts */ /*----------------------------------------------------------------*/ /* convert into DVI space and offset by H & V */ static void dvilinepts(x1, y1, x2, y2, offh, offv) int32 *x1, *y1, *x2, *y2, offh, offv; { *x1 += offh; *x2 += offh; *y1 = offv - *y1; *y2 = offv - *y2; } /*----------------------------------------------------------------*/ /* convert into DVI space and offset by H & V */ static void dvicontpts(xpts, xknots, offh, offv) int32(*xpts)[2]; int32 xknots, offh, offv; { int32 i; for (i = 0; i <= xknots; i++) { xpts[i][0] += offh; xpts[i][1] = offv - xpts[i][1]; } } /*----------------------------------------------------------------*/ /* * transform all the figure's elements according to the top-level tranformation requirements in 1st Quadrant space. then reset * the toplevel's xfms. */ static void toplevelxfm(toplev, curfig, recurlevel) Item *toplev, *curfig; int32 recurlevel; { Item *pi; ScaledPts null1, null2, old1, old2, midx, midy; midy = (toplev->BBty - toplev->BBby) / 2; midx = (toplev->BBrx - toplev->BBlx) / 2; pi = curfig->UU.U8.body->things; /* if recur==0, this is same as toplev */ while (pi != NULL) { switch (pi->kind) { /* with */ case Aline: xfmlinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2, &pi->UU.U1.ly2, 0, 0, midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy); break; case Aspline: xfmcontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, 0, 0, midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy); break; case Attspline: xfmcontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, 0, 0, midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy); break; case Aarc: null1 = 0; null2 = 0; old1 = pi->UU.U6.acentx; old2 = pi->UU.U6.acenty; xfmlinepts(&pi->UU.U6.acentx, &pi->UU.U6.acenty, &null1, &null2, 0, 0, midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy); xfmcontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, 0, 0, old1, old2, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx + pi->UU.U6.acentx - old1, toplev->UU.U8.fdy + pi->UU.U6.acenty - old2, toplev->UU.U8.fsx, toplev->UU.U8.fsy); break; case Alabel: null1 = 0; null2 = 0; xfmlinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, 0, 0, midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy); break; case Abeam: /* not transformable */ break; case Atieslur: /* not transformable */ break; case Afigure: toplevelxfm(toplev, pi, recurlevel + 1); break; } /* case */ pi = pi->nextitem; } /* while */ if (recurlevel != 0) /* reset the toplevel's xfms */ return; toplev->UU.U8.figtheta = 0.0; toplev->UU.U8.fsx = 1.0; toplev->UU.U8.fsy = 1.0; toplev->UU.U8.fdx = 0; toplev->UU.U8.fdy = 0; } /*----------------------------------------------------------------*/ static double scalefitfactor(actualwid, actualht, goalwid, goalht) int32 actualwid, actualht, goalwid, goalht; { double sx, sy; sx = (double) goalwid / actualwid; sy = (double) goalht / actualht; if (sx < sy) return sx; else return sy; } /* * ---- The handlers for each primitive ---- The result of calling each handler is either immediate output to the buffer of the * commands to produce the primitive, OR the primitive gets pushed onto a stack/list that defines a current 'figure' (set of * prims) for output at a later time * * Look at linehandle for a basic idea of how the handlers work. the others follow pretty closely. */ /*------------------------------------------------------------*/ void linehandle(figdepth, scalefact, x1, y1, x2, y2, dvih, dviv, thk, vk, patt, minx, maxx, miny, maxy, tx, ty, sx, sy, r) int32 figdepth; double scalefact; int32 x1, y1, x2, y2, dvih, dviv; VThickness thk; VectKind vk; LineStyle patt; int32 minx, maxx, miny, maxy, tx, ty; double sx, sy, r; { /* possible dvi-offsets */ ScaledPts midx, midy; Item *lineitem; midx = (minx + maxx) / 2; midy = (miny + maxy) / 2; /* do local primitive -level transformations */ xfmlinepts(&x1, &y1, &x2, &y2, dvih, dviv, midx, midy, scalefact, r, tx, ty, sx, sy); if (figdepth == 0) { /* ---- do the primitive by itself */ /* re-transform it to the 4th Quadrant */ dvilinepts(&x1, &y1, &x2, &y2, h, v); /* global h and v posit */ IPUSH(); TylLine(x1, y1, x2, y2, thk, vk, patt); IPOP(); return; } if (figdepth <= 0) { /* ---- Pack it and stack it */ if (figdepth < 0) { /* ---- just do it right away without any PUSH/POP pair */ /* * this is the case when we are unpacking a figure for immediate output */ TylLine(x1, y1, x2, y2, thk, vk, patt); } return; } lineitem = NewItem(Aline); lineitem->BBlx = minx; lineitem->BBby = miny; lineitem->BBrx = maxx; lineitem->BBty = maxy; lineitem->UU.U1.lx1 = x1; lineitem->UU.U1.ly1 = y1; lineitem->UU.U1.lx2 = x2; lineitem->UU.U1.ly2 = y2; lineitem->itemthick = thk; lineitem->itemvec = (unsigned) vk; lineitem->itempatt = (unsigned) patt; pushItem(figdepth, lineitem); } /* linehandle */ /* --- Simple Splines ----- */ /*-----------------------------------------------------*/ void splinehandle(figdepth, scalefact, thetype, isclosed, markdiam, contpts, nknots, dvih, dviv, thk, vec, patt, minx, maxx, miny, maxy, tx, ty, sx, sy, r) int32 figdepth; double scalefact; SplineKind thetype; int isclosed; int32 markdiam; int32(*contpts)[2]; int32 nknots, dvih, dviv; VThickness thk; VectKind vec; LineStyle patt; int32 minx, maxx, miny, maxy, tx, ty; double sx, sy, r; { /* possible dvi-offsets */ ScaledPts midx, midy; Item *splineitem; int32 i; midx = (minx + maxx) / 2; midy = (miny + maxy) / 2; xfmcontpts(contpts, nknots, dvih, dviv, midx, midy, scalefact, r, tx, ty, sx, sy); if (figdepth == 0) { /* ---- do the primitive */ /* transform to 4th quad */ dvicontpts(contpts, nknots, h, v); IPUSH(); TylSpline(thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam); IPOP(); return; } if (figdepth <= 0) { if (figdepth < 0) TylSpline(thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam); return; } splineitem = NewItem(Aspline); splineitem->BBlx = minx; splineitem->BBby = miny; splineitem->BBrx = maxx; splineitem->BBty = maxy; splineitem->itemthick = thk; splineitem->itemvec = (unsigned) vec; splineitem->itempatt = (unsigned) patt; splineitem->UU.U2.nsplknots = nknots; splineitem->UU.U2.spltype = (unsigned) thetype; splineitem->UU.U2.sclosed = isclosed; splineitem->UU.U2.dosmarks = markdiam; for (i = 1; i <= nknots; i++) { splineitem->UU.U2.spts[i][0] = contpts[i][0]; splineitem->UU.U2.spts[i][1] = contpts[i][1]; } pushItem(figdepth, splineitem); } /* splinehandle */ /* --- Variable thickness splines ----- */ /*-----------------------------------------------------*/ void ttsplhandle(figdepth, scalefact, thetype, isclosed, markdiam, contpts_, ttks_, nknots, dvih, dviv, vec, patt, minx, maxx, miny, maxy, tx, ty, sx, sy, r) int32 figdepth; double scalefact; SplineKind thetype; int isclosed; int32 markdiam; int32(*contpts_)[2]; VThickness *ttks_; int32 nknots, dvih, dviv; VectKind vec; LineStyle patt; int32 minx, maxx, miny, maxy, tx, ty; double sx, sy, r; { /* possible dvi-offsets */ ControlPoints contpts; ThickAryType ttks; ScaledPts midx, midy; Item *ttsplitem; int32 i; char *memcpy PP((char *, char *, int)); (void) memcpy((char *)contpts, (char *)contpts_, sizeof(ControlPoints)); (void) memcpy((char *)ttks, (char *)ttks_, sizeof(ThickAryType)); midx = (minx + maxx) / 2; midy = (miny + maxy) / 2; xfmcontpts(contpts, nknots, dvih, dviv, midx, midy, scalefact, r, tx, ty, sx, sy); if (figdepth == 0) { /* transform to 4th quad */ dvicontpts(contpts, nknots, h, v); IPUSH(); TylThickThinSpline(thetype, isclosed, contpts, ttks, nknots, vec, patt, markdiam); IPOP(); return; } if (figdepth <= 0) { if (figdepth < 0) TylThickThinSpline(thetype, isclosed, contpts, ttks, nknots, vec, patt, markdiam); return; } ttsplitem = NewItem(Attspline); ttsplitem->BBlx = minx; ttsplitem->BBby = miny; ttsplitem->BBrx = maxx; ttsplitem->BBty = maxy; ttsplitem->itemvec = (unsigned) vec; ttsplitem->itempatt = (unsigned) patt; ttsplitem->UU.U3.nttknots = nknots; ttsplitem->UU.U3.tspltype = (unsigned) thetype; ttsplitem->UU.U3.dottmarks = markdiam; ttsplitem->UU.U3.tclosed = isclosed; for (i = 1; i <= nknots; i++) { /* ttsplitem */ ttsplitem->UU.U3.ttpts[i][0] = contpts[i][0]; ttsplitem->UU.U3.ttpts[i][1] = contpts[i][1]; ttsplitem->UU.U3.ttarry[i] = ttks[i]; } pushItem(figdepth, ttsplitem); } /* ttsplhandle */ /* ---- Musical Beams ---- */ /*-----------------------------------------------------*/ void beamhandle(depth, siz, bk, x1, y1, x2, y2) int32 depth, siz; BeamKind bk; int32 x1, y1, x2, y2; { Item *bmitem; if (depth == 0) { dvilinepts(&x1, &y1, &x2, &y2, h, v); IPUSH(); TylBeam(x1, y1, x2, y2, siz, bk); IPOP(); return; } if (depth <= 0) { if (depth < 0) { TylBeam(x1, y1, x2, y2, siz, bk); } /* else */ return; } bmitem = NewItem(Abeam); bmitem->BBlx = min(x1, x2); bmitem->BBby = min(y1, y2); bmitem->BBrx = max(x1, x2); bmitem->BBty = max(y1, y2); bmitem->UU.U4.bx1 = x1; bmitem->UU.U4.by1 = y1; bmitem->UU.U4.bx2 = x2; bmitem->UU.U4.by2 = y2; bmitem->UU.U4.staf = siz; bmitem->UU.U4.bkind = (unsigned) bk; /* with */ pushItem(depth, bmitem); } /* beamhandle */ /* ---- Musical Ties and Slurs ----- */ /*-----------------------------------------------------*/ void tieslurhandle(depth, pts_, numk, minthick, maxthick) int32 depth; int32(*pts_)[2]; int32 numk; VThickness minthick, maxthick; { ControlPoints pts; Item *tsitem; int32 i; char *memcpy PP((char *, char *, int)); (void) memcpy((char *)pts, (char *)pts_, sizeof(ControlPoints)); if (depth == 0) { dvicontpts(pts, numk, h, v); IPUSH(); TylTieSlur(pts, numk, minthick, maxthick); IPOP(); return; } if (depth <= 0) { if (depth < 0) { TylTieSlur(pts, numk, minthick, maxthick); } /* else */ return; } tsitem = NewItem(Atieslur); tsitem->UU.U5.ntknots = numk; for (i = 1; i <= numk; i++) { tsitem->UU.U5.tspts[i][0] = pts[i][0]; tsitem->UU.U5.tspts[i][1] = pts[i][1]; } tsitem->UU.U5.minth = minthick; tsitem->UU.U5.maxth = maxthick; /* with */ pushItem(depth, tsitem); } /* tieslurhandle */ /*---------------------------------------------------------*/ void arccirclehandle(figdepth, scalefact, cx, cy, radius, ang1, ang2, contpts, nknots, dvih, dviv, thk, vec, patt, minx, maxx, miny, maxy, tx, ty, sx, sy, r) int32 figdepth; double scalefact; int32 cx, cy, radius, ang1, ang2; int32(*contpts)[2]; int32 nknots, dvih, dviv; VThickness thk; VectKind vec; LineStyle patt; int32 minx, maxx, miny, maxy, tx, ty; double sx, sy, r; { /* IN */ /* possible dvi-offsets */ ScaledPts midx, midy; Item *arcitem; int32 i; int isclosedarc; midx = cx; midy = cy; isclosedarc = (ang1 == ang2); /* * if (isclosedarc) then maxspanlen := round ((360.0 / 16.0) * DEGTORAD * radius) else maxspanlen := round ((abs(ang2 - * ang1) / 16.0) * DEGTORAD * radius); { */ xfmcontpts(contpts, nknots + 1, dvih, dviv, midx, midy, scalefact, r, tx, ty, sx, sy); if (figdepth == 0) { /* ---- just do the primitive */ /* transform to 4th quad */ dvicontpts(contpts, nknots + 1, h, v); IPUSH(); doTylArc(isclosedarc, contpts, nknots, thk, vec, patt); IPOP(); return; } if (figdepth <= 0) { if (figdepth < 0) doTylArc(isclosedarc, contpts, nknots, thk, vec, patt); return; } arcitem = NewItem(Aarc); arcitem->BBlx = minx; arcitem->BBby = miny; arcitem->BBrx = maxx; arcitem->BBty = maxy; arcitem->itemthick = thk; arcitem->itemvec = (unsigned) vec; arcitem->itempatt = (unsigned) patt; arcitem->UU.U6.narcknots = nknots; arcitem->UU.U6.acentx = cx; arcitem->UU.U6.acenty = cy; arcitem->UU.U6.aradius = radius; arcitem->UU.U6.firstang = ang1; arcitem->UU.U6.lastang = ang2; for (i = 0; i <= nknots + 1; i++) { arcitem->UU.U6.arcpts[i][0] = contpts[i][0]; arcitem->UU.U6.arcpts[i][1] = contpts[i][1]; } pushItem(figdepth, arcitem); } /* arccirclehandle */ /*---------------------------------------------------------*/ void labelhandle(depth, scalefact, lax, lay, dvih, dviv, style, phrase, tx, ty) int32 depth; double scalefact; int32 lax, lay, dvih, dviv, style; charstring phrase; int32 tx, ty; { /* possible dvi-offsets */ Item *labitem; ScaledPts null1, null2; /* xfm the label point if necessary */ lax += (int32) floor(tx * scalefact + 0.5); lay += (int32) floor(ty * scalefact + 0.5); if (depth == 0) { null1 = 0; null2 = 0; dvilinepts(&lax, &lay, &null1, &null2, h, v); IPUSH(); TylLabel(lax, lay, style, phrase, strlen(phrase)); IPOP(); return; } if (depth <= 0) { if (depth < 0) TylLabel(lax, lay, style, phrase, strlen(phrase)); return; } labitem = NewItem(Alabel); labitem->UU.U7.labx = lax; labitem->UU.U7.laby = lay; labitem->UU.U7.fontstyle = style; strcpy(labitem->UU.U7.labeltext, phrase); pushItem(depth, labitem); } /* * #### Insert new handlers here for new "primitives" i.e., names callable from the \special[tyl ...] level */ /*----------------------------------------------------------------*/ /* transform the current bbox coordinates, and output the new one */ static void newbbox(minx, maxx, miny, maxy, midx, midy, sx, sy, rot, tx, ty) int32 *minx, *maxx, *miny, *maxy, midx, midy; double sx, sy, rot; int32 tx, ty; { /* coords of full bbox for transformation [n/s][e/w][x/y] */ ScaledPts nex, ney, sex, sey, swx, swy, nwx, nwy; int32 temp1, temp2; /* describe and transform the bbox */ nwx = (int32) floor(*minx * sx + 0.5); nex = (int32) floor(*maxx * sx + 0.5); sex = (int32) floor(*maxx * sx + 0.5); swx = (int32) floor(*minx * sx + 0.5); ney = (int32) floor(*maxy * sy + 0.5); nwy = (int32) floor(*maxy * sy + 0.5); swy = (int32) floor(*miny * sy + 0.5); sey = (int32) floor(*miny * sy + 0.5); ptrotate(&nex, &ney, midx, midy, rot); ptrotate(&sex, &sey, midx, midy, rot); ptrotate(&swx, &swy, midx, midy, rot); ptrotate(&nwx, &nwy, midx, midy, rot); nex += tx; sex += tx; swx += tx; nwx += tx; ney += ty; sey += ty; swy += ty; nwy += ty; /* now find the actual extents of the bbox */ temp1 = min(nex, nwx); temp2 = min(swx, sex); *minx = min(temp1, temp2); temp1 = min(ney, nwy); temp2 = min(swy, sey); *miny = min(temp1, temp2); temp1 = max(nex, nwx); temp2 = max(swx, sex); *maxx = max(temp1, temp2); temp1 = max(ney, nwy); temp2 = max(swy, sey); *maxy = max(temp1, temp2); } /*-----------------------------------------------*/ /* * find the bounding box of the list of primitives and/or sub-figures in this Item */ static void findBBox(blot, mnx, mxx, mny, mxy) Item *blot; int32 *mnx, *mxx, *mny, *mxy; { Item *pi; ScaledPts bmnx, bmxx, bmny, bmxy, midx, midy; /* bbox [min/max][x/y] */ ScaledPts tmnx, tmxx, tmny, tmxy; /* temporary, in case of recursion */ ScaledPts null1, null2, old1, old2; double prescale, postscale; bmnx = TWO24; bmny = TWO24; bmxx = -TWO24; bmxy = -TWO24; if (blot->kind == Afigure) { /* afigure */ pi = blot->UU.U8.body->things; while (pi != NULL) { /* find the current bbox of the list of items here */ if (pi->kind == Afigure) { /* recur */ findBBox(pi, &tmnx, &tmxx, &tmny, &tmxy); bmnx = min(bmnx, tmnx); bmny = min(bmny, tmny); bmxx = max(bmxx, tmxx); bmxy = max(bmxy, tmxy); } else { bmnx = min(bmnx, pi->BBlx); bmny = min(bmny, pi->BBby); bmxx = max(bmxx, pi->BBrx); bmxy = max(bmxy, pi->BBty); } pi = pi->nextitem; } /* while */ /* now transform the items inside, AND the bbox */ pi = blot->UU.U8.body->things; midx = (bmnx + bmxx) / 2; midy = (bmny + bmxy) / 2; /* now take care of any pre and post size requirements */ /* see also the "figurehandle" proc. */ /* #### Keep this scaling biz here, too, for now. May blast it later */ if (blot->UU.U8.preWid != 0 && blot->UU.U8.preHt != 0) { prescale = scalefitfactor(bmxx - bmnx, bmxy - bmny, blot->UU.U8.preWid, blot->UU.U8.preHt); blot->UU.U8.fsx *= prescale; blot->UU.U8.fsy *= prescale; } if (blot->UU.U8.postWid != 0 && blot->UU.U8.postHt != 0) { /* with */ postscale = scalefitfactor(bmxx - bmnx, bmxy - bmny, blot->UU.U8.postWid, blot->UU.U8.postHt); blot->UU.U8.fsx *= postscale; blot->UU.U8.fsy *= postscale; } /* the actual scale-up is taken care of later in this proc. */ while (pi != NULL) { switch (pi->kind) { /* with */ case Aline: xfmlinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2, &pi->UU.U1.ly2, 0, 0, midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx, blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy); break; case Aspline: xfmcontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, 0, 0, midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx, blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy); break; case Attspline: xfmcontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, 0, 0, midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx, blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy); break; case Aarc: null1 = 0; null2 = 0; old1 = pi->UU.U6.acentx; old2 = pi->UU.U6.acenty; xfmlinepts(&pi->UU.U6.acentx, &pi->UU.U6.acenty, &null1, &null2, 0, 0, midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx, blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy); xfmcontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, 0, 0, old1, old2, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx + pi->UU.U6.acentx - old1, blot->UU.U8.fdy + pi->UU.U6.acenty - old2, blot->UU.U8.fsx, blot->UU.U8.fsy); break; case Alabel: null1 = 0; null2 = 0; xfmlinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, 0, 0, midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx, blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy); break; case Abeam: /* not transformable */ break; case Atieslur: /* not transformable */ break; case Afigure: /* do not need to re-transform */ break; } /* case */ pi = pi->nextitem; } /* while */ /* transform the bbox, and re-find the new bbox */ newbbox(&bmnx, &bmxx, &bmny, &bmxy, midx, midy, blot->UU.U8.fsx, blot->UU.U8.fsy, blot->UU.U8.figtheta, blot->UU.U8.fdx, blot->UU.U8.fdy); *mnx = bmnx; *mny = bmny; *mxx = bmxx; *mxy = bmxy; return; } /* if */ *mnx = blot->BBlx; *mny = blot->BBby; *mxx = blot->BBrx; *mxy = blot->BBty; /* some other primitive */ /* else */ } /* findBBox */ /*---------------------------------------------------------*/ /* * traverse the list, determining the current bounding box for the items. We need this to find the mid-point for doing any * remaining rotations */ static void traverse(thefig, theitem) Item *thefig, *theitem; { ScaledPts minx, maxx, miny, maxy, curminx, curmaxx, curminy, curmaxy; minx = TWO24; maxx = -TWO24; miny = TWO24; maxy = -TWO24; while (theitem != NULL) { /* set the bounding box for this upper-level symbol defn */ if (theitem->kind == Afigure) { /* recur */ findBBox(theitem, &curminx, &curmaxx, &curminy, &curmaxy); theitem->BBlx = curminx; theitem->BBby = curminy; theitem->BBrx = curmaxx; theitem->BBty = curmaxy; /* * reset the symbol's parameters since all the primitives in it have now been transformed according to * the previous specifications */ theitem->UU.U8.figtheta = 0.0; theitem->UU.U8.fsx = 1.0; theitem->UU.U8.fsy = 1.0; theitem->UU.U8.fdx = 0; theitem->UU.U8.fdy = 0; theitem->UU.U8.preWid = 0; theitem->UU.U8.preHt = 0; theitem->UU.U8.postWid = 0; theitem->UU.U8.postHt = 0; /* with */ minx = min(minx, curminx); miny = min(miny, curminy); maxx = max(maxx, curmaxx); maxy = max(maxy, curmaxy); } /* if a figure/symbol */ else { /* a primitive */ minx = min(minx, theitem->BBlx); miny = min(miny, theitem->BBby); maxx = max(maxx, theitem->BBrx); maxy = max(maxy, theitem->BBty); /* with */ } /* else */ theitem = theitem->nextitem; } /* while */ thefig->BBlx = minx; thefig->BBby = miny; thefig->BBrx = maxx; thefig->BBty = maxy; /* with */ } /* traverse */ #define DoItNow (-1) #define NoScale 1 /* ----- Figure symbols ----- */ /*---------------------------------------------------*/ void figurehandle(globalsymlist, symbollist, dopush) Item *globalsymlist, *symbollist; int32 dopush; { Item *pi, *curfig; ScaledPts midx, midy, null1, null2, tmnx, tmny, tmxx, tmxy; double prescale, postscale; /* * PUSH. traverse the lists (recursively if necessary) and compute the transformed points. Convert to 4th quadrant and * offset by H & V. We can do this destructively here since we're going to output them right away anyhow. Then call * each respective primitive handler with a level of -1 to indicate to do its job immediately. POP. */ curfig = symbollist; pi = curfig->UU.U8.body->things; /* * find and set the bounding box for the figure's sub-symbols and primitives */ if (dopush > 0) traverse(curfig, pi); /* * We eventually transform the items to 4th Quadrant DVI space and output them! */ pi = curfig->UU.U8.body->things; midy = (globalsymlist->BBby + globalsymlist->BBty) / 2; midx = (globalsymlist->BBlx + globalsymlist->BBrx) / 2; if (dopush > 0) { /* the top-level figure for outputting */ /* * convert the bounding box because we are about to enter into DVI space, and all calls to handlers hereafter * are in terms of DVI coordinates */ /* * Since there were external specifications about this figure, fit the current figure's actual size to the * "pre" size (specified by W marker) and/or to the "post" size (specified by the F marker). We do this by * simple scaling, *without* changing the midpoint of the bounding box, just its extents */ if (globalsymlist->UU.U8.preWid != 0 && globalsymlist->UU.U8.preHt != 0) { prescale = scalefitfactor(globalsymlist->BBrx - globalsymlist->BBlx, globalsymlist->BBty - globalsymlist->BBby, globalsymlist->UU.U8.preWid, globalsymlist->UU.U8.preHt); globalsymlist->UU.U8.fsx *= prescale; globalsymlist->UU.U8.fsy *= prescale; } if (globalsymlist->UU.U8.postWid != 0 && globalsymlist->UU.U8.postHt != 0) { postscale = scalefitfactor(globalsymlist->BBrx - globalsymlist->BBlx, globalsymlist->BBty - globalsymlist->BBby, globalsymlist->UU.U8.postWid, globalsymlist->UU.U8.postHt); globalsymlist->UU.U8.fsx *= postscale; globalsymlist->UU.U8.fsy *= postscale; } tmnx = globalsymlist->BBlx; tmny = globalsymlist->BBby; tmxx = globalsymlist->BBrx; tmxy = globalsymlist->BBty; xfmlinepts(&tmnx, &tmny, &tmxx, &tmxy, 0, 0, midx, midy, 1.0, 0.0, 0, 0, globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy); toplevelxfm(globalsymlist, globalsymlist, 0); dviBBlx = tmnx; dviBBrx = tmxx; dviBBby = tmny; dviBBty = tmxy; xfmlinepts(&dviBBlx, &dviBBby, &dviBBrx, &dviBBty, 0, 0, midx, midy, 1.0, 0.0, globalsymlist->BBlx - tmnx, globalsymlist->BBby - tmny, 1.0, 1.0); globalsymlist->UU.U8.fdx += globalsymlist->BBlx - tmnx; globalsymlist->UU.U8.fdy += globalsymlist->BBby - tmny; dvilinepts(&dviBBlx, &dviBBby, &dviBBrx, &dviBBty, h, v); pgfigurenum++; /* We are ready to output the figure to the page */ fprintf(logfile, "\nFigure #%ld on page %ld is approx. ", pgfigurenum, currpagenum); /* * write(logfile,((globalsymlist^.BBty - globalsymlist^.BBby) div SPPERPT):0,' pts high and '); * writeln(logfile,((globalsymlist^.BBrx - globalsymlist^.BBlx) div SPPERPT):0,' pts wide (actual size)'); */ fprintf(logfile, "%ld pts high and ", (tmxy - tmny) / SPPERPT); fprintf(logfile, "%ld pts wide (actual size)\n", (tmxx - tmnx) / SPPERPT); IPUSH(); } while (pi != NULL) { switch (pi->kind) { /* with */ case Aline: dvilinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2, &pi->UU.U1.ly2, h, v); /* DVI h and v posit */ linehandle((int32) DoItNow, (double) NoScale, pi->UU.U1.lx1, pi->UU.U1.ly1, pi->UU.U1.lx2, pi->UU.U1.ly2, 0, 0, pi->itemthick, (VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx, -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta); /* * p2c: x.p, line 4681: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] */ break; /* Aline */ case Aspline: dvicontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, h, v); splinehandle((int32) DoItNow, (double) NoScale, (SplineKind) pi->UU.U2.spltype, pi->UU.U2.sclosed, pi->UU.U2.dosmarks, pi->UU.U2.spts, pi->UU.U2.nsplknots, 0, 0, pi->itemthick, (VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx, -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta); /* * p2c: x.p, line 4693: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] */ break; /* Aspline */ case Attspline: dvicontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, h, v); ttsplhandle((int32) DoItNow, (double) NoScale, (SplineKind) pi->UU.U3.tspltype, pi->UU.U3.tclosed, pi->UU.U3.dottmarks, pi->UU.U3.ttpts, pi->UU.U3.ttarry, pi->UU.U3.nttknots, 0, 0, (VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx, -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta); /* * p2c: x.p, line 4705: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] */ break; /* Attspline */ case Abeam: dvilinepts(&pi->UU.U4.bx1, &pi->UU.U4.by1, &pi->UU.U4.bx2, &pi->UU.U4.by2, h, v); beamhandle((int32) DoItNow, pi->UU.U4.staf, (BeamKind) pi->UU.U4.bkind, pi->UU.U4.bx1, pi->UU.U4.by1, pi->UU.U4.bx2, pi->UU.U4.by2); break; /* Abeam */ case Atieslur: dvicontpts(pi->UU.U5.tspts, pi->UU.U5.ntknots, h, v); tieslurhandle((int32) DoItNow, pi->UU.U5.tspts, pi->UU.U5.ntknots, pi->UU.U5.minth, pi->UU.U5.maxth); break; /* a tie or slur */ case Aarc: dvicontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, h, v); arccirclehandle((int32) DoItNow, (double) NoScale, pi->UU.U6.acentx, pi->UU.U6.acenty, pi->UU.U6.aradius, pi->UU.U6.firstang, pi->UU.U6.lastang, pi->UU.U6.arcpts, pi->UU.U6.narcknots, 0, 0, pi->itemthick, (VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx, -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta); /* * p2c: x.p, line 4729: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] */ break; /* arc */ case Alabel: null1 = 0; null2 = 0; dvilinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, h, v); labelhandle((int32) DoItNow, (double) NoScale, pi->UU.U7.labx, pi->UU.U7.laby, 0, 0, pi->UU.U7.fontstyle, pi->UU.U7.labeltext, globalsymlist->UU.U8.fdx, -globalsymlist->UU.U8.fdy); break; /* label */ case Afigure: /* recur */ figurehandle(globalsymlist, pi, 0); break; /* another symbol */ } /* case */ /* * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] */ /* * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] */ /* * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] */ /* * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] */ pi = pi->nextitem; } /* while */ if (dopush > 0) IPOP(); } /* figurehandle */ #undef DoItNow #undef NoScale