9175bf4d730bfb3c8c328db9191480c85ebd4330
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / renderer / raster / Color.java
1 /*
2  * Sixth 3D engine. Copyright ©2012-2018, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 3 of the GNU Lesser General Public License
6  * or later as published by the Free Software Foundation.
7  *
8  */
9
10 package eu.svjatoslav.sixth.e3d.renderer.raster;
11
12 public final class Color {
13
14     public static final Color RED = new Color(255, 0, 0, 255);
15     public static final Color GREEN = new Color(0, 255, 0, 255);
16     public static final Color BLUE = new Color(0, 0, 255, 255);
17     public static final Color YELLOW = new Color(255, 255, 0, 255);
18     public static final Color WHITE = new Color(255, 255, 255, 255);
19     public static final Color BLACK = new Color(0, 0, 0, 255);
20     public static final Color PURPLE = new Color(255, 0, 255, 255);
21     public static final Color TRANSPARENT = new Color(0, 0, 0, 0);
22
23     public final int r, g, b;
24
25     /**
26      * <pre>
27      * 255 is opaque.
28      * 0 is transparent.
29      * </pre>
30      */
31     public int a;
32
33     public Color(final Color parentColor) {
34         r = parentColor.r;
35         g = parentColor.g;
36         b = parentColor.b;
37         a = parentColor.a;
38     }
39
40     public Color(final double r, final double g, final double b, final double a) {
41         this.r = ensureByteLimit((int) (r * 255d));
42         this.g = ensureByteLimit((int) (g * 255d));
43         this.b = ensureByteLimit((int) (b * 255d));
44         this.a = ensureByteLimit((int) (a * 255d));
45     }
46
47     /**
48      * <pre>
49      *     Supported formats are:
50      *
51      *     RGB
52      *     RGBA
53      *     RRGGBB
54      *     RRGGBBAA
55      * </pre>
56      */
57     public Color(String colorHexCode) {
58         switch (colorHexCode.length()) {
59             case 3:
60                 r = parseHexSegment(colorHexCode, 0, 1) * 16;
61                 g = parseHexSegment(colorHexCode, 1, 1) * 16;
62                 b = parseHexSegment(colorHexCode, 2, 1) * 16;
63                 a = 255;
64                 return;
65
66             case 4:
67                 r = parseHexSegment(colorHexCode, 0, 1) * 16;
68                 g = parseHexSegment(colorHexCode, 1, 1) * 16;
69                 b = parseHexSegment(colorHexCode, 2, 1) * 16;
70                 a = parseHexSegment(colorHexCode, 3, 1) * 16;
71                 return;
72
73             case 6:
74                 r = parseHexSegment(colorHexCode, 0, 2);
75                 g = parseHexSegment(colorHexCode, 2, 2);
76                 b = parseHexSegment(colorHexCode, 4, 2);
77                 a = 255;
78                 return;
79
80             case 8:
81                 r = parseHexSegment(colorHexCode, 0, 2);
82                 g = parseHexSegment(colorHexCode, 2, 2);
83                 b = parseHexSegment(colorHexCode, 4, 2);
84                 a = parseHexSegment(colorHexCode, 6, 2);
85                 return;
86             default:
87                 throw new IllegalArgumentException("Unsupported color code: " + colorHexCode);
88         }
89     }
90
91     public Color(final int rgb) {
92         r = (rgb & 0xFF0000) >> 16;
93         g = (rgb & 0xFF00) >> 8;
94         b = rgb & 0xFF;
95         a = 255;
96     }
97
98     public Color(final int r, final int g, final int b) {
99         this(r, g, b, 255);
100     }
101
102     public Color(final int r, final int g, final int b, final int a) {
103         this.r = ensureByteLimit(r);
104         this.g = ensureByteLimit(g);
105         this.b = ensureByteLimit(b);
106         this.a = ensureByteLimit(a);
107     }
108
109     private int parseHexSegment(String hexString, int start, int length) {
110         return Integer.parseInt(hexString.substring(start, start + length), 16);
111     }
112
113     /**
114      * Ensure that color values are within allowed limits of 0 to 255.
115      */
116     private int ensureByteLimit(final int value) {
117         if (value < 0)
118             return 0;
119
120         if (value > 255)
121             return 255;
122
123         return value;
124     }
125
126     public boolean isTransparent() {
127         return a == 0;
128     }
129
130     public java.awt.Color toAwtColor() {
131         return new java.awt.Color(r, g, b, a);
132     }
133
134     public int toInt() {
135         return toAwtColor().getRGB();
136     }
137
138     @Override
139     public boolean equals(Object o) {
140         if (this == o) return true;
141         if (o == null || getClass() != o.getClass()) return false;
142
143         Color color = (Color) o;
144
145         if (r != color.r) return false;
146         if (g != color.g) return false;
147         if (b != color.b) return false;
148         return a == color.a;
149     }
150
151     @Override
152     public int hashCode() {
153         int result = r;
154         result = 31 * result + g;
155         result = 31 * result + b;
156         result = 31 * result + a;
157         return result;
158     }
159 }