/* * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * * See packages/seacas/LICENSE for details */ /* * SUN DEC/ULTRIX ALLIANT : C routines must have underscores * SGI CONVEX : C routines must have underscores * * VAX HP IBM/aix : C routines do not have underscores * * CRAY/UNICOS : C routines must be capitalized, * and no underscores */ #if !defined(CRA) && !defined(ADDC_) && !defined(COUGAR) #define vdmova wx11mv #define vdmoni wx11mo #define vdgnam wx11gn #define vbiqdv wx11iv #define vbiqpk wx11qp #define vdlina wx11ln #define vdtext wx11tx #define vdpnta wx11pt #define vdpoly wx11py #define vdiqcp wx11cp #define vdstos wx11os #define vdiqos wx11io #define vdstfc wx11fc #define vdstbc wx11bc #define vdstin wx11in #define vdstls wx11ls #define vdstlw wx11lw #define vdstcs wx11cs #define vdaabu wx11bu #define vdaloc wx11lo #define vdabgl wx11bl #define vdakgl wx11kl #define vdstla wx11la #define vdinit wx11nt #define vdfram wx11fr #define vdterm wx11tr #define vdiqdc wx11dc #define vdnwpg wx11pg #define vdbell wx11be #define vdwait wx11wt #define vdbufl wx11fl #define vdstco wx11co #define vdiqco wx11ic #define vdescp wx11es #define vdiqes wx11ie #define vdiqnd wx11id #define vimova wx11im #define vilina wx11il #define vipnta wx11ip #define vitext wx11ix #define viinit wx11ii #define viterm wx11it #define vinwpg wx11ig #define vcjob vcjob #define vberrh wx11er #define vdloge wx11le #define cdrwfs wx11wf #define cdrrfs wx11rf #define cdrofs wx11of #define cdrof3 wx11o3 #define cdrcfs wx11cf #define cdroff wx11ff #define cdroab wx11ab #define bgpbuf wx11bf #define qmsbuf wx11qm #define qmsbu1 wx11bf #define ddcbuf wx11bf #define h75buf wx11bf #define btkbuf wx11bf #define nmtbuf wx11bf #define vbimbf wx11ib #define vbpkg wx11pk #define vbdev wx11dv #define vdiqrs wx11qr #define vdstmp wx11mp #define vdstrs wx11rs #define vdstrv wx11rv #define vdbrgb wx11bg #define vdfrgb wx11fg #define vdpixl wx11px #define vdpixi wx11pi #define vdrpix wx11rp #define vdrpxi wx11ri #define vdrscl wx11rl #define vdiqci wx11ci #define vbstmp wx1101 #define vifram wx1102 #define vcndcm wx1103 #define vcattr wx1104 #define vbini1 wx1105 #define vb2hls wx1106 #define vb2rgb wx1107 #define vccolt wx1108 #define vccrps wx1109 #define vcscal wx1110 #define vcddim wx1111 #define vipoly wx1112 #define vbout wx1113 #define cgixxx cgix11 #endif #if defined(CRA) #define vdmova WX11MV #define vdmoni WX11MO #define vdgnam WX11GN #define vbiqdv WX11IV #define vbiqpk WX11QP #define vdlina WX11LN #define vdtext WX11TX #define vdpnta WX11PT #define vdpoly WX11PY #define vdiqcp WX11CP #define vdstos WX11OS #define vdiqos WX11IO #define vdstfc WX11FC #define vdstbc WX11BC #define vdstin WX11IN #define vdstls WX11LS #define vdstlw WX11LW #define vdstcs WX11CS #define vdaabu WX11BU #define vdaloc WX11LO #define vdabgl WX11BL #define vdakgl WX11KL #define vdstla WX11LA #define vdinit WX11NT #define vdfram WX11FR #define vdterm WX11TR #define vdiqdc WX11DC #define vdnwpg WX11PG #define vdbell WX11BE #define vdwait WX11WT #define vdbufl WX11FL #define vdstco WX11CO #define vdiqco WX11IC #define vdescp WX11ES #define vdiqes WX11IE #define vdiqnd WX11ID #define vimova WX11IM #define vilina WX11IL #define vipnta WX11IP #define vitext WX11IX #define viinit WX11II #define viterm WX11IT #define vinwpg WX11IG #define cdrcom CDRCOM #define vcjob VCJOB #define vconod VCONOD #define vberrh WX11ER #define vdloge WX11LE #define cdrwfs WX11WF #define cdrrfs WX11RF #define cdrofs WX11OF #define cdrof3 WX11O3 #define cdrcfs WX11CF #define cdroff WX11FF #define cdroab WX11AB #define bgpbuf WX11BF #define qmsbuf WX11QM #define qmsbu1 WX11BF #define ddcbuf WX11BF #define h75buf WX11BF #define btkbuf WX11BF #define nmtbuf WX11BF #define vbimbf WX11IB #define vbpkg WX11PK #define vbdev WX11DV #define vdiqrs WX11QR #define vdstmp WX11MP #define vdstrs WX11RS #define vdstrv WX11RV #define vdbrgb WX11BG #define vdfrgb WX11FG #define vdpixl WX11PX #define vdpixi WX11PI #define vdrpix WX11RP #define vdrpxi WX11RI #define vdrscl WX11RL #define vdiqci WX11CI #define vbstmp WX1101 #define vifram WX1102 #define vcndcm WX1103 #define vcattr WX1104 #define vbini1 WX1105 #define vb2hls WX1106 #define vb2rgb WX1107 #define vccolt WX1108 #define vccrps WX1109 #define vcscal WX1110 #define vcddim WX1111 #define vipoly WX1112 #define vbout WX1113 #define wx11zz WX11ZZ #define cgixxx CGIX11 #endif #if defined(ADDC_) || defined(COUGAR) #define vdmova wx11mv_ #define vdmoni wx11mo_ #define vdgnam wx11gn_ #define vbiqdv wx11iv_ #define vbiqpk wx11qp_ #define vdlina wx11ln_ #define vdtext wx11tx_ #define vdpnta wx11pt_ #define vdpoly wx11py_ #define vdiqcp wx11cp_ #define vdstos wx11os_ #define vdiqos wx11io_ #define vdstfc wx11fc_ #define vdstbc wx11bc_ #define vdstin wx11in_ #define vdstls wx11ls_ #define vdstlw wx11lw_ #define vdstcs wx11cs_ #define vdaabu wx11bu_ #define vdaloc wx11lo_ #define vdabgl wx11bl_ #define vdakgl wx11kl_ #define vdstla wx11la_ #define vdinit wx11nt_ #define vdfram wx11fr_ #define vdterm wx11tr_ #define vdiqdc wx11dc_ #define vdnwpg wx11pg_ #define vdbell wx11be_ #define vdwait wx11wt_ #define vdbufl wx11fl_ #define vdstco wx11co_ #define vdiqco wx11ic_ #define vdescp wx11es_ #define vdiqes wx11ie_ #define vdiqnd wx11id_ #define vimova wx11im_ #define vilina wx11il_ #define vipnta wx11ip_ #define vitext wx11ix_ #define viinit wx11ii_ #define viterm wx11it_ #define vinwpg wx11ig_ #define cdrcom cdrcom_ #define vcjob vcjob_ #define vconod vconod_ #define vberrh wx11er_ #define vdloge wx11le_ #define cdrwfs wx11wf_ #define cdrrfs wx11rf_ #define cdrofs wx11of_ #define cdrof3 wx11o3_ #define cdrcfs wx11cf_ #define cdroff wx11ff_ #define cdroab wx11ab_ #define bgpbuf wx11bf_ #define qmsbuf wx11qm_ #define qmsbu1 wx11bf_ #define ddcbuf wx11bf_ #define h75buf wx11bf_ #define btkbuf wx11bf_ #define nmtbuf wx11bf_ #define vbimbf wx11ib_ #define vbpkg wx11pk_ #define vbdev wx11dv_ #define vdiqrs wx11qr_ #define vdstmp wx11mp_ #define vdstrs wx11rs_ #define vdstrv wx11rv_ #define vdbrgb wx11bg_ #define vdfrgb wx11fg_ #define vdpixl wx11px_ #define vdpixi wx11pi_ #define vdrpix wx11rp_ #define vdrpxi wx11ri_ #define vdrscl wx11rl_ #define vdiqci wx11ci_ #define vbstmp wx1101_ #define vifram wx1102_ #define vcndcm wx1103_ #define vcattr wx1104_ #define vbini1 wx1105_ #define vb2hls wx1106_ #define vb2rgb wx1107_ #define vccolt wx1108_ #define vccrps wx1109_ #define vcscal wx1110_ #define vcddim wx1111_ #define vipoly wx1112_ #define vbout wx1113_ #define wx11bf wx11bf_ #define wx11zz wx11zz_ #define cgixxx cgix11_ #endif #if defined(CONVEX) #define cdrcom_ _cdrcom_ #define cdrcm2_ _cdrcm2_ #define vcjob_ _vcjob_ #define vconod_ _vconod_ #define cdrunx_ _cdrunx_ #endif /* cgix11.h - header file to define device dependent stuff for driver * X.11 (x11) * Sandia National Laboratories, Div 2634 * Sun Nov 19 12:02:52 MST 1989 - last date modified */ #include "svdi.h" /******************************************************************************/ /* */ /* type and constant declarations */ /* */ /******************************************************************************/ #define MAX_DEVICE_SURFACES 1 /* num of surfaces device supports */ /* ...set to 1 for interactive device */ #define ERROR_LIST_SIZE 10 /* number of errors stored */ #define COLOR_TABLE_SIZE 256 /* max color table for SVDI is 256 */ #define MAX_TEXT_LENGTH 136 /* max text length for SVDI is 136 */ #define MAX_POLYLINE -1 /* -1 = no limit */ #define MAX_DJ_POLYLINE -1 /* -1 = no limit */ #define MAX_POLYMARKER -1 /* -1 = no limit */ #define MAX_POLYGON 256 /* uses min of this and SVDI limit */ #define MAX_ARRAY 1 /* for pixel array and cell array */ /* ...set to 1 for non raster device */ #define BUFFER_SIZE 1 /* for batch device buffer routines */ /* ...set to 1 for interactive device */ #define DEFAULT_OUTFILE_NAME "" /* not used, driver builds the name */ /* end cgix11.h */ #include "data_def.h" #include #include #include #include #include #include #include #if defined(CRA) || (defined(SUN) && (defined(SYSV) || defined(SVR4))) #include #include #endif #include "cdrcom.h" #include "cgi.h" #include "cgidef.h" #include "devid.h" #include "fortyp.h" #include "stdtyp.h" #include /* ------------------------------------------------------------*/ /* >> FUNCTION PROTOTYPES */ /*-------------------------------------------------------------*/ /* cgi/vdi routines */ static void xactivate(anything **surf_list); static void xdeactivate(anything **surf_list); static void xci(anything **params, int num_surfaces, anything **surf_list); static void xct(int num_surfaces, anything **surf_list); static void xcxdfac(int num_surfaces, anything **surf_list); static void xcpds(anything **params, int num_surfaces, anything **surf_list); static void xcendpg(int num_surfaces, anything **surf_list); static void xcbc(anything **params, int num_surfaces, anything **surf_list); static void xcvdcx(anything **params, int num_surfaces, anything **surf_list); static void xcv(anything **params, int num_surfaces, anything **surf_list); static void xccl(anything **params, int num_surfaces, anything **surf_list); static void xcdscl(anything **params, int num_surfaces, anything **surf_list); static void xcdqerr(anything **params, anything **surf_list); static void xcerhct(anything **params, int num_surfaces, anything **surf_list); static void xccixp(anything **params, int num_surfaces, anything **surf_list); static void xcesc(anything **params, int num_surfaces, anything **surf_list); static void xcqid(anything **params, anything **surf_list); static void xcqd(anything **params, anything **surf_list); static void xclf(anything **params, anything **surf_list); #ifndef sgi static void xclpr(anything **params, anything **surf_list); #endif static void xcqsp(anything **params, anything **surf_list); static void xclesc(anything **params, anything **surf_list); static void xcqp(anything **params, anything **surf_list); static void xcqcl(anything **params, anything **surf_list); static void xcpl(anything **params, int num_surfaces, anything **surf_list); static void xcdjpl(anything **params, int num_surfaces, anything **surf_list); static void xcpm(anything **params, int num_surfaces, anything **surf_list); static void xctx(anything **params, int num_surfaces, anything **surf_list); static void xcpg(anything **params, int num_surfaces, anything **surf_list); static void xcca(anything **params, int num_surfaces, anything **surf_list); static void xcpxa(anything **params, int num_surfaces, anything **surf_list); static void xclnt(anything **params, int num_surfaces, anything **surf_list); static void xclnw(anything **params, int num_surfaces, anything **surf_list); static void xclnc(anything **params, int num_surfaces, anything **surf_list); static void xcmkt(int num_surfaces, anything **surf_list); static void xcmks(anything **params, int num_surfaces, anything **surf_list); static void xcmkc(anything **params, int num_surfaces, anything **surf_list); static void xctxp(anything **params, int num_surfaces, anything **surf_list); static void xctxc(anything **params, int num_surfaces, anything **surf_list); static void xcchh(anything **params, int num_surfaces, anything **surf_list); static void xccho(anything **params, int num_surfaces, anything **surf_list); static void xcis(anything **params, int num_surfaces, anything **surf_list); static void xcflc(anything **params, int num_surfaces, anything **surf_list); static void xccsm(anything **params, int num_surfaces, anything **surf_list); static void xcct(anything **params, int num_surfaces, anything **surf_list); static void xcgtxx(anything **params, anything **surf_list); static void xcqprl(anything **params, anything **surf_list); static void xcqln(anything **params, anything **surf_list); static void xcqlnt(anything **params, anything **surf_list); static void xcqslw(anything **params, anything **surf_list); static void xcqmk(anything **params, anything **surf_list); static void xcqmkt(anything **params, anything **surf_list); static void xcqsms(anything **params, anything **surf_list); static void xcqchh(anything **params, anything **surf_list); static void xcqfl(anything **params, anything **surf_list); static void xcqc(anything **params, anything **surf_list); static void xcqlna(anything **params, anything **surf_list); static void xcqmka(anything **params, anything **surf_list); static void xcqtxa(anything **params, anything **surf_list); static void xcqfla(anything **params, anything **surf_list); static void xcqcte(anything **params, anything **surf_list); static void xcili(anything **params, anything **surf_list); static void xcrqlc(anything **params, anything **surf_list); /* utility routines */ static void init_state(surf_statelist *surf_state); static void set_dev_descrip(void); static void reset_vdi(surf_statelist *surf_state); static void set_mapping(surf_statelist *surf_state); static void set_clipping(surf_statelist *cur_state); static void set_foreground_color(surf_statelist *surf_state, int *colors); static void set_background_color(surf_statelist *surf_state, int *colors); static void report_error(surf_statelist *surf_state, int e_class, int e_num, int f_id); static void gettoken(int *index_p, int *numrecs_p, char *data_p, int max_chars, char *outtoken_p); static int poly_clip(point *cmin, point *cmax, float *vx, float *vy, int vlen, float *xout, float *yout, int *lenout); static int inside_bnd(point *v, point *bmin, point *bmax, int bound_num); static point intersect_bnd(point *p1, point *p2, point *bmin, point *bmax, int bound_num); /* cdr routines */ /* -- not used with interactive devices */ void cdrofs(int *); void cdrof3(int *, int *); void cdroff(int *, int *, int *, int *); void cdrrfs(int *, int *, char *, int *); void cdrwfs(int *, int *, char *, int *); void cdrcfs(int *, int *); void cdroab(int *, int *); static char *copy_string(char *dest, char const *source, long int elements) { char *d; for (d = dest; d + 1 < dest + elements && *source; d++, source++) { *d = *source; } *d = '\0'; return d; } /*-------------------------------------------------------------*/ /* >> GLOBAL VARIABLE DECLARATIONS */ /*-------------------------------------------------------------*/ /* variables used to maintain state list, free list */ static int first_free_state = -1; static int last_alloc_state = -1; /* declare one statelist per surface */ static surf_statelist surf_states[MAX_DEVICE_SURFACES]; /* declare one description table per device */ static dev_descrip_table dev_descrip; /* variable to keep track of current statelist */ /* -- this is global so CDR can know which state to look at */ static surf_statelist *cur_state; /* These arrays are global because of size. Used in cell and pixel array */ static float rarray[MAX_ARRAY], garray[MAX_ARRAY], barray[MAX_ARRAY]; static int varray[MAX_ARRAY]; /*-------------------------------------------------------------*/ /* >> CGI/SVDI DEVICE DRIVER ROUTINES */ /*-------------------------------------------------------------*/ void cgixxx(anything *params[], int num_surfaces, anything *surf_list[]) { /* Main entry point */ switch (*(short *)params[0]) { case ACTIVATE_FN: xactivate(surf_list); break; case DEACTIVATE_FN: xdeactivate(surf_list); break; case CI_FN: xci(params, num_surfaces, surf_list); break; case CT_FN: xct(num_surfaces, surf_list); break; case CXDFAC_FN: xcxdfac(num_surfaces, surf_list); break; case CPDS_FN: xcpds(params, num_surfaces, surf_list); break; case CENDPG_FN: xcendpg(num_surfaces, surf_list); break; case CBC_FN: xcbc(params, num_surfaces, surf_list); break; case CVDCX_FN: xcvdcx(params, num_surfaces, surf_list); break; case CV_FN: xcv(params, num_surfaces, surf_list); break; case CCL_FN: xccl(params, num_surfaces, surf_list); break; case CDSCL_FN: xcdscl(params, num_surfaces, surf_list); break; case CDQERR_FN: xcdqerr(params, surf_list); break; case CERHCT_FN: xcerhct(params, num_surfaces, surf_list); break; case CCIXP_FN: xccixp(params, num_surfaces, surf_list); break; case CESC_FN: xcesc(params, num_surfaces, surf_list); break; case CQID_FN: xcqid(params, surf_list); break; case CQD_FN: xcqd(params, surf_list); break; case CLF_FN: xclf(params, surf_list); break; #ifndef sgi case CLPR_FN: xclpr(params, surf_list); break; #endif case CQSP_FN: xcqsp(params, surf_list); break; case CLESC_FN: xclesc(params, surf_list); break; case CQP_FN: xcqp(params, surf_list); break; case CQCL_FN: xcqcl(params, surf_list); break; case CPL_FN: xcpl(params, num_surfaces, surf_list); break; case CDJPL_FN: xcdjpl(params, num_surfaces, surf_list); break; case CPM_FN: xcpm(params, num_surfaces, surf_list); break; case CTX_FN: xctx(params, num_surfaces, surf_list); break; case CPG_FN: xcpg(params, num_surfaces, surf_list); break; case CCA_FN: xcca(params, num_surfaces, surf_list); break; case CPXA_FN: xcpxa(params, num_surfaces, surf_list); break; case CLNT_FN: xclnt(params, num_surfaces, surf_list); break; case CLNW_FN: xclnw(params, num_surfaces, surf_list); break; case CLNC_FN: xclnc(params, num_surfaces, surf_list); break; case CMKT_FN: xcmkt(num_surfaces, surf_list); break; case CMKS_FN: xcmks(params, num_surfaces, surf_list); break; case CMKC_FN: xcmkc(params, num_surfaces, surf_list); break; case CTXP_FN: xctxp(params, num_surfaces, surf_list); break; case CTXC_FN: xctxc(params, num_surfaces, surf_list); break; case CCHH_FN: xcchh(params, num_surfaces, surf_list); break; case CCHO_FN: xccho(params, num_surfaces, surf_list); break; case CIS_FN: xcis(params, num_surfaces, surf_list); break; case CFLC_FN: xcflc(params, num_surfaces, surf_list); break; case CCSM_FN: xccsm(params, num_surfaces, surf_list); break; case CCT_FN: xcct(params, num_surfaces, surf_list); break; case CGTXX_FN: xcgtxx(params, surf_list); break; case CQPRL_FN: xcqprl(params, surf_list); break; case CQLN_FN: xcqln(params, surf_list); break; case CQLNT_FN: xcqlnt(params, surf_list); break; case CQSLW_FN: xcqslw(params, surf_list); break; case CQMK_FN: xcqmk(params, surf_list); break; case CQMKT_FN: xcqmkt(params, surf_list); break; case CQSMS_FN: xcqsms(params, surf_list); break; case CQCHH_FN: xcqchh(params, surf_list); break; case CQFL_FN: xcqfl(params, surf_list); break; case CQC_FN: xcqc(params, surf_list); break; case CQLNA_FN: xcqlna(params, surf_list); break; case CQMKA_FN: xcqmka(params, surf_list); break; case CQTXA_FN: xcqtxa(params, surf_list); break; case CQFLA_FN: xcqfla(params, surf_list); break; case CQCTE_FN: xcqcte(params, surf_list); break; case CILI_FN: xcili(params, surf_list); break; case CRQLC_FN: xcrqlc(params, surf_list); break; } /* end switch */ } /* end cgixxx */ /* ACTIVATE */ static void xactivate(anything **surf_list) { int new_state; /* index of new state to use */ if (first_free_state >= 0) { /* there is free one, use it */ new_state = first_free_state; first_free_state = surf_states[new_state].next_free_state; } else if (last_alloc_state < MAX_DEVICE_SURFACES - 1) { new_state = last_alloc_state + 1; /* can alloc one */ ++last_alloc_state; } else { /* none available */ new_state = -1; } /* end if */ if (new_state < 0) { /* problem, report error & go away */ surf_list[0] = NULL; return; } /* end if problem */ /* got new state, init it */ surf_states[new_state].cgi_inited = CNO; surf_states[new_state].this_index = new_state; /* save for dealloc */ /* -- for batch devices */ copy_string(surf_states[new_state].filename, DEFAULT_OUTFILE_NAME, 100); surf_states[new_state].file_d = -1; /* set surface state_list pointer to point to this state list */ surf_list[0] = (anything *)&(surf_states[new_state]); } /* end xactivate */ /* DEACTIVATE */ static void xdeactivate(anything **surf_list) { /* deallocate memory allocated for cgi state list */ int index; /* which state is this surface linked to */ index = ((surf_statelist *)surf_list[0])->this_index; if ((index >= 0) && (index < MAX_DEVICE_SURFACES)) { surf_states[index].next_free_state = first_free_state; first_free_state = index; } /* end if */ /* unlink cgi state list from surface */ surf_list[0] = NULL; } /* end xdeactivate */ /* INITIALIZE */ static void xci(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surf_list */ float zero = 0.; int izero = 0; for (i = 0; i < num_surfaces; ++i) { /* cur_state is global - points to current statelist */ cur_state = (surf_statelist *)surf_list[i]; /* initialize/reinit SVDI and/or set device descript table */ /* -- this needs to happen before calling init_state */ if (cur_state->cgi_inited == CNO) { /* this surface has never been initialized */ vdinit(&zero, &izero); /* set device descript table for this device only once */ if (dev_descrip.set_flag == FALSE) { set_dev_descrip(); dev_descrip.set_flag = TRUE; } /* end if set_flag */ } /* end if surface not initialized */ else { /* this surface has been initialized once already */ /* reset SVDI attributes */ reset_vdi(cur_state); /* if prepare drawing surface, issue a new page */ if (*(int *)params[1] == CYES) { vdnwpg(); } } /* end else surface initialized */ /* initialize/reinitialize the default device state */ init_state(cur_state); /* set cgi_inited to initialized */ cur_state->cgi_inited = CYES; } /* end for each surface */ } /* end xci */ /* TERMINATE */ static void xct(int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* terminate and set state to uninitialized */ vdterm(); cur_state->cgi_inited = CNO; } /* end for each surface */ } /* end xct */ /* EXECUTE DEFERRED ACTIONS */ static void xcxdfac(int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } vdbufl(); } /* end for each surface */ } /* end xcxdfac */ /* PREPARE DRAWING SURFACE */ static void xcpds(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* new page if page has been marked or parameter is forced */ if (cur_state->pic_dirty == CDIRTY || *(int *)params[1] == CFORCC) { vdnwpg(); cur_state->pic_dirty = CCLEAN; } } /* end for each surface */ } /* end xcpds */ /* END PAGE */ static void xcendpg(int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* perform an implicit execute deferred actions */ vdbufl(); /* for hardcopy, call new page only if page has been marked */ if (dev_descrip.copy_class == CHARD) { if (cur_state->pic_dirty == CDIRTY) { vdnwpg(); cur_state->pic_dirty = CCLEAN; } /* end if dirty page */ } } /* end for each surface */ } /* end xcendpg */ /* BACKGROUND COLOR */ static void xcbc(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ int bg_color[3]; /* temporary array */ bg_color[0] = *(int *)params[1]; bg_color[1] = *(int *)params[2]; bg_color[2] = *(int *)params[3]; for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } set_background_color(cur_state, bg_color); } /* end for each surface */ } /* end xcbc */ /* VDC EXTENT */ static void xcvdcx(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* store the values in the state list */ /* default integer precision is 16 - check range */ if (*(float *)params[1] > 32767.0f || *(float *)params[2] > 32767.0f || *(float *)params[3] > 32767.0f || *(float *)params[4] > 32767.0f || *(float *)params[1] < -32767.0f || *(float *)params[2] < -32767.0f || *(float *)params[3] < -32767.0f || *(float *)params[4] < -32767.0f) { /* error 1:-103 VDC Extent out of range. Function ignored */ report_error(cur_state, 1, -103, *(short *)params[0]); return; } /* end if error */ /* no error */ cur_state->vdc1.x = *(float *)params[1]; cur_state->vdc1.y = *(float *)params[2]; cur_state->vdc2.x = *(float *)params[3]; cur_state->vdc2.y = *(float *)params[4]; /* end else no error */ /* VDC to viewport (in NDC) mapping */ /* -- this routine sets effective viewport in VDC and NDC (forcing isotropic mapping) and the mapping scale */ set_mapping(cur_state); /* determine new effective clipping rectangle */ /* ..First figure out the min and max VDC points. Since * the user cannot change the clip rectangle, the min and * max clip rectangle points are known. (min = clip_rect1 = [0,0]; * max = clip_rect2 = [32767.,32767.]) */ /* need to check for degenerate case */ cur_state->eff_clip_rect1.x = max(min(cur_state->vdc1.x, cur_state->vdc2.x), cur_state->clip_rect1.x); cur_state->eff_clip_rect1.y = max(min(cur_state->vdc1.y, cur_state->vdc2.y), cur_state->clip_rect1.y); cur_state->eff_clip_rect2.x = min(max(cur_state->vdc1.x, cur_state->vdc2.x), cur_state->clip_rect2.x); cur_state->eff_clip_rect2.y = min(max(cur_state->vdc1.y, cur_state->vdc2.y), cur_state->clip_rect2.y); /* set clipping region */ set_clipping(cur_state); } /* end for each surface */ } /* end xcvdcx */ /* DEVICE VIEWPORT */ static void xcv(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* viewport - default viewport specification mode is FRACTION OF * DRAWING SURFACE. Thus, the viewport (0,0),(1,1) corresponds to * the lower and upper corners, respectively, of the default * device viewport, which is the largest unrotated rectangular area * visible on the drawing surface. Numbers outside the range * [0.0...1.0] may be specified. */ /* store values in state list */ cur_state->vp1.x = *(float *)params[1]; cur_state->vp1.y = *(float *)params[2]; cur_state->vp2.x = *(float *)params[3]; cur_state->vp2.y = *(float *)params[4]; /* do VDC to NDC mapping */ /* -- this routine sets effective viewports in VDC and NDC (forcing isotropic mapping) and the mapping scale */ set_mapping(cur_state); /* set clipping region */ set_clipping(cur_state); } /* end for each surface */ } /* end xcv */ /* CLIP INDICATOR */ static void xccl(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* check for a legal enumerated value, store in state table and set the clipping region */ if (*(int *)params[1] == CON || *(int *)params[1] == COFF) { cur_state->clip_indicator = *(int *)params[1]; set_clipping(cur_state); } else { /* error 1:-101 Enumerated parameter out of range. Function ignored */ report_error(cur_state, 1, -101, *(short *)params[0]); } } /* end for each surface */ } /* end xccl */ /* DRAWING SURFACE CLIP INDICATOR */ static void xcdscl(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* check for a legal enumerated value, store in state table and set the clipping region */ if (*(int *)params[1] == CDCOFF || *(int *)params[1] == CDCREC || *(int *)params[1] == CVPORT) { cur_state->ds_clip_indicator = *(int *)params[1]; set_clipping(cur_state); } else { /* error 1:-101 Enumerated parameter out of range. Function ignored */ report_error(cur_state, 1, -101, *(short *)params[0]); } } /* end for each surface */ } /* end xcdscl */ /* DEQUEUE ERROR REPORTS */ static void xcdqerr(anything **params, anything **surf_list) { int i; /* loop variable */ int max_ret; /* max number of errors to return */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* find the number of errors to be returned */ max_ret = (*(int *)params[1] < cur_state->err_count) ? *(int *)params[1] : cur_state->err_count; for (i = 0; i < max_ret; i++) { ((int *)params[5])[i] = cur_state->err_queue[cur_state->err_head_ptr].err_class; ((int *)params[6])[i] = cur_state->err_queue[cur_state->err_head_ptr].err_num; ((int *)params[7])[i] = cur_state->err_queue[cur_state->err_head_ptr].func_id; /* update the head of list ptr */ cur_state->err_head_ptr++; if (cur_state->err_head_ptr == ERROR_LIST_SIZE) { cur_state->err_head_ptr = 0; } /* decrement the count of errors */ cur_state->err_count--; } /* end for i */ /* number of reports remaining in the queue */ *(int *)params[3] = cur_state->err_count; /* number of reports returned */ *(int *)params[4] = i; /* validity flag */ *(int *)params[2] = CVAL; } /* end xcdqerr */ /* ERROR HANDLING CONTROL */ static void xcerhct(anything **params, int num_surfaces, anything **surf_list) { int i, j; /* loop indices */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* store error control level in state list */ for (j = 0; j < *(int *)params[1]; j++) { /* check enumeration types */ if (((int *)params[3])[j] != CEHON && ((int *)params[3])[j] != CEHROF && ((int *)params[3])[j] != CEHDOF) { /* error 1:-101 Enumerated parameter out of range. Function ignored */ report_error(cur_state, 1, -101, *(short *)params[0]); /* check for legal index */ } else if (((int *)params[2])[j] < 1 || ((int *)params[2])[j] > MAX_ERROR_CLASS) { /* error 1:-102 Index out of range. Function ignored */ report_error(cur_state, 1, -102, *(short *)params[0]); } else { cur_state->err_flag[((int *)params[2])[j] - 1] = ((int *)params[3])[j]; } } /* end for j */ } /* end for each surface */ } /* end xcerhct */ /* COLOR INDEX PRECISION */ static void xccixp(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ /* I'm not doing anything with color index precision now */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } if (*(int *)params[1] == 8 || *(int *)params[1] == 16 || *(int *)params[1] == 24 || *(int *)params[1] == 32) { cur_state->color_index_prec = *(int *)params[1]; } else { /* error 3:204 Selected precision not supported */ report_error(cur_state, 3, 204, *(short *)params[0]); } } /* end for each surface */ } /* end xccixp */ /* ESCAPE */ static void xcesc(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ int j; /* loop index */ int first; /* logical; TRUE = first time through */ char data[80]; /* temp for parsing data record */ char c; /* single character */ int vdi_esc; /* used for SVDI escape call */ int count; /* used for SVDI escape call */ float args[10]; /* used for SVDI escape call */ int tokenindex; /* index in data record of first char */ /* after end of token*/ first = TRUE; for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; switch (*(int *)params[1]) { case XEMFNM: /* file name */ if (first) { tokenindex = 0; /* first char of data record */ /* params[4] is an added parameter - contains the string length */ gettoken(&tokenindex, (int *)params[2], (char *)params[3], 80, data); first = FALSE; } /* end if first */ /* this function must be called before CI */ /* ...error message if not?? check for legal file name?? */ if (cur_state->cgi_inited != CYES) { copy_string(cur_state->filename, data, 100); } break; case XEAGMD: /* set terminal to alpha/graphics */ if (first) { tokenindex = 0; /* first char of data record */ /* params[4] is an added parameter - contains the string length */ gettoken(&tokenindex, (int *)params[2], (char *)params[3], 80, data); /* SVDI takes care of 'graphics', check for 'alpha' */ j = 0; while ((c = data[j++])) { if (isalpha(c) && isupper(c)) { data[j - 1] = tolower(c); } } first = FALSE; } /* end if first */ if (strncmp(data, "alpha", 5) == 0) { vdbufl(); } break; case XESVDI: /* SVDI escape */ if (first) { tokenindex = 0; /* first char of data record */ /* first token is SVDI escape number */ gettoken(&tokenindex, (int *)params[2], (char *)params[3], 80, data); vdi_esc = strtol(data, NULL, 10); /* second token is number of parameters to SVDI escape */ gettoken(&tokenindex, (int *)params[2], (char *)params[3], 80, data); count = strtol(data, NULL, 10); /* the rest of the tokens contain the arguments */ for (j = 0; j < count && j < 10; j++) { gettoken(&tokenindex, (int *)params[2], (char *)params[3], 80, data); args[j] = (float)strtod(data, NULL); } first = FALSE; } /* end if first */ vdescp(&vdi_esc, &count, args); break; case XEPGSZ: /* Page size */ if (first) { tokenindex = 0; /* first char of data record */ /* first token is page size in x */ gettoken(&tokenindex, (int *)params[2], (char *)params[3], 80, data); args[0] = (float)strtod(data, NULL); /* second token is page size in y */ gettoken(&tokenindex, (int *)params[2], (char *)params[3], 80, data); args[1] = (float)strtod(data, NULL); /* page size svdi number is 1400 */ vdi_esc = 1400; count = 2; first = FALSE; } /* end if first */ vdescp(&vdi_esc, &count, args); break; case XEBELL: /* Ring the bell */ vdbell(); break; default: /* error 2:001 Request unsupported feature. Function ignored */ report_error(cur_state, 2, 001, *(short *)params[0]); break; } /* end switch */ } /* end for i */ } /* end xcesc */ /* INQUIRE DEVICE IDENTIFICATION */ static void xcqid(anything **params, anything **surf_list) { char *cgi_devid; /* pointer to character device id */ int maxchr; /* max number of chars in device id */ int qdc_index = 23; /* index for inquiries to vdiqdc */ float value; /* value returned by vdiqdc */ static int set = FALSE; /* flag whether values have been set yet */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } if (!set) { /* values have't been set, inquire SVDI */ set = TRUE; /* device id */ vdiqdc(&qdc_index, &value); cgi_devid = get_devid_char(value); if (cgi_devid != NULL) { copy_string(dev_descrip.dev_id, cgi_devid, 4); } } /* end if not set */ /* response validity */ *(int *)params[2] = CVAL; /* return device class - this is set in set_dev_descrip() */ *(int *)params[3] = dev_descrip.dev_class; /* return device id */ maxchr = (*(int *)params[1] > 3) ? 3 : *(int *)params[1]; copy_string((char *)params[4], dev_descrip.dev_id, maxchr); *((char *)params[4] + maxchr) = '\0'; } /* end xcqid */ /* INQUIRE DEVICE DESCRIPTION */ static void xcqd(anything **params, anything **surf_list) { int qdc_index; /* index for inquiries to vdiqdc */ float value; /* value returned by vdiqdc */ static int set = FALSE; /* flag whether values have been set */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } if (!set) { /* values have't been set, inquire SVDI */ set = TRUE; /* display type */ qdc_index = 2; vdiqdc(&qdc_index, &value); if (value == 0.) { dev_descrip.display_type = CVECT; } else if (value == 1.) { dev_descrip.display_type = CRAST; } else { dev_descrip.display_type = COTHER; } /* background color capability */ qdc_index = 32; vdiqdc(&qdc_index, &value); dev_descrip.bcolor_cap = (value == 1.0) ? CYES : CNO; /* dynamic modification for background color */ dev_descrip.dynamic_mod_bg = CIRG; /* dynamic modification for VDC to device mapping */ dev_descrip.dynamic_mod_map = CIRG; /* width and height in millimeters */ /* ...SVDI returns 0 if it doesn't know. CGI does this also */ qdc_index = 17; vdiqdc(&qdc_index, &dev_descrip.draw_surf_width); qdc_index = 18; vdiqdc(&qdc_index, &dev_descrip.draw_surf_height); /* pixel location relative to coordinates */ dev_descrip.pix_loc = CPXON; } /* end haven't been set */ /* validity flag */ *(int *)params[1] = CVAL; /* stuff info into return values */ /* ...copy_class and device corners are set in set_dev_descrip() */ *(int *)params[2] = dev_descrip.copy_class; *(int *)params[3] = dev_descrip.display_type; *(int *)params[4] = dev_descrip.bcolor_cap; *(int *)params[5] = dev_descrip.dynamic_mod_bg; *(int *)params[6] = dev_descrip.dynamic_mod_map; *(int *)params[7] = dev_descrip.dc1.x; *(int *)params[8] = dev_descrip.dc1.y; *(int *)params[9] = dev_descrip.dc2.x; *(int *)params[10] = dev_descrip.dc2.y; *(float *)params[11] = dev_descrip.draw_surf_width; *(float *)params[12] = dev_descrip.draw_surf_height; *(int *)params[13] = dev_descrip.pix_loc; } /* end xcqd */ /* LOOKUP FUNCTION SUPPORT */ static void xclf(anything **params, anything **surf_list) { int i; /* index for loop on surfaces */ int qdc_index = 24; /* for inquire SVDI */ static float poly_support = -1.; /* level of SVDI poly support */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } for (i = 0; i < *(int *)params[1]; i++) { switch (*(short *)params[0]) { case ACTIVATE_FN: ((int *)params[5])[i] = CSYES; break; case DEACTIVATE_FN: ((int *)params[5])[i] = CSYES; break; case CI_FN: ((int *)params[5])[i] = CSYES; break; case CT_FN: ((int *)params[5])[i] = CSYES; break; case CXDFAC_FN: ((int *)params[5])[i] = CSYES; break; case CPDS_FN: ((int *)params[5])[i] = CSYES; break; case CENDPG_FN: ((int *)params[5])[i] = CSYES; break; case CBC_FN: ((int *)params[5])[i] = CSYES; break; case CVDCX_FN: ((int *)params[5])[i] = CSYES; break; case CV_FN: ((int *)params[5])[i] = CSYES; break; case CCL_FN: ((int *)params[5])[i] = CSYES; break; case CDSCL_FN: ((int *)params[5])[i] = CSYES; break; case CDQERR_FN: ((int *)params[5])[i] = CSYES; break; case CERHCT_FN: ((int *)params[5])[i] = CSYES; break; case CCIXP_FN: ((int *)params[5])[i] = CSNO; break; case CESC_FN: ((int *)params[5])[i] = CSYES; break; case CQID_FN: ((int *)params[5])[i] = CSYES; break; case CQD_FN: ((int *)params[5])[i] = CSYES; break; case CLF_FN: ((int *)params[5])[i] = CSYES; break; case CLPR_FN: ((int *)params[5])[i] = CSYES; break; case CQSP_FN: ((int *)params[5])[i] = CSYES; break; case CLESC_FN: ((int *)params[5])[i] = CSYES; break; case CQP_FN: ((int *)params[5])[i] = CSYES; break; case CQCL_FN: ((int *)params[5])[i] = CSYES; break; case CPL_FN: ((int *)params[5])[i] = CSYES; break; case CDJPL_FN: ((int *)params[5])[i] = CSYES; break; case CPM_FN: ((int *)params[5])[i] = CSYES; break; case CTX_FN: ((int *)params[5])[i] = CSYES; break; case CPG_FN: if (poly_support == -1.) { vdiqdc(&qdc_index, &poly_support); } if (poly_support < 3.) { ((int *)params[5])[i] = CSNO; } else { ((int *)params[5])[i] = CSYES; } break; case CCA_FN: ((int *)params[5])[i] = CSYES; break; case CPXA_FN: ((int *)params[5])[i] = CSYES; break; case CLNT_FN: ((int *)params[5])[i] = CSYES; break; case CLNW_FN: ((int *)params[5])[i] = CSYES; break; case CLNC_FN: ((int *)params[5])[i] = CSYES; break; case CMKT_FN: ((int *)params[5])[i] = CSYES; break; case CMKS_FN: ((int *)params[5])[i] = CSNO; break; case CMKC_FN: ((int *)params[5])[i] = CSYES; break; case CTXP_FN: ((int *)params[5])[i] = CSNO; break; case CTXC_FN: ((int *)params[5])[i] = CSNO; break; case CCHH_FN: ((int *)params[5])[i] = CSYES; break; case CCHO_FN: ((int *)params[5])[i] = CSNO; break; case CIS_FN: ((int *)params[5])[i] = CSYES; break; case CFLC_FN: ((int *)params[5])[i] = CSYES; break; case CCSM_FN: ((int *)params[5])[i] = CSYES; break; case CCT_FN: ((int *)params[5])[i] = CSYES; break; case CGTXX_FN: ((int *)params[5])[i] = CSYES; break; case CQPRL_FN: ((int *)params[5])[i] = CSYES; break; case CQLN_FN: ((int *)params[5])[i] = CSYES; break; case CQLNT_FN: ((int *)params[5])[i] = CSYES; break; case CQSLW_FN: ((int *)params[5])[i] = CSNO; break; case CQMK_FN: ((int *)params[5])[i] = CSNO; break; case CQMKT_FN: ((int *)params[5])[i] = CSYES; break; case CQSMS_FN: ((int *)params[5])[i] = CSNO; break; case CQCHH_FN: ((int *)params[5])[i] = CSYES; break; case CQFL_FN: ((int *)params[5])[i] = CSYES; break; case CQC_FN: ((int *)params[5])[i] = CSYES; break; case CQLNA_FN: ((int *)params[5])[i] = CSYES; break; case CQMKA_FN: ((int *)params[5])[i] = CSNO; break; case CQTXA_FN: ((int *)params[5])[i] = CSYES; break; case CQFLA_FN: ((int *)params[5])[i] = CSNO; break; case CQCTE_FN: ((int *)params[5])[i] = CSYES; break; case CILI_FN: ((int *)params[5])[i] = CSYES; break; case CRQLC_FN: ((int *)params[5])[i] = CSYES; break; default: ((int *)params[5])[i] = CSNO; break; } /* end switch */ } /* validity flag */ *(int *)params[4] = CVAL; } /* end xclf */ /* LOOKUP PROFILE SUPPORT */ static void xclpr(anything **params, anything **surf_list) { int i; /* index for loop on surfaces */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } for (i = 0; i < *(int *)params[1]; i++) { if (strncmp(((char **)params[2])[i], "1-WAY-OUTPUT", 12) != 0 || strncmp(((char **)params[2])[i], "2-WAY-OUTPUT", 12) || strncmp(((char **)params[2])[i], "SLATEC 1", 8) != 0) { ((int *)params[4])[i] = CSYES; } else { ((int *)params[4])[i] = CSNO; } } /* validity flag */ *(int *)params[3] = CVAL; } /* end xclpr */ /* INQUIRE SUPPORTED PRECISIONS */ static void xcqsp(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* this stuff is basically machine dependent. I return INVAL and leave it at that */ *(int *)params[1] = CINVAL; } /* end xcqsp */ /* LOOKUP ESCAPE SUPPORT */ static void xclesc(anything **params, anything **surf_list) { int i; /* loop index */ int esc = 1400; /* for inquire escape */ int support; /* for inquire escape */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } for (i = 0; i < *(int *)params[1]; i++) { /* return YES for supported escapes, else return NO */ switch (((int *)params[2])[i]) { case XEMFNM: ((int *)params[4])[i] = CSYES; break; case XEAGMD: ((int *)params[4])[i] = CSYES; break; case XESVDI: ((int *)params[4])[i] = CSYES; break; case XEBELL: ((int *)params[4])[i] = CSYES; break; case XEPGSZ: vdiqes(&esc, &support); if (support == 1 || support == 2) { ((int *)params[4])[i] = CSYES; } else { ((int *)params[4])[i] = CSNO; } break; default: ((int *)params[4])[i] = CSNO; break; } /* end switch */ } /* validity flag */ *(int *)params[3] = CVAL; } /* end xclesc */ /* INQUIRE CURRENT PRECISIONS */ static void xcqp(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* validity flag */ *(int *)params[1] = CINVAL; } /* end xcqp */ /* INQUIRE CLIPPING */ static void xcqcl(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* clip indicator */ *(int *)params[2] = cur_state->clip_indicator; /* clip rectangle */ ((float *)params[3])[0] = cur_state->clip_rect1.x; ((float *)params[3])[1] = cur_state->clip_rect1.y; ((float *)params[3])[2] = cur_state->clip_rect2.x; ((float *)params[3])[3] = cur_state->clip_rect2.y; /* drawing surface clip indicator */ *(int *)params[4] = cur_state->ds_clip_indicator; /* drawing surface clip rectangle */ /* Default is the whole drawing surface; routines to change the * drawing surface clip rectangle are not included. Since veiwport * specification mode is FRACTION OF DRAWING SURFACE, units for * rectangle are 0 - 1 */ ((float *)params[5])[0] = 0.; ((float *)params[5])[1] = 0.; ((float *)params[5])[2] = 1.; ((float *)params[5])[3] = 1.; /* validity flag */ *(int *)params[1] = CVAL; } /* end xcqcl */ /* POLYLINE */ static void xcpl(anything **params, int num_surfaces, anything **surf_list) { int i, j; /* indices for loops */ int np; /* number of points in polyline */ float prev_x, prev_y; /* line end points */ float cur_x, cur_y; /* line end points */ float save_x, save_y; /* used for clipping */ int prev_code, cur_code; /* encoded endpoints - for clipping */ int mode = 0, done; /* stuff used for clipping */ static unsigned mask = ~(~0u << 1); /* for masking off bits */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* do some error checking */ if (MAX_POLYLINE != -1 && *(int *)params[1] > MAX_POLYLINE) { /* error 6:301 - Number of points too large. Max is used */ report_error(cur_state, 6, 301, *(short *)params[0]); np = MAX_POLYLINE; } else { np = *(int *)params[1]; } /* set SVDI foreground color if needed */ set_foreground_color(cur_state, cur_state->line_color); /* take a short cut if no clipping is on */ if (!cur_state->clip_on) { for (j = 0; j < np; j++) { /* map VDC to NDC */ cur_x = *((float *)params[2] + j) * cur_state->xscale + cur_state->xoffset; cur_y = *((float *)params[3] + j) * cur_state->yscale + cur_state->yoffset; if (j == 0) { vdmova(&cur_x, &cur_y); } else { vdlina(&cur_x, &cur_y); } } /* end for j */ } /* end no clipping on */ else { /* clipping is on */ /* This clipping algorithm is loosely based on the Cohen- * Sutherland algorithm. This algorithm takes into account * the fact that points are consecutive, ie., it tries to * encode each point only once. Everything is done * inline for efficiency */ /* convert VDC to NDC */ prev_x = *((float *)params[2]) * cur_state->xscale + cur_state->xoffset; prev_y = *((float *)params[3]) * cur_state->yscale + cur_state->yoffset; /* encode the point */ prev_code = 0; if ((cur_state->clipmax.y - prev_y) < 0) { prev_code = prev_code | (1 << 3); } else if ((prev_y - cur_state->clipmin.y) < 0) { prev_code = prev_code | (1 << 2); } if ((cur_state->clipmax.x - prev_x) < 0) { prev_code = prev_code | (1 << 1); } else if ((prev_x - cur_state->clipmin.x) < 0) { prev_code = prev_code | (1 << 0); } if (!prev_code) { vdmova(&prev_x, &prev_y); } j = 0; while (++j < np) { /* convert VDC to NDC */ cur_x = *((float *)params[2] + j) * cur_state->xscale + cur_state->xoffset; cur_y = *((float *)params[3] + j) * cur_state->yscale + cur_state->yoffset; /* encode the endpoint */ cur_code = 0; if ((cur_state->clipmax.y - cur_y) < 0) { cur_code = cur_code | (1 << 3); } else if ((cur_y - cur_state->clipmin.y) < 0) { cur_code = cur_code | (1 << 2); } if ((cur_state->clipmax.x - cur_x) < 0) { cur_code = cur_code | (1 << 1); } else if ((cur_x - cur_state->clipmin.x) < 0) { cur_code = cur_code | (1 << 0); } /* determine which case this is */ if (!prev_code && !cur_code) { /* trivial accept */ vdlina(&cur_x, &cur_y); prev_x = cur_x; prev_y = cur_y; done = TRUE; } /* end trivial accept */ else if (prev_code & cur_code) { /* trivial reject */ prev_x = cur_x; prev_y = cur_y; prev_code = cur_code; done = TRUE; } else { done = FALSE; if (prev_code) { if (cur_code) { mode = 2; /* both out */ } else { mode = 1; /* prev out; cur in */ } } else { mode = 3; /* prev in; cur out */ } } while (!done) { switch (mode) { case 1: /* prev out, cur in... clip */ case 2: /* both out, clip prev first */ if (prev_code & mask) { /* clip at left edge */ prev_y = prev_y + (cur_y - prev_y) * (cur_state->clipmin.x - prev_x) / (cur_x - prev_x); prev_x = cur_state->clipmin.x; } else if ((prev_code >> 1) & mask) { /* clip at right edge */ prev_y = prev_y + (cur_y - prev_y) * (cur_state->clipmax.x - prev_x) / (cur_x - prev_x); prev_x = cur_state->clipmax.x; } if ((prev_code >> 2) & mask) { /* clip at bottom edge */ prev_x = prev_x + (cur_x - prev_x) * (cur_state->clipmin.y - prev_y) / (cur_y - prev_y); prev_y = cur_state->clipmin.y; } else if ((prev_code >> 3) & mask) { /* clip at top edge */ prev_x = prev_x + (cur_x - prev_x) * (cur_state->clipmax.y - prev_y) / (cur_y - prev_y); prev_y = cur_state->clipmax.y; } switch (mode) { case 1: /* not looping through, draw it */ vdmova(&prev_x, &prev_y); vdlina(&cur_x, &cur_y); prev_x = cur_x; prev_y = cur_y; prev_code = cur_code; done = TRUE; break; case 2: /* both were out, encode new point */ prev_code = 0; if ((cur_state->clipmax.y - prev_y) < 0) { prev_code = prev_code | (1 << 3); } else if ((prev_y - cur_state->clipmin.y) < 0) { prev_code = prev_code | (1 << 2); } if ((cur_state->clipmax.x - prev_x) < 0) { prev_code = prev_code | (1 << 1); } else if ((prev_x - cur_state->clipmin.x) < 0) { prev_code = prev_code | (1 << 0); } if (prev_code) { /* reject it */ prev_x = cur_x; prev_y = cur_y; prev_code = cur_code; done = TRUE; } else { /* prev is in */ vdmova(&prev_x, &prev_y); mode = 3; /* cur is still out, go through again */ } break; } /* end inner switch */ break; case 3: /* prev in, cur out...clip */ save_x = cur_x; save_y = cur_y; if (cur_code & mask) { /* clip at left edge */ cur_y = cur_y + (prev_y - cur_y) * (cur_state->clipmin.x - cur_x) / (prev_x - cur_x); cur_x = cur_state->clipmin.x; } else if ((cur_code >> 1) & mask) { /* clip at right edge */ cur_y = cur_y + (prev_y - cur_y) * (cur_state->clipmax.x - cur_x) / (prev_x - cur_x); cur_x = cur_state->clipmax.x; } if ((cur_code >> 2) & mask) { /* clip at bottom edge */ cur_x = cur_x + (prev_x - cur_x) * (cur_state->clipmin.y - cur_y) / (prev_y - cur_y); cur_y = cur_state->clipmin.y; } else if ((cur_code >> 3) & mask) { /* clip at top edge */ cur_x = cur_x + (prev_x - cur_x) * (cur_state->clipmax.y - cur_y) / (prev_y - cur_y); cur_y = cur_state->clipmax.y; } vdlina(&cur_x, &cur_y); prev_x = save_x; prev_y = save_y; prev_code = cur_code; done = TRUE; break; default: done = TRUE; break; } /* end switch */ } /* end while !done */ } /* end while j*/ } /* end else clipping is on */ /* flag that the page has been marked */ cur_state->pic_dirty = CDIRTY; } /* end for i */ } /* end xcpl */ /* DISJOINT POLYLINE */ static void xcdjpl(anything **params, int num_surfaces, anything **surf_list) { int i, j; /* indices for loops */ int np; /* number of points in polyline */ float x1, y1, x2, y2; /* line endpoints in NDC */ int code1, code2; /* encoded endpoints for clipping */ int mode = 0, done; /* variables used for clipping */ static unsigned mask = ~(~0u << 1); /* for masking off bits */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* check for errors */ if (MAX_DJ_POLYLINE != -1 && *(int *)params[1] > MAX_DJ_POLYLINE) { /* error 6:301 - Number of points too large. Max is used */ report_error(cur_state, 6, 301, *(short *)params[0]); np = MAX_DJ_POLYLINE; } else { np = *(int *)params[1]; } /* set SVDI foreground color if needed */ set_foreground_color(cur_state, cur_state->line_color); /* if clipping is off, just do it */ if (!cur_state->clip_on) { for (j = 0; j < np - 1; j = j + 2) { /* map VDC to NDC */ x1 = *((float *)params[2] + j) * cur_state->xscale + cur_state->xoffset; y1 = *((float *)params[3] + j) * cur_state->yscale + cur_state->yoffset; x2 = *((float *)params[2] + j + 1) * cur_state->xscale + cur_state->xoffset; y2 = *((float *)params[3] + j + 1) * cur_state->yscale + cur_state->yoffset; vdmova(&x1, &y1); vdlina(&x2, &y2); } /* end for j */ } /* end if clipping is off */ else { /* clipping is on */ /* Clip a line. Kind of based on Cohen-Sutherland algorithm. * Everything is done inline for efficiency. */ for (j = 0; j < np - 1; j = j + 2) { /* map VDC to NDC */ x1 = *((float *)params[2] + j) * cur_state->xscale + cur_state->xoffset; y1 = *((float *)params[3] + j) * cur_state->yscale + cur_state->yoffset; x2 = *((float *)params[2] + j + 1) * cur_state->xscale + cur_state->xoffset; y2 = *((float *)params[3] + j + 1) * cur_state->yscale + cur_state->yoffset; /* encode the two points */ code1 = 0; if ((cur_state->clipmax.y - y1) < 0) { code1 = code1 | (1 << 3); } else if ((y1 - cur_state->clipmin.y) < 0) { code1 = code1 | (1 << 2); } if ((cur_state->clipmax.x - x1) < 0) { code1 = code1 | (1 << 1); } else if ((x1 - cur_state->clipmin.x) < 0) { code1 = code1 | (1 << 0); } code2 = 0; if ((cur_state->clipmax.y - y2) < 0) { code2 = code2 | (1 << 3); } else if ((y2 - cur_state->clipmin.y) < 0) { code2 = code2 | (1 << 2); } if ((cur_state->clipmax.x - x2) < 0) { code2 = code2 | (1 << 1); } else if ((x2 - cur_state->clipmin.x) < 0) { code2 = code2 | (1 << 0); } /* determine which case this is */ if (!code1 && !code2) { /* trivial accept - draw it */ vdmova(&x1, &y1); vdlina(&x2, &y2); done = TRUE; } /* end trivial accept */ else if (code1 & code2) { /* trivial reject - do nothing */ done = TRUE; } else { done = FALSE; if (code1) { if (code2) { mode = 2; /* both out */ } else { mode = 1; /* x1,y1 out; x2,y2 in */ } } else { mode = 3; /* x1,y1 in; x2,y2 out */ } } while (!done) { switch (mode) { case 1: /* x1,y1 out, x2,y2 in... clip x1,y1*/ case 2: /* both out, clip x1,y1 first */ if (code1 & mask) { /* clip at left edge */ y1 = y1 + (y2 - y1) * (cur_state->clipmin.x - x1) / (x2 - x1); x1 = cur_state->clipmin.x; } else if ((code1 >> 1) & mask) { /* clip at right edge */ y1 = y1 + (y2 - y1) * (cur_state->clipmax.x - x1) / (x2 - x1); x1 = cur_state->clipmax.x; } if ((code1 >> 2) & mask) { /* clip at bottom edge */ x1 = x1 + (x2 - x1) * (cur_state->clipmin.y - y1) / (y2 - y1); y1 = cur_state->clipmin.y; } else if ((code1 >> 3) & mask) { /* clip at top edge */ x1 = x1 + (x2 - x1) * (cur_state->clipmax.y - y1) / (y2 - y1); y1 = cur_state->clipmax.y; } switch (mode) { case 1: /* not looping through, draw it */ vdmova(&x1, &y1); vdlina(&x2, &y2); done = TRUE; break; case 2: /* both were out, encode new point */ code1 = 0; if ((cur_state->clipmax.y - y1) < 0) { code1 = code1 | (1 << 3); } else if ((y1 - cur_state->clipmin.y) < 0) { code1 = code1 | (1 << 2); } if ((cur_state->clipmax.x - x1) < 0) { code1 = code1 | (1 << 1); } else if ((x1 - cur_state->clipmin.x) < 0) { code1 = code1 | (1 << 0); } if (code1) { done = TRUE; /* new point is out, reject */ } else { mode = 3; /* x1,y1 in; x2,y2 out; clip x2,y2 */ } break; } /* end inner switch */ break; case 3: /* x1,y1 in, x2,y2 out...clip */ if (code2 & mask) { /* clip at left edge */ y2 = y2 + (y1 - y2) * (cur_state->clipmin.x - x2) / (x1 - x2); x2 = cur_state->clipmin.x; } else if ((code2 >> 1) & mask) { /* clip at right edge */ y2 = y2 + (y1 - y2) * (cur_state->clipmax.x - x2) / (x1 - x2); x2 = cur_state->clipmax.x; } if ((code2 >> 2) & mask) { /* clip at bottom edge */ x2 = x2 + (x1 - x2) * (cur_state->clipmin.y - y2) / (y1 - y2); y2 = cur_state->clipmin.y; } else if ((code2 >> 3) & mask) { /* clip at top edge */ x2 = x2 + (x1 - x2) * (cur_state->clipmax.y - y2) / (y1 - y2); y2 = cur_state->clipmax.y; } vdmova(&x1, &y1); vdlina(&x2, &y2); done = TRUE; break; default: done = TRUE; break; } /* end switch */ } /* end while !done */ } /* end for j */ } /* end else clipping is on */ /* flag that the page has been marked */ cur_state->pic_dirty = CDIRTY; } /* end for i */ } /* end xcdjpl */ /* POLYMARKER */ static void xcpm(anything **params, int num_surfaces, anything **surf_list) { int i, j; /* indices for loops */ int np; /* number of points */ float *x, *y; /* x,y values */ float x_vdi, y_vdi; /* x,y values in NDC */ int ok; /* flag TRUE =mark lies in clip region */ for (i = 0; i < num_surfaces; ++i) { np = *(int *)params[1]; x = (float *)params[2]; y = (float *)params[3]; cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* check for errors */ if (MAX_POLYMARKER != -1 && *(int *)params[1] > MAX_POLYMARKER) { /* error 6:301 - Number of points too large. Max is used */ report_error(cur_state, 6, 301, *(short *)params[0]); np = MAX_POLYMARKER; } else { np = *(int *)params[1]; } /* set SVDI foreground color if needed */ set_foreground_color(cur_state, cur_state->mark_color); /* set marker type */ /* --only support "dot" for now - so nothing to set */ /* set marker size */ /* --only support "dot" for now - so nothing to set */ for (j = 0; j < np; j++) { /* map VDC to NDC */ x_vdi = x[j] * cur_state->xscale + cur_state->xoffset; y_vdi = y[j] * cur_state->yscale + cur_state->yoffset; ok = TRUE; if (cur_state->clip_on) { /* clip is on */ /* ...clip the whole polymarker - it's in or it's out */ ok = ((x_vdi <= cur_state->clipmax.x && x_vdi >= cur_state->clipmin.x) && (y_vdi <= cur_state->clipmax.y && y_vdi >= cur_state->clipmin.y)); } if (ok) { vdpnta(&x_vdi, &y_vdi); } } /* end for j */ /* flag that the page has been marked */ cur_state->pic_dirty = CDIRTY; } /* end for i */ } /* end xcpm */ /* TEXT */ static void xctx(anything **params, int num_surfaces, anything **surf_list) { int i, j; /* indices for loops */ float x, y; /* x,y starting position */ char *ch; /* input character string */ char c; /* 1 character */ int np; /* number of chars in text string */ int ich[MAX_TEXT_LENGTH]; /* array of ascii chars to pass SVDI */ int ok; /* flag TRUE =line lies in clip region */ float temp_array[14]; /* used for SVDI inquiries */ float char_height; /* char height, in VDC or NDC */ float char_width; /* char width, in VDC or NDC */ int skip; /* nbr of chars to skip when clipping */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* error checking */ if (*(int *)params[3] != CFINAL) { /* compound text not supported */ /* error 2:001 - Request for unsupported feature. Function ignored */ report_error(cur_state, 2, 001, *(short *)params[0]); break; } /* params[5] is an added parameter which is length of string */ else if (MAX_TEXT_LENGTH != -1 && *(int *)params[5] > MAX_TEXT_LENGTH) { /* error 6:301 - Number of points too large. Max is used */ report_error(cur_state, 6, 301, *(short *)params[0]); np = MAX_TEXT_LENGTH; } else { np = *(int *)params[5]; } /* if there is nothing to draw, break */ if (np <= 0) { break; } /* set SVDI foreground color if needed */ set_foreground_color(cur_state, cur_state->text_color); /* find out what the SVDI character height/width is */ vdiqos(&temp_array[1]); /* convert stuff to NDC */ char_width = temp_array[7]; char_height = temp_array[6]; /* map VDC to NDC */ x = *(float *)params[1] * cur_state->xscale + cur_state->xoffset; y = *(float *)params[2] * cur_state->yscale + cur_state->yoffset; ok = TRUE; skip = 0; /* this text clipping assumes no backspaces, etc.,and only the * default character orientation. */ if (cur_state->clip_on) { /* clipping is on, do it */ /* if the string doesn't fit in y, reject it */ ok = (y >= cur_state->clipmin.y && (y + char_height) <= cur_state->clipmax.y); if (ok) { /* ok in y, check it in x */ /* check for trivial reject */ ok = (x < cur_state->clipmax.x && (x + (np * char_width)) > cur_state->clipmin.x); if (ok) { /* it's in there, clip it */ /* clip to left edge */ if (x < cur_state->clipmin.x) { /* ...compute how many chars to skip */ skip = ceil((cur_state->clipmin.x - x) / char_width); /* ...compute new x */ x = x + ((float)skip * char_width); /* ...compute new number of chars */ np = np - skip; } /* clip to right edge */ if (x + (np * char_width) > cur_state->clipmax.x) { /* ...compute how many chars fit */ np = (int)((cur_state->clipmax.x - x) / char_width); } } /* end if ok in x */ } /* end if ok in y */ } /* end if clip_on */ ok = ok && np > 0; /* make sure there is still some text left */ if (ok) { /* everything is still ok */ /* move to position, and draw the text */ vdmova(&x, &y); ch = &(((char *)params[4])[skip]); for (j = 0; j < np; j++) { c = *ch++; /* this works for ASCII machines */ ich[j] = (int)c; } vdtext(&j, ich); } /* end if ok */ } /* end for each surface */ } /* end xctx */ /* POLYGON */ static void xcpg(anything **params, int num_surfaces, anything **surf_list) { int i, j; /* indices for loops */ int np; /* number of points */ float *x, *y; /* x,y VDC values */ float xnew[MAX_POLYGON]; /* clipped x,y values (VDC or NDC) */ float ynew[MAX_POLYGON]; int npnew; /* number of points after clip */ float temp_array[14]; /* temp used for SVDI inquire */ int qdc_index; /* for inquire SVDI */ int vdi_ls; /* SVDI linestyle */ int ok; /* flag TRUE =line lies in clip region */ static float poly_support = -1.; /* save whether SVDI does polygons */ static float vdi_polymax = -1.; /* store SVDI polygon max value */ /* find out SVDI support for polygons. */ if (poly_support == -1.) { qdc_index = 24; vdiqdc(&qdc_index, &poly_support); } /* get and store max polygon points from SVDI */ if (vdi_polymax == -1.) { qdc_index = 25; vdiqdc(&qdc_index, &vdi_polymax); } for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* error checking */ if (MAX_POLYGON != -1 && (*(int *)params[1] > MAX_POLYGON || *(int *)params[1] > vdi_polymax)) { /* error 6:302 - Number of points in polygon too large. Max used */ report_error(cur_state, 6, 302, *(short *)params[0]); np = (MAX_POLYGON < vdi_polymax) ? MAX_POLYGON : vdi_polymax; } else { np = *(int *)params[1]; } x = (float *)params[2]; y = (float *)params[3]; /* set SVDI foreground color if needed */ set_foreground_color(cur_state, cur_state->fill_color); /* map VDC to NDC */ for (j = 0; j < np; j++) { xnew[j] = *x++ * cur_state->xscale + cur_state->xoffset; ynew[j] = *y++ * cur_state->yscale + cur_state->yoffset; } /* end for j */ ok = TRUE; if (cur_state->clip_on) { /* clip is on */ /* poly clip returns new x,y values and a count */ /* this routine should be done inline for efficiency */ ok = poly_clip(&cur_state->clipmin, &cur_state->clipmax, xnew, ynew, np, xnew, ynew, &npnew); } else { /* no clpping */ npnew = np; } if (ok) { /* everything's ok, do the polygon */ /* if hollow or if no polygon support, draw the border lines. if solid, call vdpoly */ if ((cur_state->interior_style == CHOLLO) || /* hallow OR */ (poly_support < 3.)) { /*no poly supp */ vdiqos(&temp_array[1]); /* make sure line style is solid */ if (temp_array[4] != 0) { vdi_ls = 0; vdstls(&vdi_ls); } vdmova(&xnew[0], &ynew[0]); for (j = 1; j < npnew; j++) { vdlina(&xnew[j], &ynew[j]); } vdlina(&xnew[0], &ynew[0]); if (temp_array[4] != 0) { /* set line style back */ vdi_ls = (int)temp_array[4]; vdstls(&vdi_ls); } } /* end if hollow OR no poly support */ else { /* solid polygon */ vdpoly(xnew, ynew, &npnew); } /* flag that the page has been marked */ cur_state->pic_dirty = CDIRTY; } /*end if ok */ } /* end for i */ } /* end xcpg */ /* CELL ARRAY */ static void xcca(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ int j, k; /* loop indices */ int index, index_inc, count; /* array indices */ int nx, ny; /* number of cells in x,y */ int nx1, ny1; /* number of cells in x,y after clipping */ int *cells; /* color values */ int ix, iy, yinc; /* SVDI logical raster coordinates */ float x1, x2, y1, y2; /* corners of rectangle in NDC */ float xmin, xmax, ymin, ymax; /* SVDI raster viewport (NDC) */ int xdir, ydir; /* x,y directions on the device */ int imap; float xcell, ycell; /* area per cell */ int ok; /* flag TRUE =line lies in clip region */ int skipx, skipy; /* number of cells clipped in xmin,ymin */ /* if there isn't anything to draw, return */ if (*(int *)params[7] == 0 || *(int *)params[8] == 0) { return; } /* if cell array has negative dimension, use absolute values */ nx = nx1 = abs(*(int *)params[7]); ny = ny1 = abs(*(int *)params[8]); cells = (int *)params[10]; for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* if color selection mode is in error, ignore function */ if (cur_state->csm == -1) { break; } /* for now, only allow 4 cases (same as pixel array), * where nx runs only horizontal, and ny runs vertical. * this routine needs to be fixed to allow all 8 cases * Also, this routine does not allow skewing. */ if (*(float *)params[2] != *(float *)params[6] || *(float *)params[3] != *(float *)params[5]) { /* error 1:-106 Illegal cell array. Function ignored */ report_error(cur_state, 1, -106, *(short *)params[0]); return; } /* map corners to NDC */ x1 = *(float *)params[1] * cur_state->xscale + cur_state->xoffset; x2 = *(float *)params[3] * cur_state->xscale + cur_state->xoffset; y1 = *(float *)params[2] * cur_state->yscale + cur_state->yoffset; y2 = *(float *)params[4] * cur_state->yscale + cur_state->yoffset; /* figure out the raster viewport limits, and figure * out x and y directions based on mappings and * rectangle orientation. */ if (x1 < x2) { xmin = x1; xmax = x2; xdir = CINCR; } else { xmin = x2; xmax = x1; xdir = CDECR; } if (y1 < y2) { ymin = y1; ymax = y2; ydir = CINCR; } else { ymin = y2; ymax = y1; ydir = CDECR; } ok = TRUE; skipx = skipy = 0; if (cur_state->clip_on) { /* clipping is on, do it */ /* trivial reject */ ok = ((xmin < cur_state->clipmax.x && xmax > cur_state->clipmin.x) && (ymin < cur_state->clipmax.y && ymax > cur_state->clipmin.y)); if (ok) { /* it's in there, clip it */ /* clip in x first */ xcell = (xmax - xmin) / nx; /* area per cell */ /* clip at left edge */ if (xmin < cur_state->clipmin.x) { /* ...compute how many cells to skip */ skipx = ceil((cur_state->clipmin.x - xmin) / xcell); /* ...compute new xmin */ xmin = xmin + ((float)skipx * xcell); /* ...compute new nx */ nx1 = nx - skipx; } /* end clip at left edge */ /* clip at right edge */ if (xmax > cur_state->clipmax.x) { /* ...compute new nx - how much will fit */ nx1 = (int)((cur_state->clipmax.x - xmin) / xcell); /* ...compute new xmax */ xmax = xmin + (nx1 * xcell); } /* end clip at right edge */ /* now clip in y */ ycell = (ymax - ymin) / ny; /* area per cell */ /* clip at bottom edge */ if (ymin < cur_state->clipmin.y) { /* ...compute how many cells to skip */ skipy = ceil((cur_state->clipmin.y - ymin) / ycell); /* ...compute new ymin */ ymin = ymin + ((float)skipy * ycell); /* ...compute new ny */ ny1 = ny - skipy; } /* end clip at bottom edge */ /* clip at top edge */ if (ymax > cur_state->clipmax.y) { /* ...compute new ny - how much will fit */ ny1 = (int)((cur_state->clipmax.y - ymin) / ycell); /* ...compute new ymax */ ymax = ymin + (ny1 * ycell); } /* end clip at top edge */ } /* end if ok */ } /* end if clip is on */ /* make sure there is still something left */ ok = ok && (nx1 > 0 && ny1 > 0); if (ok) { /* everything is still ok */ /* set the raster space */ vdstrs(&nx1, &ny1); imap = 3; vbstmp(&imap); imap = 5; vbstmp(&imap); /* set the raster viewport */ vdstrv(&xmin, &xmax, &ymin, &ymax); /* direct color or indexed */ if (cur_state->csm == CINDEX) { /* indexed color */ /* Indexing into the cell array is based on clipping info * and the orientation of the rectangle. SVDI+raster puts * [0,0] at the top left corner. */ /* There are 4 different cases based on the orientation * of the rectangle. ( really, there are 8, but I'm not * supporting the other 4 right now ). If x is increasing, * the most natural case, the cell array will be written * out one raster line at a time, either top to bottom or * bottom to top depending on the y direction. If x is * decreasing, the cell array will have to be copied and * reordered, so it will be written out in chunks. In this * case, it will always be written out top to bottom. */ if (xdir == CINCR) { /* x increasing */ ix = 0; /* compute iy and y increment based on y direction */ if (ydir == CINCR) { /* y increasing */ iy = ny1 - 1; yinc = -1; } else { iy = 0; yinc = 1; } /* This special case is for efficiency, since is will probably * be most of the cases: If no clipping is on and [0,0] is at * the top left (like SVDI+raster) draw the whole cell array. */ if (!cur_state->clip_on && iy == 0) { count = nx * ny; vdpixi(&ix, &iy, &cells[0], &count); } /* end special case */ else { /* special case doesn't apply, draw one line at a time */ /* starting index based on clipping info */ index = (ny - ny1 - skipy) * nx + skipx; /* output one raster line at a time */ for (k = 0; k < ny1; k++) { vdpixi(&ix, &iy, &cells[index], &nx1); index = index + nx; /* compute next index */ iy = iy + yinc; /* compute next raster line */ } /* end for k */ } /* end else no special case */ } /* end x increasing */ else { /* x decreasing */ /* always write top to bottom */ ix = iy = count = 0; /* starting index and index increment are based on clipping info and the y direction*/ if (ydir == CINCR) { /* y increasing */ index = (ny1 + skipy) * nx - skipx - 1; index_inc = -nx + nx1; yinc = -1; } else { /* y decreasing */ index = (ny - ny1 - skipy) * nx + (nx - 1) - skipx; index_inc = nx + nx1; yinc = 1; } /* reorder the cell colors */ for (k = 0; k < ny1; k++) { for (j = 0; j < nx1; j++) { assert(count < MAX_ARRAY); varray[count++] = cells[index--]; } /* if another row won't fit, or done, output varray */ if (count + nx1 > MAX_ARRAY || k == ny1 - 1) { vdpixi(&ix, &iy, varray, &count); count = 0; /* reset varray counter */ iy = iy + (yinc * (k + 1)); /* update iy */ } /* compute next index */ index = index + index_inc; } /* end for k */ } /* end x decreasing */ } /* end if indexed color */ else { /* direct color */ /* Indexing into the cells array is based on clipping info, * and the orientation of the cell array. In SVDI+raster, * the top left corner is [0,0]. For direct color, the cell * array is always drawn from top to bottom. If the cell array * is oriented with [0,0] at the the bottom left corner, the * way the cells array is indexed takes care of the flipping. */ ix = iy = count = 0; if (xdir == CINCR) { /* x increasing */ /* starting index and index increment are based on clipping info and the y direction */ if (ydir == CINCR) { /* y increasing */ index = ((ny1 + skipy - 1) * nx * 3) + (skipx * 3); index_inc = -(nx + nx1) * 3; } else { /* y decreasing */ index = (ny - ny1 - skipy) * nx * 3 + (skipx * 3); index_inc = (nx - nx1) * 3; } /* store as much info as possible before calling vdpixl */ for (k = 0; k < ny1; k++) { for (j = 0; j < nx1; j++) { assert(count < MAX_ARRAY); rarray[count] = (float)cells[index++] / 255.0f; garray[count] = (float)cells[index++] / 255.0f; barray[count] = (float)cells[index++] / 255.0f; count++; } /* end for j */ /* if another row won't fit, or done, output rgb arrays */ if (count + nx1 > MAX_ARRAY || k == ny1 - 1) { vdpixl(&ix, &iy, rarray, garray, barray, &count); count = 0; /* reset rgb array counter */ iy = k + 1; /* update iy */ } /* compute next index into the cells array */ index = index + index_inc; } /* end for k */ } /* end if x increasing */ else { /* x decreasing */ /* starting index and index increment are based on clipping info and the y direction */ if (ydir == CINCR) { /* y increasing */ index = (ny1 + skipy) * nx * 3 - (skipx * 3) - 3; index_inc = (-nx + nx1) * 3; } else { /* y decreasing */ index = (ny - ny1 - skipy) * nx * 3 + ((nx - 1) * 3) - (skipx * 3); index_inc = (nx + nx1) * 3; } /* store as much info as possible before calling vdpixl */ for (k = 0; k < ny1; k++) { for (j = 0; j < nx1; j++) { assert(count < MAX_ARRAY); rarray[count] = (float)cells[index] / 255.0f; garray[count] = (float)cells[index + 1] / 255.0f; barray[count] = (float)cells[index + 2] / 255.0f; index = index - 3; count++; } /* end for j */ /* if another row won't fit, or done, output rgb arrays */ if (count + nx1 > MAX_ARRAY || k == ny1 - 1) { vdpixl(&ix, &iy, rarray, garray, barray, &count); count = 0; /* reset rgb array counter */ iy = k + 1; /* update iy */ } /* compute next index into the cells array */ index = index + index_inc; } /* end for k */ } /* end else x decreasing */ } /* end else direct color */ /* flag that the page has been marked */ cur_state->pic_dirty = CDIRTY; } /* end if ok */ } /* end for each surface */ } /* end xcca */ /* PIXEL ARRAY */ static void xcpxa(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ int j, k; /* loop indices */ int *pxclrs; /* pixel color values */ int nx, ny; /* size of pixel color array */ int nx1, ny1; /* number of pixels after clipping */ int index, index_inc; /* index into pxclrs array */ int count; /* index into temp pixel arrays */ int repx, repy; /* replication in x and y */ int xdir, ydir; /* x and y direction on the DEVICE */ float x_orig, y_orig; /* x and y origin */ float x_dist, y_dist; /* distance pixels run from the origin */ int ix, iy, yinc; /* SVDI logical raster coordinates */ float xmin, xmax, ymin, ymax; /* SVDI raster viewport after clipping */ int ok; /* flag TRUE =line lies in clip region */ int skipx, skipy; /* count pixels skipped in xmin,ymin */ int imap; int qrs_index; /* index for SVDI inquiries */ float temp_array[2]; /* temporary array for SVDI inquiries */ float x_pxl_scale; /* for converting pixels to NDC/VDC space */ float y_pxl_scale; static float x_pixels = -1.; /* number of pixels in full NDC space */ static float y_pixels = -1.; float zero = 0.0; /* if nx,ny,repx,or repy are non positive, nothing is drawn */ if (*(int *)params[3] < 0 || *(int *)params[4] < 0 || *(int *)params[5] < 0 || *(int *)params[6] < 0) { return; } /* set up initial values */ nx = nx1 = *(int *)params[3]; ny = ny1 = *(int *)params[4]; repx = *(int *)params[5]; repy = *(int *)params[6]; pxclrs = (int *)params[9]; /* find (and save) the number of pixels in full NDC space */ if (x_pixels == -1. && y_pixels == -1.) { vdstrv(&zero, &dev_descrip.xndc_max, &zero, &dev_descrip.yndc_max); qrs_index = 2; vdiqrs(&qrs_index, temp_array); x_pixels = temp_array[0]; y_pixels = temp_array[1]; } /* end find number of pixels */ /* loop through surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* if color selection mode is in error, ignore function */ if (cur_state->csm == -1) { break; } /* check enumerated types */ if ((*(int *)params[7] != CINCR && *(int *)params[7] != CDECR) || (*(int *)params[8] != CINCR && *(int *)params[8] != CDECR)) { /* error 1:-101 enumerated parameter out of range. Function ignored */ report_error(cur_state, 1, -101, *(short *)params[0]); break; } /* figure out what x direction and y direction are in terms * of the device, since x direction and y direction are dependent * on the VDC to device mapping. If xscale is positive, then * VDC and VP are either both increasing or both decreasing and * x direction on the device is the same as x direction in VDC. * If xscale is negative, one is increasing and one is decreasing, * and x direction on the device is opposite of x direction in * VDC. Same holds for y (where "increasing" means bottom to top) */ if (cur_state->xscale > 0) { xdir = *(int *)params[7]; } else { xdir = (*(int *)params[7] == CINCR) ? CDECR : CINCR; } if (cur_state->yscale > 0) { ydir = *(int *)params[8]; } else { ydir = (*(int *)params[8] == CINCR) ? CDECR : CINCR; } /* map to NDC */ /* origin */ x_orig = *(float *)params[1] * cur_state->xscale + cur_state->xoffset; y_orig = *(float *)params[2] * cur_state->yscale + cur_state->yoffset; /* scale to convert pixels to NDC space */ x_pxl_scale = dev_descrip.xndc_max / x_pixels; y_pxl_scale = dev_descrip.yndc_max / y_pixels; /* figure out raster viewport mins and maxes */ x_dist = nx * repx * x_pxl_scale; y_dist = ny * repy * y_pxl_scale; /* ...x is increasing or decreasing */ if (xdir == CINCR) { xmin = x_orig; xmax = x_orig + x_dist; } else { xmin = x_orig - x_dist; xmax = x_orig; } /* y is increasing or decreasing */ if (ydir == CINCR) { ymin = y_orig; ymax = y_orig + y_dist; } else { ymin = y_orig - y_dist; ymax = y_orig; } ok = TRUE; skipx = skipy = 0; if (cur_state->clip_on) { /* do the clipping */ /* trivial reject */ ok = ((xmin < cur_state->clipmax.x && xmax > cur_state->clipmin.x) && (ymin < cur_state->clipmax.y && ymax > cur_state->clipmin.y)); if (ok) { /* it's in there, clip it */ /* clip in x first */ if (xmin < cur_state->clipmin.x) { /* ...left edge */ /* ...compute how many pixels to skip */ skipx = ceil((cur_state->clipmin.x - xmin) / (x_pxl_scale * repx)); /* ...compute new xmin */ xmin = xmin + ((float)skipx * x_pxl_scale * repx); /* ...compute new nx */ nx1 = nx - skipx; } /* end clip left edge */ if (xmax > cur_state->clipmax.x) { /* ...right edge */ /* ...compute new nx */ nx1 = (int)((cur_state->clipmax.x - xmin) / (x_pxl_scale * repx)); /* ...compute new xmax */ xmax = xmin + (nx1 * x_pxl_scale * repx); } /* end clip right edge */ /* now clip in y */ if (ymin < cur_state->clipmin.y) { /* ...bottom edge */ /* ...compute how many pixels to skip */ skipy = ceil((cur_state->clipmin.y - ymin) / (y_pxl_scale * repy)); /* ...compute new ymin */ ymin = ymin + ((float)skipy * y_pxl_scale * repy); /* ...compute new ny */ ny1 = ny - skipy; } /* end bottom left edge */ if (ymax > cur_state->clipmax.y) { /* ...top edge */ /* ...compute new ny */ ny1 = (int)((cur_state->clipmax.y - ymin) / (y_pxl_scale * repy)); /* ...comput new ymax */ ymax = ymin + (ny1 * y_pxl_scale * repy); } /* end clip top edge */ } /* end if ok */ } /* end if clip_on */ /* make sure there is still something to draw */ ok = ok && (nx1 > 0 && ny1 > 0); if (ok) { /* everything is still ok */ /* set the raster viewport */ vdstrv(&xmin, &xmax, &ymin, &ymax); imap = 2; vbstmp(&imap); imap = 5; vbstmp(&imap); /* set the raster space to number of device pixels in viewport */ vdstrs(&nx1, &ny1); /* direct color or indexed */ if (cur_state->csm == CINDEX) { /* indexed color */ /* Indexing into the pixel array is based on clipping info * and the orientation of the pixel array, which is * determined by whether x and y are increasing or * decreasing in VDC from the origin. SVDI+raster puts * [0,0] at the top left corner. */ /* There are 4 different cases based on the x and y * directions. If x is increasing, the most natural * case, the pixel array will be written out one raster * line at a time, either top to bottom or bottom to * top depending on the y direction. If x is decreasing, * the pixel array will have to be copied and reordered, * so it will be written out in chunks. In this case, * it will always be written out top to bottom. */ if (xdir == CINCR) { /* x increasing */ ix = 0; /* compute iy and y increment based on y direction */ if (ydir == CINCR) { /* y increasing */ iy = ny1 - 1; yinc = -1; } else { /* y decreasing */ iy = 0; yinc = 1; } /* This special case is for efficiency, since is will probably * be most of the cases: If no clipping is on and [0,0] is at * the top left (like SVDI+raster) draw the whole pixel array. */ if (!cur_state->clip_on && iy == 0) { count = nx * ny; vdpixi(&ix, &iy, &pxclrs[0], &count); } /* end special case */ else { /* special case doesn't apply, draw one line at a time */ /* starting index based on clipping info */ index = (ny - ny1 - skipy) * nx + skipx; /* output one raster line at a time */ for (k = 0; k < ny1; k++) { vdpixi(&ix, &iy, &pxclrs[index], &nx1); index = index + nx; /* compute next index */ iy = iy + yinc; /* compute next raster line */ } /* end for k */ } /* end else no special case */ } /* end x increasing */ else { /* x decreasing */ /* always write top to bottom */ ix = iy = count = 0; /* starting index and index increment are based on clipping info and the y direction*/ if (ydir == CINCR) { /* y increasing */ index = (ny1 + skipy) * nx - skipx - 1; index_inc = -nx + nx1; yinc = -1; } else { /* y decreasing */ index = (ny - ny1 - skipy) * nx + (nx - 1) - skipx; index_inc = nx + nx1; yinc = 1; } /* reorder the pixel colors */ for (k = 0; k < ny1; k++) { for (j = 0; j < nx1; j++) { assert(count < MAX_ARRAY); varray[count++] = pxclrs[index--]; } /* if another row won't fit, or done, output varray */ if (count + nx1 > MAX_ARRAY || k == ny1 - 1) { vdpixi(&ix, &iy, varray, &count); count = 0; /* reset varray counter */ iy = iy + (yinc * (k + 1)); /* update iy */ } /* compute next index */ index = index + index_inc; } /* end for k */ } /* end x decreasing */ } /* end if indexed color */ else { /* direct color */ /* For direct color, the color values always have to be * copied, so the raster lines are written out in chucks. * The raster lines will always be written top to bottom; * indexing and reordering of the color values will be * based on x and y direction. */ ix = iy = count = 0; if (xdir == CINCR) { /* x increasing */ /* starting index and index increment are based on clipping info and the y direction */ if (ydir == CINCR) { /* y increasing */ index = ((ny1 + skipy - 1) * nx * 3) + (skipx * 3); index_inc = -(nx + nx1) * 3; } else { /* y decreasing */ index = (ny - ny1 - skipy) * nx * 3 + (skipx * 3); index_inc = (nx - nx1) * 3; } /* store as much info as possible before calling vdpixl */ for (k = 0; k < ny1; k++) { for (j = 0; j < nx1; j++) { assert(count < MAX_ARRAY); rarray[count] = (float)pxclrs[index++] / 255.0f; garray[count] = (float)pxclrs[index++] / 255.0f; barray[count] = (float)pxclrs[index++] / 255.0f; count++; } /* end for j */ /* if another row won't fit, or done, output rgb arrays */ if (count + nx1 > MAX_ARRAY || k == ny1 - 1) { vdpixl(&ix, &iy, rarray, garray, barray, &count); count = 0; /* reset rgb array counter */ iy = k + 1; /* update iy */ } /* compute next index into the pxclrs array */ index = index + index_inc; } /* end for k */ } /* end if x increasing */ else { /* x decreasing */ /* starting index and index increment are based on clipping info and the y direction */ if (ydir == CINCR) { /* y increasing */ index = (ny1 + skipy) * nx * 3 - (skipx * 3) - 3; index_inc = (-nx + nx1) * 3; } else { /* y decreasing */ index = (ny - ny1 - skipy) * nx * 3 + ((nx - 1) * 3) - (skipx * 3); index_inc = (nx + nx1) * 3; } /* store as much info as possible before calling vdpixl */ for (k = 0; k < ny1; k++) { for (j = 0; j < nx1; j++) { assert(count < MAX_ARRAY); rarray[count] = (float)pxclrs[index] / 255.0f; garray[count] = (float)pxclrs[index + 1] / 255.0f; barray[count] = (float)pxclrs[index + 2] / 255.0f; index = index - 3; count++; } /* end for j */ /* if another row won't fit, or done, output rgb arrays */ if (count + nx1 > MAX_ARRAY || k == ny1 - 1) { vdpixl(&ix, &iy, rarray, garray, barray, &count); count = 0; /* reset rgb array counter */ iy = k + 1; /* update iy */ } /* compute next index into the pxclrs array */ index = index + index_inc; } /* end for k */ } /* end else x decreasing */ } /* end else direct color */ /* flag that the page has been marked */ cur_state->pic_dirty = CDIRTY; } /* end if ok */ } /* end for each surface */ } /* end xcpxa */ /* LINE TYPE */ static void xclnt(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ int vdi_style; /* SVDI linestyle */ /* CGI line types: */ /* 1: solid - supported * 2: dash - supported * 3: dot - supported * 4: dash dot - supported * 5: dash dot dot - not supported */ /* SVDI linestyles: */ /* 0: solid * 1: dotted * 2: dot dash * 3: short dash * 4: long dash * 5: medium dash */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* let SVDI catch any out of range indices */ cur_state->line_type = *(int *)params[1]; /* make sure it really needs to be set */ if (cur_state->line_type != cur_state->vdi_attrib.line_type) { cur_state->vdi_attrib.line_type = cur_state->line_type; /* map to SVDI styles */ switch (cur_state->line_type) { case 1: vdi_style = 0; break; case 2: vdi_style = 5; break; case 3: vdi_style = 1; break; case 4: vdi_style = 2; break; case 5: vdi_style = 0; break; /* not supported, set to solid */ default: vdi_style = cur_state->line_type; break; } /* end switch */ vdstls(&vdi_style); } /* end it needs to be set */ } /* end for each surface */ } /* end xclnt */ /* LINE WIDTH */ static void xclnw(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ float vdi_lw; /* SVDI linewidth */ float temp_array[14]; /* use for SVDI inquiry */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* make sure it needs to be updated */ if (*(float *)params[1] != cur_state->vdi_attrib.line_width) { /* save the original in vdi_attrib array */ cur_state->vdi_attrib.line_width = *(float *)params[1]; /* convert to NDC and set the linewidth */ vdi_lw = dev_descrip.linewidth_nominal * *(float *)params[1] * fabs(cur_state->xscale); vdstlw(&vdi_lw); /* find out what it really got set at */ vdiqos(&temp_array[1]); /* map it back to (scaled) VDC and store it in state table */ cur_state->line_width = (temp_array[5] * fabs(cur_state->xscale) * 100) / dev_descrip.linewidth_nominal; } /* end it needs to be updated */ } /* end for each surface */ } /* end xclnw */ /* LINE COLOR */ static void xclnc(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* if color selection mode is in error, ignore function */ if (cur_state->csm == -1) { break; } if (cur_state->csm == CINDEX) { /* indexed mode */ /* let SVDI catch out of range indices */ cur_state->line_csm = CINDEX; cur_state->line_color[0] = *(int *)params[1]; } /* end indexed mode */ else { /* direct color mode */ /* let SVDI catch illegal color values */ cur_state->line_csm = CDRECT; cur_state->line_color[0] = *((int *)params[1] + 0); cur_state->line_color[1] = *((int *)params[1] + 1); cur_state->line_color[2] = *((int *)params[1] + 2); } /* end direct color mode */ } /* end for each surface */ } /* end xclnc */ /* MARKER TYPE */ static void xcmkt(int num_surfaces, anything **surf_list) { /* CGI marker types: */ /* 1: dot - supported * 2: plus - not supported * 3: asterisk - not supported * 4: circle - not supported * 5: cross - not supported */ /* SVDI only supports a dot, which is the default */ /* An unsupported index is mapped to a supported value, such * as the default, without error. So can just ignore this * function. */ } /* end xcmkt */ /* MARKER SIZE */ static void xcmks(anything **params, int num_surfaces, anything **surf_list) { /* marker size is mapped to nearest avail marker size on * the device. SVDI only supports 1 marker size, which is * the default size, so this function not supported. */ /* error 4:001 - Function not supported. Function ignored */ report_error(cur_state, 4, 001, *(short *)params[0]); } /* end xcmks */ /* MARKER COLOR */ static void xcmkc(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* if color selection mode is in error, ignore function */ if (cur_state->csm == -1) { break; } if (cur_state->csm == CINDEX) { /* indexed mode */ /* let SVDI catch out of range indices */ cur_state->mark_csm = CINDEX; cur_state->mark_color[0] = *(int *)params[1]; } /* end indexed mode */ else { /* direct color mode */ /* let SVDI catch illegal color values */ cur_state->mark_csm = CDRECT; cur_state->mark_color[0] = *((int *)params[1] + 0); cur_state->mark_color[1] = *((int *)params[1] + 1); cur_state->mark_color[2] = *((int *)params[1] + 2); } /* end direct color mode */ } /* end for each surface */ } /* end xcmkc */ /* TEXT PRECISION */ static void xctxp(anything **params, int num_surfaces, anything **surf_list) { /* error 4:001 - Function not supported. Function ignored */ report_error(cur_state, 4, 001, *(short *)params[0]); } /* end xctxp */ /* TEXT COLOR */ static void xctxc(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* if color selection mode is in error, ignore function */ if (cur_state->csm == -1) { break; } if (cur_state->csm == CINDEX) { /* indexed mode */ /* let SVDI catch out of range indices */ cur_state->text_csm = CINDEX; cur_state->text_color[0] = *(int *)params[1]; } /* end indexed mode */ else { /* direct color mode */ /* let SVDI catch illegal color values */ cur_state->text_csm = CDRECT; cur_state->text_color[0] = *((int *)params[1] + 0); cur_state->text_color[1] = *((int *)params[1] + 1); cur_state->text_color[2] = *((int *)params[1] + 2); } /* end direct mode */ } /* end for each surface */ } /* end xctxc */ /* CHARACTER HEIGHT */ static void xcchh(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ float vdi_cs; /* SVDI character size */ float temp_array[14]; /* used for SVDI inquire */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* set SVDI character size if needed */ if (*(float *)params[1] != cur_state->vdi_attrib.char_x) { /* let SVDI catch illegal character height */ cur_state->vdi_attrib.char_x = *(float *)params[1]; /* map to NDC */ vdi_cs = *(float *)params[1] * fabs(cur_state->xscale); vdstcs(&vdi_cs); /* inquire to find out what it really got set to */ vdiqos(&temp_array[1]); /* map back to VDC and store in state table */ cur_state->char_height = temp_array[6] / fabs(cur_state->xscale); } /* end if char size needs to be set */ } /* end for each surface */ } /* end xcchh */ /* CHARACTER ORIENTATION */ static void xccho(anything **params, int num_surfaces, anything **surf_list) { /* error 4:001 - Function not supported. Function ignored */ report_error(cur_state, 4, 001, *(short *)params[0]); } /* end xccho */ /* INTERIOR STYLE */ static void xcis(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ /* CGI interior styles: */ /* hollow - supported * solid - supported * pattern - not supported * hatch - not supported * empty - not supported * bitmap - not supported */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* check for legal enumerated value */ if (*(int *)params[1] == CHOLLO || *(int *)params[1] == CSOLID) { cur_state->interior_style = *(int *)params[1]; } else { /* error 1:-101 Enumerated parameter out of range. Function ignored */ report_error(cur_state, 1, -101, *(short *)params[0]); } } /* end for each surface */ } /* end xcis */ /* FILL COLOR */ static void xcflc(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* if color selection mode is in error, ignore function */ if (cur_state->csm == -1) { break; } if (cur_state->csm == CINDEX) { /* indexed mode */ /* let SVDI catch out of range indices */ cur_state->fill_csm = CINDEX; cur_state->fill_color[0] = *(int *)params[1]; } /* end indexed color */ else { /* direct color mode */ /* let SVDI catch illegal color values */ cur_state->fill_csm = CDRECT; cur_state->fill_color[0] = *((int *)params[1] + 0); cur_state->fill_color[1] = *((int *)params[1] + 1); cur_state->fill_color[2] = *((int *)params[1] + 2); } /* end direct color mode */ } /* end for each surface */ } /* end xcflc */ /* COLOR SELECTION MODE */ static void xccsm(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* check enumerated parameters */ if (*(int *)params[1] != CDRECT && *(int *)params[1] != CINDEX) { /* error 1:-101 enumerated parameter out of range. Function ignored */ report_error(cur_state, 1, -101, *(short *)params[0]); } else { /* if the device supports both index and direct, or the request if only for index, everything is honky-dory */ if (dev_descrip.csm_avail == CCLRID || *(int *)params[1] == CINDEX) { cur_state->csm = *(int *)params[1]; } else { /* must be an error */ /* error 3:305 - Color selection mode not supported. All functions with affected parameters ignored until reset */ report_error(cur_state, 3, 305, *(short *)params[0]); cur_state->csm = -1; /* flag error condition */ } /* end else must be an error */ } /* end else */ } /* end for each surface */ } /* end xccsm */ /* COLOR TABLE */ static void xcct(anything **params, int num_surfaces, anything **surf_list) { int i; /* index for loop on surfaces */ int j, k; /* indices for looping */ int starti; /* starting color index */ int num_cols; /* number of colors in color list */ int tmp_array[3]; /* temp array used for setting bg color */ float color_array[256][3]; /* used for setting SVDI color table */ int num_set; /* number of colors being set, for SVDI */ int maxindex; /* max color index to set */ int indx_ptr; /* for keeping track of color indices */ int index1, index2; /* defines a range of indices to set */ int one = 1; /* starting color index and number of colors */ starti = *(int *)params[1]; num_cols = *(int *)params[2]; /* error checking */ /* an out of range index in an index definition function should be ignored. should an error be reported ?? */ if (starti < 0) { starti = 0; } if ((starti + num_cols - 1) > dev_descrip.num_cols) { /* error 6:308 - Too many color specifiers. Discard extras */ report_error(cur_state, 6, 308, *(short *)params[0]); num_cols = dev_descrip.num_cols - starti + 1; } /* end error */ /* convert rgb to lie between 0. and 1. */ /* ...only do this once */ int *iparam = (int *)params[3]; k = 0; for (j = starti; j < starti + num_cols; j++) { color_array[j][0] = (float)iparam[k++] / 255.0f; color_array[j][1] = (float)iparam[k++] / 255.0f; color_array[j][2] = (float)iparam[k++] / 255.0f; } /* loop through surfaces */ for (i = 0; i < num_surfaces; ++i) { cur_state = (surf_statelist *)surf_list[i]; if (cur_state->cgi_inited != CYES) { break; } /* mark that the color table has been set */ cur_state->color_set = TRUE; /* update the current state color table */ k = 0; for (j = starti; j < starti + num_cols; j++) { cur_state->color_table[j].r = ((int *)params[3])[k++]; cur_state->color_table[j].g = ((int *)params[3])[k++]; cur_state->color_table[j].b = ((int *)params[3])[k++]; } /* set the SVDI color table */ /* color indices are mapped so that fg and bg colors are * 'reasonable' colors. If the user sets either the fg index * color or bg color index, map those colors so that the * fg and bg colors won't change */ /* color index mappings: * if set index 0 --> set bg_index * if set index 1 --> set fg_index * if set bg_index --> set 0 * if set fg_index --> set 1 */ /* set the special cases first */ /* 1. caller setting index 0 - set the background color */ /* --set_background_color() will set color table entry bg_index */ if (starti == 0) { tmp_array[0] = cur_state->color_table[0].r; tmp_array[1] = cur_state->color_table[0].g; tmp_array[2] = cur_state->color_table[0].b; set_background_color(cur_state, tmp_array); } /* 2. caller setting index 1 - set index fg_index */ if (starti <= 1 && (starti + num_cols > 1)) { vdstco(&one, &dev_descrip.index_array[cur_state->fg_index], &color_array[1], &dev_descrip.col_mode); } /* 3. caller setting index bg_index - set index 0 */ if (cur_state->bg_index != 0) { /* .. don't do it twice */ if (starti <= cur_state->bg_index && (starti + num_cols > cur_state->bg_index)) { vdstco(&one, &dev_descrip.index_array[0], &color_array[cur_state->bg_index], &dev_descrip.col_mode); } } /* 4. caller setting index fg_index - set index 1 */ if (cur_state->fg_index != 1) { /* .. don't do it twice */ if (starti <= cur_state->fg_index && (starti + num_cols > cur_state->fg_index)) { vdstco(&one, &dev_descrip.index_array[1], &color_array[cur_state->fg_index], &dev_descrip.col_mode); } } /* now do all the rest */ /* ...sort for convenience */ if (cur_state->fg_index < cur_state->bg_index) { index1 = cur_state->fg_index; index2 = cur_state->bg_index; } else { index1 = cur_state->bg_index; index2 = cur_state->fg_index; } /* end sort */ maxindex = starti + num_cols - 1; indx_ptr = starti; if (indx_ptr < 2) { indx_ptr = 2; } /* 1. set color table between index 1 and index1 */ if (indx_ptr <= 2) { num_set = min(index1 - 2, maxindex - 1); if (num_set > 0) { vdstco(&num_set, &dev_descrip.index_array[2], &color_array[2], &dev_descrip.col_mode); indx_ptr = index1 + 1; } } if (indx_ptr == index1) { /* update indx_ptr */ indx_ptr = indx_ptr + 1; } /* 2. set color table between index1 and index2 */ if (indx_ptr < index2) { num_set = min(index2 - indx_ptr, maxindex - indx_ptr + 1); if (num_set > 0) { vdstco(&num_set, &dev_descrip.index_array[indx_ptr], &color_array[indx_ptr], &dev_descrip.col_mode); indx_ptr = index2 + 1; } } if (indx_ptr == index2) { /* update indx_ptr */ indx_ptr = indx_ptr + 1; } /* 3. set color table after index 2 */ if (indx_ptr >= index2 + 1) { num_set = maxindex - indx_ptr + 1; if (num_set > 0) { vdstco(&num_set, &dev_descrip.index_array[indx_ptr], &color_array[indx_ptr], &dev_descrip.col_mode); } } } /* end for each surface */ } /* end xcct */ /* GET TEXT EXTENT */ static void xcgtxx(anything **params, anything **surf_list) { float act_h, act_w; /* actual char height and width (VDC) */ float x1, y1, x2; /* parrallelogram parts */ float save, temp_h; /* temporary variables */ float temp_array[14]; /* temp array used for SVDI inquires */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* find out actual height and width from SVDI for this size */ /* ..save the old value */ vdiqos(&temp_array[1]); save = temp_array[6]; /* ..set current height value */ temp_h = cur_state->char_height * fabs(cur_state->xscale); vdstcs(&temp_h); /* ..find out actual height and width */ vdiqos(&temp_array[1]); act_h = temp_array[6] / fabs(cur_state->xscale); act_w = temp_array[7] / fabs(cur_state->xscale); /* set it back to original */ vdstcs(&save); /* parallelogram */ /* x1, y1 = bottom left corner of string */ x1 = *(float *)params[1]; y1 = *(float *)params[2]; *(float *)params[8] = x1; *(float *)params[9] = y1; /* x2, y2 = bottom right corner of string */ /* params[4] is an added parameter that contains string size */ x2 = x1 + (*(int *)params[16] * act_w); *(float *)params[10] = x2; *(float *)params[11] = y1; /* x3, y3 = top right corner of string ( x3 = x2 )*/ *(float *)params[12] = x2; *(float *)params[13] = y1 + act_h; /* x4, y4 = top left corner of string ( y4 = y3 )*/ *(float *)params[14] = x1; *(float *)params[15] = y1 + act_h; /* concatenation point is bottom right corner ( x2, y2 )*/ *(float *)params[6] = x2; *(float *)params[7] = y1; /* validity flags */ *(int *)params[4] = CVAL; *(int *)params[5] = CVAL; } /* end xcgtxx */ /* INQUIRE PRIMITIVE SUPPORT LEVELS */ static void xcqprl(anything **params, anything **surf_list) { int qdc_index = 25; /* index for inquiries to vdiqdc */ float value; /* value returned by vdiqdc */ static int set = FALSE; /* flag whether values have been set */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } if (!set) { /* values have't been set, inquire SVDI */ set = TRUE; /* max points for a polyline */ dev_descrip.max_pts_polyline = MAX_POLYLINE; /* max points for a disjoint polyline */ dev_descrip.max_pts_disj_polyline = MAX_DJ_POLYLINE; /* max points for a polygon */ vdiqdc(&qdc_index, &value); dev_descrip.max_pts_polygon = (value == 99999.) ? MAX_POLYGON : min((int)value, MAX_POLYGON); /* max points for a polygon set */ /* --not supported */ dev_descrip.max_pts_polygon_set = 0; /* max points for a polymarker */ dev_descrip.max_pts_polymarker = MAX_POLYMARKER; /* max number of points for a closed figure */ /* --not supported */ dev_descrip.max_pts_closed_fig = 0; /* max characters of text */ dev_descrip.max_chars_text = MAX_TEXT_LENGTH; /* max number of cell color specifiers for cell array */ dev_descrip.max_pts_cellarray = -1; /* cell array fill capability */ dev_descrip.cellarray_fill_cap = CFILLD; /* cell array alignment */ dev_descrip.cellarray_align_cap = CAXIS; /* compound text capability */ dev_descrip.compound_text_cap = CCNONE; /* closed figure capability */ dev_descrip.compound_fig_cap = CCNONE; } /* end if not set */ /* validity flag */ *(int *)params[1] = CVAL; /* stuff all the values into the return parameters */ *(int *)params[2] = dev_descrip.max_pts_polyline; *(int *)params[3] = dev_descrip.max_pts_disj_polyline; *(int *)params[4] = dev_descrip.max_pts_polygon; *(int *)params[5] = dev_descrip.max_pts_polygon_set; *(int *)params[6] = dev_descrip.max_pts_polymarker; *(int *)params[7] = dev_descrip.max_pts_closed_fig; *(int *)params[8] = dev_descrip.max_chars_text; *(int *)params[9] = dev_descrip.max_pts_cellarray; *(int *)params[10] = dev_descrip.cellarray_fill_cap; *(int *)params[11] = dev_descrip.cellarray_align_cap; *(int *)params[12] = dev_descrip.compound_text_cap; *(int *)params[13] = dev_descrip.compound_fig_cap; } /* end xcqprl */ /* INQUIRE LINE CAPABILITY */ static void xcqln(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* set the validity flag */ *(int *)params[1] = CVAL; /* number of predefined line bundles - bundles not supported */ *(int *)params[2] = 0; /* number of settable line bundles - bundles not supported */ *(int *)params[3] = 0; /* max line bundle index - bundles not supported */ *(int *)params[4] = 0; /* dynamic modification for line bundles- bundles not supported */ *(int *)params[5] = 0; /* nom, min, max, get set in set_dev_descrip() at initialization */ *(int *)params[6] = dev_descrip.linewidth_nominal; *(int *)params[7] = dev_descrip.linewidth_min; *(int *)params[8] = dev_descrip.linewidth_max; } /* end xcqln */ /* INQUIRE LIST OF AVAILABLE LINE TYPES */ static void xcqlnt(anything **params, anything **surf_list) { int i, j; /* loop indices */ int qdc_index = 6; /* index for inquiries to vdiqdc */ float value; /* value returned by vdiqdc */ static int set = FALSE; /* flag whether values have been set */ static int ntotal; /* save total nbr of linestyles */ static unsigned mask = ~(~0u << 1); /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } if (!set) { /* values have't been set, inquire SVDI */ set = TRUE; /* inquire supported linestyles from SVDI */ vdiqdc(&qdc_index, &value); /* SVDI always supports linestyle 0 */ ntotal = 0; dev_descrip.line_types[ntotal++] = 0; /* find all SVDI linestyles supported by looking at bits */ for (i = 0; i < 5; i++) { if (((int)value & mask << i) >> i == 1) { dev_descrip.line_types[ntotal++] = i + 1; } } /* map to CGI linestyles */ /* cgi linestyles: 1 - solid 2 - dash 3 - dot, * 4 - dashdot 5 - dash dot dot * vdi linestyles: 0 - solid 1 - dotted 2 - dot dash * 3 - short dash 4 - long dash 5 - medium dash */ for (i = 0; i < ntotal; i++) { switch (dev_descrip.line_types[i]) { case 0: dev_descrip.line_types[i] = 1; break; case 1: dev_descrip.line_types[i] = 3; break; case 2: dev_descrip.line_types[i] = 4; break; /* ...all SVDI dashes map to cgi dash */ case 3: dev_descrip.line_types[i] = 2; break; case 4: dev_descrip.line_types[i] = 2; break; case 5: dev_descrip.line_types[i] = 2; break; default: break; } /* end switch */ } /* take out duplicates */ for (i = 0; i < ntotal; i++) { if (dev_descrip.line_types[i] == 2) { break; } } ntotal = i + 1; } /* end if not set */ /* set the total */ *(int *)params[4] = ntotal; /* do some error checking */ if (*(int *)params[2] < 1) { /* error - set validity flag to invalid */ *(int *)params[3] = CINVAL; } else { /* send back only the ones requested - zero out the rest */ i = *(int *)params[2] - 1; j = 0; *(int *)params[5] = 0; /* actual number of list elements sent back */ while (j < ntotal) { if (j < *(int *)params[1] && i < ntotal) { ((int *)params[6])[j++] = dev_descrip.line_types[i++]; (*(int *)params[5])++; } else { ((int *)params[6])[j++] = 0; } } /* set validity flag */ *(int *)params[3] = CVAL; } /* end else send back */ } /* end xcqlnt */ /* INQUIRE LIST OF AVAILABLE SCALED LINE WIDTHS */ static void xcqslw(anything **params, anything **surf_list) { int qdc_index = 5; /* index for inquiries to vdiqdc */ float value; /* value returned by vdiqdc */ static int set = FALSE; /* flag whether values have been set */ static int ntotal; /* save total nbr of linewidths */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } if (!set) { /* values have't been set, inquire SVDI */ set = TRUE; /* number of linewidths available */ vdiqdc(&qdc_index, &value); ntotal = (int)value; } /* end if not set */ /* validity flag */ *(int *)params[3] = CVAL; *(int *)params[4] = ntotal; /* nlist = 0 means empty list ( continuous range ) */ /* --leave list (params[6]) untouched */ *(int *)params[5] = 0; } /* end xcqslw */ /* INQUIRE MARKER CAPABILITY */ static void xcqmk(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* set the validity flag */ *(int *)params[1] = CVAL; /* number of predefined marker bundles - bundles not supported */ *(int *)params[2] = 0; /* number of settable marker bundles - bundles not supported */ *(int *)params[3] = 0; /* max marker bundle index - bundles not supported */ *(int *)params[4] = 0; /* dynamic modification for marker bundles- bundles not supported */ *(int *)params[5] = 0; /* nom, min, max, get set in set_dev_descrip() at initialization */ *(int *)params[6] = dev_descrip.mark_nominal; *(int *)params[7] = dev_descrip.mark_min; *(int *)params[8] = dev_descrip.mark_max; } /* end xcqmk */ /* INQUIRE LIST OF AVAILABLE MARKER TYPES */ static void xcqmkt(anything **params, anything **surf_list) { static int set = FALSE; /* flag whether values have been set */ static int ntotal; /* save total nbr of linestyles */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } if (!set) { /* values have't been set, inquire SVDI */ set = TRUE; /* SVDI only supports 1 marker type - "dot" */ ntotal = 1; dev_descrip.mark_types[0] = 1; } /* end if not set */ /* set validity flag */ *(int *)params[3] = CVAL; *(int *)params[4] = ntotal; if (*(int *)params[1] > 0) { *(int *)params[5] = 1; ((int *)params[6])[0] = dev_descrip.mark_types[0]; } else { *(int *)params[5] = 0; } } /* end xcqmkt */ /* INQUIRE LIST OF AVAILABLE SCALED MARKER SIZES */ static void xcqsms(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* validity flag */ *(int *)params[3] = CVAL; /* there is only 1 size */ *(int *)params[4] = 1; *(int *)params[5] = 1; ((int *)params[6])[0] = dev_descrip.mark_nominal; } /* end xcqsms */ /* INQUIRE LIST OF AVAILABLE CHARACTER HEIGHTS */ static void xcqchh(anything **params, anything **surf_list) { int qdc_index = 7; /* index for inquiries to vdiqdc */ float value; /* value returned by vdiqdc */ static int set = FALSE; /* flag whether values have been set */ static int ntotal; /* save total nbr of char heights */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } if (!set) { /* values have't been set, inquire SVDI */ set = TRUE; /* number of char sizes */ vdiqdc(&qdc_index, &value); ntotal = (int)value; } /* end if not set */ /* font - SRCP does not support multiple fonts; use null string */ /* I don't check for font, anything goes */ /* only string precision is supported */ if (*(int *)params[2] == CSTRNG) { /* total number of character heights */ *(int *)params[6] = ntotal; /* set nlist = 0 means empty list ( continuous range ) */ /* --leave list (params[8]) untouched */ *(int *)params[7] = 0; /* validity flag */ *(int *)params[5] = CVAL; } /* end if */ else { *(int *)params[5] = CINVAL; } } /* end xcqchh */ /* INQUIRE FILL CAPABILITY */ static void xcqfl(anything **params, anything **surf_list) { static int set = FALSE; /* flag whether values have been set */ static int ntotal; /* save total nbr of fill styles */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } if (!set) { /* values have't been set */ set = TRUE; ntotal = 2; dev_descrip.interior_styles[0] = CHOLLO; dev_descrip.interior_styles[1] = CSOLID; } /* end if not set */ /* set the validity flag */ *(int *)params[1] = CVAL; /* number of predefined fill bundles - bundles not supported */ *(int *)params[2] = 0; /* number of settable fill bundles - bundles not supported */ *(int *)params[3] = 0; /* max fill bundle index - bundles not supported */ *(int *)params[4] = 0; /* dynamic modification for fill bundles- bundles not supported */ *(int *)params[5] = 0; /* interior styles */ *(int *)params[6] = ntotal; ((int *)params[7])[0] = dev_descrip.interior_styles[0]; ((int *)params[7])[1] = dev_descrip.interior_styles[1]; /* number of predefined patterns - patterns not supported */ *(int *)params[8] = 0; /* number of settable patterns - patterns not supported */ *(int *)params[9] = 0; /* maximum pattern index - patterns not supported */ *(int *)params[10] = 0; /* preferred pattern size divisor - patterns not supported */ *(int *)params[11] = 0; /* maximum pattern size - patterns not supported */ *(int *)params[12] = 0; *(int *)params[13] = 0; /* pattern transformation support - patterns not supported */ *(int *)params[14] = CPTNO; } /* end xcqfl */ /* INQUIRE COLOR CAPABILITIES */ static void xcqc(anything **params, anything **surf_list) { int qdc_index; /* index for inquiries to vdiqdc */ float value; /* value returned by vdiqdc */ static int set = FALSE; /* flag whether values have been set */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } if (!set) { /* values have't been set, inquire SVDI */ set = TRUE; /* number of simultaneous colors */ dev_descrip.num_simul_colors = dev_descrip.num_cols; /* number of available colors */ qdc_index = 27; vdiqdc(&qdc_index, &value); dev_descrip.num_avail_colors = (int)value; /* number of available intensities */ /* --see 7.1.4 about direct color */ qdc_index = 3; vdiqdc(&qdc_index, &value); dev_descrip.num_avail_int = (int)value; /* dynamic modification accepted for color table */ dev_descrip.dynamic_mod_ct = CIRG; /* color overwrite capability */ /* --what is the answer?? */ /* dev_descrip.color_overwrite = ??; */ /* monochromatic device */ qdc_index = 32; vdiqdc(&qdc_index, &value); dev_descrip.monochrome_device = (value == 0.0) ? CYES : CNO; } /* end not set */ /* validity flag */ *(int *)params[1] = CVAL; /* return the answers */ *(int *)params[2] = dev_descrip.num_simul_colors; *(int *)params[3] = dev_descrip.num_avail_colors; ((int *)params[4])[0] = dev_descrip.num_avail_int; *(int *)params[5] = dev_descrip.csm_avail; /* set in set_dev_descrip()*/ *(int *)params[6] = dev_descrip.dynamic_mod_ct; *(int *)params[7] = dev_descrip.color_overwrite; *(int *)params[8] = dev_descrip.monochrome_device; } /* end xcqc */ /* INQUIRE LINE ATTRIBUTES */ static void xcqlna(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* validity flag */ *(int *)params[1] = CVAL; /* line bundle index - bundles not supported */ *(int *)params[2] = 0; /* line type */ *(int *)params[3] = cur_state->line_type; /* line width spcification mode - only support scaled */ *(int *)params[4] = CSCA; /* line width */ *(float *)params[5] = cur_state->line_width; /* color selection mode in which line color was last specified */ *(int *)params[6] = cur_state->line_csm; /* line color in color selection mode last specified */ ((int *)params[7])[0] = cur_state->line_color[0]; if (cur_state->line_csm == CDRECT) { ((int *)params[7])[1] = cur_state->line_color[1]; ((int *)params[7])[2] = cur_state->line_color[2]; } /* line clipping mode */ *(int *)params[8] = CLOCUS; } /* end xcqlna */ /* INQUIRE MARKER ATTRIBUTES */ static void xcqmka(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* validity flag */ *(int *)params[1] = CVAL; /* marker bundle index - bundles not supported */ *(int *)params[2] = 0; /* marker type */ *(int *)params[3] = cur_state->mark_type; /* marker size spcification mode - only support scaled */ *(int *)params[4] = CSCA; /* marker size */ *(float *)params[5] = cur_state->mark_size; /* color selection mode in which marker color was last specified */ *(int *)params[6] = cur_state->mark_csm; /* marker color in color selection mode last specified */ ((int *)params[7])[0] = cur_state->mark_color[0]; if (cur_state->mark_csm == CDRECT) { ((int *)params[7])[1] = cur_state->mark_color[1]; ((int *)params[7])[2] = cur_state->mark_color[2]; } /* marker clipping mode */ *(int *)params[8] = CLOCUS; } /* end xcqmka */ /* INQUIRE TEXT ATTRIBUTES */ static void xcqtxa(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* validity flag */ *(int *)params[1] = CVAL; /* text bundle index - bundles not supported */ *(int *)params[2] = 0; /* font index - only the default font is supported */ *(int *)params[3] = 1; /* font precision */ *(int *)params[4] = CSTRNG; /* character expansion factor */ *(float *)params[5] = 1.0; /* character spacing */ *(float *)params[6] = 0.0; /* color selection mode in which text color was last specified */ *(int *)params[7] = cur_state->text_csm; /* text color in color selection mode last specified */ ((int *)params[8])[0] = cur_state->text_color[0]; if (cur_state->text_csm == CDRECT) { ((int *)params[8])[1] = cur_state->text_color[1]; ((int *)params[8])[2] = cur_state->text_color[2]; } /* character height */ *(float *)params[9] = cur_state->char_height; /* character orientation */ ((float *)params[10])[0] = 0.; ((float *)params[10])[1] = 1.; ((float *)params[10])[2] = 1.; ((float *)params[10])[3] = 0.; /* text path */ *(int *)params[11] = CTPRIT; /* horizontal alignment */ *(int *)params[12] = CTANH; /* continuous horizontal alignment */ *(float *)params[13] = 1.0; /* vertical alignment */ *(int *)params[14] = CTANV; /* continuous horizontal alignment */ *(float *)params[15] = 1.0; /* character set index ?? */ *(int *)params[16] = 1; /* alternate character set index ?? */ *(int *)params[17] = 1; } /* end xcqtxa */ /* INQUIRE FILL ATTRIBUTES */ static void xcqfla(anything **params, anything **surf_list) { /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* validity flag */ *(int *)params[1] = CVAL; /* fill bundle index - bundles not supported */ *(int *)params[2] = 0; /* interior style */ *(int *)params[3] = cur_state->interior_style; /* color selection mode in which fill color was last specified */ *(int *)params[4] = cur_state->fill_csm; /* fill color in color selection mode last specified */ ((int *)params[5])[0] = cur_state->fill_color[0]; if (cur_state->fill_csm == CDRECT) { ((int *)params[5])[1] = cur_state->fill_color[1]; ((int *)params[5])[2] = cur_state->fill_color[2]; } /* hatch index - not supported */ *(int *)params[6] = 0; /* pattern index - not supported */ *(int *)params[7] = 0; /* --i don't know what any of the following means */ /* fill bitmap identifier */ *(int *)params[8] = 0; /* fill bitmap region */ *(float *)params[9] = 0.; *(float *)params[10] = 0.; *(float *)params[11] = 0.; *(float *)params[12] = 0.; /* fill reference point */ *(float *)params[13] = 0.; *(float *)params[14] = 0.; /* pattern orientation and size */ *(float *)params[15] = 0.; *(float *)params[16] = 0.; *(float *)params[17] = 0.; *(float *)params[18] = 0.; } /* end xcqfla */ /* INQUIRE LIST OF COLOR TABLE ENTRIES */ static void xcqcte(anything **params, anything **surf_list) { int i; /* loop index */ int first; /* index of first element to return */ int nreq; /* number of list elements requested */ int j = 0; /* array index */ /* there is only one surface for inquiries */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* number of requested elements, and the first index */ nreq = *(int *)params[1]; first = *(int *)params[2]; /* error checking */ if (first < 1) { first = 1; } if ((first + nreq - 1) > dev_descrip.num_cols) { nreq = dev_descrip.num_cols - first + 1; } /* actual number of colors returned */ *(int *)params[5] = nreq; for (i = first; i < (first + *(int *)params[5]); i++) { ((int *)params[6])[j++] = cur_state->color_table[i - 1].r; ((int *)params[6])[j++] = cur_state->color_table[i - 1].g; ((int *)params[6])[j++] = cur_state->color_table[i - 1].b; } /* end for i */ /* return total number of colors */ *(int *)params[4] = dev_descrip.num_cols; /* validity flag */ *(int *)params[3] = CVAL; } /* end xcqcte */ /* INITIALIZE LOGICAL INPUT DEVICE */ static void xcili(anything **params, anything **surf_list) { /* there is only one surface for input */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* only support locator */ if (*(int *)params[1] != CLOCAT) { /* error 2:001 - Request for an unsupported feature. Function ignored */ report_error(cur_state, 2, 001, *(short *)params[0]); } else if (*(int *)params[2] != 1) { /* error 3:501 - LID index exceeds number of this class of LID. Function ignored */ report_error(cur_state, 3, 501, *(short *)params[0]); } else if (dev_descrip.dev_class == CINPUT || dev_descrip.dev_class == COUTIN) { /* device does input */ cur_state->input_dev_class = CLOCAT; cur_state->input_dev_index = 1; cur_state->input_dev_state = CREADY; } /* end if device does input */ } /* end xcili */ /* REQUEST LOCATOR */ static void xcrqlc(anything **params, anything **surf_list) { float x, y; /* x,y values of locator */ /* there is only one surface for input */ cur_state = (surf_statelist *)surf_list[0]; if (cur_state->cgi_inited != CYES) { return; } /* check if device has been initialized */ /* ...only support input device index 1 */ if (*(int *)params[1] != 1 || cur_state->input_dev_state != CREADY) { /* error 5:501 - Function illegal in LID state RELEASED. Function ignored */ report_error(cur_state, 5, 501, *(short *)params[0]); *(int *)params[3] = CINVAL; } else if (dev_descrip.dev_class == CINPUT || dev_descrip.dev_class == COUTIN) { /* device does input */ /* for now only allow limited timeout */ /* positive and negative values = wait forever, 0 = no wait */ if (*(int *)params[2] == 0) { *(int *)params[3] = CINVAL; return; } /* get location and trigger */ vdakgl((int *)params[6], &x, &y); /* convert location from NDC to VDC */ *(float *)params[7] = (x - (cur_state->vp1.x * dev_descrip.xndc_max)) / cur_state->xscale + cur_state->vdc1.x; *(float *)params[8] = (y - (cur_state->vp1.y * dev_descrip.yndc_max)) / cur_state->yscale + cur_state->vdc1.y; /* response validity */ *(int *)params[3] = CVAL; /* request status, SVDI only has trigger */ *(int *)params[4] = CTRIGR; /* measure validity */ /* --i'm not sure when measure validity is invalid */ *(int *)params[5] = CVAL; } /* end else device does input */ else { /* device doesn't do input */ /* response validity */ *(int *)params[3] = CVAL; } } /* end xcrqlc */ /*-------------------------------------------------------------*/ /* >> UTILITY ROUTINES */ /*-------------------------------------------------------------*/ /* init_state */ /* Initialize the state list */ static void init_state(surf_statelist *surf_state) /* surface statelist to init */ { int i; /* loop index */ float tmp_array[1][3]; /* temp array to set SVDI color table */ int one = 1; /* set default error control: class 1 : DETECTION OFF class 2 - MAX_ERROR_CLASS : REPORTING OFF */ surf_state->err_flag[0] = CEHDOF; for (i = 1; i < MAX_ERROR_CLASS; i++) { surf_state->err_flag[i] = CEHROF; } /* initialize to 0 errors */ surf_state->err_head_ptr = 0; surf_state->err_count = 0; /* default vdc extent */ surf_state->vdc1.x = 0.0; surf_state->vdc1.y = 0.0; surf_state->vdc2.x = 32767.; surf_state->vdc2.y = 32767.; /* viewport - default viewport specification mode is FRACTION OF * DRAWING SURFACE. Thus, the viewport (0,0),(1,1) corresponds to * the lower and upper corners, respectively, of the default * device viewport, which is the largest unrotated rectangular area * visible on the drawing surface. */ /* default viewport is (0,0),(1,1) */ surf_state->vp1.x = 0.0; surf_state->vp1.y = 0.0; surf_state->vp2.x = 1.0; surf_state->vp2.y = 1.0; /* VDC to viewport in NDC mapping */ /* --device viewport mapping defaults are: isotropy forced, horizontal alignment left, vertical alignment bottom */ /* -- this routine sets effective viewport in VDC and NDC (forcing isotropic mapping) and the mapping scale */ set_mapping(surf_state); /* default clip indicator is off (VDC clipping) */ surf_state->clip_indicator = COFF; /* default view surface clip indicator is viewport */ surf_state->ds_clip_indicator = CVPORT; /* default clip rectangle is (0,0) (32767,32767) */ /* ...can't be changed in SS-CGI */ surf_state->clip_rect1.x = 0.0; surf_state->clip_rect1.y = 0.0; surf_state->clip_rect2.x = 32767.; surf_state->clip_rect2.y = 32767.; /* effective clip rectangle is intersection of VDC extent and clip rectangle */ surf_state->eff_clip_rect1.x = 0.0; surf_state->eff_clip_rect1.y = 0.0; surf_state->eff_clip_rect2.x = 32767.; surf_state->eff_clip_rect2.y = 32767.; /* set the clip region */ set_clipping(surf_state); /* default color mode is indexed */ surf_state->csm = CINDEX; /* default line, fill, text, and marker color indices */ surf_state->line_color[0] = 1; surf_state->fill_color[0] = 1; surf_state->text_color[0] = 1; surf_state->mark_color[0] = 1; /* default line type is solid */ surf_state->line_type = 1; /* default interior style is hollow */ surf_state->interior_style = CHOLLO; /* char size is in VDC - default is 1/100 of default VDC extent */ surf_state->char_height = 327.; /* default line width specification mode is scaled, default linewidth is 1.*/ surf_state->line_width = 1.; /* default marker specification mode is scaled, default marker size is 1. */ surf_state->mark_size = 1.; /* the only default colors defined in CGI are index 0 = background, * and index 1 = foreground. Use SVDI's bg and fg until the user * sets the color table. */ if (dev_descrip.svdi_type == 0) { /* vector SVDI */ /* set up the fg and bg mappings */ surf_state->bg_index = dev_descrip.att_array[2]; surf_state->fg_index = dev_descrip.att_array[1]; /* set the current surface color table */ vdiqco(&one, &dev_descrip.index_array[surf_state->bg_index], tmp_array, &dev_descrip.col_mode); surf_state->color_table[0].r = (int)(tmp_array[0][0] * 255.0f); surf_state->color_table[0].g = (int)(tmp_array[0][1] * 255.0f); surf_state->color_table[0].b = (int)(tmp_array[0][2] * 255.0f); vdiqco(&one, &dev_descrip.index_array[surf_state->fg_index], tmp_array, &dev_descrip.col_mode); surf_state->color_table[1].r = (int)(tmp_array[0][0] * 255.0f); surf_state->color_table[1].g = (int)(tmp_array[0][1] * 255.0f); surf_state->color_table[1].b = (int)(tmp_array[0][2] * 255.0f); } /* end if vector SVDI */ else { /* raster SVDI */ vdiqci(&dev_descrip.att_array[11], &dev_descrip.att_array[12], &dev_descrip.att_array[13], &surf_state->bg_index); vdiqci(&dev_descrip.att_array[8], &dev_descrip.att_array[9], &dev_descrip.att_array[10], &surf_state->fg_index); /* set the current surface color table */ surf_state->color_table[0].r = (int)(dev_descrip.att_array[8] * 255.0f); surf_state->color_table[0].g = (int)(dev_descrip.att_array[9] * 255.0f); surf_state->color_table[0].b = (int)(dev_descrip.att_array[10] * 255.0f); surf_state->color_table[1].r = (int)(dev_descrip.att_array[11] * 255.0f); surf_state->color_table[1].g = (int)(dev_descrip.att_array[12] * 255.0f); surf_state->color_table[1].b = (int)(dev_descrip.att_array[13] * 255.0f); } /* end else raster SVDI */ /* set/reset the SVDI attribute array */ /* --set everything to -1 to force resetting of attributes */ surf_state->vdi_attrib.fg_color = -1; surf_state->vdi_attrib.bg_color = -1; surf_state->vdi_attrib.intensity = -1.0; surf_state->vdi_attrib.line_type = -1; surf_state->vdi_attrib.line_width = -1.0; surf_state->vdi_attrib.char_x = -1.0; surf_state->vdi_attrib.char_y = -1.0; surf_state->vdi_attrib.fg_rgb[0] = -1.0; surf_state->vdi_attrib.fg_rgb[1] = -1.0; surf_state->vdi_attrib.fg_rgb[2] = -1.0; surf_state->vdi_attrib.bg_rgb[0] = -1.0; surf_state->vdi_attrib.bg_rgb[1] = -1.0; surf_state->vdi_attrib.bg_rgb[2] = -1.0; /* set color_set flag to false = color table not set by user */ surf_state->color_set = FALSE; /* set picture state to clean */ surf_state->pic_dirty = CCLEAN; } /* end init_state */ /* set_dev_descrip */ /* Set the device description table */ static void set_dev_descrip(void) { /* dev_descrip is global */ int j; /* loop index */ int qdc_index; /* used for inquiring SVDI */ float value; /* value returned from inquire SVDI */ /* set copy_class */ qdc_index = 1; vdiqdc(&qdc_index, &value); if (value == 0.) { dev_descrip.copy_class = CHARD; } else { dev_descrip.copy_class = CSOFT; } /* device corners in device coords */ dev_descrip.dc1.x = 0; dev_descrip.dc1.y = 0; qdc_index = 15; vdiqdc(&qdc_index, &value); dev_descrip.dc2.x = (int)value; qdc_index = 16; vdiqdc(&qdc_index, &value); dev_descrip.dc2.y = (int)value; /* vector or raster SVDI (0=vector, 1=raster) */ qdc_index = 29; vdiqdc(&qdc_index, &value); dev_descrip.svdi_type = (int)value; /* vector SVDI only does indexed color, raster does both */ if (dev_descrip.svdi_type == 0) { dev_descrip.csm_avail = CCLRI; } else { dev_descrip.csm_avail = CCLRID; } /* device class */ qdc_index = 13; vdiqdc(&qdc_index, &value); dev_descrip.dev_class = (value == 0.) ? COUTPT : COUTIN; /* NDC space */ vdiqnd(&dev_descrip.xndc_max, &dev_descrip.yndc_max); /* output status */ vdiqos(&dev_descrip.att_array[1]); /* min line width - SVDI returns value in DC */ qdc_index = 19; vdiqdc(&qdc_index, &value); dev_descrip.linewidth_min = (int)value; /* max line width - SVDI returns value in DC */ qdc_index = 31; vdiqdc(&qdc_index, &value); dev_descrip.linewidth_max = (int)value; /* use the default SVDI linewidth as nominal */ /* --convert to device coordinates */ value = (dev_descrip.att_array[5] / dev_descrip.xndc_max) * .01 * (dev_descrip.dc2.x - dev_descrip.dc1.x); dev_descrip.linewidth_nominal = (int)max(value, 1.); /* --make sure that for some reason it isn't out of range */ dev_descrip.linewidth_nominal = max(min(dev_descrip.linewidth_nominal, dev_descrip.linewidth_max), dev_descrip.linewidth_min); /* nominal,min,max marker size - only one size */ qdc_index = 20; vdiqdc(&qdc_index, &value); dev_descrip.mark_nominal = (int)value; dev_descrip.mark_min = (int)value; dev_descrip.mark_max = (int)value; /* inquire the number of colors */ qdc_index = 4; vdiqdc(&qdc_index, &value); /* check for max colors */ dev_descrip.num_cols = ((int)value > COLOR_TABLE_SIZE) ? COLOR_TABLE_SIZE : (int)value; /* set up a color index array for use in color table stuff */ for (j = 0; j < 256; j++) { dev_descrip.index_array[j] = j; } /* set SVDI color mode */ dev_descrip.col_mode = 0; /* inquire default SVDI color table. */ vdiqco(&dev_descrip.num_cols, dev_descrip.index_array, dev_descrip.color_array, &dev_descrip.col_mode); } /* end set_dev_descrip */ /* reset_vdi */ /* Reset SVDI values. Used if CI is called twice */ static void reset_vdi(surf_statelist *surf_state) /* current surface statelist */ { /* reset the output status */ vdstos(&dev_descrip.att_array[1]); /* only reset color table is user has changed it */ if (surf_state->color_set) { vdstco(&dev_descrip.num_cols, dev_descrip.index_array, dev_descrip.color_array, &dev_descrip.col_mode); } } /* end reset_vdi */ /* set_mapping */ /* Set up the VDC to NDC mappings. Also sets the effective viewports * in NDC and VDC. */ static void set_mapping(surf_statelist *surf_state) { point ndc_vp1, ndc_vp2; /* viewport in NDC space */ ndc_vp1.x = cur_state->vp1.x * dev_descrip.xndc_max; ndc_vp1.y = cur_state->vp1.y * dev_descrip.yndc_max; ndc_vp2.x = cur_state->vp2.x * dev_descrip.xndc_max; ndc_vp2.y = cur_state->vp2.y * dev_descrip.yndc_max; /* x and y scale maps VDC to viewport in NDC (ISOTROPIC Mapping) */ /* ...smallest scale magnitude, but keep the original sign */ surf_state->xscale = (ndc_vp2.x - ndc_vp1.x) / (surf_state->vdc2.x - surf_state->vdc1.x); surf_state->yscale = (ndc_vp2.y - ndc_vp1.y) / (surf_state->vdc2.y - surf_state->vdc1.y); if (fabs(surf_state->xscale) < fabs(surf_state->yscale)) { surf_state->yscale = (surf_state->yscale < 0) ? -1 * fabs(surf_state->xscale) : fabs(surf_state->xscale); } else { surf_state->xscale = (surf_state->xscale < 0) ? -1 * fabs(surf_state->yscale) : fabs(surf_state->yscale); } /* x and y offset for VDC to NDC mapping */ surf_state->xoffset = (ndc_vp1.x < ndc_vp2.x) ? ndc_vp1.x - surf_state->vdc1.x * surf_state->xscale : ndc_vp2.x - surf_state->vdc2.x * surf_state->xscale; surf_state->yoffset = (ndc_vp1.y < ndc_vp2.y) ? ndc_vp1.y - surf_state->vdc1.y * surf_state->yscale : ndc_vp2.y - surf_state->vdc2.y * surf_state->yscale; /* effective viewport */ /* - mode is FRACTION OF DRAWING SURFACE */ surf_state->eff_vp1.x = cur_state->vp1.x; surf_state->eff_vp1.y = cur_state->vp1.y; surf_state->eff_vp2.x = (surf_state->vdc2.x * surf_state->xscale + surf_state->xoffset) / dev_descrip.xndc_max; surf_state->eff_vp2.y = (surf_state->vdc2.y * surf_state->yscale + surf_state->yoffset) / dev_descrip.yndc_max; } /* end set_mapping */ /* set_clipping */ /* Set up the clip region. */ static void set_clipping(surf_statelist *my_cur_state) { point clip1, clip2; /* temp clip values */ clip1.x = clip1.y = clip2.x = clip2.y = 0; /* The clip region depends on clip indicator and drawing surface * clip indicator. */ switch (my_cur_state->clip_indicator) { case CON: /* VDC clipping is on */ switch (my_cur_state->ds_clip_indicator) { case CDCOFF: /* view surface clipping off */ /* map the effective clip rectangle to NDC */ my_cur_state->clip_on = TRUE; clip1.x = my_cur_state->eff_clip_rect1.x * my_cur_state->xscale + my_cur_state->xoffset; clip1.y = my_cur_state->eff_clip_rect1.y * my_cur_state->yscale + my_cur_state->yoffset; clip2.x = my_cur_state->eff_clip_rect2.x * my_cur_state->xscale + my_cur_state->xoffset; clip2.y = my_cur_state->eff_clip_rect2.y * my_cur_state->yscale + my_cur_state->yoffset; break; /* end case CDCOFF */ case CVPORT: /* clip at viewport */ /* map the effective clip rectangle to NDC */ my_cur_state->clip_on = TRUE; clip1.x = my_cur_state->eff_clip_rect1.x * my_cur_state->xscale + my_cur_state->xoffset; clip1.y = my_cur_state->eff_clip_rect1.y * my_cur_state->yscale + my_cur_state->yoffset; clip2.x = my_cur_state->eff_clip_rect2.x * my_cur_state->xscale + my_cur_state->xoffset; clip2.y = my_cur_state->eff_clip_rect2.y * my_cur_state->yscale + my_cur_state->yoffset; break; /* end case CVPORT */ case CDCREC: /* clip at display surface */ /* map the effective clip rectangle to NDC and intersect it with the max NDC space */ my_cur_state->clip_on = TRUE; clip1.x = my_cur_state->eff_clip_rect1.x * my_cur_state->xscale + my_cur_state->xoffset; clip1.y = my_cur_state->eff_clip_rect1.y * my_cur_state->yscale + my_cur_state->yoffset; clip2.x = my_cur_state->eff_clip_rect2.x * my_cur_state->xscale + my_cur_state->xoffset; clip2.y = my_cur_state->eff_clip_rect2.y * my_cur_state->yscale + my_cur_state->yoffset; clip1.x = max(min(clip1.x, clip2.x), 0.0); clip1.y = max(min(clip1.y, clip2.y), 0.0); clip2.x = min(max(clip1.x, clip2.x), dev_descrip.xndc_max); clip2.y = min(max(clip1.y, clip2.y), dev_descrip.yndc_max); break; /* end case CDCREC */ default: /* illegal enumeration type - ignore function */ break; } /* end switch ds_clip_indicator */ break; /* end case CON */ case COFF: /* VDC clipping is off */ switch (my_cur_state->ds_clip_indicator) { case CDCOFF: /* display surface clipping off */ /* no clip */ my_cur_state->clip_on = FALSE; break; /* end case CDCOFF */ case CVPORT: /* clip at viewport */ /* clip at NDC effective viewport */ my_cur_state->clip_on = TRUE; clip1.x = my_cur_state->eff_vp1.x * dev_descrip.xndc_max; clip1.y = my_cur_state->eff_vp1.y * dev_descrip.yndc_max; clip2.x = my_cur_state->eff_vp2.x * dev_descrip.xndc_max; clip2.y = my_cur_state->eff_vp2.y * dev_descrip.yndc_max; break; /* end case CVPORT */ case CDCREC: /* clip at display surface */ /* clip at max NDC space */ my_cur_state->clip_on = TRUE; clip1.x = 0.0; clip1.y = 0.0; clip2.x = dev_descrip.xndc_max; clip2.y = dev_descrip.yndc_max; break; /* end case CDCREC */ default: /* illegal enumeration type - ignore function */ break; } /* end switch ds_clip_indicator */ break; /* end case COFF */ default: /* illegal enumeration type - ignore function */ break; } /* end switch clip_indicator */ /* set clipmin and clipmax such that clipmin is the minimum corner of * the clipping window, and clipmax is the maximum. This is done * so that the clipping algorithms work correctly with mirroring. */ if (my_cur_state->clip_on) { my_cur_state->clipmin.x = min(clip1.x, clip2.x); my_cur_state->clipmax.x = max(clip1.x, clip2.x); my_cur_state->clipmin.y = min(clip1.y, clip2.y); my_cur_state->clipmax.y = max(clip1.y, clip2.y); } } /* end set_clipping */ /* set_foreground_color */ /* Set the SVDI foreground color */ static void set_foreground_color(surf_statelist *surf_state, int *colors) { int zero = 0; int one = 1; /* if color selection mode is in error, ignore function */ if (surf_state->csm == -1) { return; } /* indexed or direct color? */ /* --vector SVDI only does indexed color */ if (surf_state->csm == CINDEX || dev_descrip.svdi_type == 0) { /* does foreground need to be updated? */ if (colors[0] != cur_state->vdi_attrib.fg_color) { /* color index mappings: * if set index 0 --> set bg_index * if set index 1 --> set fg_index * if set bg_index --> set 0 * if set fg_index --> set 1 */ if (colors[0] == 0) { vdstfc(&cur_state->bg_index); } else if (colors[0] == 1) { vdstfc(&cur_state->fg_index); } else if (colors[0] == cur_state->bg_index) { vdstfc(&zero); } else if (colors[0] == cur_state->fg_index) { vdstfc(&one); } else { vdstfc(&colors[0]); } /* update att_array */ cur_state->vdi_attrib.fg_color = colors[0]; /* flag (direct) that foreground color has changed */ /* do i need to do this? */ cur_state->vdi_attrib.fg_rgb[0] = -1.0; cur_state->vdi_attrib.fg_rgb[1] = -1.0; cur_state->vdi_attrib.fg_rgb[2] = -1.0; } /* end does foreground... */ } /* end indexed color */ else /* direct color */ /* does foreground need to be updated? */ /* -- i need to check this out - might need to store as int */ if (colors[0] != (int)(cur_state->vdi_attrib.fg_rgb[0] * 255.0f) || colors[1] != (int)(cur_state->vdi_attrib.fg_rgb[1] * 255.0f) || colors[2] != (int)(cur_state->vdi_attrib.fg_rgb[2] * 255.0f)) { /* update att_array */ cur_state->vdi_attrib.fg_rgb[0] = (float)colors[0] / 255.0f; cur_state->vdi_attrib.fg_rgb[1] = (float)colors[1] / 255.0f; cur_state->vdi_attrib.fg_rgb[2] = (float)colors[2] / 255.0f; /* set new foreground color */ vdfrgb(&cur_state->vdi_attrib.fg_rgb[0], &cur_state->vdi_attrib.fg_rgb[1], &cur_state->vdi_attrib.fg_rgb[2]); /* flag (indexed) that foreground color has changed */ /* do i need to do this? */ cur_state->vdi_attrib.fg_color = -1; } /* end does foreground... */ } /* end set_foreground_color */ /* set_background_color */ /* Set the SVDI background color */ static void set_background_color(surf_statelist *surf_state, int *colors) { int i = 0; /* loop index */ int index = 0; /* color index */ float dr, dg, db, dmin, dist; /* for finding the closet index */ int one = 1; float epsilon = .001; /* does background need to be updated */ /* --background color is saved in att_array, even for vector */ if (colors[0] != (int)(cur_state->vdi_attrib.bg_rgb[0] * 255.0f) || colors[1] != (int)(cur_state->vdi_attrib.bg_rgb[1] * 255.0f) || colors[2] != (int)(cur_state->vdi_attrib.bg_rgb[2] * 255.0f)) { /* store new values in att_array */ cur_state->vdi_attrib.bg_rgb[0] = (float)colors[0] / 255.0f; cur_state->vdi_attrib.bg_rgb[1] = (float)colors[1] / 255.0f; cur_state->vdi_attrib.bg_rgb[2] = (float)colors[2] / 255.0f; /* set the cgi state color table - index 0 */ cur_state->color_table[0].r = colors[0]; cur_state->color_table[0].g = colors[1]; cur_state->color_table[0].b = colors[2]; /* has the SVDI color table ever been set */ if (!surf_state->color_set) { /* has never been set */ /* find out if default SVDI table contains this color */ if (dev_descrip.svdi_type == 1) { /* raster SVDI */ vdiqci(&cur_state->vdi_attrib.bg_rgb[0], &cur_state->vdi_attrib.bg_rgb[1], &cur_state->vdi_attrib.bg_rgb[2], &i); /* does it match */ dr = cur_state->vdi_attrib.bg_rgb[0] - dev_descrip.color_array[i][0]; dg = cur_state->vdi_attrib.bg_rgb[1] - dev_descrip.color_array[i][1]; db = cur_state->vdi_attrib.bg_rgb[2] - dev_descrip.color_array[i][2]; dmin = dr * dr + dg * dg + db * db; } /* end raster SVDI */ else { /* vector SVDI */ for (i = 0; i < 8; i++) { dr = cur_state->vdi_attrib.bg_rgb[0] - dev_descrip.color_array[i][0]; dg = cur_state->vdi_attrib.bg_rgb[1] - dev_descrip.color_array[i][1]; db = cur_state->vdi_attrib.bg_rgb[2] - dev_descrip.color_array[i][2]; dist = dr * dr + dg * dg + db * db; if (i == 0 || dist < dmin) { dmin = dist; index = i; } } /* end for i */ } /* end vector SVDI */ /* is it close enough? */ if (dmin <= epsilon) { cur_state->bg_index = index; } else { /* not close enough, set SVDI color table */ cur_state->bg_index = 0; vdstco(&one, &dev_descrip.index_array[cur_state->bg_index], &cur_state->vdi_attrib.bg_rgb, &dev_descrip.col_mode); cur_state->color_set = TRUE; /* flag that CT has been set */ } /* end else not close enough */ } /* end has never been set */ else { /* color table has been set */ /* set SVDI color table */ vdstco(&one, &dev_descrip.index_array[cur_state->bg_index], &cur_state->vdi_attrib.bg_rgb, &dev_descrip.col_mode); } /* end else has been set */ /* set the SVDI background color */ if (dev_descrip.svdi_type == 1) { /* raster SVDI */ vdbrgb(&cur_state->vdi_attrib.bg_rgb[0], &cur_state->vdi_attrib.bg_rgb[1], &cur_state->vdi_attrib.bg_rgb[2]); } else { /* vector SVDI */ /* once the ct has been set, bg_index never changes */ /* if( !cur_state->color_set ) */ vdstbc(&cur_state->bg_index); } } /* end does background need to be updated */ } /* end set_background_color */ /* report_error */ /* Stuff the error info into the error queue */ static void report_error(surf_statelist *surf_state, int e_class, int e_num, int f_id) { int err_slot; /* slot in the queue to put the error */ /* is error reporting on for this class? */ if (surf_state->err_flag[e_class - 1] == CEHON) { /* figure out where the next slot is */ err_slot = surf_state->err_head_ptr + surf_state->err_count; if (err_slot >= ERROR_LIST_SIZE) { err_slot = err_slot - ERROR_LIST_SIZE; } /* store errors if there is room in the queue */ if (surf_state->err_count < ERROR_LIST_SIZE) { surf_state->err_queue[err_slot].err_class = e_class; surf_state->err_queue[err_slot].err_num = e_num; surf_state->err_queue[err_slot].func_id = f_id; surf_state->err_count++; } /* end if room in the queue */ else { /* not enuff room in the queue */ /* if the most recent error is ERROR REPORTS LOST, increase count of errors lost by one (count is stored in func_id) */ if (surf_state->err_queue[err_slot - 1].err_class == -1 && surf_state->err_queue[err_slot - 1].err_num == 0) { surf_state->err_queue[err_slot - 1].func_id++; } else { /* create an ERROR REPORTS LOST error */ /* The format for an ERROR REPORTS LOST has not yet * been defined. For now, use error class -1, error * number 0, and the count in function id. * (as defined in SRCP document) */ surf_state->err_queue[err_slot - 1].err_class = -1; surf_state->err_queue[err_slot - 1].err_num = 0; surf_state->err_queue[err_slot - 1].func_id = 2; } /* end else create */ } /* end not enuff room in the queue */ } /* end if error reporting is on */ } /* end report_error */ /* gettoken */ /* Return one token from data record....written by Pat MaGee, LANL */ static void gettoken(int *index_p, int *numrecs_p, char *data_p, int max_chars, char *outtoken_p) /* in: 1st char of whitespace before token */ /* out: 1st char past token */ /* in: number of data records */ /* in: 80 character records */ /* in: max # of chars to put into outtoken */ /* out: where to put output token */ { char c; /* char from data record */ int num_chars; /* # chars put into outtoken so far */ int workstate; /* 0=whitespace,1=nonwhite,2=endofstring */ num_chars = 0; workstate = 0; if (*index_p >= (*numrecs_p * 80)) { workstate = 2; } while (workstate == 0) { /* while scanning whitespace */ c = data_p[*index_p]; if ((c == ' ') || (c == '\t') || (c == '\r')) { /* c is whitespace, keep scanning */ ++(*index_p); if (*index_p >= *numrecs_p * 80) { workstate = 2; } /* end if off end of data */ } else { /* c is not whitespace, is start of token */ workstate = 1; } /* end if c is whitespace */ } /* end while skipping whitespace */ while (workstate == 1) { /* while in token */ c = data_p[*index_p]; if (num_chars >= max_chars) { workstate = 3; } if ((c == ' ') || (c == '\t') || (c == '\r')) { workstate = 0; } else { /* c is not whitespace, output and keep scanning */ outtoken_p[num_chars] = c; ++num_chars; ++(*index_p); if (*index_p >= *numrecs_p * 80) { workstate = 2; } /* end if off end of data */ } /* end if c is whitespace */ } /* end while putting chars into outtoken */ outtoken_p[num_chars] = 0; } /* end gettoken */ /* poly_clip */ /* Clip a polygon. Based on Sutherland - Hodgman algorithm * Returns the new polygon vertices, and the new vertex count. * One day, I need to make this more efficient by moving everything * inline. */ static int poly_clip(point *cmin, point *cmax, float *vx, float *vy, int vlen, float *xout, float *yout, int *lenout) { point s, p, t; int i, j, bnd, curlen; float xtemp[MAX_POLYGON]; float ytemp[MAX_POLYGON]; /* make sure there is something to clip */ if (vlen <= 0) { return (FALSE); } for (bnd = 0; bnd < 4; bnd++) { /* loop through all boundaries */ /* start with last vertex */ if (bnd == 0) { /* 1st time through use original vertex list */ curlen = vlen; *lenout = 0; s.x = vx[curlen - 1]; s.y = vy[curlen - 1]; } else { /* after 1st time through, use new vertex list */ curlen = *lenout; *lenout = 0; if (curlen > 0) { s.x = xout[curlen - 1]; s.y = yout[curlen - 1]; } } for (i = 0; i < curlen; i++) { /* loop through all vertices */ if (bnd == 0) { p.x = vx[i]; p.y = vy[i]; } else { p.x = xout[i]; p.y = yout[i]; } /* is vertex p 'inside' current boundary */ if (inside_bnd(&p, cmin, cmax, bnd)) { /* is vertex s 'inside' current boundary */ if (inside_bnd(&s, cmin, cmax, bnd)) { /* both p and s are inside, add p to vertex list */ xtemp[*lenout] = p.x; ytemp[(*lenout)++] = p.y; } /* end s is inside */ else { /* p is inside, s is outside, intersect */ t = intersect_bnd(&s, &p, cmin, cmax, bnd); /* add t and p to the vertex list */ xtemp[*lenout] = t.x; ytemp[(*lenout)++] = t.y; xtemp[*lenout] = p.x; ytemp[(*lenout)++] = p.y; } /* end else intersect */ } /* end if p is inside */ else { /* p is outside, is s inside */ if (inside_bnd(&s, cmin, cmax, bnd)) { /* p is outside, s is inside, intersect */ t = intersect_bnd(&s, &p, cmin, cmax, bnd); /* add t to the vertex list */ xtemp[*lenout] = t.x; ytemp[(*lenout)++] = t.y; } /* end intersect */ } /* end else p outside, s inside */ s.x = p.x; s.y = p.y; } /* end for i */ for (j = 0; j < *lenout; j++) { xout[j] = xtemp[j]; yout[j] = ytemp[j]; } /* end for j */ } /* end for bnd */ if (*lenout <= 0) { return (FALSE); } return (TRUE); } /* end poly_clip */ /* inside_bnd */ /* Used by poly_clip and returns true if the vertex is within the * boundary. ( where the boundaries are numbered 1-4,corresponding to * top, right, bottom, left ) */ static int inside_bnd(point *v, point *bmin, point *bmax, int bound_num) { /* this routine assumes a rectangular boundary */ switch (bound_num) { case 0: return (v->y <= bmax->y); /* top */ case 1: return (v->x <= bmax->x); /* right */ case 2: return (v->y >= bmin->y); /* bottom */ case 3: return (v->x >= bmin->x); /* left */ default: return (FALSE); } /* end switch */ } /* end inside_bnd */ /* intersect_bnd */ /* Used by poly_clip. Returns the the intersection point of a polygon * edge with a clip boundary. The clip boundary is coded 1-4, corresponding * to top, right, bottom, and left boundary edges, respectsively. */ static point intersect_bnd(point *p1, point *p2, point *bmin, point *bmax, int bound_num) { point temp; temp.x = temp.y = 0; switch (bound_num) { case 0: /* top */ temp.x = p1->x + (p2->x - p1->x) * (bmax->y - p1->y) / (p2->y - p1->y); temp.y = bmax->y; break; case 1: /* right */ temp.y = p1->y + (p2->y - p1->y) * (bmax->x - p1->x) / (p2->x - p1->x); temp.x = bmax->x; break; case 2: /* bottom */ temp.x = p1->x + (p2->x - p1->x) * (bmin->y - p1->y) / (p2->y - p1->y); temp.y = bmin->y; break; case 3: /* left */ temp.y = p1->y + (p2->y - p1->y) * (bmin->y - p1->x) / (p2->x - p1->x); temp.x = bmin->x; break; default: /* error check ? */ break; } /* end switch */ return (temp); } /* end intersect_bnd */ /*-------------------------------------------------------------*/ /* >> CDR ROUTINES */ /*-------------------------------------------------------------*/ /* cur_state is global - points to current statelist */ /* Open file for sequential access. FORTRAN unit number is ignored. File descriptor which is returned from open is stored in current statelist */ void cdrofs(int *ifilcd) { int errnum, errsev; char symbol[1024]; int qdc_index; float value; char *devid; char *env; static int file_cnt = 1; /* if user hasn't named the file, build a default */ if (!cur_state->filename[0]) { /* filename is blank */ /* get the SVDI device code */ qdc_index = 23; vdiqdc(&qdc_index, &value); devid = get_devid_char(value); if (devid != NULL) { snprintf(cur_state->filename, 100, "cgi%s%d", devid, file_cnt++); } else { snprintf(cur_state->filename, 100, "cgiout%d", file_cnt++); } } /* copy filename to symbol */ copy_string(symbol, cur_state->filename, 1024); /* check the environment to see if a file name has been assigned */ env = getenv(symbol); if (env != 0 && strlen(env) < 1024) { snprintf(symbol, 1024, "%s", env); } /* open the file - if it doesn't exist, create it with mode 664 */ /* -- open returns a file descriptor which is stored in the statelist */ /* -- O_TRUNC ??? read/writing??? */ if ((cur_state->file_d = open(symbol, (O_CREAT | O_TRUNC | O_RDWR), 0664)) == -1) { errnum = 722; errsev = 10; char err[50]; snprintf(err, 50, "SVDI ERROR NUMBER %d SEVERITY CODE %d", errnum, errsev); perror(err); } } /* this routine is here only for compatibility with SVDI drivers */ void cdrof3(int *ifilcd, int *idum) { cdrofs(ifilcd); } /* this routine is here only for compatibility with SVDI drivers */ void cdroff(int *ifilcd, int *idum1, int *idum2, int *idum3) { cdrofs(ifilcd); } /* Try to read LENGTH words from the file. Return the actual number of words read. FORTRAN unit number is ignored, file descriptor is gotten from the current statelist */ void cdrrfs(int *ifilcd, int *length, char *buffer, int *istat) { /* if the file hasn't been opened, open it */ if (cur_state->file_d == -1) { cdrofs(ifilcd); } /* read the data as a byte stream */ if ((*istat = read(cur_state->file_d, buffer, (*length * cdrcom.KCPW))) != -1) { *istat = *istat / cdrcom.KCPW; } } /* Write LENGTH words from BUFFER to the file. FORTRAN unit number is ignored, file descriptor is gotten from the current state list */ void cdrwfs(int *ifilcd, int *length, char *buffer, int *istat) { /* if the file hasn't been opened, open it */ if (cur_state->file_d == 0) { cdrofs(ifilcd); } /* write out the data as a byte stream. */ if ((*istat = write(cur_state->file_d, buffer, (*length * cdrcom.KCPW))) == -1) { *istat = 1; } else { *istat = 0; } } /* Close file sequential. FORTRAN unit number is ignore and file descriptor is gotten from current state */ void cdrcfs(int *ifilcd, int *eof) { int istat; char buf[4]; char err[50]; /* if eof = 1 then write eof on file */ if (*eof == 1) { *buf = EOF; if ((istat = write(cur_state->file_d, buf, 4)) == -1) { snprintf(err, 50, "%s", "CDRCFS error"); perror(err); } } /* close the file */ close(cur_state->file_d); } /* open routine for the Abekas */ void cdroab(int *ifilcd, int *frame) { char ic[5]; int i, inbr; /* form the file name from the frame number */ inbr = *frame; for (i = 3; i >= 0; i--) { ic[i] = inbr % 10 + '0'; inbr = inbr / 10; } ic[4] = '\0'; /* set the file name in the state list */ snprintf(cur_state->filename, 100, "%s.RGB", ic); cdrofs(ifilcd); }