summaryrefslogtreecommitdiff
path: root/dviware/umddvi/dev/dmd-sp.c
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/umddvi/dev/dmd-sp.c')
-rw-r--r--dviware/umddvi/dev/dmd-sp.c568
1 files changed, 568 insertions, 0 deletions
diff --git a/dviware/umddvi/dev/dmd-sp.c b/dviware/umddvi/dev/dmd-sp.c
new file mode 100644
index 0000000000..40bf02424b
--- /dev/null
+++ b/dviware/umddvi/dev/dmd-sp.c
@@ -0,0 +1,568 @@
+/*
+ * Support drawing routines for Chris Torek's DVI->ImPress program.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "types.h"
+#include "dmdcodes.h"
+
+/* Put a two-byte (word) value to the Imagen */
+#define putword(w) (putchar((w) >> 8), putchar(w))
+
+extern char *malloc();
+
+
+#define TRUE 1
+#define FALSE 0
+
+#define PI 3.14157926536
+#define TWOPI (PI*2.0)
+#define MAXPOINTS 300 /* Most number of points in a path */
+
+
+/* Graphics operations */
+#define WHITE 0
+#define SHADE 3
+#define OR 7
+#define BLACK 15
+
+extern double cos(), sin(), sqrt();
+extern int DPI; /* Resolution of device */
+#define PixPerInX DPI
+#define PixPerInY DPI
+
+extern int UserMag;
+#define fconv(x, f)\
+ (((double)(x)/1000.0) * ((double)(f)) * ((double)UserMag/1000.0))
+#define conv(x, f)\
+ ((int) ((((double)(x)/1000.0) * ((double)(f)) * ((double)UserMag/1000.0)) + 0.5))
+#define xconv(x) conv(x, PixPerInX)
+#define yconv(y) conv(y, PixPerInY)
+
+extern int ImHH; /* Imagen horizontal position */
+extern int ImVV; /* Imagen vertical position */
+extern int hh; /* current horizontal position, in DEVs */
+extern int vv; /* current vertical position, in DEVs */
+
+
+static int xx[MAXPOINTS], yy[MAXPOINTS], pathlen,
+ pensize = 1; /* Size we want Imagen to draw at, default 2 pixels */
+
+#define MAXPENSIZE 20 /* Imagen restriction */
+
+static int
+ family_defined = FALSE, /* Have we chosen family yet? */
+ texture_defined = FALSE,/* Have we done a set_texture yet? */
+ whiten_next = FALSE, /* Should next object be whitened? */
+ blacken_next = FALSE, /* Should next object be blackened? */
+ shade_next = FALSE; /* Should next object be shaded? */
+
+/* Predefined shading (texture) glyph */
+/* First, define size of glyph */
+#define THEIGHT 32 /* bits high */
+#define TWIDTH 4 /* bytes wide */
+/* Next, declare the bit map for the glyph */
+static char stexture[THEIGHT][TWIDTH]={
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
+
+/*
+ * Copy a default texture into the stexture array
+ */
+static void glyph_init()
+{
+ static char btexture[THEIGHT][TWIDTH]={
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
+
+ int i;
+ for (i=0; i<THEIGHT; i++)
+ bcopy(btexture[i],stexture[i],TWIDTH);
+
+}
+
+#define push_location()
+#define pop_location()
+
+#ifdef notdef
+/*
+ * Push the state of the Imagen and set up a new virtual coord system
+ */
+static void push_location()
+{
+ putchar(imP_Push);
+ putchar(imP_SetHVSystem);
+ putchar(0140);
+}
+
+
+/*
+ * Create the pushed virtual page, and pop the state of the printer
+ */
+static void pop_location()
+{
+ putchar(imP_Pop);
+}
+#endif
+
+
+/*
+ * Set the pen size
+ * Called as \special{pn size}
+ * eg: \special{pn 8}
+ * The size is the number of milli-inches for the diameter of the pen.
+ * This routine converts that value to device-dependent pixels, and makes
+ * sure that the resulting value is within legal bounds.
+ */
+static void im_pensize(cp)
+char *cp;
+{
+ int size;
+
+ if (sscanf(cp, " %d ", &size) != 1) return;
+ pensize = yconv(size);
+ if (pensize < 1) pensize = 1;
+ else if (pensize > MAXPENSIZE) pensize = MAXPENSIZE;
+}
+
+
+/*
+ * Make sure the pen size is set. Since we push and pop the state,
+ * this has to be sent for each different object (I think).
+ */
+static void set_pen_size()
+{
+ putchar(DMD_PENSIZE);
+ putchar(pensize);
+}
+
+
+/*
+ * Actually apply the attributes (shade, whiten, or blacken) to the currently
+ * defined path/figure.
+ */
+static void do_attributes()
+{
+ static int family; /* Family of downloaded texture glyph */
+ static int member; /* Member of family */
+ int i,j; /* Loop through glyph array */
+
+ if (shade_next) {
+ shade_next = FALSE;
+#ifdef notdef
+ if (!family_defined) {
+ family_defined = TRUE;
+ family = fnum++;
+ member = -1;
+ }
+ if (!texture_defined) {
+ texture_defined = TRUE;
+ member++;
+ putchar(imP_DefGlyph);
+ putchar((family & 0x7e) >> 1);
+ putchar((family & 0x01) << 7 | (member & 0x7f));
+ /*putword(0); */ /* Advance width */
+ putword(32);
+ putword(TWIDTH*8); /* pixel width (8 x number of bytes) */
+ /*putword(0); */ /* left offset */
+ putword(32);
+ putword(THEIGHT); /* and height of glyph */
+ /*putword(0); */ /* top offset */
+ putword(32);
+ for (i=0; i<THEIGHT; i++)/* Do rows */
+ for (j=0; j<TWIDTH; j++) putchar(stexture[i][j]);
+ }
+ putchar(imP_SetTexture);
+ putchar((family & 0x7e) >> 1);
+ putchar((family & 0x01) << 7 | (member & 0x7f));
+#endif
+ putchar(DMD_FILLPATH);
+ putchar(SHADE);
+ glyph_init(); /* reinitialize the array */
+ }
+ else if (whiten_next) {
+ whiten_next = FALSE;
+ putchar(DMD_FILLPATH);
+ putchar(WHITE);
+ }
+ else if (blacken_next) {
+ blacken_next = FALSE;
+ putchar(DMD_FILLPATH);
+ putchar(BLACK);
+ }
+}
+
+
+/*
+ * Flush the path that we've built up with im_drawto()
+ * Called as \special{fp}
+ */
+static void im_flushpath()
+{
+ register int i;
+
+ push_location();
+ if (pathlen <= 0) return;
+ set_pen_size();
+ putchar(DMD_SEGMENT);
+ putword(pathlen);
+ for (i=1; i<=pathlen; i++) {
+ putword(xx[i]);
+ putword(yy[i]);
+ }
+ pathlen = 0;
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+ do_attributes();
+ pop_location();
+}
+
+
+/* Helper routine for dashed_line() */
+static void connect(x0, y0, x1, y1)
+int x0, y0, x1, y1;
+{
+ set_pen_size();
+ putchar(DMD_SEGMENT);
+ putword(2); /* Path length */
+ putword(x0); putword(y0);/* The path */
+ putword(x1); putword(y1);
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+}
+
+
+/* Another helper. Draw a dot at the indicated point */
+static void dot_at(x, y)
+int x,y;
+{
+ set_pen_size();
+ putchar(DMD_SEGMENT);
+ putword(1); /* Path length */
+ putword(x); putword(y); /* The path */
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+}
+
+
+/*
+ * Draw a dashed or dotted line between the first pair of points in the array
+ * Called as \special{da <inchesperdash>} (dashed line)
+ * or \special{dt <inchesperdot>} (dotted line)
+ * eg: \special{da 0.05}
+ */
+static void dashed_line(cp, dotted)
+char *cp;
+int dotted; /* boolean */
+{
+ int i, numdots, x0, y0, x1, y1;
+ double cx0, cy0, cx1, cy1;
+ double d, spacesize, a, b, dx, dy, pixperdash;
+ float inchesperdash;
+
+ if (sscanf(cp, " %f ", &inchesperdash) != 1) return;
+ if (pathlen <= 1) return;
+ pixperdash = inchesperdash * ((float) PixPerInY);
+ if (pixperdash < 2.)
+ pixperdash = 2.;
+ x0 = xx[1]; x1 = xx[2];
+ y0 = yy[1]; y1 = yy[2];
+ dx = x1 - x0;
+ dy = y1 - y0;
+ push_location();
+ if (dotted) {
+ numdots = sqrt(dx*dx + dy*dy) / pixperdash + 0.5;
+ if (numdots > 0)
+ for (i = 0; i <= numdots; i++) {
+ a = (float) i / (float) numdots;
+ cx0 = ((float) x0) + (a*dx) + 0.5;
+ cy0 = ((float) y0) + (a*dy) + 0.5;
+ dot_at((int) cx0, (int) cy0);
+ }
+ }
+ else {
+ d = sqrt(dx*dx + dy*dy);
+ if (d <= 2 * pixperdash) {
+ connect(x0, y0, x1, y1);
+ pathlen = 0;
+ pop_location();
+ return;
+ }
+ numdots = d / (2 * pixperdash) + 1;
+ spacesize = (d - numdots * pixperdash) / (numdots - 1);
+ for (i=0; i<numdots-1; i++) {
+ a = i * (pixperdash + spacesize) / d;
+ b = a + pixperdash / d;
+ cx0 = ((float) x0) + (a*dx) + 0.5;
+ cy0 = ((float) y0) + (a*dy) + 0.5;
+ cx1 = ((float) x0) + (b*dx) + 0.5;
+ cy1 = ((float) y0) + (b*dy) + 0.5;
+ connect((int) cx0, (int) cy0, (int) cx1, (int) cy1);
+ b += spacesize / d;
+ }
+ cx0 = ((float) x0) + (b*dx) + 0.5;
+ cy0 = ((float) y0) + (b*dy) + 0.5;
+ connect((int) cx0, (int) cy0, x1, y1);
+ }
+ pathlen = 0;
+ pop_location();
+}
+
+
+/*
+ * Virtually draw to a given x,y position on the virtual page.
+ * X and Y are expressed in thousandths of an inch, and this
+ * routine converts them to pixels.
+ *
+ * Called as \special{pa <x> <y>}
+ * eg: \special{pa 0 1200}
+ */
+static void im_drawto(cp)
+char *cp;
+{
+ int x,y;
+
+ if (sscanf(cp, " %d %d ", &x, &y) != 2) return;
+
+ if (++pathlen >= MAXPOINTS)
+ error(1, 0, "Too many points specified");
+ xx[pathlen] = xconv(x) + ImHH;
+ yy[pathlen] = yconv(y) + ImVV;
+}
+
+/* Same routine as above, but it uses the special graphics primitives */
+static void im_arc(cp)
+char *cp;
+{
+ int xc, yc, xrad, yrad;
+ float start_angle, end_angle, fxrad, fyrad;
+ int xp, yp;
+
+ if (sscanf(cp, " %d %d %d %d %f %f ", &xc, &yc, &xrad, &yrad, &start_angle,
+ &end_angle) != 6) return;
+ push_location();
+ set_pen_size();
+ xc = xconv(xc) + ImHH;
+ yc = yconv(yc) + ImVV;
+ {
+ double temp;
+ temp = start_angle;
+ start_angle = end_angle;
+ end_angle = temp;
+ }
+ if (xrad >= yrad-1 && xrad <= yrad+1) { /* Circle or arc */
+ putchar(DMD_CIRCLE);
+ putword(xc); putword(yc);
+ /* starting point */
+ fyrad = fconv(yrad, PixPerInY);
+ xp = fyrad * cos(start_angle) + xc + .5;
+ yp = fyrad * sin(start_angle) + yc + .5;
+ putword(xp); putword(yp);
+ /* finishing point */
+ xp = fyrad * cos(end_angle) + xc + .5;
+ yp = fyrad * sin(end_angle) + yc + .5;
+ putword(xp); putword(yp);
+ }
+ else { /* Ellipse */
+ putchar(DMD_ELLIPSE);
+ putword(xc); putword(yc);
+ /* starting point */
+ fxrad = fconv(xrad, PixPerInX);
+ fyrad = fconv(yrad, PixPerInY);
+ xp = fxrad * cos(start_angle) + xc + .5;
+ yp = fyrad * sin(start_angle) + yc + .5;
+ putword(xp); putword(yp);
+ /* finishing point */
+ xp = fxrad * cos(end_angle) + xc + .5;
+ yp = fyrad * sin(end_angle) + yc + .5;
+ putword(xp); putword(yp);
+ putword(xconv(xrad));
+ putword(yconv(yrad));
+ }
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+ do_attributes();
+ pop_location();
+}
+
+
+/*
+ * Create a spline through the points in the array.
+ * Called like flush path (fp) command, after points
+ * have been defined via pa command(s).
+ *
+ * eg: \special{sp}
+ */
+static void flush_spline()
+{
+ register int i;
+
+ push_location();
+ if (pathlen <= 0) return;
+ set_pen_size();
+ putchar(DMD_SPLINE);
+ putword(pathlen);
+ for (i=1; i<=pathlen; i++) {
+ putword(xx[i]);
+ putword(yy[i]);
+ }
+ pathlen = 0;
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+ do_attributes();
+ pop_location();
+}
+
+
+/*
+ * Whiten the interior of the next figure (path). Command is:
+ * \special{wh}
+ */
+static void im_whiten()
+{
+ whiten_next = TRUE;
+}
+
+
+/*
+ * Blacken the interior of the next figure (path). Command is:
+ * \special{bk}
+ */
+static void im_blacken()
+{
+ blacken_next = TRUE;
+}
+
+
+/*
+ * Shade the interior of the next figure (path) with the predefined
+ * texture. Command is:
+ * \special{sh}
+ */
+static void im_shade()
+{
+ shade_next = TRUE;
+}
+
+
+/*
+ * Define the texture array. Command is:
+ * \special{tx 32bits 32bits ....}
+ */
+static void im_texture(pcount,bitpattern)
+int pcount, bitpattern[32];
+{
+ int i,j,k;
+ unsigned long ul_one;
+
+#ifdef notdef
+#ifdef DEBUG
+ if (sizeof ul_one != TWIDTH)
+ error(1, 0, "pointer/size mismatch");
+#endif
+ j = 0;
+ for (k=0; k < THEIGHT/pcount; k++) {
+ for (i=0; i<pcount; i++) {
+ ul_one = htonl((unsigned long) bitpattern[i]);
+ bcopy((char *) &ul_one, stexture[j++], TWIDTH);
+ }
+ }
+ texture_defined = FALSE;
+#endif
+}
+
+
+/*
+ * This routine takes the string argument for a tx command and
+ * parses out the separate bitpatterns to call im_texture with.
+ * Written by Tinh Tang
+ */
+static void do_texture(t)
+char *t;
+{
+ int bitpattern[32];
+ int pcount = 0;
+
+ while (isspace (*t)) t++;
+ while (*t) {
+ if (sscanf(t, "%x", &bitpattern[pcount++]) != 1) {
+ error(0, 0, "malformed tx command");
+ return;
+ }
+ while (*t && !isspace(*t)) t++;/* Skip to space */
+ while (*t && isspace(*t)) t++;/* Skip to nonspace */
+ }
+ if (pcount != 4 && pcount != 8 && pcount != 16 && pcount != 32) {
+ error(0, 0, "malformed tx command");
+ return;
+ }
+ im_texture(pcount, bitpattern);
+}
+
+
+#define COMLEN 3 /* Length of a tpic command plus one */
+
+DoSpecial(k)
+ i32 k;
+{
+ char *spstring, *cp, command[COMLEN];
+ register int len;
+
+ spstring = malloc((unsigned) (k+1));
+ if (spstring == NULL) error(2, 0, "Out of memory");
+ len = 0;
+ while (k--) spstring[len++] = GetByte(stdin);
+ spstring[len] = '\0';
+ cp = spstring;
+ while (isspace(*cp)) ++cp;
+ len = 0;
+ while (!isspace(*cp) && *cp && len < COMLEN-1) command[len++] = *cp++;
+ command[len] = '\0';
+
+ if (ImHH != hh || ImVV != vv)
+ ImSetPosition(hh, vv);
+
+ if (strcmp(command, "pn") == 0) im_pensize(cp);
+ else if (strcmp(command, "fp") == 0) im_flushpath();
+ else if (strcmp(command, "da") == 0) dashed_line(cp, 0);
+ else if (strcmp(command, "dt") == 0) dashed_line(cp, 1);
+ else if (strcmp(command, "pa") == 0) im_drawto(cp);
+ else if (strcmp(command, "ar") == 0) im_arc(cp);
+ else if (strcmp(command, "sp") == 0) flush_spline();
+ else if (strcmp(command, "sh") == 0) im_shade();
+ else if (strcmp(command, "wh") == 0) im_whiten();
+ else if (strcmp(command, "bk") == 0) im_blacken();
+ else if (strcmp(command, "tx") == 0) im_texture(cp);
+ else error(0, 0, "warning: ignoring \\special");
+
+ free(spstring);
+}