src/de/matthiasmann/twl/Color.java
author Matthias Mann
Sat May 19 19:02:37 2012 +0200 (22 hours ago)
changeset 1038 0dda4b118c36
parent 924 5702d2687f85
permissions -rw-r--r--
TextArea: added CSS attribute "tab-size" with "-moz-tab-size" alias
     1 /*
     2  * Copyright (c) 2008-2012, Matthias Mann
     3  *
     4  * All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *     * Redistributions of source code must retain the above copyright notice,
    10  *       this list of conditions and the following disclaimer.
    11  *     * Redistributions in binary form must reproduce the above copyright
    12  *       notice, this list of conditions and the following disclaimer in the
    13  *       documentation and/or other materials provided with the distribution.
    14  *     * Neither the name of Matthias Mann nor the names of its contributors may
    15  *       be used to endorse or promote products derived from this software
    16  *       without specific prior written permission.
    17  *
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    29  */
    30 package de.matthiasmann.twl;
    31 
    32 import java.lang.reflect.Field;
    33 import java.lang.reflect.Modifier;
    34 import java.util.Locale;
    35 
    36 /**
    37  * A immutable color class. Colors are represented as bytes.
    38  *
    39  * @author Matthias Mann
    40  */
    41 public final class Color {
    42 
    43     public static final Color BLACK = new Color(0xFF000000);
    44     public static final Color SILVER = new Color(0xFFC0C0C0);
    45     public static final Color GRAY = new Color(0xFF808080);
    46     public static final Color WHITE = new Color(0xFFFFFFFF);
    47     public static final Color MAROON = new Color(0xFF800000);
    48     public static final Color RED = new Color(0xFFFF0000);
    49     public static final Color PURPLE = new Color(0xFF800080);
    50     public static final Color FUCHSIA = new Color(0xFFFF00FF);
    51     public static final Color GREEN = new Color(0xFF008000);
    52     public static final Color LIME = new Color(0xFF00FF00);
    53     public static final Color OLIVE = new Color(0xFF808000);
    54     public static final Color ORANGE = new Color(0xFFFFA500);
    55     public static final Color YELLOW = new Color(0xFFFFFF00);
    56     public static final Color NAVY = new Color(0xFF000080);
    57     public static final Color BLUE = new Color(0xFF0000FF);
    58     public static final Color TEAL = new Color(0xFF008080);
    59     public static final Color AQUA = new Color(0xFF00FFFF);
    60     public static final Color SKYBLUE = new Color(0xFF87CEEB);
    61     
    62     public static final Color LIGHTBLUE    = new Color(0xFFADD8E6);
    63     public static final Color LIGHTCORAL   = new Color(0xFFF08080);
    64     public static final Color LIGHTCYAN    = new Color(0xFFE0FFFF);
    65     public static final Color LIGHTGRAY    = new Color(0xFFD3D3D3);
    66     public static final Color LIGHTGREEN   = new Color(0xFF90EE90);
    67     public static final Color LIGHTPINK    = new Color(0xFFFFB6C1);
    68     public static final Color LIGHTSALMON  = new Color(0xFFFFA07A);
    69     public static final Color LIGHTSKYBLUE = new Color(0xFF87CEFA);
    70     public static final Color LIGHTYELLOW  = new Color(0xFFFFFFE0);
    71     
    72     public static final Color TRANSPARENT = new Color(0);
    73     
    74     private final byte r;
    75     private final byte g;
    76     private final byte b;
    77     private final byte a;
    78 
    79     public Color(byte r, byte g, byte b, byte a) {
    80         this.r = r;
    81         this.g = g;
    82         this.b = b;
    83         this.a = a;
    84     }
    85 
    86     /**
    87      * Creates a new color object from an integer in ARGB order.
    88      * 
    89      * bits  0- 7 are blue
    90      * bits  8-15 are green
    91      * bits 16-23 are red
    92      * bits 24-31 are alpha
    93      * 
    94      * @param argb the color value as integer
    95      */
    96     public Color(int argb) {
    97         this.a = (byte)(argb >> 24);
    98         this.r = (byte)(argb >> 16);
    99         this.g = (byte)(argb >>  8);
   100         this.b = (byte)(argb      );
   101     }
   102 
   103     /**
   104      * Converts this color into an integer in ARGB format
   105      *
   106      * @return the color value as integer
   107      * @see #Color(int)
   108      */
   109     public int toARGB() {
   110         return ((a & 255) << 24) |
   111                 ((r & 255) << 16) |
   112                 ((g & 255) <<  8) |
   113                 ((b & 255)      );
   114     }
   115 
   116     public byte getR() {
   117         return r;
   118     }
   119 
   120     public byte getG() {
   121         return g;
   122     }
   123 
   124     public byte getB() {
   125         return b;
   126     }
   127 
   128     public byte getA() {
   129         return a;
   130     }
   131 
   132     public int getRed() {
   133         return r&255;
   134     }
   135 
   136     public int getGreen() {
   137         return g&255;
   138     }
   139 
   140     public int getBlue() {
   141         return b&255;
   142     }
   143 
   144     public int getAlpha() {
   145         return a&255;
   146     }
   147 
   148     public float getRedFloat() {
   149         return (r & 255) * (1.0f / 255f);
   150     }
   151 
   152     public float getGreenFloat() {
   153         return (g & 255) * (1.0f / 255f);
   154     }
   155 
   156     public float getBlueFloat() {
   157         return (b & 255) * (1.0f / 255f);
   158     }
   159 
   160     public float getAlphaFloat() {
   161         return (a & 255) * (1.0f / 255f);
   162     }
   163 
   164     public void getFloats(float[] dst, int off) {
   165         dst[off+0] = getRedFloat();
   166         dst[off+1] = getGreenFloat();
   167         dst[off+2] = getBlueFloat();
   168         dst[off+3] = getAlphaFloat();
   169     }
   170 
   171     /**
   172      * Retrieves a color by it's name. This uses the case insensitive lookup
   173      * for the color constants defined in this class.
   174      *
   175      * @param name the color name to lookup
   176      * @return a Color or null if the name was not found
   177      */
   178     public static Color getColorByName(String name) {
   179         name = name.toUpperCase(Locale.ENGLISH);
   180         try {
   181             Field f = Color.class.getField(name);
   182             if(Modifier.isStatic(f.getModifiers()) && f.getType() == Color.class) {
   183                 return (Color)f.get(null);
   184             }
   185         } catch (Throwable ex) {
   186             // ignore
   187         }
   188         return null;
   189     }
   190 
   191     /**
   192      * Parses a numeric or symbolic color. Symbolic names are resolved by getColorByName
   193      *
   194      * The following hex formats are supported:
   195      * #RGB
   196      * #ARGB
   197      * #RRGGBB
   198      * #AARRGGBB
   199      *
   200      * @param value the color to parse
   201      * @return a Color object or null
   202      * @throws NumberFormatException if the hex color code can't be parsed
   203      * @see #getColorByName(java.lang.String)
   204      */
   205     public static Color parserColor(String value) throws NumberFormatException {
   206         if(value.length() > 0 && value.charAt(0) == '#') {
   207             String hexcode = value.substring(1);
   208             switch (value.length()) {
   209                 case 4: {
   210                     int rgb4 = Integer.parseInt(hexcode, 16);
   211                     int r = ((rgb4 >> 8) & 0xF) * 0x11;
   212                     int g = ((rgb4 >> 4) & 0xF) * 0x11;
   213                     int b = ((rgb4     ) & 0xF) * 0x11;
   214                     return new Color(0xFF000000 | (r << 16) | (g << 8) | b);
   215                 }
   216                 case 5: {
   217                     int rgb4 = Integer.parseInt(hexcode, 16);
   218                     int a = ((rgb4 >> 12) & 0xF) * 0x11;
   219                     int r = ((rgb4 >>  8) & 0xF) * 0x11;
   220                     int g = ((rgb4 >>  4) & 0xF) * 0x11;
   221                     int b = ((rgb4      ) & 0xF) * 0x11;
   222                     return new Color((a << 24) | (r << 16) | (g << 8) | b);
   223                 }
   224                 case 7:
   225                     return new Color(0xFF000000 | Integer.parseInt(hexcode, 16));
   226                 case 9:
   227                     return new Color((int)Long.parseLong(hexcode, 16));
   228                 default:
   229                     throw new NumberFormatException("Can't parse '" + value + "' as hex color");
   230             }
   231         }
   232         return Color.getColorByName(value);
   233     }
   234 
   235     /**
   236      * Converts this color into it's hex string.
   237      *
   238      * If alpha is 255 then a string in "#RRGGBB" format is created,
   239      * otherwise the "#AARRGGBB" format is created
   240      *
   241      * @return hex representation of this color
   242      */
   243     @Override
   244     public String toString() {
   245         if(a != -1) {
   246             return String.format("#%08X", toARGB());
   247         } else {
   248             return String.format("#%06X", toARGB() & 0xFFFFFF);
   249         }
   250     }
   251 
   252     @Override
   253     public boolean equals(Object obj) {
   254         if(!(obj instanceof Color)) {
   255             return false;
   256         }
   257         final Color other = (Color)obj;
   258         return this.toARGB() == other.toARGB();
   259     }
   260 
   261     @Override
   262     public int hashCode() {
   263         return toARGB();
   264     }
   265 
   266     public Color multiply(Color other) {
   267         return new Color(
   268                 mul(r, other.r),
   269                 mul(g, other.g),
   270                 mul(b, other.b),
   271                 mul(a, other.a));
   272     }
   273 
   274     private byte mul(byte a, byte b) {
   275         return (byte)(((a & 255) * (b & 255)) / 255);
   276     }
   277 }