| |
| /* Copyright (c) Mark J. Kilgard, 1994, 1996, 1997. */ |
| |
| /* This program is freely distributable without licensing fees |
| and is provided without guarantee or warrantee expressed or |
| implied. This program is -not- in the public domain. */ |
| |
| #include <stdlib.h> |
| #include "glutint.h" |
| |
| #define CLAMP(i) ((i) > 1.0 ? 1.0 : ((i) < 0.0 ? 0.0 : (i))) |
| |
| /* CENTRY */ |
| void GLUTAPIENTRY |
| glutSetColor(int ndx, GLfloat red, GLfloat green, GLfloat blue) |
| { |
| GLUTcolormap *cmap, *newcmap; |
| XVisualInfo *vis; |
| XColor color; |
| int i; |
| |
| if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) { |
| cmap = __glutCurrentWindow->colormap; |
| vis = __glutCurrentWindow->vis; |
| } else { |
| cmap = __glutCurrentWindow->overlay->colormap; |
| vis = __glutCurrentWindow->overlay->vis; |
| if (ndx == __glutCurrentWindow->overlay->transparentPixel) { |
| __glutWarning( |
| "glutSetColor: cannot set color of overlay transparent index %d\n", |
| ndx); |
| return; |
| } |
| } |
| |
| if (!cmap) { |
| __glutWarning("glutSetColor: current window is RGBA"); |
| return; |
| } |
| #if defined(_WIN32) |
| if (ndx >= 256 || /* always assume 256 colors on Win32 */ |
| #else |
| if (ndx >= vis->visual->map_entries || |
| #endif |
| ndx < 0) { |
| __glutWarning("glutSetColor: index %d out of range", ndx); |
| return; |
| } |
| if (cmap->refcnt > 1) { |
| newcmap = __glutAssociateNewColormap(vis); |
| cmap->refcnt--; |
| /* Wouldn't it be nice if XCopyColormapAndFree could be |
| told not to free the old colormap's entries! */ |
| for (i = cmap->size - 1; i >= 0; i--) { |
| if (i == ndx) { |
| /* We are going to set this cell shortly! */ |
| continue; |
| } |
| if (cmap->cells[i].component[GLUT_RED] >= 0.0) { |
| color.pixel = i; |
| newcmap->cells[i].component[GLUT_RED] = |
| cmap->cells[i].component[GLUT_RED]; |
| color.red = (GLfloat) 0xffff * |
| cmap->cells[i].component[GLUT_RED]; |
| newcmap->cells[i].component[GLUT_GREEN] = |
| cmap->cells[i].component[GLUT_GREEN]; |
| color.green = (GLfloat) 0xffff * |
| cmap->cells[i].component[GLUT_GREEN]; |
| newcmap->cells[i].component[GLUT_BLUE] = |
| cmap->cells[i].component[GLUT_BLUE]; |
| color.blue = (GLfloat) 0xffff * |
| cmap->cells[i].component[GLUT_BLUE]; |
| color.flags = DoRed | DoGreen | DoBlue; |
| #if defined(_WIN32) |
| if (IsWindowVisible(__glutCurrentWindow->win)) { |
| XHDC = __glutCurrentWindow->hdc; |
| } else { |
| XHDC = 0; |
| } |
| #endif |
| XStoreColor(__glutDisplay, newcmap->cmap, &color); |
| } else { |
| /* Leave unallocated entries unallocated. */ |
| } |
| } |
| cmap = newcmap; |
| if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) { |
| __glutCurrentWindow->colormap = cmap; |
| __glutCurrentWindow->cmap = cmap->cmap; |
| } else { |
| __glutCurrentWindow->overlay->colormap = cmap; |
| __glutCurrentWindow->overlay->cmap = cmap->cmap; |
| } |
| XSetWindowColormap(__glutDisplay, |
| __glutCurrentWindow->renderWin, cmap->cmap); |
| |
| #if !defined(_WIN32) |
| { |
| GLUTwindow *toplevel; |
| |
| toplevel = __glutToplevelOf(__glutCurrentWindow); |
| if (toplevel->cmap != cmap->cmap) { |
| __glutPutOnWorkList(toplevel, GLUT_COLORMAP_WORK); |
| } |
| } |
| #endif |
| } |
| color.pixel = ndx; |
| red = CLAMP(red); |
| cmap->cells[ndx].component[GLUT_RED] = red; |
| color.red = (GLfloat) 0xffff *red; |
| green = CLAMP(green); |
| cmap->cells[ndx].component[GLUT_GREEN] = green; |
| color.green = (GLfloat) 0xffff *green; |
| blue = CLAMP(blue); |
| cmap->cells[ndx].component[GLUT_BLUE] = blue; |
| color.blue = (GLfloat) 0xffff *blue; |
| color.flags = DoRed | DoGreen | DoBlue; |
| #if defined(_WIN32) |
| if (IsWindowVisible(__glutCurrentWindow->win)) { |
| XHDC = __glutCurrentWindow->hdc; |
| } else { |
| XHDC = 0; |
| } |
| #endif |
| XStoreColor(__glutDisplay, cmap->cmap, &color); |
| } |
| |
| GLfloat GLUTAPIENTRY |
| glutGetColor(int ndx, int comp) |
| { |
| GLUTcolormap *colormap; |
| XVisualInfo *vis; |
| |
| if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) { |
| colormap = __glutCurrentWindow->colormap; |
| vis = __glutCurrentWindow->vis; |
| } else { |
| colormap = __glutCurrentWindow->overlay->colormap; |
| vis = __glutCurrentWindow->overlay->vis; |
| if (ndx == __glutCurrentWindow->overlay->transparentPixel) { |
| __glutWarning("glutGetColor: requesting overlay transparent index %d\n", |
| ndx); |
| return -1.0; |
| } |
| } |
| |
| if (!colormap) { |
| __glutWarning("glutGetColor: current window is RGBA"); |
| return -1.0; |
| } |
| #if defined(_WIN32) |
| #define OUT_OF_RANGE_NDX(ndx) (ndx >= 256 || ndx < 0) |
| #else |
| #define OUT_OF_RANGE_NDX(ndx) (ndx >= vis->visual->map_entries || ndx < 0) |
| #endif |
| if (OUT_OF_RANGE_NDX(ndx)) { |
| __glutWarning("glutGetColor: index %d out of range", ndx); |
| return -1.0; |
| } |
| return colormap->cells[ndx].component[comp]; |
| } |
| |
| void GLUTAPIENTRY |
| glutCopyColormap(int winnum) |
| { |
| GLUTwindow *window = __glutWindowList[winnum - 1]; |
| GLUTcolormap *oldcmap, *newcmap; |
| XVisualInfo *dstvis; |
| |
| if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) { |
| oldcmap = __glutCurrentWindow->colormap; |
| dstvis = __glutCurrentWindow->vis; |
| newcmap = window->colormap; |
| } else { |
| oldcmap = __glutCurrentWindow->overlay->colormap; |
| dstvis = __glutCurrentWindow->overlay->vis; |
| if (!window->overlay) { |
| __glutWarning("glutCopyColormap: window %d has no overlay", winnum); |
| return; |
| } |
| newcmap = window->overlay->colormap; |
| } |
| |
| if (!oldcmap) { |
| __glutWarning("glutCopyColormap: destination colormap must be color index"); |
| return; |
| } |
| if (!newcmap) { |
| __glutWarning( |
| "glutCopyColormap: source colormap of window %d must be color index", |
| winnum); |
| return; |
| } |
| if (newcmap == oldcmap) { |
| /* Source and destination are the same; now copy needed. */ |
| return; |
| } |
| #if !defined(_WIN32) |
| /* Play safe: compare visual IDs, not Visual*'s. */ |
| if (newcmap->visual->visualid == oldcmap->visual->visualid) { |
| #endif |
| /* Visuals match! "Copy" by reference... */ |
| __glutFreeColormap(oldcmap); |
| newcmap->refcnt++; |
| if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) { |
| __glutCurrentWindow->colormap = newcmap; |
| __glutCurrentWindow->cmap = newcmap->cmap; |
| } else { |
| __glutCurrentWindow->overlay->colormap = newcmap; |
| __glutCurrentWindow->overlay->cmap = newcmap->cmap; |
| } |
| XSetWindowColormap(__glutDisplay, __glutCurrentWindow->renderWin, |
| newcmap->cmap); |
| #if !defined(_WIN32) |
| __glutPutOnWorkList(__glutToplevelOf(window), GLUT_COLORMAP_WORK); |
| } else { |
| GLUTcolormap *copycmap; |
| XColor color; |
| int i, last; |
| |
| /* Visuals different - need a distinct X colormap! */ |
| copycmap = __glutAssociateNewColormap(dstvis); |
| /* Wouldn't it be nice if XCopyColormapAndFree could be |
| told not to free the old colormap's entries! */ |
| last = newcmap->size; |
| if (last > copycmap->size) { |
| last = copycmap->size; |
| } |
| for (i = last - 1; i >= 0; i--) { |
| if (newcmap->cells[i].component[GLUT_RED] >= 0.0) { |
| color.pixel = i; |
| copycmap->cells[i].component[GLUT_RED] = |
| newcmap->cells[i].component[GLUT_RED]; |
| color.red = (GLfloat) 0xffff * |
| newcmap->cells[i].component[GLUT_RED]; |
| copycmap->cells[i].component[GLUT_GREEN] = |
| newcmap->cells[i].component[GLUT_GREEN]; |
| color.green = (GLfloat) 0xffff * |
| newcmap->cells[i].component[GLUT_GREEN]; |
| copycmap->cells[i].component[GLUT_BLUE] = |
| newcmap->cells[i].component[GLUT_BLUE]; |
| color.blue = (GLfloat) 0xffff * |
| newcmap->cells[i].component[GLUT_BLUE]; |
| color.flags = DoRed | DoGreen | DoBlue; |
| XStoreColor(__glutDisplay, copycmap->cmap, &color); |
| } |
| } |
| } |
| #endif |
| } |
| /* ENDCENTRY */ |