1/*
2 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. 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.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * 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}
551