]> git.eshelyaron.com Git - emacs.git/commitdiff
(defined_color): If colormap is full, find closest match.
authorRichard M. Stallman <rms@gnu.org>
Mon, 6 Mar 1995 04:33:56 +0000 (04:33 +0000)
committerRichard M. Stallman <rms@gnu.org>
Mon, 6 Mar 1995 04:33:56 +0000 (04:33 +0000)
src/xfns.c

index c62bdd4a090f56725f71b9d2e96a6850bae4def4..7a5e4ff9d717ae353f05f655a035f79f3ee10459 100644 (file)
@@ -963,6 +963,7 @@ x_report_frame_params (f, alistptr)
                   : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
 }
 \f
+
 /* Decide if color named COLOR is valid for the display associated with
    the selected frame; if so, return the rgb values in COLOR_DEF.
    If ALLOC is nonzero, allocate a new colormap cell.  */
@@ -974,20 +975,72 @@ defined_color (f, color, color_def, alloc)
      XColor *color_def;
      int alloc;
 {
-  register int foo;
+  register int status;
   Colormap screen_colormap;
+  Display *display = FRAME_X_DISPLAY (f);
 
   BLOCK_INPUT;
-  screen_colormap
-    = DefaultColormap (FRAME_X_DISPLAY (f),
-                      XDefaultScreen (FRAME_X_DISPLAY (f)));
+  screen_colormap = DefaultColormap (display, XDefaultScreen (display));
 
-  foo = XParseColor (FRAME_X_DISPLAY (f), screen_colormap, color, color_def);
-  if (foo && alloc)
-    foo = XAllocColor (FRAME_X_DISPLAY (f), screen_colormap, color_def);
+  status = XParseColor (display, screen_colormap, color, color_def);
+  if (status && alloc) 
+    {
+      status = XAllocColor (display, screen_colormap, color_def);
+      if (!status)
+       {
+         /* If we got to this point, the colormap is full, so we're 
+            going to try and get the next closest color.
+            The algorithm used is a least-squares matching, which is
+            what X uses for closest color matching with StaticColor visuals.  */
+
+         XColor *cells;
+         int no_cells;
+         int nearest;
+         long nearest_delta, trial_delta;
+         int x;
+
+         no_cells = XDisplayCells (display, XDefaultScreen (display));
+         cells = (XColor *) alloca (sizeof (XColor) * no_cells);
+
+         for (x = 0; x < no_cells; x++) 
+           cells[x].pixel = x;
+
+         XQueryColors (display, screen_colormap, cells, no_cells);
+         nearest = 0;
+         /* I'm assuming CSE so I'm not going to condense this. */
+         nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
+                           * ((color_def->red >> 8) - (cells[0].red >> 8)))
+                          +
+                          (((color_def->green >> 8) - (cells[0].green >> 8))
+                           * ((color_def->green >> 8) - (cells[0].green >> 8)))
+                          +
+                          (((color_def->blue >> 8) - (cells[0].blue >> 8))
+                           * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
+         for (x = 1; x < no_cells; x++) 
+           {
+             trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
+                             * ((color_def->red >> 8) - (cells[x].red >> 8)))
+                            +
+                            (((color_def->green >> 8) - (cells[x].green >> 8))
+                             * ((color_def->green >> 8) - (cells[x].green >> 8))) +
+                            +
+                            (((color_def->blue >> 8) - (cells[x].blue >> 8))
+                             * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
+             if (trial_delta < nearest_delta) 
+               {
+                 nearest = x;
+                 nearest_delta = trial_delta;
+               }
+           }
+         color_def->red = cells[nearest].red;
+         color_def->green = cells[nearest].green;
+         color_def->blue = cells[nearest].blue;
+         status = XAllocColor (display, screen_colormap, color_def);
+       }
+    }
   UNBLOCK_INPUT;
 
-  if (foo)
+  if (status)
     return 1;
   else
     return 0;