1
2/* Copyright (c) Mark J. Kilgard, 1994, 1996, 1997. */
3
4/* This program is freely distributable without licensing fees
5   and is provided without guarantee or warrantee expressed or
6   implied. This program is -not- in the public domain. */
7
8#include <stdlib.h>
9#include "glutint.h"
10
11#define CLAMP(i) ((i) > 1.0 ? 1.0 : ((i) < 0.0 ? 0.0 : (i)))
12
13/* CENTRY */
14void GLUTAPIENTRY
15glutSetColor(int ndx, GLfloat red, GLfloat green, GLfloat blue)
16{
17  GLUTcolormap *cmap, *newcmap;
18  XVisualInfo *vis;
19  XColor color;
20  int i;
21
22  if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
23    cmap = __glutCurrentWindow->colormap;
24    vis = __glutCurrentWindow->vis;
25  } else {
26    cmap = __glutCurrentWindow->overlay->colormap;
27    vis = __glutCurrentWindow->overlay->vis;
28    if (ndx == __glutCurrentWindow->overlay->transparentPixel) {
29      __glutWarning(
30        "glutSetColor: cannot set color of overlay transparent index %d\n",
31        ndx);
32      return;
33    }
34  }
35
36  if (!cmap) {
37    __glutWarning("glutSetColor: current window is RGBA");
38    return;
39  }
40#if defined(_WIN32)
41  if (ndx >= 256 ||     /* always assume 256 colors on Win32 */
42#else
43  if (ndx >= vis->visual->map_entries ||
44#endif
45    ndx < 0) {
46    __glutWarning("glutSetColor: index %d out of range", ndx);
47    return;
48  }
49  if (cmap->refcnt > 1) {
50    newcmap = __glutAssociateNewColormap(vis);
51    cmap->refcnt--;
52    /* Wouldn't it be nice if XCopyColormapAndFree could be
53       told not to free the old colormap's entries! */
54    for (i = cmap->size - 1; i >= 0; i--) {
55      if (i == ndx) {
56        /* We are going to set this cell shortly! */
57        continue;
58      }
59      if (cmap->cells[i].component[GLUT_RED] >= 0.0) {
60        color.pixel = i;
61        newcmap->cells[i].component[GLUT_RED] =
62          cmap->cells[i].component[GLUT_RED];
63        color.red = (GLfloat) 0xffff *
64          cmap->cells[i].component[GLUT_RED];
65        newcmap->cells[i].component[GLUT_GREEN] =
66          cmap->cells[i].component[GLUT_GREEN];
67        color.green = (GLfloat) 0xffff *
68          cmap->cells[i].component[GLUT_GREEN];
69        newcmap->cells[i].component[GLUT_BLUE] =
70          cmap->cells[i].component[GLUT_BLUE];
71        color.blue = (GLfloat) 0xffff *
72          cmap->cells[i].component[GLUT_BLUE];
73        color.flags = DoRed | DoGreen | DoBlue;
74#if defined(_WIN32)
75        if (IsWindowVisible(__glutCurrentWindow->win)) {
76          XHDC = __glutCurrentWindow->hdc;
77        } else {
78          XHDC = 0;
79        }
80#endif
81        XStoreColor(__glutDisplay, newcmap->cmap, &color);
82      } else {
83        /* Leave unallocated entries unallocated. */
84      }
85    }
86    cmap = newcmap;
87    if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
88      __glutCurrentWindow->colormap = cmap;
89      __glutCurrentWindow->cmap = cmap->cmap;
90    } else {
91      __glutCurrentWindow->overlay->colormap = cmap;
92      __glutCurrentWindow->overlay->cmap = cmap->cmap;
93    }
94    XSetWindowColormap(__glutDisplay,
95      __glutCurrentWindow->renderWin, cmap->cmap);
96
97#if !defined(_WIN32)
98    {
99      GLUTwindow *toplevel;
100
101      toplevel = __glutToplevelOf(__glutCurrentWindow);
102      if (toplevel->cmap != cmap->cmap) {
103        __glutPutOnWorkList(toplevel, GLUT_COLORMAP_WORK);
104      }
105    }
106#endif
107  }
108  color.pixel = ndx;
109  red = CLAMP(red);
110  cmap->cells[ndx].component[GLUT_RED] = red;
111  color.red = (GLfloat) 0xffff *red;
112  green = CLAMP(green);
113  cmap->cells[ndx].component[GLUT_GREEN] = green;
114  color.green = (GLfloat) 0xffff *green;
115  blue = CLAMP(blue);
116  cmap->cells[ndx].component[GLUT_BLUE] = blue;
117  color.blue = (GLfloat) 0xffff *blue;
118  color.flags = DoRed | DoGreen | DoBlue;
119#if defined(_WIN32)
120  if (IsWindowVisible(__glutCurrentWindow->win)) {
121    XHDC = __glutCurrentWindow->hdc;
122  } else {
123    XHDC = 0;
124  }
125#endif
126  XStoreColor(__glutDisplay, cmap->cmap, &color);
127}
128
129GLfloat GLUTAPIENTRY
130glutGetColor(int ndx, int comp)
131{
132  GLUTcolormap *colormap;
133  XVisualInfo *vis;
134
135  if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
136    colormap = __glutCurrentWindow->colormap;
137    vis = __glutCurrentWindow->vis;
138  } else {
139    colormap = __glutCurrentWindow->overlay->colormap;
140    vis = __glutCurrentWindow->overlay->vis;
141    if (ndx == __glutCurrentWindow->overlay->transparentPixel) {
142      __glutWarning("glutGetColor: requesting overlay transparent index %d\n",
143        ndx);
144      return -1.0;
145    }
146  }
147
148  if (!colormap) {
149    __glutWarning("glutGetColor: current window is RGBA");
150    return -1.0;
151  }
152#if defined(_WIN32)
153#define OUT_OF_RANGE_NDX(ndx) (ndx >= 256 || ndx < 0)
154#else
155#define OUT_OF_RANGE_NDX(ndx) (ndx >= vis->visual->map_entries || ndx < 0)
156#endif
157  if (OUT_OF_RANGE_NDX(ndx)) {
158    __glutWarning("glutGetColor: index %d out of range", ndx);
159    return -1.0;
160  }
161  return colormap->cells[ndx].component[comp];
162}
163
164void GLUTAPIENTRY
165glutCopyColormap(int winnum)
166{
167  GLUTwindow *window = __glutWindowList[winnum - 1];
168  GLUTcolormap *oldcmap, *newcmap;
169  XVisualInfo *dstvis;
170
171  if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
172    oldcmap = __glutCurrentWindow->colormap;
173    dstvis = __glutCurrentWindow->vis;
174    newcmap = window->colormap;
175  } else {
176    oldcmap = __glutCurrentWindow->overlay->colormap;
177    dstvis = __glutCurrentWindow->overlay->vis;
178    if (!window->overlay) {
179      __glutWarning("glutCopyColormap: window %d has no overlay", winnum);
180      return;
181    }
182    newcmap = window->overlay->colormap;
183  }
184
185  if (!oldcmap) {
186    __glutWarning("glutCopyColormap: destination colormap must be color index");
187    return;
188  }
189  if (!newcmap) {
190    __glutWarning(
191      "glutCopyColormap: source colormap of window %d must be color index",
192      winnum);
193    return;
194  }
195  if (newcmap == oldcmap) {
196    /* Source and destination are the same; now copy needed. */
197    return;
198  }
199#if !defined(_WIN32)
200  /* Play safe: compare visual IDs, not Visual*'s. */
201  if (newcmap->visual->visualid == oldcmap->visual->visualid) {
202#endif
203    /* Visuals match!  "Copy" by reference...  */
204    __glutFreeColormap(oldcmap);
205    newcmap->refcnt++;
206    if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
207      __glutCurrentWindow->colormap = newcmap;
208      __glutCurrentWindow->cmap = newcmap->cmap;
209    } else {
210      __glutCurrentWindow->overlay->colormap = newcmap;
211      __glutCurrentWindow->overlay->cmap = newcmap->cmap;
212    }
213    XSetWindowColormap(__glutDisplay, __glutCurrentWindow->renderWin,
214      newcmap->cmap);
215#if !defined(_WIN32)
216    __glutPutOnWorkList(__glutToplevelOf(window), GLUT_COLORMAP_WORK);
217  } else {
218    GLUTcolormap *copycmap;
219    XColor color;
220    int i, last;
221
222    /* Visuals different - need a distinct X colormap! */
223    copycmap = __glutAssociateNewColormap(dstvis);
224    /* Wouldn't it be nice if XCopyColormapAndFree could be
225       told not to free the old colormap's entries! */
226    last = newcmap->size;
227    if (last > copycmap->size) {
228      last = copycmap->size;
229    }
230    for (i = last - 1; i >= 0; i--) {
231      if (newcmap->cells[i].component[GLUT_RED] >= 0.0) {
232        color.pixel = i;
233        copycmap->cells[i].component[GLUT_RED] =
234          newcmap->cells[i].component[GLUT_RED];
235        color.red = (GLfloat) 0xffff *
236          newcmap->cells[i].component[GLUT_RED];
237        copycmap->cells[i].component[GLUT_GREEN] =
238          newcmap->cells[i].component[GLUT_GREEN];
239        color.green = (GLfloat) 0xffff *
240          newcmap->cells[i].component[GLUT_GREEN];
241        copycmap->cells[i].component[GLUT_BLUE] =
242          newcmap->cells[i].component[GLUT_BLUE];
243        color.blue = (GLfloat) 0xffff *
244          newcmap->cells[i].component[GLUT_BLUE];
245        color.flags = DoRed | DoGreen | DoBlue;
246        XStoreColor(__glutDisplay, copycmap->cmap, &color);
247      }
248    }
249  }
250#endif
251}
252/* ENDCENTRY */
253