Mercurial > hg > xemacs-beta
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 /************************************************************************/ |