to use: REQUIRE “DDHDR.SAI[GRA,HPM]” SOURCE_FILE;
uses: DDFAI.REL[GRA], DDSAI.REL[GRA]
| DDINIT | initialize the DD buffer |
| SCREEN(REAL XLO, YLO, XHI, YHI) | declare the full screen dimensions |
| SCREEM(REAL XLO, YLO, XHI, YHI) | returns the full screen dimensions |
| DRKEN | cause subsequent outputs to be dark |
| LITEN | cause them to be light |
| INVEN | cause them to invert the state of things |
| DOT(X, Y, THICK(0)) | display a point at X, Y |
| LINE(X1, Y1, X2, Y2, THICK(0)) | display a line |
| RECTAN(X1, Y1, X2, Y2) | fill in rectangle |
| ELLIPS(X1, Y1, X2, Y2) | fill ellipse bounded by X1, Y1, X2, Y2 |
| POLYGO(N, X[1:N], Y[1:N]) | fill in a polygon (concave and star ok) |
| TXTPOS(X, Y, XS, YS, DXS(0), DYS(0)) | Position text start at X, Y with general linear transf. First char's corners will be (X, Y), (X+DXS, Y+YS), (X+XS+DXS, Y+YS+DYS), (X+XS, Y+DYS). To make normal horizontal text of characters $W$ wide and $H$ high, do $$TXTPOS(X, Y, W, H, 0, 0)$$ or just $TXTPOS(X, Y, W, H)$. To make sideways text lying on its left side, do $$TXTPOS(X, Y, 0, 0, -H, W)$$ To make text on its right side (reading downwards), do $$TXTPOS(X, Y, 0, 0, H, -W)$$ To make text rotated from the horizontal by an arbitrary angle $T$, do $$TXTPOS(X, Y, W\cos{T}, H\cos{T}, -H\sin{T}, W\sin{T})$$ To make horizontal, italicized, text, do $$TXTPOS(X, Y, W, H, W/2, 0)$$ I leave the other possibilities to you. Consider $XS$ and $YS$ the main diagonal of a $2 \times 2$ matrix that takes a straight, horizontal, prototype character into the skewed, rotated one actually drawn. $DXS$ and $DYS$ are the off-diagonal elements of that matrix. Text can thus be rotated, italicized and reflected. |
| TEXT(STRING) | vector text, positioned by previous TXTPOS |
| TEXTD(STRING) | dot char text. Look better for tiny, inven |
| CHAN = GDDCHN(CHAN) | get a DD channel ($-1$ for any, failure) |
| RDDCHN(CHAN) | release a channel |
| ERASE(CHAN) | clear a DD channel ($-1$ means yours) |
| DPYUP(CHAN, BUFFER(-1)) | Deposit the buffer on DD channel CHAN |
| PJUP | send buffer to MOS display on PDP11 |
| SHOW(CHAN, LIN(-1)) | video switch LIN ($-1$ for yours) to CHAN |
| SHOWA(CHAN, LIN(-1)) | add CHAN to LIN |
| SHOWS(CHAN, LIN(-1)) | subtract CHAN from LIN |
| PPPOS(YLO, YHI) | position page printer between YLO, YHI |
| XGPUP(SIZE) | send the DD buffer to the XGP, SIZE$ = -5$ to $+5$ |
| XGPQUE(SIZE) | like XGPUP, but creates a new job to do XGPing |
| DDFONT(X1, Y1, X2, Y2, FONTFIL, CHAR(“A”), BASE(0), LKERN(0), RKERN(0)) | insert DD buffer bounded by X1, Y1, X2, Y2 into font file. |
| DDPAK(I, LBUF, J1, J2) | pack scanline I bet. J1, J2 into LBUF 36 bit/word |
| CHAN = SYNMAP(ORDER) | which channels are the video synthesizer's. ORDER = $0$ is most significant $+$ or $-$ $1$ next, etc. |
| SUCCESS = MAPSET(F) | set video inten table. F(X) is real $[0, 1] \rightarrow [0, 1]$ |
| SUCCESS = MAPMON(P) | set v.i.t. to a monotonic function $X^P$ |
| SUCCESS = MAPGRY(P) | set v.i.t. to a gray coded monotonic function $X^P$ |
| LINSCN(N, MAP, DT, LINENO) | scan channels in MAP at rate DT |
| MAPSCN(N, MAP, DT, LINENO) | LINSCN, but VDS bit maps in MAP |
| SCNOFF | turn off the scanning (in SW mode) |
| SCNFRZ | SCNOFF, but doesn't restore screen |
| SCNINC(INC) | change the stepsize in the scan |
| DDSTOR(DDARRAY) | store the buffer in an array |
| DDLOAD(DDARRAY) | load the buffer from an array |
| DDOR(DDARRAY) | or an array into the buffer |
| DDAND(DDARRAY) | and the buffer with an array |
| DDEXCH(DDARRAY) | exchange an array with the buffer |
| GETDDF(FILENAME) | load the buffer from a file |
| PUTDDF(FILENAME) | save the buffer in a file |
| GETMIT(FILENAME) | load the buffer from a file |
| PUTMIT(FILENAME) | save the buffer in a file |
| FNTSEL(FONT$\#$, “FONTNAME”) | define a font $\#$ |
| FNTPOS(XP, YP, XS(1), YS(1), DXS(0), DYS(0)) | position & transform fonted text |
| FNTEXT(X, Y, F, TXT) | deposit fonted text |
| FNTLIN(X1, Y1, X2, Y2, THICK(0)) | draw line in FNTPOS co-ordinates |
| FNTDOT(X1, Y1, THICK(0)) | dot in FNTPOS co-ordinates |
| FNTREC(X1, Y1, X2, Y2) | rectangle |
| FNTELL(X1, Y1, X2, Y2) | ellipse |
| FNTPOL(N, X1[1:N], Y1[1:N]) | polygon |
| DDSIZ | a constant, the number of words in a DD array |
Arguments followed by a value in parens default to the bracketed value.
The absolute physical screen dimension are 512 pixels in $X$ by 481 in $Y$. TEXTD characters are 6 logical pixels in $X$ by 10 in $Y$, spaces included.
Regarding TXTPOS parameters, note that, in terms of character height $H$, character width $W$, clockwise rotation angle $ccwrot$ and clockwise slant angle $ccwslant$ $$\begin{bmatrix} X \\ Y \end{bmatrix} \quad = \quad \begin{bmatrix} {W\cos(ccwrot)} & {H(\cos(ccwrot)\tan(cwslant)-\sin(ccwrot))} \\ {W\sin(ccwrot)} & {H(\sin(ccwrot)\tan(cwslant)+\cos(ccwrot))} \end{bmatrix} \;\begin{bmatrix} x \\ y \end{bmatrix}$$ $$\begin{bmatrix} X \\ Y \end{bmatrix} \quad = \quad \begin{bmatrix}{XS}&{DXS}\\{DYS}&{YS}\end{bmatrix} \;\begin{bmatrix} x \\ y \end{bmatrix}$$ thus $$\begin{matrix} XS & = & W\,\cos(ccwrot)\\ DXS & = & H\,(\cos(ccwrot)\,\tan(cwslant)-\sin(ccwrot))\\ DYS & = & W\,\sin(ccwrot)\\ YS & = & H\,(\sin(ccwrot)\,\tan(cwslant)+\cos(ccwrot))\end{matrix}$$
It might be useful to introduce a parameterization that accepts corner, width, height, rotation and slant angles (degrees): $$TP(X, Y, W, H, CCWROT, CWSLANT)$$
to use: REQUIRE “GRAHDR.SAI[GOD,HPM]” SOURCE_FILE;
uses: GRASAI.REL[GOD]
The graphics routines on [GOD,HPM] are superficially similar to the ones on [GRA,HPM], but provide an extended device-independent graphics service. To make a drawing one or more devices (graphics servers) must be activated to receive graphics commands. Currently there are servers for Data discs, the XGP and the video synthesizer. In addition the graphics commands can be written into files (called GOD files), which can be displayed later with system programs called DDJOB, XGPJOB and SYNJOB. GOD files can be called as subroutines in graphics programs. GOD files can also be fed to a program called TSTJOB which makes a SAIL program that, if run, recreates the GOD file given to the TSTJOB. Editing the SAIL program provides a way of modifying existing GOD files.
Diagrams in the form of GOD files can be included in documents by the graphics escape features of XGPSYG.
The following calls are provided in addition to the ones in the GRA package.
| JOBID = DDJOB | create a server that draws on Data Disc displays. |
| JOBID = XGPJOB | create a graphics server that will output on the XGP. |
| JOBID = SYNJOB(HIG(480),WID(512),BIT(9)) | make a server that produces gray scale renditions of a drawing. |
| JOBID = FILJOB(“FILENAME”) | make a graphics server that writes graphics commands into a GOD file. |
| JOBID = TSTJOB | create a server that prints graphics commands as a SAIL program. |
| JOBID = QUASH(JOBID) | temporarily deafen a server.It still exists but will not act on subsequent display commands. |
| JOBID = INCITE(JOBID) | reactivate a server. Undoes the effect of a QUASH. |
| JOBID = KILJOB(INTEGER JOBID) | kill a server. Closes the file opened by a FILJOB, simply expunges all other server types. |
| JOBID = DETJOB(JOBID,GRAFILE) | detach a server, but give it a graphics file to process first. Server is lost to main program. |
| GRAFIL(GRAFILE) | tell currently active servers to begin processing a graphics file. Afterwards they will be ready to listen to main program again. |
| FNTSEL(FONT$\#$,FONTNAME) | select a font, and give it a number $(0-127)$. |
| FNTPOS(XP,YP,XS(1),YS(1),DXS(0),DYS(0)) | position a font pixel grid at XP, YP in SCREEN co-ordinates, with transformation set by other four parameters. 1, 1, 0, 0 results in undistorted characters. |
| FNTEXT(X,Y,FONT$\#$,TEXT) | deposit TEXT in the indicated font with lower left corner offset (X,Y) font pixels (as distorted by FNTPOS parameters) from the last FNTPOS position. |
| FNTLIN(X1,Y1,X2,Y2,THICK(0)) | draw a line between pixel co-ordinates indicated, in grid defined by last FNTPOS. |
| FNTDOT(X1,Y1,THICK(0)) | a dot in FNTPOS co-ordinates. |
| FNTREC(X1,Y1,X2,Y2) | a FNTPOS rectangle. |
| FNTELL(X1,Y1,X2,Y2) | a FNTPOS ellipse. |
| FNTPOL(N,X[1:N],Y[1:N]) | a FNTPOS polygon. |
| PICFIL(X1,Y1,X2,Y2,PICFILE) | insert a picture in the rectangle bounded in X by X1 and X2 and by Y1 and Y2 in Y. On gray scale servers this picture will come out shaded. On binary devices a halftone is produced. PICFILE should be in hand/eye format. |
| PICFIT(X1,Y1,X2,Y2,FILE) | insert a transposed picture in the indicated rectangle. |
| BUFSIZ = DDSIZ(INTEGER JOBID($-1$)) | return the display buffer size of the indicated server. |
The TYPHDR routines extend the GRAHDR package to permit reasonably convenient two dimensional typesetting of text in mixed fonts, for inclusion in GOD diagrams. The central concept is of a box of a certain size containing a two dimensional assembly of text and graphics. Such a box has an origin, which may be plopped down at a given place in diagram. Some of the commands create new boxes out of text, some by gluing together other ones, and some change the size or the origin of a box.
The following procedures are provided:
| FNTSELECT(FONT$\#$,FONTNAME) | use this instead of FNTSEL in the GRAHDR. |
| BOX = JTXT(FONT$\#$,TEXT) | return a box containing TEXT in the indicated font. |
| BOX = JCAT(A,B) thru JCAT6(A,B,C,D,E,F) | horizontally combine a number of boxes. Origin ends up on left edge of resulting box. Useful for stringing together different fonts. |
| BOX = JTAC(A,B) thru JTAC7(A,B,C,D,E,F,G) | horizontally combine boxes, but leave origin on the right end. |
| BOX = JBEL(A,B) thru JBEL7(A,B,C,D,E,F,G) | vertically stack text boxes. Useful for assembling multiple lines of text. |
| BOX = JSUB(A,B) | make new box that is box A subscripted by box B. |
| BOX = JEXP(A,B) | make box with A superscripted by B. |
| BOX = JXBP(A,B,C) | make box with A sub B super C. |
| BOX = PADD(DX1,DY1,DX2,DY2,A) | padd box A on all four sides (margins). |
| BOX = SHIF(DX1,DY1,A) | shift origin of box A. |
| BOX = JUL(A) | make new box with contents of A underlined. |
| BOX = JSQR(A) | make a square root sign around A. |
| BOX = JDIV(A,B) | center A above B and put a division bar between. |
| BOX = XCENTER(A) | center the origin of box A in X. |
| BOX = YCENTER(A) | center A in Y. |
| BOX = CENTER(A) | move origin of A to its center in X and Y. |
| BOX = RIGHTIFY(A) | move origin to right of A. |
| BOX = LEFTIFY(A) | move origin to left of A. |
| BOX = TOPIFY(A) | move origin to top of A. |
| BOX = BOTTOMIFY(A) | move origin to bottom of A. |
| DEPOSIT(X,Y,A) | deposit box A into the diagram such that its origin is X (FNTPOS distorted) pixels to the right and Y pixels above the text position specified by the last FNTPOS. |
PIXHDR.SAI utility routines for getting, saving, moving, etc. pictures
requires: PIXFAI.REL, PIXSAI.REL
| PCLN, PCWD, PCBY, PCBYA, LNWD, LNBY, LNBYA, WDBY, WDBI, BYBI, BPTAB, LINTAB | where to find things in picture arrays |
| VALUE = PIXEL(PICTURE, ROW, COLUMN) | value of a particular pixel |
| VALUE = INTREL(PIC, ROW, COL) | interpolating PIXEL. ROW, COL, VALUE real. |
| PUTEL(PICTURE, ROW, COLUMN, VALUE) | change a pixel |
| ADDEL(PICTURE, ROW, COLUMN, VALUE) | increment a pixel |
| ADDIEL(PIC, ROW, COL, VAL) | interpolating ADDEL. R, C, V real. |
| SIZE = PFLDIM(FILENAME) | size of array needed for pic file |
| SIZE = GETPFD(FILENAME, DIM[0:10]) | read in parameters of picture |
| SIZE = GETPFL(FILENAME, PICTURE) | read in a pic file |
| PUTPFL(PICTURE, FILENAME, MODE(1)) | write PICTURE into a file. if MODE = 2, file is data compressed, otherwise normal |
| CHAN = OPNPFL(FILENAME, DIM[0:10]) | read in parameters of picture, opened for input at 1st scanline |
| CHAN = CREPFL(DIM[0:10], FILENAME, MODE(1)) | write header for PIC file, opened for output at 1st scanline. compressed if MODE = 2 |
| PFLIN(CHAN, AR[1], NWDS) | read next NWDS words from pic into AR |
| PFLOUT(CHAN, AR[1], NWDS) | write next NWDS words to pic from AR |
| PFLCLS(CHAN) | close picture open on channel |
| SIZE = PIXDIM(HEIGHT, WIDTH, BITS) | size of array for $H \times W \times B$ picture |
| SIZE = MAKPIX(HEIGHT, WIDTH, BITS, PICTURE) | make skeleton $H \times W \times B$ picture |
| SIZE = MAKDIM(H, W, B, P[0:10]) | make 11 word skeleton, for out of core pix |
| WIPE(PICTURE, VALUE(0)) | make every data word (not byte!) = VALUE |
| PIXTRN(SRC, TR, DEST) | transforms src into dst by array tr. tr is a 3 by 3 real array. For all pixels $(y, x)$ in dest set $(ty, tx, foo) = (y, x, 1) \times transform$. If $(ty, tx)$ is in src then $dest(y, x) = src(ty, tx)$ |
| COPPIC(PICTURE1, PICTURE2) | copy pic1 into pic2 |
| TILE(PIC1, YL1, XL1, TY, TX, PIC2, YL2, XL2) | take piece of size $TY \times TX$ at $[YL1, XL1]$ in PIC1, deposit at $[YL2, XL2]$ in PIC2 |
| SQTILE(PIC1, YL1, XL1, TY, TX, YSQ, XSQ, PIC2, YL2, XL2) | a $TY \times YSQ$ by $TX \times XSQ$ tile from PIC1 with upleft at $[YL1, XL1]$ is squished into a $TY$ by $TX$ tile in PIC2 $[YL2, XL2]$ upleft. The $YSQ$ by $XSQ$ areas in PIC1 are summed and scaled as needed |
| SATILE(PIC1, YL1, XL1, TY, TX, YSQ, XSQ, PIC2, YL2, XL2) | like SQTILE, but 0 samples in PIC1 leave PIC2 unchanged |
| HAFPIC(PICTURE1, PICTURE2, MAXBIT) | reduce pic to half resolution |
| SHRINK(PICT1, PICT2) | squeeze or expand PICT1 into PICT2 pixels are sampled, not interpolated or averaged. |
| PICADD(PICTURE, PICSUM) | add a picture to a picture |
| PICSUB(PICA, PICDIFF) | subtract. PICA$-$PICDIFF → PICDIFF |
| PICMUL(PICTURE, PICPRD) | multiply pictures. no bounds check. |
| PICSH(PIC1, PIC2, DIV) | every pixel in PIC1/DIV→PIC2 |
| GRAY(PIC) | Convert to gray code. |
| UNGRAY(PIC) | Convert back. |
| RETRY = CAMPIX(CAMERA, YEDGE, XEDGE, PICTURE, SUMS(1), BCLIP(7), TCLIP(0), MAXTRY(20)) | read from a camera |
| NRETRY = CLPADJ(CAM, BLCIP, TCLIP) | find optimum clip levels for CAM |
| NRETRY = TVSNAP(CAM, YEDGE, XEDGE, PIC, BCLIP, TCLIP, NTRY) | primitive camera routine, used by CAMPIX |
| NRETRY = TVRAW(CAM, YEDGE, XEDGE, PIC, BCLIP, TCLIP, NTRY) | primitive camera routine, used by CAMPIX |
| TVBTMX(PIC4, PICN, XFRM, INHIBEQ) | primitive camera routine, used by CAMPIX |
| TVBTMY(PIC4, PICN, XFRM, INHIBLE) | primitive camera routine, used by CAMPIX |
| TVBTMZ(PIC4, PICN, XFRM, INHIBGE) | primitive camera routine, used by CAMPIX |
| SUM = INTOP(PIC, WINSIZE, ANSARRY, YEDGE(0), XEDGE(0)) | interest operator |
| INTLOM(HIG, WID, ANSARRY) | intop local max operator |
| SIZE = INTERESTDIM(PICTURE, WINDOWSIZE) | pic size needed for interest op |
| INTEREST(PICTURE, WINDOW, RESULTPICTURE) | make interest op picture |
| BESTVAL = MATCH(PICTURE1, SY1, SX1, SY2, SX2, PICTURE2, DY1, DX1, DY2, DX2) | correlator, find Source window in pic1 in Dest in pic2 |
| BSTCOEF = NORCOR(PICTURE1, SY1, SX1, SY2, SX2, PICTURE2, DY1, DX1, DY2, DX2) | normalized correlator, find Source window in pic1 in Dest in pic2 |
| CLEAN(PICTURE) | remove single pixel noise, blurs a little |
| PASSHI(PICTURE1, WINDOWSIZE, PICTURE2) | high pass filter |
| LOWPAS(PICTURE) | in place low pass filter. 4 pixels → 1 pixel. |
| SUM = CMPPAR(PICTURE1, PICTURE2) | compare two pics: $\sum(x-y)^2$ |
| SUM = CMPPAD(PICTURE1, PICTURE2) | quick and dirty compare |
| PERBIT(PICTURE, TRANSFORM) | transform each pixel of pic |
| HISTOG(PICTURE, HISTOGRAM) | count # of occurences of each gray val |
| ENHANCE(PICTURE) | make histogram flat |
| SYNCHRONIZE(PICTURE1) | do a vertical roll fixup |
| ROWSUM(PICTURE1, ROWSUMS) | sum up the pixels in each row |
| ROWSUD(PICTURE1, ROWSUMS) | dirty rowsums, one pixel/word used |
| COLSUM(PICTURE1, COLSUMS) | sum up the pixels in each col |
| LONG REAL = SUMSQR(PIC) | double prec. sum of squares of pixels |
| MASS = CENTRO(PIC, YL, XL, YH, XH, THR) | centroid and moment of a dark area |
| UNPACK(SOURCEARRAY, PICTURE) | copy a dense byte arry into a pic |
| GETPAR(ARRY, PICTURE) | copy full word array of pixels to pic |
| PUTPAR(PICTURE, ARRY) | copy pic to full word array of pixels |
| EDGEINIT(PICTURE, SIZE) | initialize edge operator |
| EDGE(X, Y, EDGERESULT) | apply edge operator |
NOTE: all picture and other arrays are zero origin in all dimensions
VIXHDR.SAI for displaying gray scale and halftone pictures on data disc. an extension for the display routines in DDSUB.SAI[GRA,HPM]
requires: PIXHDR.SAI[VIS], DDHDR.SAI[GRA], VIXFAI.REL[VIS], VIXSAI.REL[VIS]
| VIDEO(X1, Y1, X2, Y2, PICTURE, BIT) | display PICTURE between X1, Y1, X2, Y2 in SCREEN co-ordinates. If BIT = $-1$ then a fast, low quality halftone, if $-2$ then a high quality halftone, if $-3$ then a buggy halftone. If positive then BIT represents a bit mask, which is anded with each pixel. If the result is nonzero, a bit is turned on in the corresponding part of the display. |
| VIDONE(PICTURE, BT, I(0), J(0)) | similar to VID but faster and simpler. Maps picture elements one to one to data disc points. Upper left corner of picture is placed I physical DD scanlines from the top of the picture, and indented J DD elements from the left. Complements the masked bit instead of setting it to one. |
| VIDFOR(PICTURE, BUF1, BUF2, BUF4, BUF8, I(0), J(0)) | Like VIDONE, but for 4 bit pictures and four DD buffers. Sets up all buffers at once, clearing displayed area and inverting bits for compatibility with the inverted gray code produced by TVRAW. |
| VIDFRT(PICTURE, BUF1, BUF2, BUF4, BUF8, I(0), J(0)) | Transposed VIDFOR; picture twice as wide on its side. |
| VIDFRX(PICTURE, BUF1, BUF2, BUF4, BUF8, I(0), J(0)) | Like VIDFOR, but makes picture twice as wide and tall. One picture pixel → 4 DD pixels. |
| VID1(PICTURE, BUF1, I(0), J(0)) | Like VIDFOR, for 1 bit pictures, but assumes normal gray code and produces a complemented display. |
| VID3(PICTURE, BUF1, BUF2, BUF4, I(0), J(0)) | Like VID1, for 3 bit pictures. |
| VID4(PICTURE, BUF1, BUF2, BUF4, BUF8, I(0), J(0)) | Like VID1, for 4 bit pictures. |
| VID5(PICTURE, BUF1, BUF2, BUF4, BUF8, BUF16, I(0), J(0)) | Like VID1, for 5 bit pictures. |
| SUCCESS = VIDXGP(PIC, I0, J0, PLEN) | Send a picture to the XGP. Dumb thing to do except for one bit pictures. Wait if XGP busy. |
| SUCCESS = VIDXG(PIC, I0, J0, PLEN) | VIDXGP, but return with failure if XGP busy |
| SUCCESS = VIDXGQ(PIC, I0, J0, PLEN) | VIDXGP, but set up detached job to do XGPing if XGP busy |
FNTHDR.SAI for inserting XGP font characters into pictures.
requires: FNTFAI.REL[VIS], FNTSAI.REL[VIS]
| FNTSEL(FNTNUM, FILSPEC, FNTHEAD) | define font number FNTNUM to be font FILSPEC. FNTHEAD is the first word of an array $204_8$ words long which must be reserved for this font. |
| CHRDEP(FNTNUM, CHR, PIC, YLO, XLO, YCOMP, XCOMP) | add character CHR to the picture PIC in font $\#$ FNTNUM starting at position YLO, XLO compressed by YCOMP in Y and XCOMP in X. |
| CHRPED(FNTNUM, CHR, PIC, YLO, XLO, YCOMP, XCOMP) | add CHR to PIC, sideways, writing bottom to top. X and Y positions and compressions refer to text, not picture, reference system. |
| CHR3X2(FNTNUM, CHR, PIC, YLO, XLO) | like CHRDEP, but compresses X by 3 and Y by 2, and goes faster |
| CHR6X4(FNTNUM, CHR, PIC, YLO, XLO) | like CHRDEP, but compresses X by 6 and Y by 4, and goes faster |
| CHR3Y4(FNTNUM, CHR, PIC, YLO, XLO) | like CHRPED, but compresses X by 3 and Y by 4, and goes faster |
| FCACHE(BUFFER, BUFSIZ) | set up a buffer for caching letter descriptions. Doing this greatly speeds up CHRDEP. 5 or 10 K is a good buffer size. |
Defines FNTHIG, position in FNTHEAD where height is stored, and FNTBAS, where baseline is stored.
| WORD | CONTENTS | |
| 0 | PCLN | number of scanlines in the picture |
| 1 | PCWD | words in the pixel portion of the picture |
| 2 | PCBY | valid bytes in the picture |
| 3 | PCBYA | bytes in the picture, including null bytes at end of each scanline |
| 4 | LNWD | words per scanline |
| 5 | LNBY | valid bytes per scanline |
| 6 | LNBYA | bytes per scanline, including the nulls |
| 7 | WDBY | bytes per word |
| 8 | WDBI | bits in the valid portion of each word |
| 9 | BYBI | bits per byte |
| 10 | BMAX | $2^{BYBI}-1$, the maximum value of a byte |
| 11 | BPTAB | address of SECOND entry in byte pointer table, 13+PCLN+address of array |
| 12 to 11+PCLN | LINTAB | table containg the actual address of the first word of each scanline, in top to bottom order |
| 12+PCLN to 12+PCLN+LNBYA | table containing byte pointers to samples within lines, to be added to line address. The first entry, when ILDB'ed causes loading of the first byte in the line. | |
| 13+PCLN+LNBYA to 12+PCLN+LNBYA+PCWD | the picture |
Simplified hand-eye file format, as written by PIXSAI routines, for a picture HIG samples high by WID samples wide by BIT bits/sample:
The first $200_8$ word disk block of the file contains the following seven words of data (the rest of the block is unused).
| WORD | CONTENTS | |
| 0 | -1 | This identifies the file as a standard Stanford Hand Eye picture file |
| 1 | BIT | Number of bits/sample |
| 2 | $\lceil WID/\lfloor 36/BIT\rfloor \rceil$ | $\#$ of words/scanline. $\lfloor \rfloor$ is FLOOR, $\lceil \rceil$ is CEILING |
| 3 | 1 | first scanline number |
| 4 | HIG | last scanline number |
| 5 | 1 | first column number |
| 6 | WID | last column number |
The data begins on word $200_8$ of the file, $\lceil WID/\lfloor 36/BIT\rfloor \rceil$ words per scanline, left to right, top to bottom, for HIG scanlines. Each scanline begins on a word boundary.
The data compressed variant has the same header information except word $0$ is $-2$ instead of $-1$. For each successive block of 36 words in a standard file a compressed file has from 1 to 37 words. Each bit of the first word in such a group represents one of the 36 words in the standard file block, sequenced left to right. The bit is zero if the corresponding word is the same as the previous word in the file, or one if it differs. Each word that differs is given in the group that follows the mask word.
XGPSYN displays files on the video synthesizer, imitating the XGP. It can fill the screen with 1/2, 1 or 2 pages at time. XGPSYN can also list documents on the XGP, with no complexity limit, and make hand/eye compatible picture files which can be sent to printers like the VARIAN, or displayed on screens. XGPSYG has the added capability of inserting drawings and pictures into the assembled pages.
To run the programs, tell them which file you want to look at, either in the command line (R XGPSYN;FILENAME) or in answer to the FILE: question, and any spooler style switches, such as /FONT = BASL30 (.XGP files already contain most necessary switches). The page number questions can be answered with the page you want to view, any additional spooler switches, or one of the following commands:
| H | Half density. Next display will be one half page per screen. |
| F | Full density. A whole page per screen. |
| D | Double density. Two sequential pages per screen. |
| C | Display pages on your own DD channel instead of on the video synthesizer. |
| S | Use the video synthesizer instead of your own channel. |
| V | view. Redraw the last display (in case it was clobbered). |
| W | negate subsequent displays. Black on white becomes white on black, and vice versa. |
| K | kill. Erase the video synthesizer. |
| Q | quit. Exit from the program and load the line editor with an XSPOOL command. |
| L(a:b) | list pages a to b on the XGP. More tolerant than XSPOOL, but slower. Alternate forms for this command are L to list the whole document and L(a) to list a single page. |
| B | Bitwise resolution. Next display will be a full size bit raster suitable for XGPing or sending to a picture file for printing on other devices. |
| T | Transposed bitwise resolution. Like B mode, but page is generated 90° rotated. |
| E | Enormous resolution. Next display will be at bit raster resolution, but only upper left 480 by 512 pixel portion will be generated. |
| O | output the last display as a data compressed picture file. |
| P | output the last display as a standard hand/eye picture file. |
| X | XGP output the last B,T or E display. |
The video synthesizer is a video rate D/A driven by data disc channels 30 through 37. H density requires 3 of these channels, F needs 4 and D wants 5. These are rarely available during heavy system load. It takes about 6 CPU seconds to compose a single page.
XGPSYN and XGPSYG understand the following switches, some of which are not standard with the spooler or the COPY program. The switch names may be abbreviated to the capitalized portion.
| /FONT = “fontname” | Select font number 0 for the document |
| /FONT$\#$n = “fontname” | Select font number n for the document |
| /THickness = t | Select line thickness for Leland's music files |
| /ESCape = ... | change the escape sequence. Any characters except slash are ok. |
| /REpeat = n | When listing, make n copies of each page. |
| /TMar = n | Set the top margin of a listing n raster lines from top of page. |
| /PMar = n | Set the text portion of the page to be n lines tall |
| /BMar = n | Make the bottom margin n raster lines big. In listings the sum of TMAR+PMAR+BMAR is the physical length of the page. |
| /LMar = n | Set the left margin n pixels from left edge of paper. |
| /RMar = n | Set the right margin n pixels from the left edge of the paper. When writing picture files of page images, RMAR is the physical width of the resulting image. |
| /List | List the document on the XGP. Possible forms are /L to list the whole document, /L(n) to list page n and /L(a:b) to list all the pages between a and b. The simplest way to list a document with XGPSYN is by incanting R XGPSYN;file/L |
| /XLine = n | Insert n extra scanlines between lines of text. This number is initially 3. |
| /INterchar = n | Insert n extra columns between characters of text. This number is usually zero. |
| /XShift = n | Shift the contents of a page n pixels to the right on the image. Useful if you want to tweak the margins in a listing, and also for making images too large to fit in XGPSYN's core image all at once. Set RMAR small, the output the same page repeatedly with different XSHIFTS. Resulting windows can be combined later into a single file representing a large page. |
| /YShift = n | Shift the page contents n pixels up. For tweaking vertical margins, and also for making very long pages. Set TMAR+PMAR+BMAR small, then window through the file by changing YSHIFT. If resulting windows are to be assembled later the EDGE switch is also recommended. |
| /EDge | Normally characters that extend past the top margin of a page are not displayed. /EDGE selects a slower mode in which such fractional characters do appear. This is necessary if large pages are to be assembled from small windows. |
| /XGp | This file is in .XGP format, whether or not the file extension says so. |
| /NOXgp | This file is not in .XGP form (is not preceded by a switch page) |
| /NOQueue | When listing on the XGP, XGPSYN will create a detached job which waits if the XGP is not available when a page is to be generated. NOQUEUE supresses this feature. Instead, XGPSYN itself waits for the XGP. |
| /NODpy | Supresses video synthesizer display. Useful if XGPSYN is being used solely to generate files containing page images. /L invokes this mode automatically. |
| /AUTocr | Insert carriage returns when lines run beyond right margin. |
| /NOAutocr | Suppress insertion of extra carriage returns. |
| /Halfdensity | Select half page/screen mode. |
| /Fulldensity | Select full page/screen mode. |
| /Doubledensity | Select two page/screen mode. |
| /Enormousresolution | In this mode a screenful of display is generated without any compression of the original page raster. Very little of a standard page is visible, but every pixel can be resolved in that portion. |
| /Bitwisedensity | Create a one bit/pixel image of the whole page. This can be sent to the XGP (/L uses this density) or written into a hand-eye picture file. Such files can be listed on other printing devices. |
| /Transposedbitwisedensity | Like /B, but the image comes out on its side, rotated 90°. |
| /Varian | Useful only with XGPSYG. Causes halftones to be generated in a high density mode which works well with the Varian printer, but causes washing out on the XGP. |
The following program writes the GOD file that produced Figure 10-1 in Chapter 10.
BEGIN "PRETTY"
REQUIRE "TYPHDR.SAI[GOD,HPM]" SOURCE_FILE;
INTEGER FJ,I,J,K,L,M,N; REAL P,Q;
REAL ARRAY X,Y[1:10];
FJ←FILJOB("DSK:PRETTY.GOD[DIA,HPM]");
comment open the GOD file;
DDINIT; SCREEN(-1.2,-1.2,1.2,1.2);
PICFIL(-1,-1,1,1,"U:SF2.PIC[DIA,HPM]"); LITEN;
comment insert a picture;
LINE(-1,-1,-1,1); LINE(1,1,-1,1);
LINE(1,1,1,-1); LINE(-1,-1,1,-1);
comment outline it;
FNTSELECT(2,"METMBM"); FNTSELECT(3,"METSBM");
FNTSELECT(103,"BASL30");
comment select some fonts;
FNTPOS(-1,1.03,1,1,0,0);
FNTEXT(0,0,2,"See the pretty aeroplane");
comment use font 2;
DRKEN;
BEGIN REAL ARRAY X,Y[1:20]; INTEGER I;
FOR I←1 STEP 1 UNTIL 20 DO
BEGIN X[I]←.89+0.304*COS((I-1)*2*3.14159/20);
Y[I]←.5+0.12*SIN((I-1)*2*3.14159/20); END;
X[12]←.62; Y[12]←-.23;
POLYGO(20,X[1],Y[1]);
LITEN;
FOR I←1 STEP 1 UNTIL 20 DO
LINE(X[I],Y[I],X[(I MOD 20)+1],Y[(I MOD 20)+1],3);
END;
comment make a balloon;
FNTPOS(.89,.5);
DEPOSIT(0,0,CENTER(JTXT(3,"Yow !!! I am an L1011 !!")));
comment put font 3 text into it;
DPYUP(-1); KILJOB(FJ); comment close the GOD file;
END;
The GOD file contains graphics commands like line, dot, text, picture etc. When PRETTY.SAI says LINE(...) a line command gets written into PRETTY.GOD. When it says PICFIL(..., “SF1.PIC”) a binary rendition of the command gets written into the file. It is the job of whatever program reads PRETTY.GOD to deposit the picture when it encounters the PICFIL command in it, just like it's its responsibility to draw a line when it sees a LINE command.
You can insert a .GOD file into as document with XGPSYG by including a line of the form
in your text. This means
| ⊂⊗⊃ | Here is an escape |
| G | it's a GOD file escape |
| [0,.5] | diagram center is 0 in right and .5 above page center |
| (5,4) | diagram is to be 5 inches wide by 4 inches high |
| PRETTY.GOD | get your graphics commands from this file |
| ⊂⊗⊃ | Here is the end of the escape |
The position field in square brackets and the size field in parens are optional. If left out, the picture will be centered around where your escape text would have appeared if you had XSPOOLED'd or XGPSYN'ed your document. An alternative form for the position field is [%-2.3,%+3.7], which means the center of the diagram is to be put 2.3 inches to the left and 3.7 inches above where your escape sequence would have been deposited. Thus you can position diagrams on the page either absolutely, or relative to the position of the escape sequence. It is ok to make the X position, say, relative and the Y position absolute.
<-- Previous  Next -->