/* emul.c 20 January 1999 */ /* copyright 1989 Phil Andrews, Pittsburgh Supercomputing Center */ /* this is the emulation module to help device drivers who can't have it all */ #include #include #include #include "defs.h" /* store these pointers to allow lookups into the CGM data structures */ static struct one_opt *popt; /* the command line options, in only */ static struct mf_d_struct *pc1; /* the class 1 elements, in only */ static struct pic_d_struct *pc2; /* the class 2 elements, in only */ static struct control_struct *pc3; /* the class 3 elements, in only */ static struct attrib_struct *pc5; /* the class 5 elements, in only */ static struct info_struct *dptr; /* device info, in only */ /* these will tell us what the device can do */ static int (**p_delim)(); /* delimiter functions */ static int (**p_mfdesc)(); /* metafile descriptor functions */ static int (**p_pdesc)(); /* page descriptor functions */ static int (**p_mfctrl)(); /* controller functions */ static int (**p_gprim)(); /* graphical primitives */ static int (**p_attr)(); /* the attribute functions */ static int (**p_escfun)(); /* the escape functions */ static int (**p_extfun)(); /* the external functions */ static int (**p_ctrl)(); /* controller functions */ static double pi; /* guess */ static int setup = 0; #define int_size (sizeof(int)) /* PROCEDURE DECLARATIONS */ static int em_arc ( int x, int y, int r, double theta0, double theta1, int *no_points, int extra_points, int **x_ptr, int **y_ptr ); /* this is the routine that sets everything up */ /* the initialising routine for the emulation module */ void em_setup(opt, dev_info, c1, c2, c3, c5, delim, mfdesc, pdesc, mfctrl, gprim, attr, escfun, extfun, ctrl, pargc, argv) struct one_opt *opt; /* the command line options, in only */ struct info_struct *dev_info; /* device info */ struct mf_d_struct *c1; /* the class 1 elements, in only */ struct pic_d_struct *c2; /* the class 2 elements, in only */ struct control_struct *c3; /* the class 3 elements, in only */ struct attrib_struct *c5; /* the class 5 elements, in only */ int (*delim[])(); /* delimiter functions */ int (*mfdesc[])(); /* metafile descriptor functions */ int (*pdesc[])(); /* page descriptor functions */ int (*mfctrl[])(); /* controller functions */ int (*gprim[])(); /* graphical primitives */ int (*attr[])(); /* the attribute functions */ int (*escfun[])(); /* the escape functions */ int (*extfun[])(); /* the external functions */ int (*ctrl[])(); /* controller functions */ int *pargc; /* pointer to argc */ char **argv; /* the main argv */ { /* store the command line argument pointer */ popt = opt; /* store the device info pointer */ dptr = dev_info; /* and the cgm data strucures */ pc1 = c1; pc2 = c2; pc3 = c3; pc5 = c5; /* and the device function array pointers */ p_delim = delim; p_mfdesc = mfdesc; p_pdesc = pdesc; p_mfctrl = mfctrl; p_gprim = gprim; p_attr = attr; p_escfun = escfun; p_extfun = extfun; p_ctrl = ctrl; pi = 4.0 * atan(1.0); setup = 1; return; } /* emulate polymarker routine with polylines */ /* the present marker types are 1 dot 2 plus 3 asterisk 4 circle 5 cross */ em_pmarker(no_pairs, x1_ptr, y1_ptr) int no_pairs, *x1_ptr, *y1_ptr; { /* simple descriptions of the marker types */ #define NO_MARKERS 5 static int no_points[NO_MARKERS] = {2, 4, 6, 0, 4}; static int offsets[NO_MARKERS] = {0, 2, 6, 12, 12}; static float markers[32] = { 0.0, 0.0, 0.0, 0.0, /* dot */ 0.0, 0.5, 0.0, -0.5, 0.5, 0.0, -0.5, 0.0, /* plus */ 0.0, 0.5, 0.0, -0.5, 0.25, 0.433, -0.25, -0.433, -0.25, 0.433, 0.25, -0.433, /* asterisk */ 0.354, 0.354, -0.354, -0.354, -0.354, 0.354, 0.354, -0.354}; /* cross */ int ret, i, j, xptr[2], yptr[2], my_off, r, *xnew, *ynew, c_points; if (!setup) return(2); if (!p_gprim[(int) PolyLine]) return(2); /* helpless */ switch(pc5->mk_type) { case 1 : case 2 : case 3 : case 5 : for (i=0; imk_type - 1] * 2; for (j=0; j<(no_points[pc5->mk_type - 1] / 2); ++j) { xptr[0] = x1_ptr[i] + (int) (pc5->mk_size.i * markers[my_off]); yptr[0] = y1_ptr[i] + (int) (pc5->mk_size.i * markers[my_off + 1]); my_off += 2; xptr[1] = x1_ptr[i] + (int) (pc5->mk_size.i * markers[my_off]); yptr[1] = y1_ptr[i] + (int) (pc5->mk_size.i * markers[my_off + 1]); my_off += 2; ret = (*p_gprim[(int) PolyLine])(2, xptr, yptr); } } break; case 4 : for (i=0; imk_size.i * 0.5); if (!em_arc(x1_ptr[i], y1_ptr[i], r, 0.0, 2.0 * pi, &c_points, 0, &xnew, &ynew)) return(2); ret = (*p_gprim[(int) PolyLine])(c_points, xnew, ynew); free(xnew); free(ynew); } break; default: fprintf(stderr, "illegal marker type ! = %d\n", pc5->mk_type); return(2); } return(ret); } #undef NO_MARKERS /* emulate the disjoint poyline */ em_dpline(no_pairs, x1_ptr, y1_ptr) int no_pairs, *x1_ptr, *y1_ptr; { int i; if (!setup || !p_gprim[(int) PolyLine]) { /* helpless */ return(2); } for (i=0; i< (no_pairs / 2); ++i) { (*p_gprim[(int) PolyLine]) (2, x1_ptr + 2 * i, y1_ptr + 2 * i); } return(1); } /* emulate a polygon, implement later */ em_pgon(no_pairs, x1_ptr, y1_ptr) int no_pairs, *x1_ptr, *y1_ptr; { return(1); } /* emulate a polyset, implement later */ em_polyset(no_pairs, x1_ptr, y1_ptr, edge_ptr) int no_pairs, *x1_ptr, *y1_ptr; unsigned char *edge_ptr; { return(1); } /* emulate a cell array, implement later */ em_cell_array(cp, cq, cr, nx, ny, l_col_prec, dat_ptr, rep_mode, no_bytes) int *cp, *cq, *cr, nx, ny, l_col_prec, rep_mode, no_bytes; unsigned char *dat_ptr; { return(1); } /* emulate a graphical drawing primitive, implement later */ em_g_d_p(gdp_id, no_pairs, x_ptr, y_ptr, data_record) int gdp_id, no_pairs, *x_ptr, *y_ptr; char *data_record; { return(1); } /* emulate the rectangle function */ em_rectangle(x1, y1, x2, y2) int x1, y1, x2, y2; { int xarray[5], yarray[5]; if (!setup) { return(2); } if (p_gprim[(int) Polygon]) { xarray[0] = x1; yarray[0] = y1; xarray[2] = x2; yarray[2] = y2; xarray[1] = x2; yarray[1] = y1; xarray[3] = x1; yarray[3] = y2; (*p_gprim[(int) Polygon]) (4, xarray, yarray); } else if (p_gprim[(int) PolyLine]) { xarray[0] = x1; yarray[0] = y1; xarray[2] = x2; yarray[2] = y2; xarray[1] = x2; yarray[1] = y1; xarray[3] = x1; yarray[3] = y2; xarray[4] = x1; yarray[4] = y1; (*p_gprim[(int) PolyLine]) (5, xarray, yarray); } else return(2); /* can't do anything */ return(1); } /* basic circle routine */ static int em_arc ( int x, int y, int r, double theta0, double theta1, int *no_points, int extra_points, int **x_ptr, int **y_ptr ) { double dtheta, dctheta, dstheta, cth0, sth0, cth1, sth1; int i; /* first find a reasonable no. points, get angles between 0 and 2 pi */ while (theta0 < 0.0) theta0 += 2 * pi; while (theta1 < 0.0) theta1 += 2 * pi; while (theta0 > 2.0 * pi) theta0 -= 2 * pi; while (theta1 > 2.0 * pi) theta1 -= 2 * pi; /* how many points ? */ *no_points = (theta1 - theta0) * r / pi; /* reasonable */ if (*no_points < 0) *no_points = (2 * pi + theta0 - theta1) * r / pi; if (*no_points < 2) *no_points = 2; /* must be > 2 */ /* now order them correctly */ if (theta0 > theta1) theta0 -= 2.0 * pi; /* make some memory */ if (!(*x_ptr = (int *) allocate_mem((*no_points + extra_points) * int_size, 0)) || !(*y_ptr = (int *) allocate_mem((*no_points + extra_points) * int_size, 0))) return(0); /* now fill out *no_points worth */ cth0 = cos(theta0); sth0 = sin(theta0); dtheta = (theta1 - theta0) / (*no_points - 1); dctheta = cos(dtheta); dstheta = sin(dtheta); /* starting point */ (*x_ptr)[0] = x + r * cth0; (*y_ptr)[0] = y + r * sth0; /* double precision should take care of roundoff */ for (i=1; i<*no_points; ++i) { /* use recursion relation */ cth1 = cth0 * dctheta - sth0 * dstheta; sth1 = sth0 * dctheta + cth0 * dstheta; (*x_ptr)[i] = x + r * cth1; (*y_ptr)[i] = y + r * sth1; /* update the point */ cth0 = cth1; sth0 = sth1; } return(1); } /* emulate a circle */ em_circle(x, y, r) int x, y, r; /* center (x,y) and radius r */ { int no_points, *xptr, *yptr, extra_points, ret; if (!setup) { return(2); } if (!p_gprim[(int) PolyLine] && !p_gprim[(int) Polygon]) return(2); /* can't do anything */ extra_points = (p_gprim[(int) Polygon]) ? 0 : 1; /* get the points on the circumference */ if (!em_arc(x, y, r, 0.0, 2.0 * pi, &no_points, extra_points, &xptr, &yptr)) return(2); /* do we have a polygon ? */ if (p_gprim[(int) Polygon]) { ret = (*p_gprim[(int) Polygon])(no_points, xptr, yptr); } else if (p_gprim[(int) PolyLine]) { xptr[no_points] = xptr[0]; yptr[no_points] = yptr[0]; ++no_points; ret = (*p_gprim[(int) PolyLine])(no_points, xptr, yptr); } free(xptr); free(yptr); return(ret); } /* emulate an arc, specified by 3 pts */ em_c3(pt_ptr) int *pt_ptr; { int x, y, r; /* circle centre and radius */ float deg[3]; /* starting and ending degrees (0 at top) */ double theta[3]; extern get_c_info(); /* utils.c */ int no_points, *xptr, *yptr, extra_points, ret; if (!setup) { return(2); } if (!p_gprim[(int) PolyLine]) return(2); /* can't do anything */ extra_points = 0; if (!get_c_info(pt_ptr, &x, &y, &r, theta, deg)) return(2); /* get the points on the circumference */ if (!em_arc(x, y, r, theta[0], theta[2], &no_points, extra_points, &xptr, &yptr)) return(2); ret = (*p_gprim[(int) PolyLine])(no_points, xptr, yptr); free(xptr); free(yptr); return(ret); } /* emulate an arc, specified by 3 pts, close it */ em_c3_close(pt_ptr, chord) int *pt_ptr; enum boolean chord; { int x, y, r; /* circle centre and radius */ float deg[3]; /* starting and ending degrees (0 at top) */ double theta[3]; extern get_c_info(); /* utils.c */ int no_points, *xptr, *yptr, extra_points, ret; if (!setup) { return(2); } if (!p_gprim[(int) PolyLine] && !p_gprim[(int) Polygon]) return(2); /* can't do anything */ extra_points = (chord) ? 0 : 1; if (!p_gprim[(int) Polygon]) ++extra_points; if (!get_c_info(pt_ptr, &x, &y, &r, theta, deg)) return(2); /* get the points on the circumference */ if (!em_arc(x, y, r, theta[0], theta[2], &no_points, extra_points, &xptr, &yptr)) return(2); if (! (int) chord) { xptr[no_points] = x; yptr[no_points] = y; ++no_points; } if (p_gprim[(int) Polygon]) ret = (*p_gprim[(int) Polygon]) (no_points, xptr, yptr); else { xptr[no_points] = pt_ptr[4]; yptr[no_points] = pt_ptr[5]; ++no_points; ret = (*p_gprim[(int) PolyLine])(no_points, xptr, yptr); } free(xptr); free(yptr); return(ret); } /* set an arc, ends specified by vectors */ em_c_centre(x, y, vec_array, r) int x, y, *vec_array, r; { float deg0; double theta0, theta1; extern get_angle(); /* utils.c */ int no_points, *xptr, *yptr, extra_points, ret; if (!setup) { return(2); } if (!p_gprim[(int) PolyLine]) return(2); /* can't do anything */ extra_points = 0; get_angle(vec_array, °0, &theta0); get_angle(vec_array + 2, °0, &theta1); /* get the points on the circumference */ if (!em_arc(x, y, r, theta0, theta1, &no_points, extra_points, &xptr, &yptr)) return(2); ret = (*p_gprim[(int) PolyLine])(no_points, xptr, yptr); free(xptr); free(yptr); return(ret); } /* set an arc, ends specified by vectors, but close it */ em_c_c_close(x, y, vec_array, r, chord) int x, y, *vec_array, r; enum boolean chord; { float deg0; double theta0, theta1; extern get_angle(); /* utils.c */ int no_points, *xptr, *yptr, extra_points, ret, x_1, y_1; if (!setup) { return(2); } if (!p_gprim[(int) PolyLine] && !p_gprim[(int) Polygon]) return(2); /* can't do anything */ extra_points = (chord) ? 0 : 1; if (!p_gprim[(int) Polygon]) ++extra_points; get_angle(vec_array, °0, &theta0); get_angle(vec_array + 2, °0, &theta1); x_1 = x + r * cos(theta1); y_1 = y + r * sin(theta1); /* get the points on the circumference */ if (!em_arc(x, y, r, theta0, theta1, &no_points, extra_points, &xptr, &yptr)) return(2); if (! (int) chord) { xptr[no_points] = x; yptr[no_points] = y; ++no_points; } if (p_gprim[(int) Polygon]) ret = (*p_gprim[(int) Polygon]) (no_points, xptr, yptr); else { xptr[no_points] = x_1; yptr[no_points] = y_1; ++no_points; ret = (*p_gprim[(int) PolyLine])(no_points, xptr, yptr); } free(xptr); free(yptr); return(ret); } /* emulate an ellipse, implement later */ em_ellipse(pt_array) int *pt_array; { return(1); } /* emulate an elliptical arc, implement later */ em_ell_arc(pt_array, vec_array) int *pt_array, *vec_array; { return(1); } /* emulate a closed elliptical arc, implement later */ em_e_a_close(pt_array, vec_array, chord) int *pt_array, *vec_array; enum boolean chord; { return(1); } /* direct colour stuff */ /* work out the the three pivot indices */ get_cinds(n, ninds) int n, *ninds; { int i, dif, prod; /* first try for a cube root */ if (n<=0) return(0); for (i=1; i*i*i <= n; ++i); --i; ninds[0] = ninds[1] = ninds[2] = i; /* now purturb about this */ while (ninds[0]*ninds[1]*ninds[2] <= n) { ++ninds[1]; ++ninds[2]; } --ninds[1]; --ninds[2]; /* now purturb about this */ while (ninds[0]*ninds[1]*ninds[2] <= n) { ++ninds[2]; } --ninds[2]; return(1); }