3a2ea7001fbdfabc742c65a9967ee6b210087d81
[jvcard.git] / TextColor.java
1 /*
2 * This file is part of lanterna (http://code.google.com/p/lanterna/).
3 *
4 * lanterna is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Copyright (C) 2010-2015 Martin
18 */
19 package com.googlecode.lanterna;
20
21
22 import java.awt.*;
23
24 /**
25 * This is an abstract base class for terminal color definitions. Since there are different ways of specifying terminal
26 * colors, all with a different range of adoptions, this makes it possible to program an API against an implementation-
27 * agnostic color definition. Please remember when using colors that not all terminals and terminal emulators supports
28 * them. The 24-bit color mode is very unsupported, for example, and even the default Linux terminal doesn't support
29 * the 256-color indexed mode.
30 *
31 * @author Martin
32 */
33 public interface TextColor {
34 /**
35 * Returns the byte sequence in between CSI and character 'm' that is used to enable this color as the foreground
36 * color on an ANSI-compatible terminal.
37 * @return Byte array out data to output in between of CSI and 'm'
38 */
39 byte[] getForegroundSGRSequence();
40
41 /**
42 * Returns the byte sequence in between CSI and character 'm' that is used to enable this color as the background
43 * color on an ANSI-compatible terminal.
44 * @return Byte array out data to output in between of CSI and 'm'
45 */
46 byte[] getBackgroundSGRSequence();
47
48 /**
49 * Converts this color to an AWT color object, assuming a standard VGA palette.
50 * @return TextColor as an AWT Color
51 */
52 Color toColor();
53
54 /**
55 * This class represent classic ANSI colors that are likely to be very compatible with most terminal
56 * implementations. It is limited to 8 colors (plus the 'default' color) but as a norm, using bold mode (SGR code)
57 * will slightly alter the color, giving it a bit brighter tone, so in total this will give you 16 (+1) colors.
58 * <p>
59 * For more information, see http://en.wikipedia.org/wiki/File:Ansi.png
60 */
61 enum ANSI implements TextColor {
62 BLACK((byte)0, 0, 0, 0),
63 RED((byte)1, 170, 0, 0),
64 GREEN((byte)2, 0, 170, 0),
65 YELLOW((byte)3, 170, 85, 0),
66 BLUE((byte)4, 0, 0, 170),
67 MAGENTA((byte)5, 170, 0, 170),
68 CYAN((byte)6, 0, 170, 170),
69 WHITE((byte)7, 170, 170, 170),
70 DEFAULT((byte)9, 0, 0, 0);
71
72 private final byte index;
73 private final Color color;
74
75 ANSI(byte index, int red, int green, int blue) {
76 this.index = index;
77 this.color = new Color(red, green, blue);
78 }
79
80 @Override
81 public byte[] getForegroundSGRSequence() {
82 return new byte[] { (byte)'3', (byte)(48 + index)}; //48 is ascii code for '0'
83 }
84
85 @Override
86 public byte[] getBackgroundSGRSequence() {
87 return new byte[] { (byte)'4', (byte)(48 + index)}; //48 is ascii code for '0'
88 }
89
90 @Override
91 public Color toColor() {
92 return color;
93 }
94 }
95
96 /**
97 * This class represents a color expressed in the indexed XTerm 256 color extension, where each color is defined in a
98 * lookup-table. All in all, there are 256 codes, but in order to know which one to know you either need to have the
99 * table at hand, or you can use the two static helper methods which can help you convert from three 8-bit
100 * RGB values to the closest approximate indexed color number. If you are interested, the 256 index values are
101 * actually divided like this:<br>
102 * 0 .. 15 - System colors, same as ANSI, but the actual rendered color depends on the terminal emulators color scheme<br>
103 * 16 .. 231 - Forms a 6x6x6 RGB color cube<br>
104 * 232 .. 255 - A gray scale ramp (without black and white endpoints)<br>
105 * <p>
106 * Support for indexed colors is somewhat widely adopted, not as much as the ANSI colors (TextColor.ANSI) but more
107 * than the RGB (TextColor.RGB).
108 * <p>
109 * For more details on this, please see <a
110 * href="https://github.com/robertknight/konsole/blob/master/user-doc/README.moreColors">
111 * this</a> commit message to Konsole.
112 */
113 class Indexed implements TextColor {
114 private static final byte[][] COLOR_TABLE = new byte[][] {
115 //These are the standard 16-color VGA palette entries
116 {(byte)0,(byte)0,(byte)0 },
117 {(byte)170,(byte)0,(byte)0 },
118 {(byte)0,(byte)170,(byte)0 },
119 {(byte)170,(byte)85,(byte)0 },
120 {(byte)0,(byte)0,(byte)170 },
121 {(byte)170,(byte)0,(byte)170 },
122 {(byte)0,(byte)170,(byte)170 },
123 {(byte)170,(byte)170,(byte)170 },
124 {(byte)85,(byte)85,(byte)85 },
125 {(byte)255,(byte)85,(byte)85 },
126 {(byte)85,(byte)255,(byte)85 },
127 {(byte)255,(byte)255,(byte)85 },
128 {(byte)85,(byte)85,(byte)255 },
129 {(byte)255,(byte)85,(byte)255 },
130 {(byte)85,(byte)255,(byte)255 },
131 {(byte)255,(byte)255,(byte)255 },
132
133 //Starting 6x6x6 RGB color cube from 16
134 {(byte)0x00,(byte)0x00,(byte)0x00 },
135 {(byte)0x00,(byte)0x00,(byte)0x5f },
136 {(byte)0x00,(byte)0x00,(byte)0x87 },
137 {(byte)0x00,(byte)0x00,(byte)0xaf },
138 {(byte)0x00,(byte)0x00,(byte)0xd7 },
139 {(byte)0x00,(byte)0x00,(byte)0xff },
140 {(byte)0x00,(byte)0x5f,(byte)0x00 },
141 {(byte)0x00,(byte)0x5f,(byte)0x5f },
142 {(byte)0x00,(byte)0x5f,(byte)0x87 },
143 {(byte)0x00,(byte)0x5f,(byte)0xaf },
144 {(byte)0x00,(byte)0x5f,(byte)0xd7 },
145 {(byte)0x00,(byte)0x5f,(byte)0xff },
146 {(byte)0x00,(byte)0x87,(byte)0x00 },
147 {(byte)0x00,(byte)0x87,(byte)0x5f },
148 {(byte)0x00,(byte)0x87,(byte)0x87 },
149 {(byte)0x00,(byte)0x87,(byte)0xaf },
150 {(byte)0x00,(byte)0x87,(byte)0xd7 },
151 {(byte)0x00,(byte)0x87,(byte)0xff },
152 {(byte)0x00,(byte)0xaf,(byte)0x00 },
153 {(byte)0x00,(byte)0xaf,(byte)0x5f },
154 {(byte)0x00,(byte)0xaf,(byte)0x87 },
155 {(byte)0x00,(byte)0xaf,(byte)0xaf },
156 {(byte)0x00,(byte)0xaf,(byte)0xd7 },
157 {(byte)0x00,(byte)0xaf,(byte)0xff },
158 {(byte)0x00,(byte)0xd7,(byte)0x00 },
159 {(byte)0x00,(byte)0xd7,(byte)0x5f },
160 {(byte)0x00,(byte)0xd7,(byte)0x87 },
161 {(byte)0x00,(byte)0xd7,(byte)0xaf },
162 {(byte)0x00,(byte)0xd7,(byte)0xd7 },
163 {(byte)0x00,(byte)0xd7,(byte)0xff },
164 {(byte)0x00,(byte)0xff,(byte)0x00 },
165 {(byte)0x00,(byte)0xff,(byte)0x5f },
166 {(byte)0x00,(byte)0xff,(byte)0x87 },
167 {(byte)0x00,(byte)0xff,(byte)0xaf },
168 {(byte)0x00,(byte)0xff,(byte)0xd7 },
169 {(byte)0x00,(byte)0xff,(byte)0xff },
170 {(byte)0x5f,(byte)0x00,(byte)0x00 },
171 {(byte)0x5f,(byte)0x00,(byte)0x5f },
172 {(byte)0x5f,(byte)0x00,(byte)0x87 },
173 {(byte)0x5f,(byte)0x00,(byte)0xaf },
174 {(byte)0x5f,(byte)0x00,(byte)0xd7 },
175 {(byte)0x5f,(byte)0x00,(byte)0xff },
176 {(byte)0x5f,(byte)0x5f,(byte)0x00 },
177 {(byte)0x5f,(byte)0x5f,(byte)0x5f },
178 {(byte)0x5f,(byte)0x5f,(byte)0x87 },
179 {(byte)0x5f,(byte)0x5f,(byte)0xaf },
180 {(byte)0x5f,(byte)0x5f,(byte)0xd7 },
181 {(byte)0x5f,(byte)0x5f,(byte)0xff },
182 {(byte)0x5f,(byte)0x87,(byte)0x00 },
183 {(byte)0x5f,(byte)0x87,(byte)0x5f },
184 {(byte)0x5f,(byte)0x87,(byte)0x87 },
185 {(byte)0x5f,(byte)0x87,(byte)0xaf },
186 {(byte)0x5f,(byte)0x87,(byte)0xd7 },
187 {(byte)0x5f,(byte)0x87,(byte)0xff },
188 {(byte)0x5f,(byte)0xaf,(byte)0x00 },
189 {(byte)0x5f,(byte)0xaf,(byte)0x5f },
190 {(byte)0x5f,(byte)0xaf,(byte)0x87 },
191 {(byte)0x5f,(byte)0xaf,(byte)0xaf },
192 {(byte)0x5f,(byte)0xaf,(byte)0xd7 },
193 {(byte)0x5f,(byte)0xaf,(byte)0xff },
194 {(byte)0x5f,(byte)0xd7,(byte)0x00 },
195 {(byte)0x5f,(byte)0xd7,(byte)0x5f },
196 {(byte)0x5f,(byte)0xd7,(byte)0x87 },
197 {(byte)0x5f,(byte)0xd7,(byte)0xaf },
198 {(byte)0x5f,(byte)0xd7,(byte)0xd7 },
199 {(byte)0x5f,(byte)0xd7,(byte)0xff },
200 {(byte)0x5f,(byte)0xff,(byte)0x00 },
201 {(byte)0x5f,(byte)0xff,(byte)0x5f },
202 {(byte)0x5f,(byte)0xff,(byte)0x87 },
203 {(byte)0x5f,(byte)0xff,(byte)0xaf },
204 {(byte)0x5f,(byte)0xff,(byte)0xd7 },
205 {(byte)0x5f,(byte)0xff,(byte)0xff },
206 {(byte)0x87,(byte)0x00,(byte)0x00 },
207 {(byte)0x87,(byte)0x00,(byte)0x5f },
208 {(byte)0x87,(byte)0x00,(byte)0x87 },
209 {(byte)0x87,(byte)0x00,(byte)0xaf },
210 {(byte)0x87,(byte)0x00,(byte)0xd7 },
211 {(byte)0x87,(byte)0x00,(byte)0xff },
212 {(byte)0x87,(byte)0x5f,(byte)0x00 },
213 {(byte)0x87,(byte)0x5f,(byte)0x5f },
214 {(byte)0x87,(byte)0x5f,(byte)0x87 },
215 {(byte)0x87,(byte)0x5f,(byte)0xaf },
216 {(byte)0x87,(byte)0x5f,(byte)0xd7 },
217 {(byte)0x87,(byte)0x5f,(byte)0xff },
218 {(byte)0x87,(byte)0x87,(byte)0x00 },
219 {(byte)0x87,(byte)0x87,(byte)0x5f },
220 {(byte)0x87,(byte)0x87,(byte)0x87 },
221 {(byte)0x87,(byte)0x87,(byte)0xaf },
222 {(byte)0x87,(byte)0x87,(byte)0xd7 },
223 {(byte)0x87,(byte)0x87,(byte)0xff },
224 {(byte)0x87,(byte)0xaf,(byte)0x00 },
225 {(byte)0x87,(byte)0xaf,(byte)0x5f },
226 {(byte)0x87,(byte)0xaf,(byte)0x87 },
227 {(byte)0x87,(byte)0xaf,(byte)0xaf },
228 {(byte)0x87,(byte)0xaf,(byte)0xd7 },
229 {(byte)0x87,(byte)0xaf,(byte)0xff },
230 {(byte)0x87,(byte)0xd7,(byte)0x00 },
231 {(byte)0x87,(byte)0xd7,(byte)0x5f },
232 {(byte)0x87,(byte)0xd7,(byte)0x87 },
233 {(byte)0x87,(byte)0xd7,(byte)0xaf },
234 {(byte)0x87,(byte)0xd7,(byte)0xd7 },
235 {(byte)0x87,(byte)0xd7,(byte)0xff },
236 {(byte)0x87,(byte)0xff,(byte)0x00 },
237 {(byte)0x87,(byte)0xff,(byte)0x5f },
238 {(byte)0x87,(byte)0xff,(byte)0x87 },
239 {(byte)0x87,(byte)0xff,(byte)0xaf },
240 {(byte)0x87,(byte)0xff,(byte)0xd7 },
241 {(byte)0x87,(byte)0xff,(byte)0xff },
242 {(byte)0xaf,(byte)0x00,(byte)0x00 },
243 {(byte)0xaf,(byte)0x00,(byte)0x5f },
244 {(byte)0xaf,(byte)0x00,(byte)0x87 },
245 {(byte)0xaf,(byte)0x00,(byte)0xaf },
246 {(byte)0xaf,(byte)0x00,(byte)0xd7 },
247 {(byte)0xaf,(byte)0x00,(byte)0xff },
248 {(byte)0xaf,(byte)0x5f,(byte)0x00 },
249 {(byte)0xaf,(byte)0x5f,(byte)0x5f },
250 {(byte)0xaf,(byte)0x5f,(byte)0x87 },
251 {(byte)0xaf,(byte)0x5f,(byte)0xaf },
252 {(byte)0xaf,(byte)0x5f,(byte)0xd7 },
253 {(byte)0xaf,(byte)0x5f,(byte)0xff },
254 {(byte)0xaf,(byte)0x87,(byte)0x00 },
255 {(byte)0xaf,(byte)0x87,(byte)0x5f },
256 {(byte)0xaf,(byte)0x87,(byte)0x87 },
257 {(byte)0xaf,(byte)0x87,(byte)0xaf },
258 {(byte)0xaf,(byte)0x87,(byte)0xd7 },
259 {(byte)0xaf,(byte)0x87,(byte)0xff },
260 {(byte)0xaf,(byte)0xaf,(byte)0x00 },
261 {(byte)0xaf,(byte)0xaf,(byte)0x5f },
262 {(byte)0xaf,(byte)0xaf,(byte)0x87 },
263 {(byte)0xaf,(byte)0xaf,(byte)0xaf },
264 {(byte)0xaf,(byte)0xaf,(byte)0xd7 },
265 {(byte)0xaf,(byte)0xaf,(byte)0xff },
266 {(byte)0xaf,(byte)0xd7,(byte)0x00 },
267 {(byte)0xaf,(byte)0xd7,(byte)0x5f },
268 {(byte)0xaf,(byte)0xd7,(byte)0x87 },
269 {(byte)0xaf,(byte)0xd7,(byte)0xaf },
270 {(byte)0xaf,(byte)0xd7,(byte)0xd7 },
271 {(byte)0xaf,(byte)0xd7,(byte)0xff },
272 {(byte)0xaf,(byte)0xff,(byte)0x00 },
273 {(byte)0xaf,(byte)0xff,(byte)0x5f },
274 {(byte)0xaf,(byte)0xff,(byte)0x87 },
275 {(byte)0xaf,(byte)0xff,(byte)0xaf },
276 {(byte)0xaf,(byte)0xff,(byte)0xd7 },
277 {(byte)0xaf,(byte)0xff,(byte)0xff },
278 {(byte)0xd7,(byte)0x00,(byte)0x00 },
279 {(byte)0xd7,(byte)0x00,(byte)0x5f },
280 {(byte)0xd7,(byte)0x00,(byte)0x87 },
281 {(byte)0xd7,(byte)0x00,(byte)0xaf },
282 {(byte)0xd7,(byte)0x00,(byte)0xd7 },
283 {(byte)0xd7,(byte)0x00,(byte)0xff },
284 {(byte)0xd7,(byte)0x5f,(byte)0x00 },
285 {(byte)0xd7,(byte)0x5f,(byte)0x5f },
286 {(byte)0xd7,(byte)0x5f,(byte)0x87 },
287 {(byte)0xd7,(byte)0x5f,(byte)0xaf },
288 {(byte)0xd7,(byte)0x5f,(byte)0xd7 },
289 {(byte)0xd7,(byte)0x5f,(byte)0xff },
290 {(byte)0xd7,(byte)0x87,(byte)0x00 },
291 {(byte)0xd7,(byte)0x87,(byte)0x5f },
292 {(byte)0xd7,(byte)0x87,(byte)0x87 },
293 {(byte)0xd7,(byte)0x87,(byte)0xaf },
294 {(byte)0xd7,(byte)0x87,(byte)0xd7 },
295 {(byte)0xd7,(byte)0x87,(byte)0xff },
296 {(byte)0xd7,(byte)0xaf,(byte)0x00 },
297 {(byte)0xd7,(byte)0xaf,(byte)0x5f },
298 {(byte)0xd7,(byte)0xaf,(byte)0x87 },
299 {(byte)0xd7,(byte)0xaf,(byte)0xaf },
300 {(byte)0xd7,(byte)0xaf,(byte)0xd7 },
301 {(byte)0xd7,(byte)0xaf,(byte)0xff },
302 {(byte)0xd7,(byte)0xd7,(byte)0x00 },
303 {(byte)0xd7,(byte)0xd7,(byte)0x5f },
304 {(byte)0xd7,(byte)0xd7,(byte)0x87 },
305 {(byte)0xd7,(byte)0xd7,(byte)0xaf },
306 {(byte)0xd7,(byte)0xd7,(byte)0xd7 },
307 {(byte)0xd7,(byte)0xd7,(byte)0xff },
308 {(byte)0xd7,(byte)0xff,(byte)0x00 },
309 {(byte)0xd7,(byte)0xff,(byte)0x5f },
310 {(byte)0xd7,(byte)0xff,(byte)0x87 },
311 {(byte)0xd7,(byte)0xff,(byte)0xaf },
312 {(byte)0xd7,(byte)0xff,(byte)0xd7 },
313 {(byte)0xd7,(byte)0xff,(byte)0xff },
314 {(byte)0xff,(byte)0x00,(byte)0x00 },
315 {(byte)0xff,(byte)0x00,(byte)0x5f },
316 {(byte)0xff,(byte)0x00,(byte)0x87 },
317 {(byte)0xff,(byte)0x00,(byte)0xaf },
318 {(byte)0xff,(byte)0x00,(byte)0xd7 },
319 {(byte)0xff,(byte)0x00,(byte)0xff },
320 {(byte)0xff,(byte)0x5f,(byte)0x00 },
321 {(byte)0xff,(byte)0x5f,(byte)0x5f },
322 {(byte)0xff,(byte)0x5f,(byte)0x87 },
323 {(byte)0xff,(byte)0x5f,(byte)0xaf },
324 {(byte)0xff,(byte)0x5f,(byte)0xd7 },
325 {(byte)0xff,(byte)0x5f,(byte)0xff },
326 {(byte)0xff,(byte)0x87,(byte)0x00 },
327 {(byte)0xff,(byte)0x87,(byte)0x5f },
328 {(byte)0xff,(byte)0x87,(byte)0x87 },
329 {(byte)0xff,(byte)0x87,(byte)0xaf },
330 {(byte)0xff,(byte)0x87,(byte)0xd7 },
331 {(byte)0xff,(byte)0x87,(byte)0xff },
332 {(byte)0xff,(byte)0xaf,(byte)0x00 },
333 {(byte)0xff,(byte)0xaf,(byte)0x5f },
334 {(byte)0xff,(byte)0xaf,(byte)0x87 },
335 {(byte)0xff,(byte)0xaf,(byte)0xaf },
336 {(byte)0xff,(byte)0xaf,(byte)0xd7 },
337 {(byte)0xff,(byte)0xaf,(byte)0xff },
338 {(byte)0xff,(byte)0xd7,(byte)0x00 },
339 {(byte)0xff,(byte)0xd7,(byte)0x5f },
340 {(byte)0xff,(byte)0xd7,(byte)0x87 },
341 {(byte)0xff,(byte)0xd7,(byte)0xaf },
342 {(byte)0xff,(byte)0xd7,(byte)0xd7 },
343 {(byte)0xff,(byte)0xd7,(byte)0xff },
344 {(byte)0xff,(byte)0xff,(byte)0x00 },
345 {(byte)0xff,(byte)0xff,(byte)0x5f },
346 {(byte)0xff,(byte)0xff,(byte)0x87 },
347 {(byte)0xff,(byte)0xff,(byte)0xaf },
348 {(byte)0xff,(byte)0xff,(byte)0xd7 },
349 {(byte)0xff,(byte)0xff,(byte)0xff },
350
351 //Grey-scale ramp from 232
352 {(byte)0x08,(byte)0x08,(byte)0x08 },
353 {(byte)0x12,(byte)0x12,(byte)0x12 },
354 {(byte)0x1c,(byte)0x1c,(byte)0x1c },
355 {(byte)0x26,(byte)0x26,(byte)0x26 },
356 {(byte)0x30,(byte)0x30,(byte)0x30 },
357 {(byte)0x3a,(byte)0x3a,(byte)0x3a },
358 {(byte)0x44,(byte)0x44,(byte)0x44 },
359 {(byte)0x4e,(byte)0x4e,(byte)0x4e },
360 {(byte)0x58,(byte)0x58,(byte)0x58 },
361 {(byte)0x62,(byte)0x62,(byte)0x62 },
362 {(byte)0x6c,(byte)0x6c,(byte)0x6c },
363 {(byte)0x76,(byte)0x76,(byte)0x76 },
364 {(byte)0x80,(byte)0x80,(byte)0x80 },
365 {(byte)0x8a,(byte)0x8a,(byte)0x8a },
366 {(byte)0x94,(byte)0x94,(byte)0x94 },
367 {(byte)0x9e,(byte)0x9e,(byte)0x9e },
368 {(byte)0xa8,(byte)0xa8,(byte)0xa8 },
369 {(byte)0xb2,(byte)0xb2,(byte)0xb2 },
370 {(byte)0xbc,(byte)0xbc,(byte)0xbc },
371 {(byte)0xc6,(byte)0xc6,(byte)0xc6 },
372 {(byte)0xd0,(byte)0xd0,(byte)0xd0 },
373 {(byte)0xda,(byte)0xda,(byte)0xda },
374 {(byte)0xe4,(byte)0xe4,(byte)0xe4 },
375 {(byte)0xee,(byte)0xee,(byte)0xee }
376 };
377
378 private final int colorIndex;
379 private final Color awtColor;
380
381 /**
382 * Creates a new TextColor using the XTerm 256 color indexed mode, with the specified index value. You must
383 * choose a value between 0 and 255.
384 * @param colorIndex Index value to use for this color.
385 */
386 public Indexed(int colorIndex) {
387 if(colorIndex > 255 || colorIndex < 0) {
388 throw new IllegalArgumentException("Cannot create a Color.Indexed with a color index of " + colorIndex +
389 ", must be in the range of 0-255");
390 }
391 this.colorIndex = colorIndex;
392 this.awtColor = new Color(COLOR_TABLE[colorIndex][0] & 0x000000ff,
393 COLOR_TABLE[colorIndex][1] & 0x000000ff,
394 COLOR_TABLE[colorIndex][2] & 0x000000ff);
395 }
396
397 @Override
398 public byte[] getForegroundSGRSequence() {
399 return ("38;5;" + colorIndex).getBytes();
400 }
401
402 @Override
403 public byte[] getBackgroundSGRSequence() {
404 return ("48;5;" + colorIndex).getBytes();
405 }
406
407 @Override
408 public Color toColor() {
409 return awtColor;
410 }
411
412 @Override
413 public String toString() {
414 return "{IndexedColor:" + colorIndex + "}";
415 }
416
417 @Override
418 public int hashCode() {
419 int hash = 3;
420 hash = 43 * hash + this.colorIndex;
421 return hash;
422 }
423
424 @Override
425 public boolean equals(Object obj) {
426 if(obj == null) {
427 return false;
428 }
429 if(getClass() != obj.getClass()) {
430 return false;
431 }
432 final Indexed other = (Indexed) obj;
433 return this.colorIndex == other.colorIndex;
434 }
435
436 /**
437 * Picks out a color approximated from the supplied RGB components
438 * @param red Red intensity, from 0 to 255
439 * @param green Red intensity, from 0 to 255
440 * @param blue Red intensity, from 0 to 255
441 * @return Nearest color from the 6x6x6 RGB color cube or from the 24 entries grey-scale ramp (whichever is closest)
442 */
443 public static Indexed fromRGB(int red, int green, int blue) {
444 if(red < 0 || red > 255) {
445 throw new IllegalArgumentException("fromRGB: red is outside of valid range (0-255)");
446 }
447 if(green < 0 || green > 255) {
448 throw new IllegalArgumentException("fromRGB: green is outside of valid range (0-255)");
449 }
450 if(blue < 0 || blue > 255) {
451 throw new IllegalArgumentException("fromRGB: blue is outside of valid range (0-255)");
452 }
453
454 int rescaledRed = (int)(((double)red / 255.0) * 5.0);
455 int rescaledGreen = (int)(((double)green / 255.0) * 5.0);
456 int rescaledBlue = (int)(((double)blue / 255.0) * 5.0);
457
458 int index = rescaledBlue + (6 * rescaledGreen) + (36 * rescaledRed) + 16;
459 Indexed fromColorCube = new Indexed(index);
460 Indexed fromGreyRamp = fromGreyRamp((red + green + blue) / 3);
461
462 //Now figure out which one is closest
463 Color colored = fromColorCube.toColor();
464 Color grey = fromGreyRamp.toColor();
465 int coloredDistance = ((red - colored.getRed()) * (red - colored.getRed())) +
466 ((green - colored.getGreen()) * (green - colored.getGreen())) +
467 ((blue - colored.getBlue()) * (blue - colored.getBlue()));
468 int greyDistance = ((red - grey.getRed()) * (red - grey.getRed())) +
469 ((green - grey.getGreen()) * (green - grey.getGreen())) +
470 ((blue - grey.getBlue()) * (blue - grey.getBlue()));
471 if(coloredDistance < greyDistance) {
472 return fromColorCube;
473 }
474 else {
475 return fromGreyRamp;
476 }
477 }
478
479 /**
480 * Picks out a color from the grey-scale ramp area of the color index.
481 * @param intensity Intensity, 0 - 255
482 * @return Indexed color from the grey-scale ramp which is the best match for the supplied intensity
483 */
484 private static Indexed fromGreyRamp(int intensity) {
485 int rescaled = (int)(((double)intensity / 255.0) * 23.0) + 232;
486 return new Indexed(rescaled);
487 }
488 }
489
490 /**
491 * This class can be used to specify a color in 24-bit color space (RGB with 8-bit resolution per color). Please be
492 * aware that only a few terminal support 24-bit color control codes, please avoid using this class unless you know
493 * all users will have compatible terminals. For details, please see
494 * <a href="https://github.com/robertknight/konsole/blob/master/user-doc/README.moreColors">
495 * this</a> commit log. Behavior on terminals that don't support these codes is undefined.
496 */
497 class RGB implements TextColor {
498 private final Color color;
499
500 /**
501 * This class can be used to specify a color in 24-bit color space (RGB with 8-bit resolution per color). Please be
502 * aware that only a few terminal support 24-bit color control codes, please avoid using this class unless you know
503 * all users will have compatible terminals. For details, please see
504 * <a href="https://github.com/robertknight/konsole/blob/master/user-doc/README.moreColors">
505 * this</a> commit log. Behavior on terminals that don't support these codes is undefined.
506 *
507 * @param r Red intensity, from 0 to 255
508 * @param g Green intensity, from 0 to 255
509 * @param b Blue intensity, from 0 to 255
510 */
511 public RGB(int r, int g, int b) {
512 if(r < 0 || r > 255) {
513 throw new IllegalArgumentException("RGB: r is outside of valid range (0-255)");
514 }
515 if(g < 0 || g > 255) {
516 throw new IllegalArgumentException("RGB: g is outside of valid range (0-255)");
517 }
518 if(b < 0 || b > 255) {
519 throw new IllegalArgumentException("RGB: b is outside of valid range (0-255)");
520 }
521 this.color = new Color(r, g, b);
522 }
523
524 @Override
525 public byte[] getForegroundSGRSequence() {
526 return ("38;2;" + getRed() + ";" + getGreen() + ";" + getBlue()).getBytes();
527 }
528
529 @Override
530 public byte[] getBackgroundSGRSequence() {
531 return ("48;2;" + getRed() + ";" + getGreen() + ";" + getBlue()).getBytes();
532 }
533
534 @Override
535 public Color toColor() {
536 return color;
537 }
538
539 /**
540 * @return Red intensity of this color, from 0 to 255
541 */
542 public int getRed() {
543 return color.getRed();
544 }
545
546 /**
547 * @return Green intensity of this color, from 0 to 255
548 */
549 public int getGreen() {
550 return color.getGreen();
551 }
552
553 /**
554 * @return Blue intensity of this color, from 0 to 255
555 */
556 public int getBlue() {
557 return color.getBlue();
558 }
559
560 @Override
561 public String toString() {
562 return "{RGB:" + getRed() + "," + getGreen() + "," + getBlue() + "}";
563 }
564
565 @Override
566 public int hashCode() {
567 int hash = 7;
568 hash = 29 * hash + color.hashCode();
569 return hash;
570 }
571
572 @SuppressWarnings("SimplifiableIfStatement")
573 @Override
574 public boolean equals(Object obj) {
575 if(obj == null) {
576 return false;
577 }
578 if(getClass() != obj.getClass()) {
579 return false;
580 }
581 final RGB other = (RGB) obj;
582 return color.equals(other.color);
583 }
584 }
585 }