/*----------------------------------------------------------------------*/ /* opengl.c --- routines defining graphics, whether OpenGL or X11 */ /* Copyright (c) 2005 Tim Edwards, MultiGiG, Inc. */ /*----------------------------------------------------------------------*/ #ifdef OPENGL /*----------------------------------------------------------------------*/ /* written by Tim Edwards, 6/1/05 */ /*----------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include /*----------------------------------------------------------------------*/ /* Local includes */ /*----------------------------------------------------------------------*/ #ifdef TCL_WRAPPER #include #endif #include "xcircuit.h" #include "colordefs.h" /*----------------------------------------------------------------------*/ /* Function prototype declarations */ /*----------------------------------------------------------------------*/ #include "prototypes.h" extern XtAppContext app; extern Colormap cmap; extern int *appcolors; extern char STIPDATA[STIPPLES][4]; extern float gl_line_limit, gl_point_limit; /*----------------------------------------------*/ /* Set color in OpenGL (this should be replaced */ /* for speed. . .) */ /*----------------------------------------------*/ void SetForeground(Display *dpy, GC nullptr, int idx) { XColor fgcolor; int red, green, blue; fgcolor.pixel = idx; fgcolor.flags = DoRed | DoGreen | DoBlue; XQueryColor(dpy, cmap, &fgcolor); glColor3us((GLushort)fgcolor.red, (GLushort)fgcolor.green, (GLushort)fgcolor.blue); } /*----------------------------------------------*/ /* Don't know if this is meaningful or not. */ /*----------------------------------------------*/ void SetBackground(Display *dpy, GC nullptr, int idx) { /* null proc */ } /*------------------------------------------------------*/ /* Set drawing function */ /*------------------------------------------------------*/ void SetFunction(Display *dpy, GC nullptr, int xfunction) { switch (xfunction) { case GXcopy: glDisable(GL_COLOR_LOGIC_OP); /* Is it better to disable the logic op? */ /* glEnable(GL_COLOR_LOGIC_OP); glLogicOp(GL_COPY); */ break; case GXxor: glEnable(GL_COLOR_LOGIC_OP); glLogicOp(GL_XOR); break; } } /*------------------------------------------------------*/ /* Set line attributes /*------------------------------------------------------*/ void SetLineAttributes(Display *dpy, GC nullptr, float lwidth, int ldash, int lcap, int lbevel) { GLfloat glwidth = (lwidth <= 0) ? 1 : (GLfloat)lwidth; glLineWidth(glwidth); glPointSize(glwidth); if (lwidth > gl_line_limit) glDisable(GL_LINE_SMOOTH); else glEnable(GL_LINE_SMOOTH); if (lwidth > gl_point_limit) glDisable(GL_POINT_SMOOTH); else glEnable(GL_POINT_SMOOTH); switch (ldash) { case LineSolid: glDisable(GL_LINE_STIPPLE); break; case LineOnOffDash: glEnable(GL_LINE_STIPPLE); break; } /* Cap and Mitre not handled by OpenGL */ } /*------------------------------------------------------*/ /* Set Line dash */ /*------------------------------------------------------*/ void SetDashes(Display *dpy, GC nullptr, int offset, char dashlist[], int n) { union { char dashbytes[2]; u_short dashpat; } dashspec; dashspec.dashbytes[0] = dashlist[0]; dashspec.dashbytes[1] = dashlist[1]; glLineStipple((GLint)1, (GLushort)dashspec.dashpat); } /*------------------------------------------------------*/ /* Set Polygon fill stipple (optimize this!) */ /*------------------------------------------------------*/ void SetStipple(Display *dpy, GC nullptr, int stipple) { u_char stipdata[128]; char *stipsrc = STIPDATA[stipple]; char *stipdest = stipdata; int i; for (i = 0; i < 32; i++) { memcpy(stipdest, stipsrc, 4); stipdest += 4; } glPolygonStipple((GLubyte *)stipdata); } /*------------------------------------------------------*/ /* Set Polygon fill style */ /* (Currently there is no differentiating between the */ /* FillStippled and FillOpaqueStippled styles) */ /*------------------------------------------------------*/ void SetFillStyle(Display *dpy, GC nullptr, int fillstyle) { switch(fillstyle) { case FillSolid: glDisable(GL_POLYGON_STIPPLE); break; case FillStippled: glEnable(GL_POLYGON_STIPPLE); break; case FillOpaqueStippled: glEnable(GL_POLYGON_STIPPLE); break; } } /*------------------------------------------------------*/ /* Draw line (compatibility function for XDrawLine() */ /*------------------------------------------------------*/ void DrawLine(Display *dpy, Window win, GC nullptr, int x1, int y1, int x2, int y2) { glBegin(GL_LINES); glVertex2i(x1, y1); glVertex2i(x2, y2); glEnd(); /* Produce round-cap ends by drawing points at the ends */ glBegin(GL_POINTS); glVertex2i(x1, y1); glVertex2i(x2, y2); glEnd(); } /*--------------------------------------------------------------*/ /* Draw multiple lines (compatibility function for XDrawLines() */ /* (This should be using a chained line segments function) */ /*--------------------------------------------------------------*/ void DrawLines(Display *dpy, Window win, GC nullptr, XPoint *points, int npoints, int mode) { int i; glBegin(GL_LINE_STRIP); for (i = 0; i < npoints; i++) glVertex2i(points[i].x, points[i].y); glEnd(); /* Round-caps */ glBegin(GL_POINTS); for (i = 0; i < npoints; i++) glVertex2i(points[i].x, points[i].y); glEnd(); } /*------------------------------------------------------*/ /* Draw point (compatibility function for XDrawPoint() */ /*------------------------------------------------------*/ void DrawPoint(Display *dpy, Window win, GC nullptr, int x, int y) { glBegin(GL_POINTS); glVertex2i(x, y); glEnd(); } /*----------------------------------------------------------------------*/ /* Draw a filled polygon (compatibility function for XFillPolygon() */ /*----------------------------------------------------------------------*/ void FillPolygon(Display *dpy, Window win, GC nullptr, XPoint *points, int npoints, int shape, int mode) { int i; static GLUtesselator *tess = NULL; GLdouble v[3]; /* glBegin(GL_POLYGON); for (i = 0; i < npoints; i++) glVertex2i(points[i].x, points[i].y); glEnd(); */ if (tess == NULL) { tess = gluNewTess(); gluTessCallback(tess, GLU_BEGIN, glBegin); gluTessCallback(tess, GLU_VERTEX, glVertex3dv); gluTessCallback(tess, GLU_END, glEnd); v[2] = 0.0; } gluBeginPolygon(tess); for (i = 0; i < npoints; i++) { v[0] = (GLdouble)points[i].x; v[1] = (GLdouble)points[i].y; gluTessVertex(tess, v, v); } gluEndPolygon(tess); } /*------------------------------------------------------*/ /* Render a background image */ /*------------------------------------------------------*/ void backgroundbbox(int b) { /* null proc for now . . . */ } void readbackground(FILE *f) { /* null proc for now . . . */ } void savebackground(FILE *f, char *c) { /* null proc for now . . . */ } void loadbackground() { /* null proc for now . . . */ } int renderbackground() { /* null proc for now . . . */ } int copybackground() { /* null proc for now . . . */ } int reset_gs() { /* This is a null proc because OpenGL doesn't use */ /* ghostscript, and it's easier to make a null proc */ /* than to #ifdef the calls. */ } int exit_gs() { /* ditto */ } /*-------------------------------------------------------------------------*/ #endif /* OPENGL */