Mercurial > hg > xemacs-beta
annotate lwlib/lwlib-colors.c @ 5481:5008a40f7460
Added tag r21-5-31 for changeset f5a0b32f4687
author | Stephen J. Turnbull <stephen@xemacs.org> |
---|---|
date | Fri, 29 Apr 2011 22:57:14 +0900 |
parents | 308d34e9f07d |
children | cb65bfaf7110 |
rev | line source |
---|---|
3094 | 1 /* Color data structures for X and Xft. |
2 | |
3 Copyright (C) 2004 Free Software Foundation, Inc. | |
4 | |
5 Author: Stephen J. Turnbull <stephen@xemacs.org> | |
6 Created: 24 Jul 2004 by Stephen J. Turnbull | |
7 | |
8 This file is part of XEmacs. | |
9 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
10 XEmacs is free software: you can redistribute it and/or modify it |
3094 | 11 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
12 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
13 option) any later version. |
3094 | 14 |
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4916
diff
changeset
|
21 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
3094 | 22 |
23 /* Synched up with: Not in GNU Emacs. */ | |
24 | |
25 #include <config.h> | |
26 #include <limits.h> /* for ULONG_MAX */ | |
27 #include <stdlib.h> /* for malloc() */ | |
28 #include <stdio.h> | |
29 #include <X11/Xlib.h> | |
30 #include <X11/IntrinsicP.h> | |
31 #include <X11/ShellP.h> /* for ShellWidget */ | |
32 #include "lwlib-colors.h" | |
33 | |
34 static int debug_colors = 1; | |
35 | |
36 #ifdef __cplusplus | |
37 #define X_CLASSFIELD c_class | |
38 #else | |
39 #define X_CLASSFIELD class | |
40 #endif | |
41 | |
42 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ | |
43 ? ((unsigned long) (x)) : ((unsigned long) (y))) | |
44 | |
45 /* WIDGET is an Xt widget, VISUAL and DEPTH are return values */ | |
46 void | |
47 visual_info_from_widget (Widget widget, Visual **visual, int *depth) | |
48 { | |
49 /* grab the visual and depth from the nearest shell ancestor */ | |
50 Widget p = XtParent(widget); | |
51 | |
52 *visual = CopyFromParent; | |
53 *depth = -1; | |
54 while (*visual == CopyFromParent && p) | |
55 { | |
56 if (XtIsShell(p)) | |
57 { | |
58 *visual = ((ShellWidget)p)->shell.visual; | |
59 *depth = p->core.depth; | |
60 } | |
61 p = XtParent(p); | |
62 } | |
63 if (*visual == CopyFromParent || !*visual) | |
64 { | |
65 if (debug_colors > 1) | |
66 fprintf (stderr, "\nvisual_info_from_widget:" | |
67 " failed, using DefaultVisualOfScreen"); | |
68 *visual = DefaultVisualOfScreen (XtScreen (widget)); | |
69 *depth = DefaultDepthOfScreen (XtScreen (widget)); | |
70 } | |
71 else if (debug_colors > 1) | |
72 fprintf (stderr, "\nvisual_info_from_widget: succeeded"); | |
73 } | |
74 | |
75 /* Do we need all this hair on modern hardware? */ | |
76 | |
77 /* Replacement for XAllocColor() that tries to return the nearest | |
78 available color if the colormap is full. Original was from FSFmacs, | |
79 but rewritten by Jareth Hein <jareth@camelot-soft.com> 97/11/25 | |
80 Modified by Lee Kindness <lkindness@csl.co.uk> 31/08/99 to handle previous | |
81 total failure which was due to a read/write colorcell being the nearest | |
82 match - tries the next nearest... | |
83 | |
84 Return value is 1 for normal success, 2 for nearest color success, | |
85 3 for Non-deallocable success. */ | |
86 int | |
87 x_allocate_nearest_color (Display *display, Colormap colormap, | |
88 Visual *visual, XColor *color_def) | |
89 { | |
90 int status; | |
91 | |
92 /* #### [[Apparently this is often called with data derived from a widget | |
93 with no ShellWidget ancestor, or before the shell has a visual. | |
94 Currently this recovery code is in xlwmenu.c and xlwscrollbar.c, but | |
95 likely should come here.]] | |
96 I suspect the problem is that the visual-tracing code was improperly | |
97 written, missing a level of indirection. | |
98 CopyFromParent == NULL in XFree86/Darwin. | |
99 */ | |
100 if (visual == CopyFromParent || !visual) | |
101 { | |
102 Screen *screen = DefaultScreenOfDisplay (display); | |
103 fprintf (stderr, "\nx_allocate_nearest_color: bad visual (%08lx)", | |
104 (unsigned long) visual); | |
105 visual = DefaultVisualOfScreen (screen); | |
106 } | |
107 | |
108 if (visual->X_CLASSFIELD == DirectColor || visual->X_CLASSFIELD == TrueColor) | |
109 { | |
110 if (XAllocColor (display, colormap, color_def) != 0) | |
111 { | |
112 status = 1; | |
113 } | |
114 else | |
115 { | |
116 /* We're dealing with a TrueColor/DirectColor visual, so play games | |
117 with the RGB values in the XColor struct. */ | |
118 /* #### JH: I'm not sure how a call to XAllocColor can fail in a | |
119 TrueColor or DirectColor visual, so I will just reformat the | |
120 request to match the requirements of the visual, and re-issue | |
121 the request. If this fails for anybody, I wanna know about it | |
122 so I can come up with a better plan */ | |
123 | |
124 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk; | |
125 junk = visual->red_mask; | |
126 rshift = 0; | |
127 while ((junk & 0x1) == 0) { | |
128 junk = junk >> 1; | |
129 rshift ++; | |
130 } | |
131 rbits = 0; | |
132 while (junk != 0) { | |
133 junk = junk >> 1; | |
134 rbits++; | |
135 } | |
136 junk = visual->green_mask; | |
137 gshift = 0; | |
138 while ((junk & 0x1) == 0) { | |
139 junk = junk >> 1; | |
140 gshift ++; | |
141 } | |
142 gbits = 0; | |
143 while (junk != 0) { | |
144 junk = junk >> 1; | |
145 gbits++; | |
146 } | |
147 junk = visual->blue_mask; | |
148 bshift = 0; | |
149 while ((junk & 0x1) == 0) { | |
150 junk = junk >> 1; | |
151 bshift ++; | |
152 } | |
153 bbits = 0; | |
154 while (junk != 0) { | |
155 junk = junk >> 1; | |
156 bbits++; | |
157 } | |
158 | |
159 color_def->red = color_def->red >> (16 - rbits); | |
160 color_def->green = color_def->green >> (16 - gbits); | |
161 color_def->blue = color_def->blue >> (16 - bbits); | |
162 if (XAllocColor (display, colormap, color_def) != 0) | |
163 status = 1; | |
164 else | |
165 { | |
166 int rd, gr, bl; | |
167 /* #### JH: I'm punting here, knowing that doing this will at | |
168 least draw the color correctly. However, unless we convert | |
169 all of the functions that allocate colors (graphics | |
170 libraries, etc) to use this function doing this is very | |
171 likely to cause problems later... */ | |
172 | |
173 if (rbits > 8) | |
174 rd = color_def->red << (rbits - 8); | |
175 else | |
176 rd = color_def->red >> (8 - rbits); | |
177 if (gbits > 8) | |
178 gr = color_def->green << (gbits - 8); | |
179 else | |
180 gr = color_def->green >> (8 - gbits); | |
181 if (bbits > 8) | |
182 bl = color_def->blue << (bbits - 8); | |
183 else | |
184 bl = color_def->blue >> (8 - bbits); | |
185 color_def->pixel = (rd << rshift) | (gr << gshift) | (bl << | |
186 bshift); | |
187 status = 3; | |
188 } | |
189 } | |
190 } | |
191 else | |
192 { | |
193 XColor *cells = NULL; | |
194 /* JH: I can't believe there's no way to go backwards from a | |
195 colormap ID and get its visual and number of entries, but X | |
196 apparently isn't built that way... */ | |
197 int no_cells = visual->map_entries; | |
198 status = 0; | |
199 | |
200 if (XAllocColor (display, colormap, color_def) != 0) | |
201 status = 1; | |
202 else while( status != 2 ) | |
203 { | |
204 /* If we got to this point, the colormap is full, so we're | |
205 going to try and get the next closest color. The algorithm used | |
206 is a least-squares matching, which is what X uses for closest | |
207 color matching with StaticColor visuals. */ | |
208 int nearest; | |
209 long nearest_delta, trial_delta; | |
210 int x; | |
211 | |
212 if( cells == NULL ) | |
213 { | |
214 /* #### this could be annoyingly slow | |
215 tell me again why lwlib can't use alloca & friends? */ | |
216 cells = (XColor *) malloc (sizeof(XColor)*no_cells); | |
217 for (x = 0; x < no_cells; x++) | |
218 cells[x].pixel = x; | |
219 | |
220 /* read the current colormap */ | |
221 XQueryColors (display, colormap, cells, no_cells); | |
222 } | |
223 | |
224 nearest = 0; | |
225 /* I'm assuming CSE so I'm not going to condense this. */ | |
226 nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8)) | |
227 * ((color_def->red >> 8) - (cells[0].red >> 8))) | |
228 + | |
229 (((color_def->green >> 8) - (cells[0].green >> 8)) | |
230 * ((color_def->green >> 8) - (cells[0].green >> | |
231 8))) | |
232 + | |
233 (((color_def->blue >> 8) - (cells[0].blue >> 8)) | |
234 * ((color_def->blue >> 8) - (cells[0].blue >> | |
235 8)))); | |
236 for (x = 1; x < no_cells; x++) | |
237 { | |
238 trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8)) | |
239 * ((color_def->red >> 8) - (cells[x].red >> 8))) | |
240 + | |
241 (((color_def->green >> 8) - (cells[x].green >> 8)) | |
242 * ((color_def->green >> 8) - (cells[x].green >> | |
243 8))) | |
244 + | |
245 (((color_def->blue >> 8) - (cells[x].blue >> 8)) | |
246 * ((color_def->blue >> 8) - (cells[x].blue >> | |
247 8)))); | |
248 | |
249 /* less? Ignore cells marked as previously failing */ | |
250 if( (trial_delta < nearest_delta) && | |
251 (cells[x].pixel != ULONG_MAX) ) | |
252 { | |
253 nearest = x; | |
254 nearest_delta = trial_delta; | |
255 } | |
256 } | |
257 color_def->red = cells[nearest].red; | |
258 color_def->green = cells[nearest].green; | |
259 color_def->blue = cells[nearest].blue; | |
260 if (XAllocColor (display, colormap, color_def) != 0) | |
261 status = 2; | |
262 else | |
263 /* LSK: Either the colour map has changed since | |
264 * we read it, or the colour is allocated | |
265 * read/write... Mark this cmap entry so it's | |
266 * ignored in the next iteration. | |
267 */ | |
268 cells[nearest].pixel = ULONG_MAX; | |
269 } | |
270 } | |
271 return status; | |
272 } | |
273 | |
274 #if 0 | |
275 /* Replacement for XAllocColor() that tries to return the nearest | |
276 available color if the colormap is full. From GNU Emacs. | |
277 #### Review this to see if there's anything our hairy version could use. */ | |
278 | |
279 int | |
280 FIXME_allocate_nearest_color (Display *display, Colormap screen_colormap, | |
281 XColor *color_def) | |
282 { | |
283 int status = XAllocColor (display, screen_colormap, color_def); | |
284 if (status) | |
285 return status; | |
286 | |
287 { | |
288 /* If we got to this point, the colormap is full, so we're | |
289 going to try to get the next closest color. | |
290 The algorithm used is a least-squares matching, which is | |
291 what X uses for closest color matching with StaticColor visuals. */ | |
292 | |
293 int nearest, x; | |
294 unsigned long nearest_delta = ULONG_MAX; | |
295 | |
296 int no_cells = XDisplayCells (display, XDefaultScreen (display)); | |
297 /* Don't use alloca here because lwlib doesn't have the | |
298 necessary configuration information that src does. */ | |
299 XColor *cells = (XColor *) malloc (sizeof (XColor) * no_cells); | |
300 | |
301 for (x = 0; x < no_cells; x++) | |
302 cells[x].pixel = x; | |
303 | |
304 XQueryColors (display, screen_colormap, cells, no_cells); | |
305 | |
306 for (nearest = 0, x = 0; x < no_cells; x++) | |
307 { | |
308 long dred = (color_def->red >> 8) - (cells[x].red >> 8); | |
309 long dgreen = (color_def->green >> 8) - (cells[x].green >> 8); | |
310 long dblue = (color_def->blue >> 8) - (cells[x].blue >> 8); | |
311 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue; | |
312 | |
313 if (delta < nearest_delta) | |
314 { | |
315 nearest = x; | |
316 nearest_delta = delta; | |
317 } | |
318 } | |
319 color_def->red = cells[nearest].red; | |
320 color_def->green = cells[nearest].green; | |
321 color_def->blue = cells[nearest].blue; | |
322 free (cells); | |
323 return XAllocColor (display, screen_colormap, color_def); | |
324 } | |
325 } | |
326 #endif | |
327 | |
328 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
3094
diff
changeset
|
329 #ifdef HAVE_XFT |
3094 | 330 |
331 XftColor | |
332 xft_convert_color (Display *dpy, Colormap cmap, Visual *visual, int c, int dim) | |
333 { | |
334 static XColor color; /* #### why is this static ?? */ | |
335 XftColor result; | |
336 | |
337 color.pixel = c; | |
338 XQueryColor(dpy, cmap, &color); | |
339 | |
340 if (dim) | |
341 { | |
342 color.red = MINL (65535, color.red * 1.5); | |
343 color.green = MINL (65535, color.green * 1.5); | |
344 color.blue = MINL (65535, color.blue * 1.5); | |
345 x_allocate_nearest_color (dpy, cmap, visual, &color); | |
346 } | |
347 | |
348 result.pixel = color.pixel; | |
349 result.color.red = color.red; | |
350 result.color.green = color.green; | |
351 result.color.blue = color.blue; | |
352 result.color.alpha = 0xffff; | |
353 | |
354 return result; | |
355 } | |
356 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
3094
diff
changeset
|
357 #endif /* HAVE_XFT */ |
3094 | 358 |
359 /* end of lwlib-colors.c */ |