|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 14471 (0x3887) Types: TextFile Names: »dmd-sp.c«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89 └─⟦this⟧ »./DVIware/laser-setters/umd-dvi/dev/dmd-sp.c«
/* * 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); }