/* drvcla.c version 1.1 */ /* module of tools for the processing of Cell Arrays */ /* Copyright Phil Andrews, Joel Welling, Pittsburgh Supercomputing Center */ /* all rights reserved */ # include "defs.h" # include # include #define byte_size 8 /* Storage for the structures which keep track of the CGM state */ static struct mf_d_struct *glbl1; /* the class 1 elements */ static struct pic_d_struct *glbl2; /* the class 2 elements */ static struct attrib_struct *glbl5; /* the class 5 elements */ /* Storage for pointers to the external arrays of driver function pointers */ typedef int (*funptr)(); static funptr *gprim, /* The graphical primitives */ *attr; /* The attribute functions */ /* Default storage space for rows of color data */ #define rowmax 100 static int irow_default[rowmax], *irow= irow_default; static float rrow_default[rowmax], grow_default[rowmax], brow_default[rowmax], *rrow= rrow_default, *grow= grow_default, *brow= brow_default; static int rowsize= rowmax; /* translate an int to a floating-point color value */ #define i_to_red(int) ( ( (float) (int - glbl1->c_v_extent.min[0]) )/ \ ( (float) (glbl1->c_v_extent.max[0] - glbl1->c_v_extent.min[0]) ) ) #define i_to_grn(int) ( ( (float) (int - glbl1->c_v_extent.min[1]) )/ \ ( (float) (glbl1->c_v_extent.max[1] - glbl1->c_v_extent.min[1]) ) ) #define i_to_blu(int) ( ( (float) (int - glbl1->c_v_extent.min[2]) )/ \ ( (float) (glbl1->c_v_extent.max[2] - glbl1->c_v_extent.min[2]) ) ) /* translate R, G, B values to a gray scale value (NTSC standard) */ #define mcr_gray(r,g,b) ( 0.3 * r + 0.59 * g + 0.11 * b ) /* Add two 2-D vectors to produce a third */ #define mcr_addvec(a,b,c) {a[0]= b[0] + c[0]; a[1]= b[1] + c[1];} /* Get an arbitrary precision color value, byte aligned or not */ #define mcr_gtcv(ptr, precision, out, bit) out = 0; switch (precision){ \ case 32: out = *ptr++; \ case 24: out = (out << byte_size) | (*ptr++ & 255); \ case 16: out = (out << byte_size) | (*ptr++ & 255); \ case 8: out = (out << byte_size) | (*ptr++ & 255); break; \ case 4: out= ( (*ptr >> (4-bit)) & 15 ); bit= bit + 4; \ if (bit == 8) { bit = 0; ++ptr; }; break; \ case 2: out= ( (*ptr >> (6-bit)) & 3 ); bit= bit + 2; \ if (bit == 8) { bit = 0; ++ptr; }; break; \ case 1: out= ( (*ptr >> (7-bit)) & 1 ); bit= bit + 1; \ if (bit == 8) { bit = 0; ++ptr; }; } \ /* Get a 2-octet integer, byte aligned or not */ #define mcr_gtei(ptr,out,bit) switch (bit) { \ case 0: out = ((*ptr << byte_size) | (*(ptr+1) & 255)); \ ptr= ptr+2; break; \ case 1: out = (((*ptr & 127) << 9)|(*(ptr+1) << 1)|(*(ptr+2) >> 7)); \ ptr= ptr+2; break; \ case 2: out = (((*ptr & 63) << 10)|(*(ptr+1) << 2)|(*(ptr+2) >> 6)); \ ptr= ptr+2; break; \ case 3: out = (((*ptr & 31) << 11)|(*(ptr+1) << 3)|(*(ptr+2) >> 5)); \ ptr= ptr+2; break; \ case 4: out = (((*ptr & 15) << 12)|(*(ptr+1) << 4)|(*(ptr+2) >> 4)); \ ptr= ptr+2; break; \ case 5: out = (((*ptr & 7) << 13)|(*(ptr+1) << 5)|(*(ptr+2) >> 3)); \ ptr= ptr+2; break; \ case 6: out = (((*ptr & 3) << 14)|(*(ptr+1) << 6)|(*(ptr+2) >> 2)); \ ptr= ptr+2; break; \ case 7: out = (((*ptr & 1) << 15)|(*(ptr+1) << 7)|(*(ptr+2) >> 1)); \ ptr= ptr+2; }; /* This routine initializes the cell array utility software */ int cla_init(pc1,pc2,pc5,pgprim,pattr) struct mf_d_struct *pc1; struct pic_d_struct *pc2; struct attrib_struct *pc5; funptr *pgprim, *pattr; { glbl1= pc1; glbl2= pc2; glbl5= pc5; gprim= pgprim; attr= pattr; return(1); } /* Creates a row's worth of dc color values (floats) */ unsigned char *cla_dc_row(dat_ptr, nx, rbuf, gbuf, bbuf, col_prec, mode) unsigned char *dat_ptr; int nx, col_prec, mode; float *rbuf,*gbuf,*bbuf; { int i, ir, ig, ib, index, ctboff, count, idup; float r, g, b; unsigned char *old_ptr= dat_ptr; unsigned int bit= 0; switch (glbl2->c_s_mode) { case i_c_mode: switch (mode) { case 0: for (i=0; i (nx - i)) count= nx - i; i = i + count; ctboff= (index <= glbl1->max_c_index) ? 3*index-1 : 0 ; r = glbl5->ctab[ctboff++]; g = glbl5->ctab[ctboff++]; b = glbl5->ctab[ctboff]; for (idup=0; idupmax_c_index) ? 3*index-1 : 0 ; *rbuf++ = glbl5->ctab[ctboff++]; *gbuf++ = glbl5->ctab[ctboff++]; *bbuf++ = glbl5->ctab[ctboff]; }; }; break; case d_c_mode: switch (mode) { case 0: for (i=0; i (nx - i)) count= nx - i; i = i + count; r = i_to_red(ir); g = i_to_grn(ig); b = i_to_blu(ib); for (idup=0; idupc_s_mode) { case i_c_mode: switch (mode) { case 0: for (i=0; i (nx - i)) count= nx - i; i = i + count; if (index > glbl1->max_c_index) index= 0; for (idup=0; idup glbl1->max_c_index) index= 0; *rowbuf++= index; }; }; break; case d_c_mode: return(NULL); }; /* Now we return an updated pointer, making sure it's word aligned */ if (bit != 0) ++dat_ptr; if ((int) (dat_ptr - old_ptr) % 2) ++dat_ptr; return(dat_ptr); } /* Creates a row's worth of gray scale values (floats) */ unsigned char *cla_g_row(dat_ptr, nx, graybuf, col_prec, mode) unsigned char *dat_ptr; int nx, col_prec, mode; float *graybuf; { int i; void exit(); /* Check for sufficient buffer space to grab a row */ if ( !cla_checkrowsize(nx) ) exit(2); /* Grab a row's worth of colors */ dat_ptr= cla_dc_row(dat_ptr, nx, rrow, grow, brow, col_prec, mode); /* Convert the row to gray scale */ for (i=0; i 0.5 ); /* Reset row buffer */ if ( !cla_resetrowsize() ) exit(2); /* Now we return an updated, word aligned pointer */ return(dat_ptr); } /* Draw a cell array using polygon primitives. The acronym is 'cell array- polygon-ballback'. */ cla_p_fb(p, q, r, nx, ny, prec, image_ptr, mode) int p[2], q[2], r[2], nx, ny, prec, mode; unsigned char *image_ptr; { float topleft[2],alpha[2],beta[2]; int xlist[4],ylist[4],j; struct { enum is_enum int_style; /* interior style */ struct rgbi_struct fill_colour; /* for polygons */ enum boolean edge_vis; /* edge visibility */ } oldattr; /* to hold saved fill attributes */ unsigned char *cla_dorow(); void exit(); /* Check for presence of needed routines */ if (!*(gprim+(int)Polygon)) { fprintf(stderr, " cla_l_fb failed for lack of polygon or fill color routine.\n"); return(8); }; /* Check availability of row data buffers, and fix if necessary. */ if ( !cla_checkrowsize(nx) ) exit(2); /* Save the current fill attributes, and set appropriate new ones */ if ( !cla_sv_pattr(&oldattr) ) exit(2); /* Set up step sizes */ alpha[0]= ((float) (r[0]-p[0])) / nx; alpha[1]= ((float) (r[1]-p[1])) / nx; beta[0]= ((float) (q[0]-r[0])) / ny; beta[1]= ((float) (q[1]-r[1])) / ny; /* Set initial point */ topleft[0]= (float) p[0]; topleft[1]= (float) p[1]; for (j=0; jc_s_mode) /* Direct color */ { image_ptr= cla_dc_row(image_ptr,nx,rrow,grow, brow,prec,mode); for (i=0; ictab + 3 * irow[i]; rrow[i]= *clrptr++; grow[i]= *clrptr++; brow[i]= *clrptr; }; }; topleft[0]= origin[0]; topleft[1]= origin[1]; mcr_addvec(botleft,topleft,beta); mcr_addvec(topright,topleft,alpha); mcr_addvec(botright,botleft,alpha); ilast= 0; inow= 0; for (i=0; i++fill_colour.red= rrow[ilast]; glbl5->fill_colour.green= grow[ilast]; glbl5->fill_colour.blue= brow[ilast]; glbl5->fill_colour.ind= irow[ilast]; if ( *(attr+(int)FillColour) ) (**(attr+(int)FillColour))( rrow[ilast], grow[ilast],brow[ilast],irow[ilast] ); (**(gprim+(int)Polygon))( 4, xlist, ylist ); ilast= inow; topleft[0]= topright[0]; topleft[1]= topright[1]; botleft[0]= botright[0]; botleft[1]= botright[1]; mcr_addvec(topright,topleft,alpha); mcr_addvec(botright,botleft,alpha); }; }; return(image_ptr); } /* This routine stores the current global polygon attributes in a temporary structure. */ cla_sv_pattr(poldattr) struct { enum is_enum int_style; /* interior style */ struct rgbi_struct fill_colour; /* for polygons */ enum boolean edge_vis; /* edge visibility */ } *poldattr; /* to hold saved fill attributes */ { poldattr->int_style= glbl5->int_style; poldattr->edge_vis= glbl5->edge_vis; poldattr->fill_colour.red= glbl5->fill_colour.red; poldattr->fill_colour.green= glbl5->fill_colour.green; poldattr->fill_colour.blue= glbl5->fill_colour.blue; poldattr->fill_colour.ind= glbl5->fill_colour.ind; glbl5->int_style= solid_i; if (*(attr+(int)IntStyle)) (**(attr+(int)IntStyle))(glbl5->int_style); glbl5->edge_vis= off; if (*(attr+(int)EdVis)) (**(attr+(int)EdVis))(glbl5->edge_vis); return(1); } /* This routine stores the current global polygon attributes in a temporary structure. */ cla_rs_pattr(poldattr) struct { enum is_enum int_style; /* interior style */ struct rgbi_struct fill_colour; /* for polygons */ enum boolean edge_vis; /* edge visibility */ } *poldattr; /* to hold saved fill attributes */ { glbl5->int_style= poldattr->int_style; glbl5->edge_vis= poldattr->edge_vis; glbl5->fill_colour.red= poldattr->fill_colour.red; glbl5->fill_colour.green= poldattr->fill_colour.green; glbl5->fill_colour.blue= poldattr->fill_colour.blue; glbl5->fill_colour.ind= poldattr->fill_colour.ind; if (*(attr+(int)IntStyle)) (**(attr+(int)IntStyle))(glbl5->int_style); if (*(attr+(int)EdVis)) (**(attr+(int)EdVis))(glbl5->edge_vis); if (*(attr+(int)FillColour)) (**(attr+(int)FillColour)) ( glbl5->fill_colour.red, glbl5->fill_colour.green, glbl5->fill_colour.blue, glbl5->fill_colour.ind ); return(1); } /* This routine checks to see if sufficient row buffer memory is available, allocating more as necessary. */ cla_checkrowsize(newsize) int newsize; { void exit(); if ( newsize > rowsize ) { if (!cla_resetrowsize()) exit(2); if ( ( irow= (int *) malloc( (unsigned int)newsize*sizeof(int) ) ) == 0 ) { fprintf(stderr, " Error allocating row buffer memory!\n"); exit(2); } if ( ( rrow= (float *) malloc( (unsigned int)newsize*sizeof(float) ) ) == 0 ) { fprintf(stderr, " Error allocating row buffer memory!\n"); exit(2); } if ( ( grow= (float *) malloc( (unsigned int)newsize*sizeof(float) ) ) == 0 ) { fprintf(stderr, " Error allocating row buffer memory!\n"); exit(2); } if ( ( brow= (float *) malloc( (unsigned int)newsize*sizeof(float) ) ) == 0 ) { fprintf(stderr, " Error allocating row buffer memory!\n"); exit(2); } rowsize= newsize; }; return(1); } /* This routine checks to see if new row memory buffers have been allocated, and if so deallocates them and aims the appropriate pointers back at the default buffers. */ cla_resetrowsize() { if (irow != irow_default) { if (cla_free((char *)irow)) { fprintf(stderr," Error freeing row buffer memory!"); return(2); }; irow= irow_default; if (cla_free((char *)rrow)) { fprintf(stderr," Error freeing row buffer memory!"); return(2); }; rrow= rrow_default; if (cla_free((char *)grow)) { fprintf(stderr," Error freeing row buffer memory!"); return(2); }; grow= grow_default; if (cla_free((char *)brow)) { fprintf(stderr," Error freeing row buffer memory!"); return(2); }; brow= brow_default; rowsize= rowmax; }; return(1); } /* This is a portable version of the 'free' routine */ int cla_free(ptr) char *ptr; { #ifdef VMS int free(); return free(ptr); #else void free(); free(ptr); return(0); #endif }