head 1.9; access ; symbols ; locks ; comment @ * @; 1.9 date 89.05.02.17.33.11; author pkern; state Exp; branches ; next 1.8; 1.8 date 89.03.23.13.22.07; author pkern; state Exp; branches ; next 1.7; 1.7 date 89.03.15.15.00.16; author pkern; state Exp; branches ; next 1.6; 1.6 date 89.03.08.19.12.06; author pkern; state Exp; branches ; next 1.5; 1.5 date 89.01.31.14.04.07; author pkern; state Exp; branches ; next 1.4; 1.4 date 89.01.31.13.27.33; author pkern; state Exp; branches ; next 1.3; 1.3 date 89.01.05.12.02.35; author pkern; state Exp; branches ; next 1.2; 1.2 date 89.01.05.11.46.15; author pkern; state Exp; branches ; next 1.1; 1.1 date 89.01.04.20.02.56; author pkern; state Exp; branches ; next ; desc @@ 1.9 log @*** empty log message *** @ text @/* * gfx.c: simple graphics access * * Copyright (c) 1989 University of Toronto. All rights reserved. * Anyone may use or copy this software, except that it may not be * sold for profit, that this copyright notice remain intact, and that * credit is given where it is due. The University of Toronto and the * author make no warranty and accept no liability for this software. */ static char rcsid[] = "$Header: gfx.c,v 1.8 89/03/23 13:22:07 pkern Exp $"; #include "cterm.h" extern int zip(); uchar gcolour=7; int gmax_x=1, gmax_y=1, gmax_clr=8; /* the above will be re-initialized in init_gfx() */ static int gx=0, gy=0; /* * gfx -- simple (dumb?) graphics access * expects "^[@@" * upper case motion cmd -> do move "with pen up" * lower case motion cmd -> draw line to new position */ gfx(s, slen) char *s; int slen; { char *p, c; int i, n, pnc, pn[8]; /* get parameter numbers */ for (i=0; i<8; i++) pn[i] = 0; for (i=2, pnc=0; i=0 && n<=9) pn[pnc] = pn[pnc] * 10 + n; else /* it's ';' or it's the final char */ pn[++pnc] = 0; } c = s[i-1]; switch (c) { case 'H': case 'h': /* goto position */ case '@@': /* & boink (ie. goto with pen up & drop pen) */ if (pn[1] > gmax_x) pn[1] = gmax_x; if (pn[0] > gmax_y) pn[0] = gmax_y; if (c & 040) bline(gx, gy, pn[1], pn[0], gcolour); gx = pn[1]; gy = pn[0]; if (c == '@@') boink(gx, gy, gcolour); break; case 'A': case 'a': /* "cursor" up */ if (!pn[0]) pn[0] = 1; if ((pn[0] = (gy - pn[0])) < 0) pn[0] = 0; if (c & 040) vline(gx, pn[0], gy-pn[0]+1, gcolour); gy = pn[0]; break; case 'B': case 'b': /* down */ if (!pn[0]) pn[0] = 1; if ((pn[0] = (gy + pn[0])) > gmax_y) pn[0] = gmax_y; if (c & 040) vline(gx, gy, pn[0]-gy+1, gcolour); gy = pn[0]; break; case 'C': case 'c': /* right */ if (!pn[0]) pn[0] = 1; if ((pn[0] = (gx + pn[0])) > gmax_x) pn[0] = gmax_x; if (c & 040) hline(gx, gy, pn[0]-gx+1, gcolour); gx = pn[0]; break; case 'D': case 'd': /* left */ if (!pn[0]) pn[0] = 1; if ((pn[0] = (gx - pn[0])) < 0) pn[0] = 0; if (c & 040) hline(pn[0], gy, gx-pn[0]+1, gcolour); gx = pn[0]; break; case 'F': /* fill */ dofill(gx, gy, gcolour, gcolour); break; case 'O': /* circle(x,y,r,colour) */ if (!pn[0]) pn[0] = 1; docirc(gx, gy, pn[0], gcolour); break; case 'L': /* ellipse(x,y,a,b,colour) */ mgr_ellipse(gx, gy, pn[1], pn[0], gcolour); break; case 'R': /* arc(x,y,xa,ya,xb,yb,colour) */ if (pn[1] > gmax_x) pn[1] = gmax_x - pn[1]; if (pn[0] > gmax_y) pn[0] = gmax_y - pn[0]; mgr_arc(pn[1], pn[0], gx, gy, pn[3], pn[2], gcolour); break; case 'J': /* erase */ gfx_erase(); break; case 'm': /* change current colour */ gcolour = gfx_colour(pn[pnc-1]); break; case 'x': /* report graphics parameters */ p = "X@@....;....x"; /* return the y,x limits */ sprintf(p, "\033@@%d;%dx", gmax_y, gmax_x); zip(p); break; default: break; } } /* * draw line from (x0,y0) to (x1,y1) with colour clr. * using Bresenham's Line Algorithm (BYTE, Mar/88, p.252) */ bline(x0,y0,x1,y1,clr) int x0,y0,x1,y1; uchar clr; { register int x, y; /* current x,y coords */ register int d, i; /* decision variable / utility */ int a, b, /* line displacements in x, y */ dx_d, dy_d, /* diagonal x/y steps for next point */ dx_nd, dy_nd, /* nondiag. x/y steps for next point */ d_inc, nd_inc; /* "d" inc for diag/nondiag steps */ x = x0; y = y0; /* start point */ a = x1 - x0; dx_d = 1; b = y1 - y0; dy_d = 1; /* if vert or horiz lines, use custom routines instead */ if (b == 0) { hline(x, y, a+1, clr); return; } if (a == 0) { vline(x, y, b+1, clr); return; } if (a < 0) { a = -a; dx_d = -1; } if (b < 0) { b = -b; dy_d = -1; } /* identify end-point octant */ if (a < b) { i = a; a = b; b = i; /* swap a and b */ dx_nd = 0; /* larger y-diff means x won't change */ dy_nd = dy_d; /* on nondiag steps, but y will */ } else { dx_nd = dx_d; /* x changes every step; y changes */ dy_nd = 0; /* only on the diag steps */ } d = b + b - a; nd_inc = b + b; d_inc = b + b - a - a; for (i=0; i <= a; i++) { /* draw a+1 points */ boink(x,y,clr); /* if midpoint is above the line ... */ if (d < 0) /* then step nondiagonally */ { x += dx_nd; y += dy_nd; d += nd_inc; } else /* else step diagonally */ { x += dx_d; y += dy_d; d += d_inc; } } } /* * Bresenham's algorithms: circles and filling */ #define BONK(a,b,A) \ if (0 <= (a) && (a) < gmax_x \ && 0 <= (b) && (b) < gmax_y) \ boink((a), (b), (A)) static docirc(x, y, r, c) int x, y, r; uchar c; { int d, xd, yd; xd = x; yd = y; x = 0; y = r; d = 3 - 2 * r; while (x < y) { BONK(xd + x, yd + y, c); BONK(xd + y, yd + x, c); BONK(xd + y, yd - x, c); BONK(xd + x, yd - y, c); BONK(xd - x, yd - y, c); BONK(xd - y, yd - x, c); BONK(xd - y, yd + x, c); BONK(xd - x, yd + y, c); if (d < 0) d = d + 4 * x + 6; else { d = d + 4 * (x - y) + 10; y = y - 1; } x = x + 1; } if (x == y) { BONK(xd + x, yd + y, c); BONK(xd + y, yd + x, c); BONK(xd + y, yd - x, c); BONK(xd + x, yd - y, c); BONK(xd - x, yd - y, c); BONK(xd - y, yd - x, c); BONK(xd - y, yd + x, c); BONK(xd - x, yd + y, c); } } static dofill(x0, y0, nc, bc) int x0, y0; uchar nc, bc; { uchar c; int i, x, y; int xi, xn, xo; int *xy, xyi; /* the "stack" and the "stack pointer" */ xyi = 0; xy = (int *) malloc(2 * gmax_x * (sizeof(xyi))); #define PUSH(a,b) xy[xyi]=(a); xy[xyi+1]=(b); xyi+=2; #define POP(a,b) xyi-=2; a=xy[xyi]; b=xy[xyi+1]; PUSH(x0,y0) x = x0; y = y0; PUSH(x,y) while (xyi > 2) { /* get next starting coords */ POP(x,y) /* find start of run */ xo = xrun(x, y, bc, -1); /* leftmost point */ /* find end of run */ x = xrun(xo, y, bc, 1); /* rightmost point */ /* do the run */ hline(xo, y, x - xo + 1, nc); /* find new runs */ for (i = -1; i < 2; i++) { if (i == 0 || 0 > y+i || y+i >= gmax_y) continue; #ifdef NORM for (xi = xo, xn = 0; xi <= x; xi++) { c = gpeek(xi, y+i); if (c != bc) { if (!xn) { PUSH(xi,y+i) } xn++; } else xn = 0; } #else /* minor optimization */ for (xi = xo; xi <= x; ) { xn = xrun(xi, y+i, bc, 1); if (xn < xi) xi++; else { PUSH(xi,y+i); xi = xn + 1; } } #endif } } } @ 1.8 log @new commands for drawing arcs and ellipses (gfx_m.c) @ text @d10 1 a10 1 static char rcsid[] = "$Header: gfx.c,v 1.7 89/03/15 15:00:16 pkern Exp $"; d90 3 a92 1 mgr_arc(gx, gy, pn[1], pn[0], pn[3], pn[2], gcolour); @ 1.7 log @parameter report added, plus some attempted speed tweaking. @ text @d10 1 a10 1 static char rcsid[] = "$Header: gfx.c,v 1.6 89/03/08 19:12:06 pkern Exp $"; d18 1 d25 2 a26 2 * upper case cmd -> do move "with pen up" * lower case cmd -> draw line to new position d36 1 a36 2 pn[0] = pn[1] = pn[2] = pn[3] = 0; pn[4] = pn[5] = pn[6] = pn[7] = 0; d82 1 a82 1 case 'O': /* circle */ d86 6 d96 1 a96 1 gcolour = pn[pnc-1] % gmax_clr; d99 3 a101 3 p = "X@@...;....;....x"; sprintf(p, "\033@@%d;%d;%dx", gmax_clr, gmax_y, gmax_x); a112 1 static d163 1 a163 1 * Bresenham's algorithms @ 1.6 log @*** empty log message *** @ text @d10 1 a10 1 static char rcsid[] = "$Header: gfx.c,v 1.5 89/01/31 14:04:07 pkern Exp $"; d14 2 d17 1 a17 1 int gmax_x=1, gmax_y=1; d90 1 a90 1 gcolour = pn[pnc-1] % 8; d92 6 d112 3 a114 3 int x, y, /* current x,y coords */ d, i, /* decision variable / utility */ a, b, /* line displacements in x, y */ @ 1.5 log @*** empty log message *** @ text @d4 5 a8 1 * copyright (c) University of Toronto, 1988. d10 1 a10 1 static char rcsid[] = "$Header$"; d117 2 a118 2 if (b == 0) { hline(x, y, a, clr); return; } if (a == 0) { vline(x, y, b, clr); return; } @ 1.4 log @clean up xy stack declaration @ text @d6 1 a6 1 static char *ID = "gfx.c Oct/88 Univ. of Toronto"; d8 1 a8 1 #include "common.h" @ 1.3 log @*** empty log message *** @ text @d203 1 a203 1 int xy[2*gmax_x], xyi; d206 1 @ 1.2 log @TI graphics nitty-gritty moved to screen.c @ text @d10 3 a13 1 static uchar gcolour=7; a14 2 int gmax_x=1, gmax_y=1; d43 2 a44 2 if (pn[1] > GMAX_X) pn[1] = GMAX_X; if (pn[0] > GMAX_Y) pn[0] = GMAX_Y; d57 1 a57 1 if ((pn[0] = (gy + pn[0])) > GMAX_Y) pn[0] = GMAX_Y; d63 1 a63 1 if ((pn[0] = (gx + pn[0])) > GMAX_X) pn[0] = GMAX_X; d149 2 a150 2 if (0 <= (a) && (a) < GMAX_X \ && 0 <= (b) && (b) < GMAX_Y) \ d203 1 a203 1 int xy[2*GMAX_X], xyi; d228 1 a228 1 if (i == 0 || 0 > y+i || y+i >= GMAX_Y) @ 1.1 log @Initial revision @ text @d2 1 a2 1 * gfx.c: simple access for TI Pro graphics d8 1 a8 5 #ifdef dbgfx #include static int fd=0; static char buf[256]; #endif a9 5 typedef unsigned char uchar; #define GMAX_X 720 #define GMAX_Y 300 d13 1 a13 4 /* graphics palette attribute latches */ #define L_BLU *((char far *)0xdf000010) #define L_GRN *((char far *)0xdf000020) #define L_RED *((char far *)0xdf000030) a14 6 static uchar l_blu=0xAA, l_red=0xCC, l_grn=0xF0; #define L_SYNC L_BLU=l_blu; L_RED=l_red; L_GRN=l_grn; extern uchar interlace; d39 1 a39 9 #ifdef dbgfx if (fd) write(fd, "@@", 1); for (n=0; n> ((a)%16)) init_gfx() { #ifdef dbgfx if (fd > 0) close(fd); fd = open("gfx.log", O_WRONLY|O_CREAT|O_APPEND, 0664); if (fd < 0) fd = 0; #endif L_BLU = L_RED = L_GRN = 0; if (interlace) { gcolour = 7; L_SYNC } } static unsigned int ofs, msk; #define BOINK(a) \ GBa(ofs) = (a & 1) ? (GBa(ofs) | msk) : (GBa(ofs) & ~msk); \ GBb(ofs) = (a & 4) ? (GBb(ofs) | msk) : (GBb(ofs) & ~msk); \ GBc(ofs) = (a & 2) ? (GBc(ofs) | msk) : (GBc(ofs) & ~msk); #define GPEEK \ ((((GBa(ofs) & msk) == msk) * 1) \ | (((GBc(ofs) & msk) == msk) * 2) \ | (((GBb(ofs) & msk) == msk) * 4)) static gpeek(x, y) int x, y; { uchar c; msk = GMASK(x); ofs = GBOFS(x,y); a91 19 * c = ((GBa(ofs) & msk) == msk); * c |= ((GBc(ofs) & msk) == msk) << 1; * c |= ((GBb(ofs) & msk) == msk) << 2; */ c = GPEEK; return(c); } static boink(x,y,c) int x, y; uchar c; { msk = GMASK(x); ofs = GBOFS(x,y); BOINK(c) } /* d135 1 a135 4 /* boink(x,y,clr); */ msk = GMASK(x); ofs = GBOFS(x,y); BOINK(clr) a145 73 * hline -- only does horizontal lines (union regulations :-) * use solid(ie. multi bit) masks and increment the offset */ static hline(x,y,n,c) int x,y,n; uchar c; { if (n < 0) { n = -n; x -= n; if (x < 0) { n += x; x = 0; } } msk = 0xffff >> (x%16); /* make mask go to end of 16bit word */ for(ofs=GBOFS(x,y); ofs < GBOFS(x+n, y); ofs++) { BOINK(c) msk = 0xffff; /* ie. solid while between end-points */ } msk &= ~(0xffff >> ((x+n)%16)); /* remainder word mask */ BOINK(c) } /* * vline -- vertical lines only * get bit mask once then move it up or down * by changing only the offset +/- 46. */ static vline(x,y,n,c) int x,y,n; uchar c; { if (n < 0) { n = -n; y -= n; if (y < 0) { n += y; y = 0; } } msk = GMASK(x); ofs = GBOFS(x,y); for (; n; n--, ofs+=46) { BOINK(c) } } #ifdef undef /* * Fill algorithm from Byte (Sept/87). */ static dofill(x, y, c) int x, y; uchar c; { uchar bc; if (x < 1 || y < 1 || x > GMAX_X || y > GMAX_Y) return; msk = GMASK(x); ofs = GBOFS(x,y); bc = GPEEK; if (bc != c) { BOINK(c) dofill(x-1,y,c); dofill(x+1,y,c); dofill(x,y-1,c); dofill(x,y+1,c); } } #endif /* d230 1 a230 1 #ifdef OPTIM d242 1 a242 1 #else a254 31 } /* * optimize search for runs */ static xrun(x, y, c, dir) int x, y, dir; uchar c; { uchar cx; unsigned int ba, bb, bc; msk = GMASK(x); ofs = GBOFS(x,y); ba = GBa(ofs); bb = GBb(ofs); bc = GBc(ofs); while (0 <= x && x < GMAX_X) { cx = ((ba & msk) == msk) \ + (((bc & msk) == msk) * 2)\ + (((bb & msk) == msk) * 4); if (c == cx) break; x += dir; msk = GMASK(x); if (((dir > 0) && (x%16) == 0) || ((dir < 0) && (x%16) == 15)) { ofs = GBOFS(x,y); ba = GBa(ofs); bb = GBb(ofs); bc = GBc(ofs); } } if (c == cx) x -= dir; return(x); @