home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xmu / CrCmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  16.8 KB  |  514 lines

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