blob: 2de7df3eab3d8763cf778559ea8cbeff10ce5e5d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.awt.X11;
27
28import java.awt.*;
29import java.io.*;
30import sun.security.action.GetPropertyAction;
31import java.security.AccessController;
32
33/**
34 *
35 * This class contains code that is need to mimic the
36 * Motif Color selection and color defaults code.
37 *
38 * Portions of this code have been ported to java from
39 * Motif sources (Color.c) (ColorP.h) etc.
40 *
41 * Author: Bino George
42 *
43 */
44
45class MotifColorUtilities {
46
47
48 static final float XmRED_LUMINOSITY=0.30f;
49 static final float XmGREEN_LUMINOSITY=0.59f;
50 static final float XmBLUE_LUMINOSITY=0.11f;
51 static final int XmINTENSITY_FACTOR=75;
52 static final int XmLIGHT_FACTOR=0;
53 static final int XmLUMINOSITY_FACTOR=25;
54
55 static final int XmMAX_SHORT=65535;
56
57
58 static final int XmCOLOR_PERCENTILE=(XmMAX_SHORT / 100);
59
60 static final int XmDEFAULT_DARK_THRESHOLD=20;
61 static final int XmDEFAULT_LIGHT_THRESHOLD=93;
62 static final int XmDEFAULT_FOREGROUND_THRESHOLD=70;
63
64 static final int BLACK = 0xFF000000;
65 static final int WHITE = 0xFFFFFFFF;
66 static final int MOTIF_WINDOW_COLOR= 0xFFDFDFDF;
67
68 static final int DEFAULT_COLOR = 0xFFC4C4C4;
69
70 static final int XmCOLOR_LITE_THRESHOLD = XmDEFAULT_LIGHT_THRESHOLD * XmCOLOR_PERCENTILE;
71 static final int XmCOLOR_DARK_THRESHOLD = XmDEFAULT_DARK_THRESHOLD * XmCOLOR_PERCENTILE;
72 static final int XmFOREGROUND_THRESHOLD = XmDEFAULT_FOREGROUND_THRESHOLD * XmCOLOR_PERCENTILE;
73
74 /* LITE color model
75 percent to interpolate RGB towards black for SEL, BS, TS */
76
77 static final int XmCOLOR_LITE_SEL_FACTOR = 15;
78 static final int XmCOLOR_LITE_BS_FACTOR = 40;
79 static final int XmCOLOR_LITE_TS_FACTOR = 20;
80
81 /* DARK color model
82 percent to interpolate RGB towards white for SEL, BS, TS */
83
84 static final int XmCOLOR_DARK_SEL_FACTOR= 15;
85 static final int XmCOLOR_DARK_BS_FACTOR = 30;
86 static final int XmCOLOR_DARK_TS_FACTOR = 50;
87
88 /* STD color model
89 percent to interpolate RGB towards black for SEL, BS
90 percent to interpolate RGB towards white for TS
91 HI values used for high brightness (within STD)
92 LO values used for low brightness (within STD)
93 Interpolate factors between HI & LO values based on brightness */
94
95 static final int XmCOLOR_HI_SEL_FACTOR = 15;
96 static final int XmCOLOR_HI_BS_FACTOR = 40;
97 static final int XmCOLOR_HI_TS_FACTOR = 60;
98
99 static final int XmCOLOR_LO_SEL_FACTOR= 15;
100 static final int XmCOLOR_LO_BS_FACTOR = 60;
101 static final int XmCOLOR_LO_TS_FACTOR = 50;
102
103 static int brightness( int red, int green, int blue )
104 {
105 float brightness;
106 float intensity;
107 float light;
108 float luminosity, maxprimary, minprimary;
109
110 // To mimix Motif logic, we need to convert to 16 bit color values.
111
112 red = red << 8;
113 green = green << 8;
114 blue = blue << 8;
115
116
117 intensity = (red + green + blue) / 3;
118
119
120 /*
121 * The casting nonsense below is to try to control the point at
122 * the truncation occurs.
123 */
124
125 luminosity = (int) ((XmRED_LUMINOSITY * (float) red)
126 + (XmGREEN_LUMINOSITY * (float) green)
127 + (XmBLUE_LUMINOSITY * (float) blue));
128
129 maxprimary = ( (red > green) ?
130 ( (red > blue) ? red : blue ) :
131 ( (green > blue) ? green : blue ) );
132
133 minprimary = ( (red < green) ?
134 ( (red < blue) ? red : blue ) :
135 ( (green < blue) ? green : blue ) );
136
137 light = (minprimary + maxprimary) / 2;
138
139 brightness = ( (intensity * XmINTENSITY_FACTOR) +
140 (light * XmLIGHT_FACTOR) +
141 (luminosity * XmLUMINOSITY_FACTOR) ) / 100;
142 return Math.round(brightness);
143 }
144
145 static int calculateForegroundFromBackground(int r, int g, int b) {
146
147 int foreground = WHITE;
148 int brightness = brightness(r,g,b);
149
150 if (brightness > XmFOREGROUND_THRESHOLD) {
151 foreground = BLACK;
152 }
153 else foreground = WHITE;
154
155 return foreground;
156 }
157
158 static int calculateTopShadowFromBackground(int r, int g, int b) {
159
160 float color_value,f;
161
162 int br = r << 8;
163 int bg = g << 8;
164 int bb = b << 8;
165
166 int brightness = brightness(r,g,b);
167
168 float red;
169 float green;
170 float blue;
171
172 if (brightness < XmCOLOR_DARK_THRESHOLD) {
173 // dark background
174
175 color_value = br;
176 color_value += XmCOLOR_DARK_TS_FACTOR *
177 (XmMAX_SHORT - color_value) / 100;
178 red = color_value;
179
180 color_value = bg;
181 color_value += XmCOLOR_DARK_TS_FACTOR *
182 (XmMAX_SHORT - color_value) / 100;
183 green = color_value;
184
185 color_value = bb;
186 color_value += XmCOLOR_DARK_TS_FACTOR *
187 (XmMAX_SHORT - color_value) / 100;
188 blue = color_value;
189 }
190 else if (brightness > XmCOLOR_LITE_THRESHOLD) {
191 // lite background
192
193 color_value = br;
194 color_value -= (color_value * XmCOLOR_LITE_TS_FACTOR) / 100;
195 red = color_value;
196
197 color_value = bg;
198 color_value -= (color_value * XmCOLOR_LITE_TS_FACTOR) / 100;
199 green = color_value;
200
201 color_value = bb;
202 color_value -= (color_value * XmCOLOR_LITE_TS_FACTOR) / 100;
203 blue = color_value;
204
205 }
206 else {
207 // medium
208 f = XmCOLOR_LO_TS_FACTOR + (brightness
209 * ( XmCOLOR_HI_TS_FACTOR - XmCOLOR_LO_TS_FACTOR )
210 / XmMAX_SHORT);
211
212 color_value = br;
213 color_value += f * ( XmMAX_SHORT - color_value ) / 100;
214 red = color_value;
215
216 color_value = bg;
217 color_value += f * ( XmMAX_SHORT - color_value ) / 100;
218 green = color_value;
219
220 color_value = bb;
221 color_value += f * ( XmMAX_SHORT - color_value ) / 100;
222 blue = color_value;
223
224
225 }
226
227
228 int ired = ((int)red) >> 8;
229 int igreen = ((int)green) >> 8;
230 int iblue = ((int)blue) >> 8;
231
232 int ret = 0xff000000 | ired <<16 | igreen<<8 | iblue;
233
234 return ret;
235 }
236
237
238 static int calculateBottomShadowFromBackground(int r, int g, int b) {
239
240 float color_value,f;
241
242 int br = r << 8;
243 int bg = g << 8;
244 int bb = b << 8;
245
246 int brightness = brightness(r,g,b);
247
248 float red;
249 float green;
250 float blue;
251
252 if (brightness < XmCOLOR_DARK_THRESHOLD) {
253 // dark background
254 color_value = br;
255 color_value += XmCOLOR_DARK_BS_FACTOR *
256 (XmMAX_SHORT - color_value) / 100;
257 red = color_value;
258
259 color_value = bg;
260 color_value += XmCOLOR_DARK_BS_FACTOR *
261 (XmMAX_SHORT - color_value) / 100;
262 green = color_value;
263
264 color_value = bb;
265 color_value += XmCOLOR_DARK_BS_FACTOR *
266 (XmMAX_SHORT - color_value) / 100;
267 blue = color_value;
268
269 }
270 else if (brightness > XmCOLOR_LITE_THRESHOLD) {
271 // lite background
272 color_value = br;
273 color_value -= (color_value * XmCOLOR_LITE_BS_FACTOR) / 100;
274 red = color_value;
275
276 color_value = bg;
277 color_value -= (color_value * XmCOLOR_LITE_BS_FACTOR) / 100;
278 green = color_value;
279
280 color_value = bb;
281 color_value -= (color_value * XmCOLOR_LITE_BS_FACTOR) / 100;
282 blue = color_value;
283
284 }
285 else {
286 // medium
287 f = XmCOLOR_LO_BS_FACTOR + (brightness
288 * ( XmCOLOR_HI_BS_FACTOR - XmCOLOR_LO_BS_FACTOR )
289 / XmMAX_SHORT);
290
291 color_value = br;
292 color_value -= (color_value * f) / 100;
293 red = color_value;
294
295 color_value = bg;
296 color_value -= (color_value * f) / 100;
297 green = color_value;
298
299 color_value = bb;
300 color_value -= (color_value * f) / 100;
301 blue = color_value;
302 }
303
304
305 int ired = ((int)red) >> 8;
306 int igreen = ((int)green) >> 8;
307 int iblue = ((int)blue) >> 8;
308
309 int ret = 0xff000000 | ired <<16 | igreen<<8 | iblue;
310
311 return ret;
312 }
313
314 static int calculateSelectFromBackground(int r, int g, int b) {
315
316 float color_value,f;
317
318 int br = r << 8;
319 int bg = g << 8;
320 int bb = b << 8;
321
322 int brightness = brightness(r,g,b);
323
324 float red;
325 float green;
326 float blue;
327
328 if (brightness < XmCOLOR_DARK_THRESHOLD) {
329 // dark background
330 color_value = br;
331 color_value += XmCOLOR_DARK_SEL_FACTOR *
332 (XmMAX_SHORT - color_value) / 100;
333 red = color_value;
334
335 color_value = bg;
336 color_value += XmCOLOR_DARK_SEL_FACTOR *
337 (XmMAX_SHORT - color_value) / 100;
338 green = color_value;
339
340 color_value = bb;
341 color_value += XmCOLOR_DARK_SEL_FACTOR *
342 (XmMAX_SHORT - color_value) / 100;
343 blue = color_value;
344
345 }
346 else if (brightness > XmCOLOR_LITE_THRESHOLD) {
347 // lite background
348 color_value = br;
349 color_value -= (color_value * XmCOLOR_LITE_SEL_FACTOR) / 100;
350 red = color_value;
351
352 color_value = bg;
353 color_value -= (color_value * XmCOLOR_LITE_SEL_FACTOR) / 100;
354 green = color_value;
355
356 color_value = bb;
357 color_value -= (color_value * XmCOLOR_LITE_SEL_FACTOR) / 100;
358 blue = color_value;
359
360 }
361 else {
362 // medium
363 f = XmCOLOR_LO_SEL_FACTOR + (brightness
364 * ( XmCOLOR_HI_SEL_FACTOR - XmCOLOR_LO_SEL_FACTOR )
365 / XmMAX_SHORT);
366
367 color_value = br;
368 color_value -= (color_value * f) / 100;
369 red = color_value;
370
371 color_value = bg;
372 color_value -= (color_value * f) / 100;
373 green = color_value;
374
375 color_value = bb;
376 color_value -= (color_value * f) / 100;
377 blue = color_value;
378 }
379
380
381 int ired = ((int)red) >> 8;
382 int igreen = ((int)green) >> 8;
383 int iblue = ((int)blue) >> 8;
384
385 int ret = 0xff000000 | ired <<16 | igreen<<8 | iblue;
386
387 return ret;
388 }
389
390 static void loadSystemColorsForCDE(int[] systemColors) throws Exception {
391 // System.out.println("loadSystemColorsForCDE");
392 XAtom resourceManager = XAtom.get("RESOURCE_MANAGER");
393
394 String resourceString = resourceManager.getProperty(XToolkit.getDefaultRootWindow());
395
396 int index = resourceString.indexOf("ColorPalette:");
397 int len = resourceString.length();
398 while ( (index < len) && (resourceString.charAt(index) != ':')) index++;
399 index++; // skip :
400 if (resourceString.charAt(index) == '\t') index++; // skip \t
401
402 String paletteFile = resourceString.substring(index,resourceString.indexOf("\n",index));
403
404 //System.out.println("Palette File = " + paletteFile);
405
406 // Check if palette is a user palette.
407
408 String paletteFilePath = System.getProperty("user.home") + "/.dt/palettes/" + paletteFile;
409
410 File pFile = new File(paletteFilePath);
411 if (!pFile.exists())
412 {
413 // Must be a system palette
414 paletteFilePath = "/usr/dt/palettes/" + paletteFile;
415 pFile = new File(paletteFilePath);
416 if (!pFile.exists())
417 {
418 throw new FileNotFoundException("Could not open : "+ paletteFilePath);
419 }
420 }
421 BufferedReader bfr = new BufferedReader(new FileReader(pFile));
422
423 int colors[] = new int[8];
424 int r,g,b;
425 String temp,color;
426
427 for (int i=0;i<8;i++) {
428 temp = bfr.readLine();
429 color = temp.substring(1,temp.length());
430 r = Integer.valueOf(color.substring(0,4),16).intValue() >> 8;
431 g = Integer.valueOf(color.substring(4,8),16).intValue() >> 8;
432 b = Integer.valueOf(color.substring(8,12),16).intValue() >> 8;
433 colors[i] = 0xff000000 | r<<16 | g<<8 | b;
434 // System.out.println("color["+i+"]="+Integer.toHexString(colors[i]) + "r = " +r + "g="+g+"b="+b);
435 }
436
437 systemColors[SystemColor.ACTIVE_CAPTION] = colors[0];
438 systemColors[SystemColor.ACTIVE_CAPTION_BORDER] = colors[0];
439
440 systemColors[SystemColor.INACTIVE_CAPTION] = colors[1];
441 systemColors[SystemColor.INACTIVE_CAPTION_BORDER] = colors[1];
442
443 systemColors[SystemColor.WINDOW] = colors[1];
444
445 systemColors[SystemColor.WINDOW_BORDER] = colors[1];
446 systemColors[SystemColor.MENU] = colors[1];
447
448 systemColors[SystemColor.TEXT] = colors[3];
449
450 systemColors[SystemColor.SCROLLBAR] = colors[1];
451 systemColors[SystemColor.CONTROL] = colors[1];
452
453 int activeFore;
454 int inactiveFore;
455 int textFore;
456
457
458 r = (colors[0] & 0x00FF0000) >> 16;
459 g = (colors[0] & 0x0000FF00) >> 8;
460 b = (colors[0] & 0x000000FF);
461
462 activeFore = MotifColorUtilities.calculateForegroundFromBackground(r,g,b);
463
464 r = (colors[1] & 0x00FF0000) >> 16;
465 g = (colors[1] & 0x0000FF00) >> 8;
466 b = (colors[1] & 0x000000FF);
467
468 inactiveFore = MotifColorUtilities.calculateForegroundFromBackground(r,g,b);
469
470 int top_shadow = MotifColorUtilities.calculateTopShadowFromBackground(r,g,b);
471 int bottom_shadow = MotifColorUtilities.calculateBottomShadowFromBackground(r,g,b);
472
473
474 r = (colors[3] & 0x00FF0000) >> 16;
475 g = (colors[3] & 0x0000FF00) >> 8;
476 b = (colors[3] & 0x000000FF);
477
478 textFore = MotifColorUtilities.calculateForegroundFromBackground(r,g,b);
479
480
481 systemColors[SystemColor.ACTIVE_CAPTION_TEXT] = activeFore;
482 systemColors[SystemColor.INACTIVE_CAPTION_TEXT] = inactiveFore;
483 systemColors[SystemColor.WINDOW_TEXT] = inactiveFore;
484 systemColors[SystemColor.MENU_TEXT] = inactiveFore;
485 systemColors[SystemColor.TEXT_TEXT] = textFore;
486 systemColors[SystemColor.TEXT_HIGHLIGHT] = MotifColorUtilities.BLACK;
487 systemColors[SystemColor.TEXT_HIGHLIGHT_TEXT] = MotifColorUtilities.DEFAULT_COLOR;
488 systemColors[SystemColor.CONTROL_TEXT] = inactiveFore;
489 Color tmp = new Color(top_shadow);
490 systemColors[SystemColor.CONTROL_HIGHLIGHT] = top_shadow;
491 systemColors[SystemColor.CONTROL_LT_HIGHLIGHT] = tmp.brighter().getRGB();
492
493 tmp = new Color(bottom_shadow);
494 systemColors[SystemColor.CONTROL_SHADOW] = bottom_shadow;
495 systemColors[SystemColor.CONTROL_DK_SHADOW] = tmp.darker().getRGB();
496
497 }
498
499 static void loadMotifDefaultColors(int[] systemColors) {
500 //fix for 5092883. WINDOW should be light gray and TEXT should be WHITE to look similar to Motif
501 systemColors[SystemColor.WINDOW] = MotifColorUtilities.MOTIF_WINDOW_COLOR;
502 systemColors[SystemColor.TEXT] = MotifColorUtilities.WHITE;
503 systemColors[SystemColor.WINDOW_TEXT] = MotifColorUtilities.BLACK;
504 systemColors[SystemColor.MENU_TEXT] = MotifColorUtilities.BLACK;
505 systemColors[SystemColor.ACTIVE_CAPTION_TEXT] = MotifColorUtilities.BLACK;
506 systemColors[SystemColor.INACTIVE_CAPTION_TEXT] = MotifColorUtilities.BLACK;
507 systemColors[SystemColor.TEXT_TEXT] = MotifColorUtilities.BLACK;
508 systemColors[SystemColor.TEXT_HIGHLIGHT] = MotifColorUtilities.BLACK;
509 systemColors[SystemColor.TEXT_HIGHLIGHT_TEXT] = MotifColorUtilities.DEFAULT_COLOR;
510 systemColors[SystemColor.CONTROL_TEXT] = MotifColorUtilities.BLACK;
511 systemColors[SystemColor.WINDOW_BORDER] = MotifColorUtilities.DEFAULT_COLOR;
512 systemColors[SystemColor.MENU] = MotifColorUtilities.DEFAULT_COLOR;
513 systemColors[SystemColor.SCROLLBAR] = MotifColorUtilities.DEFAULT_COLOR;
514 systemColors[SystemColor.CONTROL] = MotifColorUtilities.MOTIF_WINDOW_COLOR;
515
516 int r = (MotifColorUtilities.DEFAULT_COLOR & 0x00FF0000) >> 16;
517 int g = (MotifColorUtilities.DEFAULT_COLOR & 0x0000FF00) >> 8;
518 int b = (MotifColorUtilities.DEFAULT_COLOR & 0x000000FF);
519
520
521 int top_shadow = MotifColorUtilities.calculateTopShadowFromBackground(r,g,b);
522 int bottom_shadow = MotifColorUtilities.calculateBottomShadowFromBackground(r,g,b);
523
524 Color tmp = new Color(top_shadow);
525 systemColors[SystemColor.CONTROL_HIGHLIGHT] = top_shadow;
526 systemColors[SystemColor.CONTROL_LT_HIGHLIGHT] = tmp.brighter().getRGB();
527
528 tmp = new Color(bottom_shadow);
529 systemColors[SystemColor.CONTROL_SHADOW] = bottom_shadow;
530 systemColors[SystemColor.CONTROL_DK_SHADOW] = tmp.darker().getRGB();
531
532 }
533
534
535 static void loadSystemColors(int[] systemColors) {
536 if ("Linux".equals(AccessController.doPrivileged(new GetPropertyAction("os.name")))) { // Load motif default colors on Linux.
537 loadMotifDefaultColors(systemColors);
538 }
539 else
540 {
541 try {
542 loadSystemColorsForCDE(systemColors);
543 }
544 catch (Exception e) // Failure to load CDE colors.
545 {
546 loadMotifDefaultColors(systemColors);
547 }
548 }
549 }
550}