(unsigned) (col.red * 65535),
(unsigned) (col.green * 65535),
(unsigned) (col.blue * 65535));
- success_p = (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- buf, color)
- != 0);
+ success_p = x_parse_color (f, buf, color) != 0;
#else
GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
GdkColor *grgb = get_bg
XColor xbgcolor;
Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL);
- if (STRINGP (bg) && XParseColor (FRAME_X_DISPLAY (f),
- FRAME_X_COLORMAP (f),
- SSDATA (bg),
- &xbgcolor))
+ if (STRINGP (bg) && x_parse_color (f, SSDATA (bg), &xbgcolor))
bgcolor = xcolor_to_argb32 (xbgcolor);
return bgcolor;
/* An entry in a hash table used to cache color definitions of named
colors. This cache is necessary to speed up XPM image loading in
case we do color allocations ourselves. Without it, we would need
- a call to XParseColor per pixel in the image. */
+ a call to XParseColor per pixel in the image.
+
+ FIXME Now that we're using x_parse_color and its cache, reevaluate
+ the need for this caching layer. */
struct xpm_cached_color
{
XColor color;
for (i = 0; i < attrs->numsymbols; ++i)
- if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- attrs->colorsymbols[i].value, &color))
+ if (x_parse_color (f, attrs->colorsymbols[i].value, &color))
{
color.pixel = lookup_rgb_color (f, color.red, color.green,
color.blue);
if (p != NULL)
*color = p->color;
- else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- color_name, color))
+ else if (x_parse_color (f, color_name, color))
{
color->pixel = lookup_rgb_color (f, color->red, color->green,
color->blue);
success_p = xg_check_special_colors (f, color_name, color);
#endif
if (!success_p)
- success_p = XParseColor (dpy, cmap, color_name, color) != 0;
+ success_p = x_parse_color (f, color_name, color) != 0;
if (success_p && alloc_p)
success_p = x_alloc_nearest_color (f, cmap, color);
unblock_input ();
}
+/* On frame F, translate the color name to RGB values. Use cached
+ information, if possible.
+
+ Note that there is currently no way to clean old entries out of the
+ cache. However, it is limited to names in the server's database,
+ and names we've actually looked up; list-colors-display is probably
+ the most color-intensive case we're likely to hit. */
+
+Status x_parse_color (struct frame *f, const char *color_name,
+ XColor *color)
+{
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Colormap cmap = FRAME_X_COLORMAP (f);
+ Status status;
+ struct color_name_cache_entry *cache_entry;
+
+ if (color_name[0] == '#')
+ {
+ /* The hex form is parsed directly by XParseColor without
+ talking to the X server. No need for caching. */
+ return XParseColor (dpy, cmap, color_name, color);
+ }
+
+ for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names; cache_entry;
+ cache_entry = cache_entry->next)
+ {
+ if (!xstrcasecmp(cache_entry->name, color_name))
+ {
+ *color = cache_entry->rgb;
+ return 1;
+ }
+ }
+
+ if (XParseColor (dpy, cmap, color_name, color) == 0)
+ /* No caching of negative results, currently. */
+ return 0;
+
+ cache_entry = xzalloc (sizeof *cache_entry);
+ cache_entry->rgb = *color;
+ cache_entry->name = xstrdup (color_name);
+ cache_entry->next = FRAME_DISPLAY_INFO (f)->color_names;
+ FRAME_DISPLAY_INFO (f)->color_names = cache_entry;
+ return 1;
+}
+
+
/* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
exact match can't be allocated, try the nearest color available.
Value is true if successful. Set *COLOR to the color
x_delete_display (struct x_display_info *dpyinfo)
{
struct terminal *t;
+ struct color_name_cache_entry *color_entry, *next_color_entry;
/* Close all frames and delete the generic struct terminal for this
X display. */
tail->next = tail->next->next;
}
+ for (color_entry = dpyinfo->color_names;
+ color_entry;
+ color_entry = next_color_entry)
+ {
+ next_color_entry = color_entry->next;
+ xfree (color_entry->name);
+ xfree (color_entry);
+ }
+
xfree (dpyinfo->x_id_name);
xfree (dpyinfo->x_dnd_atoms);
xfree (dpyinfo->color_cells);
};
#endif
+\f
+struct color_name_cache_entry
+{
+ struct color_name_cache_entry *next;
+ XColor rgb;
+ char *name;
+};
+
+Status x_parse_color (struct frame *f, const char *color_name,
+ XColor *color);
+
\f
/* For each X display, we have a structure that records
information about it. */
struct xim_inst_t *xim_callback_data;
#endif
+ /* A cache mapping color names to RGB values. */
+ struct color_name_cache_entry *color_names;
+
/* If non-null, a cache of the colors in the color map. Don't
use this directly, call x_color_cells instead. */
XColor *color_cells;