home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xjig / color_mapper.c < prev    next >
C/C++ Source or Header  |  1996-03-25  |  3KB  |  155 lines

  1.  
  2. #include <X11/Xlib.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6. #ifndef __color_mapper_h
  7. #    include "color_mapper.H"
  8. #endif
  9.  
  10. ColorMapper::ColorMapper(Display *dpy_in)
  11. : dpy(dpy_in)
  12. {
  13. Screen    *screen = DefaultScreenOfDisplay(dpy);
  14.  
  15.     mymap=DefaultColormapOfScreen(screen);
  16.     cells=0;
  17.     colors=0;
  18.     if (DefaultVisualOfScreen(screen)->c_class!=PseudoColor)        return;
  19.  
  20.     cells=CellsOfScreen(screen);
  21.     colors      = new XColor[cells];
  22.     setup_usage();
  23. }
  24.  
  25. ColorMapper::~ColorMapper() {
  26.     free_usage();
  27.     if (colors)            delete [] colors;
  28. }
  29.  
  30. void ColorMapper::free_usage() {
  31. int i;
  32.  
  33.     for (i=0;i<cells;i++) {
  34.         if (colors[i].flags) {
  35.            XFreeColors(dpy,mymap,&colors[i].pixel,1,0L);
  36.        }
  37.     }
  38. }
  39.  
  40. void ColorMapper::setup_usage() {
  41. int i;
  42. unsigned long    *help;
  43.  
  44.     for (i=0;i<cells;i++)    colors[i].pixel = i;
  45.     XQueryColors(dpy,mymap,colors,cells);
  46.     for (i=0;i<cells;i++)    colors[i].flags = DoRed | DoGreen | DoBlue;
  47.  
  48.     help = new unsigned long[cells];
  49. /*
  50.  * allocate unused cells of the colormap for read/write
  51.  */
  52.    i = 0;
  53.    while(XAllocColorCells( dpy, mymap, False, 0L, 0, &help[i], 1 )) {
  54.        colors[help[i]].flags = 0;        // mark unusable for shared color
  55.        i++;
  56.    }
  57.  
  58. /*
  59.  * free the pixels again
  60.  */
  61.    XFreeColors(dpy,mymap,help,i,0L);
  62.    delete [] help;
  63.    XSync( dpy, 0 );
  64.  
  65.    for (i=0;i<cells;i++) {
  66.        if (colors[i].flags) {        // still not invalidated
  67.        // all shareable colors are again allocated !!
  68.            if (XAllocColor(dpy,mymap,&colors[i])) {
  69.                if ((unsigned)i!=colors[i].pixel) {
  70.                    XFreeColors(dpy,mymap,&colors[i].pixel,1,0L);
  71.                    colors[i].flags=0;        // different pixel -> not usefull
  72.                }
  73.            }
  74.            else {
  75.                    colors[i].flags=0;        // not allocatable -> not usefull
  76.            }
  77.        }
  78.    }
  79.    return;
  80. }
  81.  
  82. unsigned long ColorMapper::alloc_color(XColor *def) {
  83. int    i;
  84. long    min_dist;
  85. int    min_i;
  86.  
  87.     if (!colors) {
  88.         def->flags=DoRed | DoGreen | DoBlue;
  89.         if (!XAllocColor(dpy,mymap,def)) {
  90.             fprintf( stderr, "\n*** failed to allocated color on '%s'\n\n", DisplayString(dpy) );
  91.             exit(0);
  92.         }
  93.         return def->pixel;
  94.     }
  95.  
  96.     min_i=-1;
  97.     min_dist=0;
  98.     for (i=0;i<cells;i++) {
  99.         if (colors[i].flags) {
  100.             long rd = ((long)colors[i].red   - (long)def->red)/4;
  101.             long gd = ((long)colors[i].green - (long)def->green)/4;
  102.             long bd = ((long)colors[i].blue  - (long)def->blue)/4;
  103.             long dist=rd*rd+gd*gd+bd*bd;
  104.  
  105.             if (min_i<0 || dist<min_dist) {
  106.                 min_dist = dist;
  107.                 min_i    = i;
  108.             }
  109.         }
  110.     }
  111.  
  112. // reuse already allocated color, when possible
  113.     if (min_i>=0 && min_dist<10000) {
  114.         return colors[min_i].pixel;
  115.     }
  116.  
  117. // allocate additional entry for that pixel
  118.     def->flags=DoRed | DoGreen | DoBlue;
  119.     if (XAllocColor(dpy,mymap,def)) {
  120.         colors[def->pixel] = *def;
  121.         return def->pixel;
  122.     }
  123.  
  124. // allocate the closest entry
  125.     if (min_i>=0) {
  126.         return colors[min_i].pixel;
  127.     }
  128.  
  129. // everything else failed ...
  130.     fprintf( stderr, "can't handle colormap overflow ...\n" );
  131.     exit(0);
  132.     return 0;
  133. }
  134.  
  135. unsigned long ColorMapper::alloc_named_color( const char *name ) {
  136. XColor   def;
  137.     if (!XLookupColor(dpy,mymap,name,&def,&def )) {
  138.         fprintf( stderr, "\n*** failed to query color '%s'\n\n", name );
  139.         exit(0);
  140.     }
  141.     def.flags = DoRed | DoGreen | DoBlue;
  142.     return alloc_color(&def);
  143. }
  144.  
  145. // ============================================================================
  146.  
  147. Port::Port(Display *dpy_in) {
  148.     dpy = dpy_in;
  149.     mapper = new ColorMapper(dpy);
  150. }
  151.  
  152. Port::~Port() {
  153.     delete mapper;
  154. }
  155.