diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/umddvi/dev/dmd-sp.c |
Initial commit
Diffstat (limited to 'dviware/umddvi/dev/dmd-sp.c')
-rw-r--r-- | dviware/umddvi/dev/dmd-sp.c | 568 |
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); +} |