comparison src/objects-x.c @ 219:262b8bb4a523 r20-4b8

Import from CVS: tag r20-4b8
author cvs
date Mon, 13 Aug 2007 10:09:35 +0200
parents 3d6bfa290dbd
children b2472a1930f2
comparison
equal deleted inserted replaced
218:c9f226976f56 219:262b8bb4a523
42 /************************************************************************/ 42 /************************************************************************/
43 /* color instances */ 43 /* color instances */
44 /************************************************************************/ 44 /************************************************************************/
45 45
46 /* Replacement for XAllocColor() that tries to return the nearest 46 /* Replacement for XAllocColor() that tries to return the nearest
47 available color if the colormap is full. From FSF Emacs. */ 47 available color if the colormap is full. Original was from FSFmacs,
48 48 but rewritten by Jareth Hein <jareth@camelot-soft.com> 97/11/25 */
49
50 /* Return value is 1 for normal success, 2 for nearest color success,
51 3 for Non-deallocable sucess, and 0 for absolute failure (shouldn't
52 happen?) */
49 int 53 int
50 allocate_nearest_color (Display *display, Colormap screen_colormap, 54 allocate_nearest_color (Display *display, Colormap colormap, Visual *visual,
51 XColor *color_def) 55 XColor *color_def)
52 { 56 {
53 int status; 57 int status;
54 58
55 status = XAllocColor (display, screen_colormap, color_def); 59 if (visual->class == DirectColor || visual->class == TrueColor)
56 if (!status) 60 {
57 { 61 if (XAllocColor (display, colormap, color_def) != 0)
58 /* If we got to this point, the colormap is full, so we're
59 going to try and get the next closest color.
60 The algorithm used is a least-squares matching, which is
61 what X uses for closest color matching with StaticColor visuals. */
62
63 XColor *cells;
64 int no_cells;
65 int nearest;
66 long nearest_delta, trial_delta;
67 int x;
68
69 no_cells = XDisplayCells (display, XDefaultScreen (display));
70 cells = alloca_array (XColor, no_cells);
71
72 for (x = 0; x < no_cells; x++)
73 cells[x].pixel = x;
74
75 XQueryColors (display, screen_colormap, cells, no_cells);
76 nearest = 0;
77 /* I'm assuming CSE so I'm not going to condense this. */
78 nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
79 * ((color_def->red >> 8) - (cells[0].red >> 8)))
80 +
81 (((color_def->green >> 8) - (cells[0].green >> 8))
82 * ((color_def->green >> 8) - (cells[0].green >> 8)))
83 +
84 (((color_def->blue >> 8) - (cells[0].blue >> 8))
85 * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
86 for (x = 1; x < no_cells; x++)
87 { 62 {
88 trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8)) 63 status = 1;
89 * ((color_def->red >> 8) - (cells[x].red >> 8))) 64 }
90 + 65 else
91 (((color_def->green >> 8) - (cells[x].green >> 8)) 66 {
92 * ((color_def->green >> 8) - (cells[x].green >> 8))) 67 /* We're dealing with a TrueColor/DirectColor visual, so play games
93 + 68 with the RGB values in the XColor struct. */
94 (((color_def->blue >> 8) - (cells[x].blue >> 8)) 69 /* ### JH: I'm not sure how a call to XAllocColor can fail in a
95 * ((color_def->blue >> 8) - (cells[x].blue >> 8)))); 70 TrueColor or DirectColor visual, so I will just reformat the
96 if (trial_delta < nearest_delta) 71 request to match the requirements of the visual, and re-issue
97 { 72 the request. If this fails for anybody, I wanna know about it
98 nearest = x; 73 so I can come up with a better plan */
99 nearest_delta = trial_delta; 74
75 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
76 junk = visual->red_mask;
77 rshift = 0;
78 while ((junk & 0x1) == 0) {
79 junk = junk >> 1;
80 rshift ++;
81 }
82 rbits = 0;
83 while (junk != 0) {
84 junk = junk >> 1;
85 rbits++;
86 }
87 junk = visual->green_mask;
88 gshift = 0;
89 while ((junk & 0x1) == 0) {
90 junk = junk >> 1;
91 gshift ++;
92 }
93 gbits = 0;
94 while (junk != 0) {
95 junk = junk >> 1;
96 gbits++;
97 }
98 junk = visual->blue_mask;
99 bshift = 0;
100 while ((junk & 0x1) == 0) {
101 junk = junk >> 1;
102 bshift ++;
103 }
104 bbits = 0;
105 while (junk != 0) {
106 junk = junk >> 1;
107 bbits++;
108 }
109
110 color_def->red = color_def->red >> (16 - rbits);
111 color_def->green = color_def->green >> (16 - gbits);
112 color_def->blue = color_def->blue >> (16 - bbits);
113 if (XAllocColor (display, colormap, color_def) != 0)
114 status = 1;
115 else
116 {
117 /* ### JH: I'm punting here, knowing that doing this will at
118 least draw the color correctly. However, unless we convert
119 all of the functions that allocate colors (graphics
120 libraries, etc) to use this function doing this is very
121 likely to cause problems later... */
122 color_def->pixel = (color_def->red << rshift) | (color_def->green << gshift) |
123 (color_def->blue << bshift);
124 status = 3;
100 } 125 }
101 } 126 }
102 color_def->red = cells[nearest].red; 127 }
103 color_def->green = cells[nearest].green; 128 else
104 color_def->blue = cells[nearest].blue; 129 {
105 status = XAllocColor (display, screen_colormap, color_def); 130 if (XAllocColor (display, colormap, color_def) != 0)
106 } 131 status = 1;
107 132 else
133 {
134 /* If we got to this point, the colormap is full, so we're
135 going to try and get the next closest color. The algorithm used
136 is a least-squares matching, which is what X uses for closest
137 color matching with StaticColor visuals. */
138 XColor *cells;
139 /* JH: I can't believe there's no way to go backwards from a
140 colormap ID and get its visual and number of entries, but X
141 apparently isn't built that way... */
142 int no_cells = visual->map_entries;
143 int nearest;
144 long nearest_delta, trial_delta;
145 int x;
146
147 cells = alloca_array (XColor, no_cells);
148
149 for (x = 0; x < no_cells; x++)
150 cells[x].pixel = x;
151
152 /* read the current colormap */
153 XQueryColors (display, colormap, cells, no_cells);
154 nearest = 0;
155 /* I'm assuming CSE so I'm not going to condense this. */
156 nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
157 * ((color_def->red >> 8) - (cells[0].red >> 8)))
158 +
159 (((color_def->green >> 8) - (cells[0].green >> 8))
160 * ((color_def->green >> 8) - (cells[0].green >> 8)))
161 +
162 (((color_def->blue >> 8) - (cells[0].blue >> 8))
163 * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
164 for (x = 1; x < no_cells; x++)
165 {
166 trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
167 * ((color_def->red >> 8) - (cells[x].red >> 8)))
168 +
169 (((color_def->green >> 8) - (cells[x].green >> 8))
170 * ((color_def->green >> 8) - (cells[x].green >> 8)))
171 +
172 (((color_def->blue >> 8) - (cells[x].blue >> 8))
173 * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
174 if (trial_delta < nearest_delta)
175 {
176 nearest = x;
177 nearest_delta = trial_delta;
178 }
179 }
180 color_def->red = cells[nearest].red;
181 color_def->green = cells[nearest].green;
182 color_def->blue = cells[nearest].blue;
183 if (XAllocColor (display, colormap, color_def) != 0)
184 status = 2;
185 else
186 status = 0; /* JH: how does this happen??? DOES this happen??? */
187 }
188 }
108 return status; 189 return status;
109 } 190 }
110 191
111 int 192 int
112 x_parse_nearest_color (struct device *d, XColor *color, Bufbyte *name, 193 x_parse_nearest_color (struct device *d, XColor *color, Bufbyte *name,
113 Bytecount len, Error_behavior errb) 194 Bytecount len, Error_behavior errb)
114 { 195 {
115 Display *dpy; 196 Display *dpy;
116 Screen *xs; 197 Screen *xs;
117 Colormap cmap; 198 Colormap cmap;
199 Visual *visual;
118 int result; 200 int result;
119 201
120 dpy = DEVICE_X_DISPLAY (d); 202 dpy = DEVICE_X_DISPLAY (d);
121 xs = DefaultScreenOfDisplay (dpy); 203 xs = DefaultScreenOfDisplay (dpy);
122 cmap = DefaultColormapOfScreen (xs); 204 cmap = DEVICE_X_COLORMAP(d);
205 visual = DEVICE_X_VISUAL (d);
123 206
124 memset (color, 0, sizeof (*color)); 207 memset (color, 0, sizeof (*color));
125 { 208 {
126 CONST Extbyte *extname; 209 CONST Extbyte *extname;
127 Extcount extnamelen; 210 Extcount extnamelen;
133 { 216 {
134 maybe_signal_simple_error ("unrecognized color", make_string (name, len), 217 maybe_signal_simple_error ("unrecognized color", make_string (name, len),
135 Qcolor, errb); 218 Qcolor, errb);
136 return 0; 219 return 0;
137 } 220 }
138 result = allocate_nearest_color (dpy, cmap, color); 221 result = allocate_nearest_color (dpy, cmap, visual, color);
139 if (!result) 222 if (!result)
140 { 223 {
141 maybe_signal_simple_error ("couldn't allocate color", 224 maybe_signal_simple_error ("couldn't allocate color",
142 make_string (name, len), Qcolor, errb); 225 make_string (name, len), Qcolor, errb);
143 return 0; 226 return 0;
144 } 227 }
145 228
146 return 1; 229 return result;
147 } 230 }
148 231
149 static int 232 static int
150 x_initialize_color_instance (struct Lisp_Color_Instance *c, Lisp_Object name, 233 x_initialize_color_instance (struct Lisp_Color_Instance *c, Lisp_Object name,
151 Lisp_Object device, Error_behavior errb) 234 Lisp_Object device, Error_behavior errb)
162 return 0; 245 return 0;
163 246
164 /* Don't allocate the data until we're sure that we will succeed, 247 /* Don't allocate the data until we're sure that we will succeed,
165 or the finalize method may get fucked. */ 248 or the finalize method may get fucked. */
166 c->data = xnew (struct x_color_instance_data); 249 c->data = xnew (struct x_color_instance_data);
250 if (result == 3)
251 COLOR_INSTANCE_X_DEALLOC (c) = 0;
252 else
253 COLOR_INSTANCE_X_DEALLOC (c) = 1;
167 COLOR_INSTANCE_X_COLOR (c) = color; 254 COLOR_INSTANCE_X_COLOR (c) = color;
168 return 1; 255 return 1;
169 } 256 }
170 257
171 static void 258 static void
185 { 272 {
186 if (c->data) 273 if (c->data)
187 { 274 {
188 if (DEVICE_LIVE_P (XDEVICE (c->device))) 275 if (DEVICE_LIVE_P (XDEVICE (c->device)))
189 { 276 {
190 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (c->device)); 277 if (COLOR_INSTANCE_X_DEALLOC (c))
191 278 {
192 XFreeColors (dpy, 279 XFreeColors (DEVICE_X_DISPLAY (XDEVICE (c->device)), DEVICE_X_COLORMAP (XDEVICE (c->device)),
193 DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy)), 280 &COLOR_INSTANCE_X_COLOR (c).pixel, 1, 0);
194 &COLOR_INSTANCE_X_COLOR (c).pixel, 1, 0); 281 }
195 } 282 }
196 xfree (c->data); 283 xfree (c->data);
197 c->data = 0; 284 c->data = 0;
198 } 285 }
199 } 286 }
200 287
201 /* Color instances are equal if they resolve to the same color on the 288 /* Color instances are equal if they resolve to the same color on the
202 screen (have the same RGB values). I imagine that 289 screen (have the same RGB values). I imagine that
203 "same RGV values" == "same cell in the colormap." Arguably we should 290 "same RGB values" == "same cell in the colormap." Arguably we should
204 be comparing their names instead. */ 291 be comparing their names or pixel values instead. */
205 292
206 static int 293 static int
207 x_color_instance_equal (struct Lisp_Color_Instance *c1, 294 x_color_instance_equal (struct Lisp_Color_Instance *c1,
208 struct Lisp_Color_Instance *c2, 295 struct Lisp_Color_Instance *c2,
209 int depth) 296 int depth)
234 static int 321 static int
235 x_valid_color_name_p (struct device *d, Lisp_Object color) 322 x_valid_color_name_p (struct device *d, Lisp_Object color)
236 { 323 {
237 XColor c; 324 XColor c;
238 Display *dpy = DEVICE_X_DISPLAY (d); 325 Display *dpy = DEVICE_X_DISPLAY (d);
326 Colormap cmap = DEVICE_X_COLORMAP (d);
327
239 CONST char *extname; 328 CONST char *extname;
240 329
241 GET_C_STRING_CTEXT_DATA_ALLOCA (color, extname); 330 GET_C_STRING_CTEXT_DATA_ALLOCA (color, extname);
242 331
243 return XParseColor (dpy, 332 return XParseColor (dpy, cmap,
244 DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy)),
245 extname, &c); 333 extname, &c);
246 } 334 }
247 335
248 336
249 /************************************************************************/ 337 /************************************************************************/