home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xmu / CrCmap.c.orig < prev    next >
Encoding:
Text File  |  1991-04-10  |  16.1 KB  |  488 lines

  1. /* $XConsortium: CrCmap.c,v 1.3 91/04/10 16:45:46 converse Exp $
  2.  *
  3.  * CreateCmap.c - given a standard colormap description, make the map.
  4.  * 
  5.  * Copyright 1989 by the Massachusetts Institute of Technology
  6.  *
  7.  * Permission to use, copy, modify, and distribute this software and its
  8.  * documentation for any purpose and without fee is hereby granted, provided 
  9.  * that the above copyright notice appear in all copies and that both that 
  10.  * copyright notice and this permission notice appear in supporting 
  11.  * documentation, and that the name of M.I.T. not be used in advertising
  12.  * or publicity pertaining to distribution of the software without specific, 
  13.  * written prior permission. M.I.T. makes no representations about the 
  14.  * suitability of this software for any purpose.  It is provided "as is"
  15.  * without express or implied warranty.
  16.  *
  17.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  18.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  19.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  20.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  21.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  22.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  23.  *
  24.  * Author:  Donna Converse, MIT X Consortium
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <X11/Xlib.h>
  29. #include <X11/Xutil.h>
  30.  
  31. extern char    *calloc();
  32.  
  33. static int    ROmap();        /* allocate entire map Read Only */
  34. static Status    ROorRWcell();        /* allocate a cell, prefer Read Only */
  35. static Status    RWcell();        /* allocate a cell Read Write */
  36. static int    compare();        /* for quicksort */
  37. static Status     contiguous();        /* find contiguous sequence of cells */
  38. static void    free_cells();        /* frees resources before quitting */
  39. static Status    readonly_map();        /* create a map in a RO visual type */
  40. static Status    readwrite_map();    /* create a map in a RW visual type */
  41.  
  42. /*
  43.  * To create any one colormap which is described by an XStandardColormap
  44.  * structure, use XmuCreateColormap().
  45.  *
  46.  * Return 0 on failure, non-zero on success.
  47.  * Resources created by this function are not made permanent.
  48.  * No argument error checking is provided.  Use at your own risk.
  49.  *
  50.  * All colormaps are created with read only allocations, with the exception
  51.  * of read only allocations of colors in the default map or otherwise
  52.  * which fail to return the expected pixel value, and these are individually 
  53.  * defined as read/write allocations.  This is done so that all the cells
  54.  * defined in the default map are contiguous, for use in image processing.
  55.  * This typically happens with White and Black in the default map.
  56.  *
  57.  * Colormaps of static visuals are considered to be successfully created if
  58.  * the map of the static visual matches the definition given in the
  59.  * standard colormap structure.
  60.  */
  61.    
  62. Status XmuCreateColormap(dpy, colormap)
  63.     Display        *dpy;        /* specifies the connection under 
  64.                      * which the map is created */
  65.     XStandardColormap    *colormap;    /* specifies the map to be created,
  66.                      * and returns, particularly if the
  67.                      * map is created as a subset of the
  68.                      * default colormap of the screen,
  69.                      * the base_pixel of the map.
  70.                      */
  71. {
  72.     XVisualInfo        vinfo_template;    /* template visual information */
  73.     XVisualInfo        *vinfo;        /* matching visual information */
  74.     XVisualInfo        *vpointer;    /* for freeing the entire list */
  75.     long        vinfo_mask;    /* specifies the visual mask value */
  76.     int         n;        /* number of matching visuals */
  77.     int            status;        
  78.  
  79.     vinfo_template.visualid = colormap->visualid;
  80.     vinfo_mask = VisualIDMask;
  81.     if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
  82.     return 0;
  83.  
  84.     /* A visual id may be valid on multiple screens.  Also, there may 
  85.      * be multiple visuals with identical visual ids at different depths.  
  86.      * If the colormap is the Default Colormap, use the Default Visual.
  87.      * Otherwise, arbitrarily, use the deepest visual.
  88.      */
  89.     vpointer = vinfo;
  90.     if (n > 1)
  91.     {
  92.     register int    i;
  93.     register int    screen_number;
  94.     Bool         def_cmap;
  95.  
  96.     def_cmap = False;
  97.     for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
  98.         if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
  99.         def_cmap = True;
  100.         break;
  101.         }
  102.  
  103.     if (def_cmap) {
  104.         for (i=0; i < n; i++, vinfo++) {
  105.         if (vinfo->visual == DefaultVisual(dpy, screen_number))
  106.             break;
  107.         }
  108.     } else {
  109.         unsigned int    maxdepth = 0;
  110.         XVisualInfo        *v;
  111.  
  112.         for (i=0; i < n; i++, vinfo++)
  113.         if (vinfo->depth > maxdepth) {
  114.             maxdepth = vinfo->depth;
  115.             v = vinfo;
  116.         }
  117.         vinfo = v;
  118.     }
  119.     }
  120.  
  121.     if (vinfo->class == PseudoColor || vinfo->class == DirectColor ||
  122.     vinfo->class == GrayScale)
  123.     status = readwrite_map(dpy, vinfo, colormap);
  124.     else 
  125.     status = readonly_map(dpy, vinfo, colormap);
  126.     
  127.     XFree((char *) vpointer);
  128.     return status;
  129. }
  130.  
  131. /****************************************************************************/
  132. static Status readwrite_map(dpy, vinfo, colormap)
  133.     Display        *dpy;
  134.     XVisualInfo        *vinfo;
  135.     XStandardColormap    *colormap;
  136. {
  137.     register int    i, n;        /* index counters */
  138.     int            ncolors;    /* number of colors to be defined */
  139.     int            npixels;    /* number of pixels allocated R/W */
  140.     int            first_index;    /* first index of pixels to use */
  141.     int            remainder;    /* first index of remainder */
  142.     XColor        color;        /* the definition of a color */
  143.     unsigned long    *pixels;    /* array of colormap pixels */
  144.  
  145.     
  146.     /* Determine ncolors, the number of colors to be defined.
  147.      * Insure that 1 < ncolors <= the colormap size.
  148.      */
  149.     ncolors = colormap->red_max * colormap->red_mult +
  150.           colormap->green_max * colormap->green_mult +
  151.           colormap->blue_max * colormap->blue_mult + 1;
  152.     if (ncolors <= 1 || ncolors > vinfo->colormap_size)    return 0;
  153.  
  154.     /* Allocate Read/Write as much of the colormap as we can possibly get.
  155.      * Then insure that the pixels we were allocated are given in 
  156.      * monotonically increasing order, using a quicksort.  Next, insure
  157.      * that our allocation includes a subset of contiguous pixels at least
  158.      * as long as the number of colors to be defined.  Now we know that 
  159.      * these conditions are met:
  160.      *    1) There are no free cells in the colormap.
  161.      *  2) We have a contiguous sequence of pixels, monotonically 
  162.      *     increasing, of length >= the number of colors requested.
  163.      *
  164.      * One cell at a time, we will free, compute the next color value, 
  165.      * then allocate read only.  This takes a long time.
  166.      * This is done to insure that cells are allocated read only in the
  167.      * contiguous order which we prefer.  If the server has a choice of
  168.      * cells to grant to an allocation request, the server may give us any
  169.      * cell, so that is why we do these slow gymnastics.
  170.      */
  171.  
  172.     if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
  173.                       sizeof(unsigned long))) == NULL)
  174.     return 0;
  175.  
  176.     if ((npixels = ROmap(dpy, colormap->colormap, pixels,
  177.                vinfo->colormap_size, ncolors)) == 0) {
  178.     free((char *) pixels);
  179.     return 0;
  180.     }
  181.  
  182.     qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
  183.  
  184.     if (! contiguous(pixels, npixels, ncolors, &first_index, &remainder))
  185.     {
  186.     /* can't find enough contiguous cells, give up */
  187.     XFreeColors(dpy, colormap->colormap, pixels, npixels,
  188.             (unsigned long) 0);
  189.     free((char *) pixels);
  190.     return 0;
  191.     }
  192.     colormap->base_pixel = pixels[first_index];
  193.  
  194.     /* construct a gray map */
  195.     if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
  196.     colormap->blue_mult == 1)
  197.     for (n=colormap->base_pixel, i=0; i < ncolors; i++, n++)
  198.     {
  199.         color.pixel = (unsigned long) n;
  200.         color.blue = color.green = color.red =
  201.         (unsigned short) ((i * 65535) / (colormap->red_max +
  202.                          colormap->green_max +
  203.                          colormap->blue_max));
  204.  
  205.         if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
  206.                  first_index + i, n))
  207.         return 0;
  208.     }
  209.  
  210.     /* construct a red ramp map */
  211.     else if (colormap->green_max == 0 && colormap->blue_max == 0)
  212.         for (n=colormap->base_pixel, i=0; i < ncolors; i++, n++)
  213.     {
  214.         color.pixel = (unsigned long) n;
  215.         color.red = (unsigned short) ((i * 65535) / colormap->red_max);
  216.         color.green = color.blue = 0;
  217.  
  218.         if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
  219.                  first_index + i, n))
  220.         return 0;
  221.     }
  222.  
  223.     /* construct a green ramp map */
  224.     else if (colormap->red_max == 0 && colormap->blue_max == 0)
  225.         for (n=colormap->base_pixel, i=0; i < ncolors; i++, n++)
  226.     {
  227.         color.pixel = (unsigned long) n;
  228.         color.green = (unsigned short) ((i * 65535) / colormap->green_max);
  229.         color.red = color.blue = 0;
  230.  
  231.         if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
  232.                  first_index + i, n))
  233.         return 0;
  234.     }
  235.  
  236.     /* construct a blue ramp map */
  237.     else if (colormap->red_max == 0 && colormap->green_max == 0)
  238.         for (n=colormap->base_pixel, i=0; i < ncolors; i++, n++)
  239.     {
  240.         color.pixel = (unsigned long) n;
  241.         color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
  242.         color.red = color.green = 0;
  243.  
  244.         if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
  245.                  first_index + i, n))
  246.         return 0;
  247.     }
  248.  
  249.     /* construct a standard red green blue cube map */
  250.     else
  251.     {
  252.     int r = colormap->red_mult;
  253.     int g = colormap->green_mult;
  254.     int gg = colormap->green_max + 1;
  255.  
  256.         for (n=colormap->base_pixel, i=0; i < ncolors; i++, n++)
  257.     {
  258.         color.pixel = (unsigned long) n;
  259.         color.red = (unsigned short) (((i/r) * 65535) / colormap->red_max);
  260.         color.green = (unsigned short) ((((i/g)%gg) * 65535) /
  261.                         colormap->green_max);
  262.         color.blue = (unsigned short) (((i%g) * 65535) /
  263.                        colormap->blue_max);
  264.         if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
  265.                  first_index + i, n))
  266.         return 0;
  267.     }
  268.     }
  269.     /* We have a read-only map defined.  Now free unused cells,
  270.      * first those occuring before the contiguous sequence begins,
  271.      * then any following the contiguous sequence.
  272.      */
  273.  
  274.     if (first_index)
  275.     XFreeColors(dpy, colormap->colormap, pixels, first_index, 
  276.             (unsigned long) 0);
  277.     if (remainder)
  278.     XFreeColors(dpy, colormap->colormap,
  279.             &(pixels[first_index + ncolors]), remainder,
  280.             (unsigned long) 0);
  281.  
  282.     free((char *) pixels);
  283.     return 1;
  284. }
  285.  
  286.  
  287. /****************************************************************************/
  288. static int ROmap(dpy, cmap, pixels, m, n)
  289.     Display        *dpy;        /* the X server connection */
  290.     Colormap        cmap;        /* specifies colormap ID */
  291.     unsigned long    pixels[];    /* returns pixel allocations */
  292.     int            m;        /* specifies colormap size */
  293.     int            n;        /* specifies number of colors */
  294. {
  295.     register int    p;
  296.  
  297.     /* first try to allocate the entire colormap */
  298.     if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, 
  299.              (unsigned) 0, pixels, (unsigned) m))
  300.     return m;
  301.  
  302.     /* Allocate all available cells in the colormap, using a binary
  303.      * algorithm to discover how many cells we can allocate in the colormap.
  304.      */
  305.     m--;
  306.     while (n <= m) {
  307.     p = n + ((m - n + 1) / 2);
  308.     if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
  309.                  (unsigned) 0, pixels, (unsigned) p)) {
  310.         if (p == m)
  311.         return p;
  312.         else {
  313.         XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
  314.         n = p;
  315.         }
  316.     }
  317.     else
  318.         m = p - 1;
  319.     }
  320.     return 0;
  321. }
  322.       
  323.  
  324. /****************************************************************************/
  325. static Status contiguous(pixels, npixels, ncolors, first, rem)
  326.     unsigned long    pixels[];    /* specifies allocated pixels */
  327.     int            npixels;    /* specifies count of alloc'd pixels */
  328.     int            ncolors;    /* specifies needed sequence length */
  329.     int            *first;        /* returns first index of sequence */
  330.     int            *rem;        /* returns first index after sequence,
  331.                      * or 0, if none follow */
  332. {
  333.     register int i = 1;        /* walking index into the pixel array */
  334.     register int count = 1;    /* length of sequence discovered so far */
  335.  
  336.     *rem = npixels - 1;
  337.     *first = 0;
  338.     while (count < ncolors && ncolors - count <= *rem)
  339.     {
  340.     if (pixels[i-1] + 1 == pixels[i])
  341.         count++;
  342.     else {
  343.         count = 1;
  344.         *first = i;
  345.     }
  346.     i++;
  347.     (*rem)--;
  348.     }
  349.     if (count != ncolors)
  350.     return 0;
  351.     return 1;
  352. }
  353.  
  354.  
  355. /****************************************************************************/
  356. static Status ROorRWcell(dpy, cmap, pixels, npixels, color, p, n)
  357.     Display        *dpy;
  358.     Colormap        cmap;
  359.     unsigned long    pixels[];
  360.     int            npixels;
  361.     XColor        *color;
  362.     int            p;
  363.     int            n;
  364. {
  365.     unsigned long    pixel;
  366.     XColor        request;
  367.  
  368.     /* Free the read/write allocation of one cell in the colormap.
  369.      * Request a read only allocation of one cell in the colormap.
  370.      * If the read only allocation cannot be granted, give up, because
  371.      * there must be no free cells in the colormap.
  372.      * If the read only allocation is granted, but gives us a cell which
  373.      * is not the one that we just freed, it is probably the case that
  374.      * we are trying allocate White or Black or some other color which
  375.      * already has a read-only allocation in the map.  So we try to 
  376.      * allocate the previously freed cell with a read/write allocation,
  377.      * because we want contiguous cells for image processing algorithms.
  378.      */
  379.      
  380.     pixel = (unsigned long) n;
  381.     request.red = color->red;
  382.     request.green = color->green;
  383.     request.blue = color->blue;
  384.  
  385.     XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
  386.     if (! XAllocColor(dpy, cmap, color) 
  387.     || (color->pixel != pixel &&
  388.         (!RWcell(dpy, cmap, color, &request, &pixel, n)))) 
  389.     {
  390.     free_cells(dpy, cmap, pixels, npixels, p);
  391.     return 0;
  392.     }
  393.     return 1;
  394. }
  395.  
  396.  
  397. /****************************************************************************/
  398. static void free_cells(dpy, cmap, pixels, npixels,  p)
  399.     Display        *dpy;
  400.     Colormap        cmap;
  401.     unsigned long    pixels[];    /* to be freed */
  402.     int            npixels;        /* original number allocated */
  403.     int            p;      
  404. {
  405.     /* One of the npixels allocated has already been freed.
  406.      * p is the index of the freed pixel.
  407.      * First free the pixels preceeding p, and there are p of them;
  408.      * then free the pixels following p, there are npixels - p - 1 of them.
  409.      */
  410.     XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
  411.     XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
  412.     free((char *) pixels);
  413. }
  414.  
  415.  
  416. /****************************************************************************/
  417. static Status RWcell(dpy, cmap, color, request, pixel, n)
  418.     Display        *dpy;
  419.     Colormap        cmap;
  420.     XColor        *color;
  421.     XColor        *request;
  422.     unsigned long    *pixel;
  423.     int            n;
  424. {
  425.     XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
  426.     if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
  427.                (unsigned) 0, pixel, (unsigned) 1))
  428.     return 0;
  429.     if (*pixel != n)
  430.     {
  431.     XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
  432.     return 0;
  433.     }
  434.     color->pixel = *pixel;
  435.     color->flags = DoRed | DoGreen | DoBlue;
  436.     color->red = request->red;
  437.     color->green = request->green;
  438.     color->blue = request->blue;
  439.     XStoreColors(dpy, cmap, color, 1);
  440.     return 1;
  441. }
  442.  
  443.  
  444. /****************************************************************************/
  445. static int compare(e1, e2)
  446.     unsigned long    *e1, *e2;
  447. {
  448.     if (*e1 < *e2)    return -1;
  449.     if (*e1 > *e2)    return 1;
  450.     return 0;
  451. }
  452.  
  453.  
  454. /****************************************************************************/
  455. static Status readonly_map(dpy, vinfo, colormap)
  456.     Display        *dpy;
  457.     XVisualInfo        *vinfo;
  458.     XStandardColormap    *colormap;
  459. {
  460.     int            i, last_pixel;
  461.     XColor        color;
  462.  
  463.     last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) * 
  464.     (colormap->blue_max + 1) + colormap->base_pixel - 1;
  465.  
  466.     for(i=colormap->base_pixel; i <= last_pixel; i++) {
  467.  
  468.     color.pixel = (unsigned long) i;
  469.     color.red = (unsigned short)
  470.         (((i/colormap->red_mult) * 65535) / colormap->red_max);
  471.  
  472.     if (vinfo->class == StaticColor || vinfo->class == TrueColor) {
  473.         color.green = (unsigned short)
  474.         ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
  475.           65535) / colormap->green_max);
  476.         color.blue = (unsigned short)
  477.         (((i%colormap->green_mult) * 65535) / colormap->blue_max);
  478.     }
  479.     else    /* vinfo->class == GrayScale, old style allocation XXX */
  480.         color.green = color.blue = color.red;
  481.  
  482.     XAllocColor(dpy, colormap->colormap, &color);
  483.     if (color.pixel != (unsigned long) i)
  484.         return 0;
  485.     }
  486.     return 1;
  487. }
  488.