home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src-glut / glut_cindex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  10.7 KB  |  362 lines

  1. /* Copyright (c) Mark J. Kilgard, 1994, 1996. */
  2.  
  3. /* This program is freely distributable without licensing fees 
  4.    and is provided without guarantee or warrantee expressed or 
  5.    implied. This program is -not- in the public domain. */
  6.  
  7. #include <stdlib.h>
  8. #include <GL/glut.h>
  9. #include "glutint.h"
  10. #include "layerutil.h"
  11.  
  12. GLUTcolormap *__glutColormapList = NULL;
  13.  
  14. static GLUTcolormap *
  15. associateNewColormap(XVisualInfo * vis)
  16. {
  17.   GLUTcolormap *cmap;
  18.   int transparentPixel, i;
  19.   unsigned long pixels[255];
  20.  
  21.   cmap = (GLUTcolormap *) malloc(sizeof(GLUTcolormap));
  22.   if (!cmap)
  23.     __glutFatalError("out of memory.");
  24. #if defined(WIN32)
  25.   pixels[0] = 0;          /* avoid compilation warnings on win32 */
  26.   cmap->visual = 0;
  27.   cmap->size = 256;            /* always assume 256 on Win32 */
  28. #else
  29.   cmap->visual = vis->visual;
  30.   cmap->size = vis->visual->map_entries;
  31. #endif
  32.   cmap->refcnt = 1;
  33.   cmap->cells = (GLUTcolorcell *)
  34.     malloc(sizeof(GLUTcolorcell) * cmap->size);
  35.   if (!cmap->cells)
  36.     __glutFatalError("out of memory.");
  37.   /* make all color cell entries be invalid */
  38.   for (i = cmap->size - 1; i >= 0; i--) {
  39.     cmap->cells[i].component[GLUT_RED] = -1.0;
  40.     cmap->cells[i].component[GLUT_GREEN] = -1.0;
  41.     cmap->cells[i].component[GLUT_BLUE] = -1.0;
  42.   }
  43.   transparentPixel = __glutGetTransparentPixel(__glutDisplay, vis);
  44.   if (transparentPixel == -1 || transparentPixel >= cmap->size) {
  45.  
  46.     /* If there is no transparent pixel or if the transparent
  47.        pixel is outside the range of valid colormap cells (HP
  48.        can implement their overlays this smart way since their
  49.        transparent pixel is 255), we can AllocAll the colormap.
  50.        See note below.  */
  51.  
  52.     cmap->cmap = XCreateColormap(__glutDisplay,
  53.       __glutRoot, cmap->visual, AllocAll);
  54.   } else {
  55.  
  56.     /* On machines where zero (or some other value in the range
  57.        of 0 through map_entries-1), BadAlloc may be generated
  58.        when an AllocAll overlay colormap is allocated since the
  59.        transparent pixel precludes all the cells in the colormap
  60.        being allocated (the transparent pixel is pre-allocated).
  61.        So in this case, use XAllocColorCells to allocate
  62.        map_entries-1 pixels (that is, all but the transparent
  63.        pixel.  */
  64.  
  65. #if defined(WIN32)
  66.     cmap->cmap = XCreateColormap(__glutDisplay,
  67.       __glutRoot, 0, AllocNone);
  68. #else
  69.     cmap->cmap = XCreateColormap(__glutDisplay,
  70.       __glutRoot, vis->visual, AllocNone);
  71. #endif
  72.     XAllocColorCells(__glutDisplay, cmap->cmap, False, 0, 0,
  73.       pixels, cmap->size - 1);
  74.   }
  75.   cmap->next = __glutColormapList;
  76.   __glutColormapList = cmap;
  77.   return cmap;
  78. }
  79.  
  80. GLUTcolormap *
  81. __glutAssociateColormap(XVisualInfo * vis)
  82. {
  83.   GLUTcolormap *cmap = __glutColormapList;
  84.  
  85.   while (cmap != NULL) {
  86. #if !defined(WIN32)
  87.     /* Play safe: compare visual IDs, not Visual*'s. */
  88.     if (cmap->visual->visualid == vis->visual->visualid) {
  89.       /* Already have created colormap for the visual. */
  90.       cmap->refcnt++;
  91.       return cmap;
  92.     }
  93. #endif
  94.     cmap = cmap->next;
  95.   }
  96.   return associateNewColormap(vis);
  97. }
  98.  
  99. #define CLAMP(i) ((i) > 1.0 ? 1.0 : ((i) < 0.0 ? 0.0 : (i)))
  100.  
  101. /* CENTRY */
  102. void APIENTRY 
  103. glutSetColor(int ndx, GLfloat red, GLfloat green, GLfloat blue)
  104. {
  105.   GLUTcolormap *cmap, *newcmap;
  106.   XVisualInfo *vis;
  107.   XColor color;
  108.   int i;
  109.  
  110.   if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  111.     cmap = __glutCurrentWindow->colormap;
  112.     vis = __glutCurrentWindow->vis;
  113.   } else {
  114.     cmap = __glutCurrentWindow->overlay->colormap;
  115.     vis = __glutCurrentWindow->overlay->vis;
  116.     if (ndx == __glutCurrentWindow->overlay->transparentPixel) {
  117.       __glutWarning(
  118.         "glutSetColor: cannot set color of overlay transparent index %d\n",
  119.         ndx);
  120.       return;
  121.     }
  122.   }
  123.  
  124.   if (!cmap) {
  125.     __glutWarning("glutSetColor: current window is RGBA");
  126.     return;
  127.   }
  128. #if defined(WIN32)
  129.   if (ndx >= 256 ||            /* always assume 256 colors on Win32 */
  130. #else
  131.   if (ndx >= vis->visual->map_entries ||
  132. #endif
  133.     ndx < 0) {
  134.     __glutWarning("glutSetColor: index %d out of range", ndx);
  135.     return;
  136.   }
  137.   if (cmap->refcnt > 1) {
  138.     GLUTwindow *toplevel;
  139.  
  140.     newcmap = associateNewColormap(vis);
  141.     cmap->refcnt--;
  142.     /* Wouldn't it be nice if XCopyColormapAndFree could be
  143.        told not to free the old colormap's entries! */
  144.     for (i = cmap->size - 1; i >= 0; i--) {
  145.       if (i == ndx) {
  146.         /* We are going to set this cell shortly! */
  147.         continue;
  148.       }
  149.       if (cmap->cells[i].component[GLUT_RED] >= 0.0) {
  150.         color.pixel = i;
  151.         newcmap->cells[i].component[GLUT_RED] =
  152.           cmap->cells[i].component[GLUT_RED];
  153.         color.red = (GLfloat) 0xffff *
  154.           cmap->cells[i].component[GLUT_RED];
  155.         newcmap->cells[i].component[GLUT_GREEN] =
  156.           cmap->cells[i].component[GLUT_GREEN];
  157.         color.green = (GLfloat) 0xffff *
  158.           cmap->cells[i].component[GLUT_GREEN];
  159.         newcmap->cells[i].component[GLUT_BLUE] =
  160.           cmap->cells[i].component[GLUT_BLUE];
  161.         color.blue = (GLfloat) 0xffff *
  162.           cmap->cells[i].component[GLUT_BLUE];
  163.         color.flags = DoRed | DoGreen | DoBlue;
  164. #if defined(WIN32)
  165.     if (IsWindowVisible(__glutCurrentWindow->win)) {
  166.       XHDC = __glutCurrentWindow->hdc;
  167.     } else {
  168.       XHDC = 0;
  169.     }
  170. #endif
  171.         XStoreColor(__glutDisplay, newcmap->cmap, &color);
  172.       } else {
  173.         /* Leave unallocated entries unallocated. */
  174.       }
  175.     }
  176.     cmap = newcmap;
  177.     if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  178.       __glutCurrentWindow->colormap = cmap;
  179.       __glutCurrentWindow->cmap = cmap->cmap;
  180.     } else {
  181.       __glutCurrentWindow->overlay->colormap = cmap;
  182.       __glutCurrentWindow->overlay->cmap = cmap->cmap;
  183.     }
  184.     XSetWindowColormap(__glutDisplay,
  185.       __glutCurrentWindow->renderWin, cmap->cmap);
  186.  
  187.     toplevel = __glutToplevelOf(__glutCurrentWindow);
  188.     if (toplevel->cmap != cmap->cmap) {
  189.       __glutPutOnWorkList(toplevel, GLUT_COLORMAP_WORK);
  190.     }
  191.   }
  192.   color.pixel = ndx;
  193.   red = CLAMP(red);
  194.   cmap->cells[ndx].component[GLUT_RED] = red;
  195.   color.red = (GLfloat) 0xffff *red;
  196.   green = CLAMP(green);
  197.   cmap->cells[ndx].component[GLUT_GREEN] = green;
  198.   color.green = (GLfloat) 0xffff *green;
  199.   blue = CLAMP(blue);
  200.   cmap->cells[ndx].component[GLUT_BLUE] = blue;
  201.   color.blue = (GLfloat) 0xffff *blue;
  202.   color.flags = DoRed | DoGreen | DoBlue;
  203. #if defined(WIN32)
  204.   if (IsWindowVisible(__glutCurrentWindow->win)) {
  205.     XHDC = __glutCurrentWindow->hdc;
  206.   } else {
  207.     XHDC = 0;
  208.   }
  209. #endif
  210.   XStoreColor(__glutDisplay, cmap->cmap, &color);
  211. }
  212.  
  213. GLfloat APIENTRY
  214. glutGetColor(int ndx, int comp)
  215. {
  216.   GLUTcolormap *colormap;
  217.   XVisualInfo *vis;
  218.  
  219.   if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  220.     colormap = __glutCurrentWindow->colormap;
  221.     vis = __glutCurrentWindow->vis;
  222.   } else {
  223.     colormap = __glutCurrentWindow->overlay->colormap;
  224.     vis = __glutCurrentWindow->overlay->vis;
  225.     if (ndx == __glutCurrentWindow->overlay->transparentPixel) {
  226.       __glutWarning("glutGetColor: requesting overlay transparent index %d\n",
  227.         ndx);
  228.       return -1.0;
  229.     }
  230.   }
  231.  
  232.   if (!colormap) {
  233.     __glutWarning("glutGetColor: current window is RGBA");
  234.     return -1.0;
  235.   }
  236. #if defined(WIN32)
  237. #define OUT_OF_RANGE_NDX(ndx) (ndx >= 256 || ndx < 0)
  238. #else
  239. #define OUT_OF_RANGE_NDX(ndx) (ndx >= vis->visual->map_entries || ndx < 0)
  240. #endif
  241.   if (OUT_OF_RANGE_NDX(ndx)) {
  242.     __glutWarning("glutGetColor: index %d out of range", ndx);
  243.     return -1.0;
  244.   }
  245.   return colormap->cells[ndx].component[comp];
  246. }
  247. /* ENDCENTRY */
  248.  
  249. void
  250. __glutFreeColormap(GLUTcolormap * cmap)
  251. {
  252.   GLUTcolormap *cur, **prev;
  253.  
  254.   cmap->refcnt--;
  255.   if (cmap->refcnt == 0) {
  256.     /* remove from colormap list */
  257.     cur = __glutColormapList;
  258.     prev = &__glutColormapList;
  259.     while (cur) {
  260.       if (cur == cmap) {
  261.         *prev = cmap->next;
  262.         break;
  263.       }
  264.       prev = &(cur->next);
  265.       cur = cur->next;
  266.     }
  267.     /* actually free colormap */
  268.     XFreeColormap(__glutDisplay, cmap->cmap);
  269.     free(cmap->cells);
  270.     free(cmap);
  271.   }
  272. }
  273.  
  274. /* CENTRY */
  275. void APIENTRY 
  276. glutCopyColormap(int winnum)
  277. {
  278.   GLUTwindow *window = __glutWindowList[winnum - 1];
  279.   GLUTcolormap *oldcmap, *newcmap, *copycmap;
  280.   XVisualInfo *dstvis;
  281.   XColor color;
  282.   int i, last;
  283.  
  284.   if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  285.     oldcmap = __glutCurrentWindow->colormap;
  286.     dstvis = __glutCurrentWindow->vis;
  287.     newcmap = window->colormap;
  288.   } else {
  289.     oldcmap = __glutCurrentWindow->overlay->colormap;
  290.     dstvis = __glutCurrentWindow->overlay->vis;
  291.     if (!window->overlay) {
  292.       __glutWarning("glutCopyColormap: window %d has no overlay", winnum);
  293.       return;
  294.     }
  295.     newcmap = window->overlay->colormap;
  296.   }
  297.  
  298.   if (!oldcmap) {
  299.     __glutWarning("glutCopyColormap: destination colormap must be color index");
  300.     return;
  301.   }
  302.   if (!newcmap) {
  303.     __glutWarning(
  304.       "glutCopyColormap: source colormap of window %d must be color index",
  305.       winnum);
  306.     return;
  307.   }
  308.   if (newcmap == oldcmap) {
  309.     /* Source and destination are the same; now copy needed. */
  310.     return;
  311.   }
  312. #if !defined(WIN32)
  313.   /* Play safe: compare visual IDs, not Visual*'s. */
  314.   if (newcmap->visual->visualid == oldcmap->visual->visualid) {
  315. #endif
  316.     /* Visuals match!  "Copy" by reference...  */
  317.     __glutFreeColormap(oldcmap);
  318.     newcmap->refcnt++;
  319.     if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  320.       __glutCurrentWindow->colormap = newcmap;
  321.       __glutCurrentWindow->cmap = newcmap->cmap;
  322.     } else {
  323.       __glutCurrentWindow->overlay->colormap = newcmap;
  324.       __glutCurrentWindow->overlay->cmap = newcmap->cmap;
  325.     }
  326.     XSetWindowColormap(__glutDisplay, __glutCurrentWindow->renderWin,
  327.       newcmap->cmap);
  328.     __glutPutOnWorkList(__glutToplevelOf(window), GLUT_COLORMAP_WORK);
  329. #if !defined(WIN32)
  330.   } else {
  331.     /* Visuals different - need a distinct X colormap! */
  332.     copycmap = associateNewColormap(dstvis);
  333.     /* Wouldn't it be nice if XCopyColormapAndFree could be
  334.        told not to free the old colormap's entries! */
  335.     last = newcmap->size;
  336.     if (last > copycmap->size) {
  337.       last = copycmap->size;
  338.     }
  339.     for (i = last - 1; i >= 0; i--) {
  340.       if (newcmap->cells[i].component[GLUT_RED] >= 0.0) {
  341.         color.pixel = i;
  342.         copycmap->cells[i].component[GLUT_RED] =
  343.           newcmap->cells[i].component[GLUT_RED];
  344.         color.red = (GLfloat) 0xffff *
  345.           newcmap->cells[i].component[GLUT_RED];
  346.         copycmap->cells[i].component[GLUT_GREEN] =
  347.           newcmap->cells[i].component[GLUT_GREEN];
  348.         color.green = (GLfloat) 0xffff *
  349.           newcmap->cells[i].component[GLUT_GREEN];
  350.         copycmap->cells[i].component[GLUT_BLUE] =
  351.           newcmap->cells[i].component[GLUT_BLUE];
  352.         color.blue = (GLfloat) 0xffff *
  353.           newcmap->cells[i].component[GLUT_BLUE];
  354.         color.flags = DoRed | DoGreen | DoBlue;
  355.         XStoreColor(__glutDisplay, copycmap->cmap, &color);
  356.       }
  357.     }
  358.   }
  359. #endif
  360. }
  361. /* ENDCENTRY */
  362.