summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/image.c14
-rw-r--r--src/xfaces.c9
-rw-r--r--src/xftfont.c3
-rw-r--r--src/xterm.c77
-rw-r--r--src/xterm.h27
5 files changed, 104 insertions, 26 deletions
diff --git a/src/image.c b/src/image.c
index 79bf21e8865..401689e940a 100644
--- a/src/image.c
+++ b/src/image.c
@@ -4442,15 +4442,7 @@ lookup_rgb_color (struct frame *f, int r, int g, int b)
r = color.red, g = color.green, b = color.blue;
}
- /* Scale down RGB values to the visual's bits per RGB, and shift
- them to the right position in the pixel color. Note that the
- original RGB values are 16-bit values, as usual in X. */
- pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
- pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
- pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
-
- /* Assemble the pixel color. */
- return pr | pg | pb;
+ return x_make_truecolor_pixel (dpyinfo, r, g, b);
}
for (p = ct_table[i]; p; p = p->next)
@@ -9542,7 +9534,6 @@ void
x_kill_gs_process (Pixmap pixmap, struct frame *f)
{
struct image_cache *c = FRAME_IMAGE_CACHE (f);
- int class;
ptrdiff_t i;
struct image *img;
@@ -9568,8 +9559,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
/* On displays with a mutable colormap, figure out the colors
allocated for the image by looking at the pixels of an XImage for
img->pixmap. */
- class = FRAME_X_VISUAL (f)->class;
- if (class != StaticColor && class != StaticGray && class != TrueColor)
+ if (x_mutable_colormap (FRAME_X_VISUAL (f)))
{
XImagePtr ximg;
diff --git a/src/xfaces.c b/src/xfaces.c
index 8cf0b427799..a3d122fbf46 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -454,11 +454,9 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
void
x_free_colors (struct frame *f, unsigned long *pixels, int npixels)
{
- int class = FRAME_DISPLAY_INFO (f)->visual->class;
-
/* If display has an immutable color map, freeing colors is not
necessary and some servers don't allow it. So don't do it. */
- if (class != StaticColor && class != StaticGray && class != TrueColor)
+ if (x_mutable_colormap (FRAME_X_VISUAL (f)))
{
#ifdef DEBUG_X_COLORS
unregister_colors (pixels, npixels);
@@ -471,7 +469,7 @@ x_free_colors (struct frame *f, unsigned long *pixels, int npixels)
#ifdef USE_X_TOOLKIT
-/* Free colors used on frame F. PIXELS is an array of NPIXELS pixel
+/* Free colors used on display DPY. PIXELS is an array of NPIXELS pixel
color values. Interrupt input must be blocked when this function
is called. */
@@ -480,11 +478,10 @@ x_free_dpy_colors (Display *dpy, Screen *screen, Colormap cmap,
unsigned long *pixels, int npixels)
{
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
- int class = dpyinfo->visual->class;
/* If display has an immutable color map, freeing colors is not
necessary and some servers don't allow it. So don't do it. */
- if (class != StaticColor && class != StaticGray && class != TrueColor)
+ if (x_mutable_colormap (dpyinfo->visual))
{
#ifdef DEBUG_X_COLORS
unregister_colors (pixels, npixels);
diff --git a/src/xftfont.c b/src/xftfont.c
index a1846e8d461..851edb69fa0 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -111,8 +111,7 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc,
colors[0].pixel = fg->pixel = xgcv.foreground;
if (bg)
colors[1].pixel = bg->pixel = xgcv.background;
- XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
- bg ? 2 : 1);
+ x_query_colors (f, colors, bg ? 2 : 1);
fg->color.alpha = 0xFFFF;
fg->color.red = colors[0].red;
fg->color.green = colors[0].green;
diff --git a/src/xterm.c b/src/xterm.c
index 6065f964063..8be893eca6f 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -2197,6 +2197,50 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ if (dpyinfo->red_bits > 0)
+ {
+ /* For TrueColor displays, we can decompose the RGB value
+ directly. */
+ int i;
+ unsigned int rmult, gmult, bmult;
+ unsigned int rmask, gmask, bmask;
+
+ rmask = (1 << dpyinfo->red_bits) - 1;
+ gmask = (1 << dpyinfo->green_bits) - 1;
+ bmask = (1 << dpyinfo->blue_bits) - 1;
+ /* If we're widening, for example, 8 bits in the pixel value to
+ 16 bits for the separate-color representation, we want to
+ extrapolate the lower bits based on those bits available --
+ in other words, we'd like 0xff to become 0xffff instead of
+ the 0xff00 we'd get by just zero-filling the lower bits.
+
+ We generate a 32-bit scaled-up value and shift it, in case
+ the bit count doesn't divide 16 evently (e.g., when dealing
+ with a 3-3-2 bit RGB display), to get more of the lower bits
+ correct.
+
+ Should we cache the multipliers in dpyinfo? Maybe
+ special-case the 8-8-8 common case? */
+ rmult = 0xffffffff / rmask;
+ gmult = 0xffffffff / gmask;
+ bmult = 0xffffffff / bmask;
+
+ for (i = 0; i < ncolors; ++i)
+ {
+ unsigned int r, g, b;
+ unsigned long pixel = colors[i].pixel;
+
+ r = (pixel >> dpyinfo->red_offset) & rmask;
+ g = (pixel >> dpyinfo->green_offset) & gmask;
+ b = (pixel >> dpyinfo->blue_offset) & bmask;
+
+ colors[i].red = (r * rmult) >> 16;
+ colors[i].green = (g * gmult) >> 16;
+ colors[i].blue = (b * bmult) >> 16;
+ }
+ return;
+ }
+
if (dpyinfo->color_cells)
{
int i;
@@ -2207,9 +2251,10 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors)
eassert (dpyinfo->color_cells[pixel].pixel == pixel);
colors[i] = dpyinfo->color_cells[pixel];
}
+ return;
}
- else
- XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
+
+ XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
}
@@ -2341,15 +2386,27 @@ x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
}
-/* Allocate the color COLOR->pixel on frame F, 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
- allocated. */
+/* Allocate the color COLOR->pixel on frame F, colormap CMAP, after
+ gamma correction. If an exact match can't be allocated, try the
+ nearest color available. Value is true if successful. Set *COLOR
+ to the color allocated. */
bool
x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
{
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+
gamma_correct (f, color);
+
+ if (dpyinfo->red_bits > 0)
+ {
+ color->pixel = x_make_truecolor_pixel (dpyinfo,
+ color->red,
+ color->green,
+ color->blue);
+ return true;
+ }
+
return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
}
@@ -2363,8 +2420,16 @@ x_copy_color (struct frame *f, unsigned long pixel)
{
XColor color;
+ /* If display has an immutable color map, freeing colors is not
+ necessary and some servers don't allow it. Since we won't free a
+ color once we've allocated it, we don't need to re-allocate it to
+ maintain the server's reference count. */
+ if (!x_mutable_colormap (FRAME_X_VISUAL (f)))
+ return pixel;
+
color.pixel = pixel;
block_input ();
+ /* The color could still be found in the color_cells array. */
x_query_color (f, &color);
XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
unblock_input ();
diff --git a/src/xterm.h b/src/xterm.h
index 300a8b769f2..d8edbc208f4 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1085,6 +1085,33 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time t)
dpyinfo->last_user_time = t;
}
+INLINE unsigned long
+x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b)
+{
+ unsigned long pr, pg, pb;
+
+ /* Scale down RGB values to the visual's bits per RGB, and shift
+ them to the right position in the pixel color. Note that the
+ original RGB values are 16-bit values, as usual in X. */
+ pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
+ pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
+ pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
+
+ /* Assemble the pixel color. */
+ return pr | pg | pb;
+}
+
+/* If display has an immutable color map, freeing colors is not
+ necessary and some servers don't allow it, so we won't do it. That
+ also allows us to make other optimizations relating to server-side
+ reference counts. */
+INLINE bool
+x_mutable_colormap (Visual *visual)
+{
+ int class = visual->class;
+ return (class != StaticColor && class != StaticGray && class != TrueColor);
+}
+
extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object);
extern bool x_wm_supports (struct frame *, Atom);
extern void x_wait_for_event (struct frame *, int);