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 /************************************************************************/ |
