19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guyimport android.annotation.AnyThread;
2080756e38882720860db52f1fcc21fa1505a02abfTor Norbyeimport android.annotation.ColorInt;
2177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guyimport android.annotation.ColorLong;
2277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guyimport android.annotation.HalfFloat;
2377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guyimport android.annotation.IntRange;
2477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guyimport android.annotation.NonNull;
25026a558ab0d9e710f385ea658687f385312b970eRomain Guyimport android.annotation.Nullable;
26b3ec733bb830f2d4425825d93f9ed95f284e9145Tor Norbyeimport android.annotation.Size;
27910e081216ac530432ac9d0aab10d5e5e4c73ab8Jeff Sharkeyimport android.annotation.SuppressAutoDoc;
2877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guyimport android.util.Half;
29a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guyimport com.android.internal.util.XmlUtils;
30a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy
3177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guyimport java.util.Arrays;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Locale;
3468bd5fdd1ad3cf0b74c225b31adf1f68393bfbb6Romain Guyimport java.util.function.DoubleUnaryOperator;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@usesMathJax}
3877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
3977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The <code>Color</code> class provides methods for creating, converting and
4077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * manipulating colors. Colors have three different representations:</p>
4177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <ul>
4277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>Color ints, the most common representation</li>
4377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>Color longs</li>
4477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li><code>Color</code> instances</li>
4577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </ul>
4677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The section below describe each representation in detail.</p>
4777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
4877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h3>Color ints</h3>
4977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>Color ints are the most common representation of colors on Android and
5077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * have been used since {@link android.os.Build.VERSION_CODES#BASE API level 1}.</p>
5177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
5277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>A color int always defines a color in the {@link ColorSpace.Named#SRGB sRGB}
5377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * color space using 4 components packed in a single 32 bit integer value:</p>
5477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
5577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <table summary="Color int definition">
5677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr>
5777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *         <th>Component</th><th>Name</th><th>Size</th><th>Range</th>
5877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     </tr>
5977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>A</td><td>Alpha</td><td>8 bits</td><td>\([0..255]\)</td></tr>
6077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>R</td><td>Red</td><td>8 bits</td><td>\([0..255]\)</td></tr>
6177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>G</td><td>Green</td><td>8 bits</td><td>\([0..255]\)</td></tr>
6277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>B</td><td>Blue</td><td>8 bits</td><td>\([0..255]\)</td></tr>
6377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </table>
6477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
6577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The components in this table are listed in encoding order (see below),
6677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * which is why color ints are called ARGB colors.</p>
6777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
6877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h4>Usage in code</h4>
6977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>To avoid confusing color ints with arbitrary integer values, it is a
7077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * good practice to annotate them with the <code>@ColorInt</code> annotation
7177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * found in the Android Support Library.</p>
7277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
7377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h4>Encoding</h4>
7477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The four components of a color int are encoded in the following way:</p>
7577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <pre class="prettyprint">
76d4012d6505c8b5368ee4607d54fb98d0a96ec136Romain Guy * int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff);
7777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </pre>
7877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
7977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>Because of this encoding, color ints can easily be described as an integer
8077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * constant in source. For instance, opaque blue is <code>0xff0000ff</code>
8177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * and yellow is <code>0xffffff00</code>.</p>
8277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
8377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>To easily encode color ints, it is recommended to use the static methods
8477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link #argb(int, int, int, int)} and {@link #rgb(int, int, int)}. The second
8577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * method omits the alpha component and assumes the color is opaque (alpha is 255).
8677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * As a convenience this class also offers methods to encode color ints from components
8777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * defined in the \([0..1]\) range: {@link #argb(float, float, float, float)} and
8877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link #rgb(float, float, float)}.</p>
8977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
9077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>Color longs (defined below) can be easily converted to color ints by invoking
9177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * the {@link #toArgb(long)} method. This method performs a color space conversion
9277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * if needed.</p>
9377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
9477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>It is also possible to create a color int by invoking the method {@link #toArgb()}
9577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * on a color instance.</p>
9677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
9777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h4>Decoding</h4>
9877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The four ARGB components can be individually extracted from a color int
9977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * using the following expressions:</p>
10077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <pre class="prettyprint">
10177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * int A = (color >> 24) & 0xff; // or color >>> 24
10277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * int R = (color >> 16) & 0xff;
10377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * int G = (color >>  8) & 0xff;
10477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * int B = (color      ) & 0xff;
10577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </pre>
10677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
10777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>This class offers convenience methods to easily extract these components:</p>
10877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <ul>
10977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #alpha(int)} to extract the alpha component</li>
11077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #red(int)} to extract the red component</li>
11177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #green(int)} to extract the green component</li>
11277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #blue(int)} to extract the blue component</li>
11377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </ul>
11477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
11577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h3>Color longs</h3>
11677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>Color longs are a representation introduced in
11777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link android.os.Build.VERSION_CODES#O Android O} to store colors in different
11877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link ColorSpace color spaces}, with more precision than color ints.</p>
11977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
12077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>A color long always defines a color using 4 components packed in a single
12177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * 64 bit long value. One of these components is always alpha while the other
12277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * three components depend on the color space's {@link ColorSpace.Model color model}.
12377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * The most common color model is the {@link ColorSpace.Model#RGB RGB} model in
12477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * which the components represent red, green and blue values.</p>
12577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
12677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p class="note"><b>Component ranges:</b> the ranges defined in the tables
12777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * below indicate the ranges that can be encoded in a color long. They do not
12877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * represent the actual ranges as they may differ per color space. For instance,
12977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * the RGB components of a color in the {@link ColorSpace.Named#DISPLAY_P3 Display P3}
13077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * color space use the \([0..1]\) range. Please refer to the documentation of the
13177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * various {@link ColorSpace.Named color spaces} to find their respective ranges.</p>
13277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
13377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p class="note"><b>Alpha range:</b> while alpha is encoded in a color long using
13477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * a 10 bit integer (thus using a range of \([0..1023]\)), it is converted to and
13577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * from \([0..1]\) float values when decoding and encoding color longs.</p>
13677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
13777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p class="note"><b>sRGB color space:</b> for compatibility reasons and ease of
13877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * use, color longs encoding {@link ColorSpace.Named#SRGB sRGB} colors do not
13977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * use the same encoding as other color longs.</p>
14077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
14177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <table summary="Color long definition">
14277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr>
14377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *         <th>Component</th><th>Name</th><th>Size</th><th>Range</th>
14477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     </tr>
14577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td colspan="4">{@link ColorSpace.Model#RGB RGB} color model</td></tr>
14677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>R</td><td>Red</td><td>16 bits</td><td>\([-65504.0, 65504.0]\)</td></tr>
14777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>G</td><td>Green</td><td>16 bits</td><td>\([-65504.0, 65504.0]\)</td></tr>
14877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>B</td><td>Blue</td><td>16 bits</td><td>\([-65504.0, 65504.0]\)</td></tr>
14977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>A</td><td>Alpha</td><td>10 bits</td><td>\([0..1023]\)</td></tr>
15077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td></td><td>Color space</td><td>6 bits</td><td>\([0..63]\)</td></tr>
15177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td colspan="4">{@link ColorSpace.Named#SRGB sRGB} color space</td></tr>
15277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>A</td><td>Alpha</td><td>8 bits</td><td>\([0..255]\)</td></tr>
15377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>R</td><td>Red</td><td>8 bits</td><td>\([0..255]\)</td></tr>
15477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>G</td><td>Green</td><td>8 bits</td><td>\([0..255]\)</td></tr>
15577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>B</td><td>Blue</td><td>8 bits</td><td>\([0..255]\)</td></tr>
15677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>X</td><td>Unused</td><td>32 bits</td><td>\(0\)</td></tr>
15777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td colspan="4">{@link ColorSpace.Model#XYZ XYZ} color model</td></tr>
15877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>X</td><td>X</td><td>16 bits</td><td>\([-65504.0, 65504.0]\)</td></tr>
15977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>Y</td><td>Y</td><td>16 bits</td><td>\([-65504.0, 65504.0]\)</td></tr>
16077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>Z</td><td>Z</td><td>16 bits</td><td>\([-65504.0, 65504.0]\)</td></tr>
16177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>A</td><td>Alpha</td><td>10 bits</td><td>\([0..1023]\)</td></tr>
16277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td></td><td>Color space</td><td>6 bits</td><td>\([0..63]\)</td></tr>
16377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td colspan="4">{@link ColorSpace.Model#XYZ Lab} color model</td></tr>
16477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>L</td><td>L</td><td>16 bits</td><td>\([-65504.0, 65504.0]\)</td></tr>
16577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>a</td><td>a</td><td>16 bits</td><td>\([-65504.0, 65504.0]\)</td></tr>
16677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>b</td><td>b</td><td>16 bits</td><td>\([-65504.0, 65504.0]\)</td></tr>
16777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td>A</td><td>Alpha</td><td>10 bits</td><td>\([0..1023]\)</td></tr>
16877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td></td><td>Color space</td><td>6 bits</td><td>\([0..63]\)</td></tr>
16977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td colspan="4">{@link ColorSpace.Model#CMYK CMYK} color model</td></tr>
17077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <tr><td colspan="4">Unsupported</td></tr>
17177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </table>
17277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
17377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The components in this table are listed in encoding order (see below),
17477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * which is why color longs in the RGB model are called RGBA colors (even if
17577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * this doesn't quite hold for the special case of sRGB colors).</p>
17677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
17777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The color long encoding relies on half-precision float values (fp16). If you
17877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * wish to know more about the limitations of half-precision float values, please
17977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * refer to the documentation of the {@link Half} class.</p>
18077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
18177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h4>Usage in code</h4>
18277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>To avoid confusing color longs with arbitrary long values, it is a
18377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * good practice to annotate them with the <code>@ColorLong</code> annotation
18477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * found in the Android Support Library.</p>
18577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
18677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h4>Encoding</h4>
18777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
18877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>Given the complex nature of color longs, it is strongly encouraged to use
18977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * the various methods provided by this class to encode them.</p>
19077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
19177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The most flexible way to encode a color long is to use the method
19277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link #pack(float, float, float, float, ColorSpace)}. This method allows you
19377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * to specify three color components (typically RGB), an alpha component and a
19477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * color space. To encode sRGB colors, use {@link #pack(float, float, float)}
19577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * and {@link #pack(float, float, float, float)} which are the
19677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * equivalent of {@link #rgb(int, int, int)} and {@link #argb(int, int, int, int)}
19777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * for color ints. If you simply need to convert a color int into a color long,
19877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * use {@link #pack(int)}.</p>
19977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
20077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>It is also possible to create a color long value by invoking the method
20177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link #pack()} on a color instance.</p>
20277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
20377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h4>Decoding</h4>
20477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
20577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>This class offers convenience methods to easily extract the components
20677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * of a color long:</p>
20777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <ul>
20877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #alpha(long)} to extract the alpha component</li>
20977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #red(long)} to extract the red/X/L component</li>
21077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #green(long)} to extract the green/Y/a component</li>
21177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #blue(long)} to extract the blue/Z/b component</li>
21277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </ul>
21377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
21477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The values returned by these methods depend on the color space encoded
21577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * in the color long. The values are however typically in the \([0..1]\) range
21677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * for RGB colors. Please refer to the documentation of the various
21777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link ColorSpace.Named color spaces} for the exact ranges.</p>
21877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
21977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h3>Color instances</h3>
22077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>Color instances are a representation introduced in
22177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link android.os.Build.VERSION_CODES#O Android O} to store colors in different
22277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link ColorSpace color spaces}, with more precision than both color ints and
22377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * color longs. Color instances also offer the ability to store more than 4
22477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * components if necessary.</p>
22577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
22677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>Colors instances are immutable and can be created using one of the various
22777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <code>valueOf</code> methods. For instance:</p>
22877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <pre class="prettyprint">
22977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * // sRGB
23077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * Color opaqueRed = Color.valueOf(0xffff0000); // from a color int
23177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * Color translucentRed = Color.valueOf(1.0f, 0.0f, 0.0f, 0.5f);
23277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
23377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * // Wide gamut color
23477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@literal @}ColorLong long p3 = pack(1.0f, 1.0f, 0.0f, 1.0f, colorSpaceP3);
23577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * Color opaqueYellow = Color.valueOf(p3); // from a color long
23677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
23777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * // CIE L*a*b* color space
23877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * ColorSpace lab = ColorSpace.get(ColorSpace.Named.LAB);
23977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * Color green = Color.valueOf(100.0f, -128.0f, 128.0f, 1.0f, lab);
24077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </pre>
24177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
24277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>Color instances can be converted to color ints ({@link #toArgb()}) or
24377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * color longs ({@link #pack()}). They also offer easy access to their various
24477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * components using the following methods:</p>
24577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <ul>
24677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #alpha()}, returns the alpha component value</li>
24777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #red()}, returns the red component value (or first
24877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     component value in non-RGB models)</li>
24977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #green()}, returns the green component value (or second
25077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     component value in non-RGB models)</li>
25177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #blue()}, returns the blue component value (or third
25277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     component value in non-RGB models)</li>
25377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #getComponent(int)}, returns a specific component value</li>
25477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #getComponents()}, returns all component values as an array</li>
25577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </ul>
25677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
25777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h3>Color space conversions</h3>
25877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>You can convert colors from one color space to another using
25977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * {@link ColorSpace#connect(ColorSpace, ColorSpace)} and its variants. However,
26077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * the <code>Color</code> class provides a few convenience methods to simplify
26177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * the process. Here is a brief description of some of them:</p>
26277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <ul>
26377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #convert(ColorSpace)} to convert a color instance in a color
26477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     space to a new color instance in a different color space</li>
26577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #convert(float, float, float, float, ColorSpace, ColorSpace)} to
26677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     convert a color from a source color space to a destination color space</li>
26777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #convert(long, ColorSpace)} to convert a color long from its
26877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     built-in color space to a destination color space</li>
26977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     <li>{@link #convert(int, ColorSpace)} to convert a color int from sRGB
27077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *     to a destination color space</li>
27177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * </ul>
27277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
27377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>Please refere to the {@link ColorSpace} documentation for more
27477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * information.</p>
27577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
27677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <h3>Alpha and transparency</h3>
27777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The alpha component of a color defines the level of transparency of a
27877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * color. When the alpha component is 0, the color is completely transparent.
27977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * When the alpha is component is 1 (in the \([0..1]\) range) or 255 (in the
28077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * \([0..255]\) range), the color is completely opaque.</p>
28177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy *
28277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <p>The color representations described above do not use pre-multiplied
28377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * color components (a pre-multiplied color component is a color component
28477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * that has been multiplied by the value of the alpha component).
28577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * For instance, the color int representation of opaque red is
28677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * <code>0xffff0000</code>. For semi-transparent (50%) red, the
28777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * representation becomes <code>0x80ff0000</code>. The equivalent color
28877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * instance representations would be <code>(1.0, 0.0, 0.0, 1.0)</code>
28977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy * and <code>(1.0, 0.0, 0.0, 0.5)</code>.</p>
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
29177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy@AnyThread
292910e081216ac530432ac9d0aab10d5e5e4c73ab8Jeff Sharkey@SuppressAutoDoc
293bae8b52c71766ea1a6e59382f8b76e2013f358f9Romain Guypublic class Color {
29480756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int BLACK       = 0xFF000000;
29580756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int DKGRAY      = 0xFF444444;
29680756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int GRAY        = 0xFF888888;
29780756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int LTGRAY      = 0xFFCCCCCC;
29880756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int WHITE       = 0xFFFFFFFF;
29980756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int RED         = 0xFFFF0000;
30080756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int GREEN       = 0xFF00FF00;
30180756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int BLUE        = 0xFF0000FF;
30280756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int YELLOW      = 0xFFFFFF00;
30380756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int CYAN        = 0xFF00FFFF;
30480756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int MAGENTA     = 0xFFFF00FF;
30580756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt public static final int TRANSPARENT = 0;
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
30877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @Size(min = 4, max = 5)
30977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    private final float[] mComponents;
31077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
31177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
31277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    private final ColorSpace mColorSpace;
31377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
31477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
31577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Creates a new color instance set to opaque black in the
31677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace.Named#SRGB sRGB} color space.
31777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
31877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #valueOf(float, float, float)
31977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #valueOf(float, float, float, float)
32077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #valueOf(float, float, float, float, ColorSpace)
32177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #valueOf(float[], ColorSpace)
32277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #valueOf(int)
32377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #valueOf(long)
32477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
32577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public Color() {
32677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        // This constructor is required for compatibility with previous APIs
32777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        mComponents = new float[] { 0.0f, 0.0f, 0.0f, 1.0f };
32877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
32977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
33077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
33177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
33277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Creates a new color instance in the {@link ColorSpace.Named#SRGB sRGB}
33377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space.
33477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
33577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param r The value of the red channel, must be in [0..1] range
33677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param g The value of the green channel, must be in [0..1] range
33777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param b The value of the blue channel, must be in [0..1] range
33877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param a The value of the alpha channel, must be in [0..1] range
33977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
34077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    private Color(float r, float g, float b, float a) {
34177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        this(r, g, b, a, ColorSpace.get(ColorSpace.Named.SRGB));
34277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
34377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
34477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
34577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Creates a new color instance in the specified color space. The color space
34677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * must have a 3 components model.
34777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
34877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param r The value of the red channel, must be in the color space defined range
34977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param g The value of the green channel, must be in the color space defined range
35077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param b The value of the blue channel, must be in the color space defined range
35177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param a The value of the alpha channel, must be in [0..1] range
35277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param colorSpace This color's color space, cannot be null
35377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
35477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    private Color(float r, float g, float b, float a, @NonNull ColorSpace colorSpace) {
35577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        mComponents = new float[] { r, g, b, a };
35677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        mColorSpace = colorSpace;
35777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
35877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
35977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
36077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Creates a new color instance in the specified color space.
36177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
36277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param components An array of color components, plus alpha
36377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param colorSpace This color's color space, cannot be null
36477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
36577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    private Color(@Size(min = 4, max = 5) float[] components, @NonNull ColorSpace colorSpace) {
36677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        mComponents = components;
36777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        mColorSpace = colorSpace;
36877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
36977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
37077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
37177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns this color's color space.
37277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
37377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null instance of {@link ColorSpace}
37477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
37577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
37677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public ColorSpace getColorSpace() {
37777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return mColorSpace;
37877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
37977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
38077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
38177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns the color model of this color.
38277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
38377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null {@link ColorSpace.Model}
38477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
38577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public ColorSpace.Model getModel() {
38677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return mColorSpace.getModel();
38777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
38877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
38977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
39077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Indicates whether this color color is in a wide-gamut color space.
39177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * See {@link ColorSpace#isWideGamut()} for a definition of a wide-gamut
39277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space.
39377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
39477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return True if this color is in a wide-gamut color space, false otherwise
39577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
39677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #isSrgb()
39777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see ColorSpace#isWideGamut()
39877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
39977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public boolean isWideGamut() {
40077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return getColorSpace().isWideGamut();
40177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
40277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
40377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
40477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Indicates whether this color is in the {@link ColorSpace.Named#SRGB sRGB}
40577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space.
40677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
40777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return True if this color is in the sRGB color space, false otherwise
40877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
40977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #isWideGamut()
41077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
41177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public boolean isSrgb() {
41277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return getColorSpace().isSrgb();
41377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
41477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
41577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
41677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns the number of components that form a color value according
41777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * to this color space's color model, plus one extra component for
41877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * alpha.
41977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
420026a558ab0d9e710f385ea658687f385312b970eRomain Guy     * @return The integer 4 or 5
42177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
42277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @IntRange(from = 4, to = 5)
42377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public int getComponentCount() {
42477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return mColorSpace.getComponentCount() + 1;
42577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
42677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
42777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
42877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Packs this color into a color long. See the documentation of this class
42977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * for a description of the color long format.
43077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
43177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long
43277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
43377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @throws IllegalArgumentException If this color's color space has the id
43477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#MIN_ID} or if this color has more than 4 components
43577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
43677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
43777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public long pack() {
43877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return pack(mComponents[0], mComponents[1], mComponents[2], mComponents[3], mColorSpace);
43977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
44077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
44177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
44277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Converts this color from its color space to the specified color space.
44377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The conversion is done using the default rendering intent as specified
44477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * by {@link ColorSpace#connect(ColorSpace, ColorSpace)}.
44577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
44677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param colorSpace The destination color space, cannot be null
44777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
44877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null color instance in the specified color space
44977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
45077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
45177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public Color convert(@NonNull ColorSpace colorSpace) {
45277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        ColorSpace.Connector connector = ColorSpace.connect(mColorSpace, colorSpace);
45377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float[] color = new float[] {
45477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                mComponents[0], mComponents[1], mComponents[2], mComponents[3]
45577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        };
45677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        connector.transform(color);
45777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return new Color(color, colorSpace);
45877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
45977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
46077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
46177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Converts this color to an ARGB color int. A color int is always in
46277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * the {@link ColorSpace.Named#SRGB sRGB} color space. This implies
46377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * a color space conversion is applied if needed.
46477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
46577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return An ARGB color in the sRGB color space
46677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
46777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorInt
46877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public int toArgb() {
46977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (mColorSpace.isSrgb()) {
47077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            return ((int) (mComponents[3] * 255.0f + 0.5f) << 24) |
47177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                   ((int) (mComponents[0] * 255.0f + 0.5f) << 16) |
47277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                   ((int) (mComponents[1] * 255.0f + 0.5f) <<  8) |
47377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    (int) (mComponents[2] * 255.0f + 0.5f);
47477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        }
47577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
47677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float[] color = new float[] {
47777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                mComponents[0], mComponents[1], mComponents[2], mComponents[3]
47877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        };
47977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        // The transformation saturates the output
48077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        ColorSpace.connect(mColorSpace).transform(color);
48177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
48277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return ((int) (color[3] * 255.0f + 0.5f) << 24) |
48377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy               ((int) (color[0] * 255.0f + 0.5f) << 16) |
48477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy               ((int) (color[1] * 255.0f + 0.5f) <<  8) |
48577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                (int) (color[2] * 255.0f + 0.5f);
48677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
48777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
48877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
48977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Returns the value of the red component in the range defined by this
49077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color's color space (see {@link ColorSpace#getMinValue(int)} and
49177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#getMaxValue(int)}).</p>
49277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
49377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>If this color's color model is not {@link ColorSpace.Model#RGB RGB},
49477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * calling this method is equivalent to <code>getComponent(0)</code>.</p>
49577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
49677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #alpha()
49777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #red()
49877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #green
49977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #getComponents()
50077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
50177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public float red() {
50277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return mComponents[0];
50377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
50477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
50577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
50677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Returns the value of the green component in the range defined by this
50777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color's color space (see {@link ColorSpace#getMinValue(int)} and
50877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#getMaxValue(int)}).</p>
50977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
51077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>If this color's color model is not {@link ColorSpace.Model#RGB RGB},
51177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * calling this method is equivalent to <code>getComponent(1)</code>.</p>
51277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
51377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #alpha()
51477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #red()
51577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #green
51677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #getComponents()
51777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
51877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public float green() {
51977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return mComponents[1];
52077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
52177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
52277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
52377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Returns the value of the blue component in the range defined by this
52477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color's color space (see {@link ColorSpace#getMinValue(int)} and
52577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#getMaxValue(int)}).</p>
52677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
52777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>If this color's color model is not {@link ColorSpace.Model#RGB RGB},
52877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * calling this method is equivalent to <code>getComponent(2)</code>.</p>
52977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
53077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #alpha()
53177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #red()
53277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #green
53377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #getComponents()
53477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
53577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public float blue() {
53677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return mComponents[2];
53777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
53877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
53977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
54077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns the value of the alpha component in the range \([0..1]\).
54177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Calling this method is equivalent to
54226ca96ecb82cdbc058a39cebbfb16b402bf0fe03Romain Guy     * <code>getComponent(getComponentCount() - 1)</code>.
54377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
54477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #red()
54577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #green()
54677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #blue()
54777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #getComponents()
54877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #getComponent(int)
54977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
55077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public float alpha() {
55177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return mComponents[mComponents.length - 1];
55277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
55377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
55477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
55577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns this color's components as a new array. The last element of the
55677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * array is always the alpha component.
55777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
55877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A new, non-null array whose size is equal to {@link #getComponentCount()}
55977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
56077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #getComponent(int)
56177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
56277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
56377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @Size(min = 4, max = 5)
56477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public float[] getComponents() {
565026a558ab0d9e710f385ea658687f385312b970eRomain Guy        return Arrays.copyOf(mComponents, mComponents.length);
566026a558ab0d9e710f385ea658687f385312b970eRomain Guy    }
567026a558ab0d9e710f385ea658687f385312b970eRomain Guy
568026a558ab0d9e710f385ea658687f385312b970eRomain Guy    /**
569026a558ab0d9e710f385ea658687f385312b970eRomain Guy     * Copies this color's components in the supplied array. The last element of the
570026a558ab0d9e710f385ea658687f385312b970eRomain Guy     * array is always the alpha component.
571026a558ab0d9e710f385ea658687f385312b970eRomain Guy     *
572026a558ab0d9e710f385ea658687f385312b970eRomain Guy     * @param components An array of floats whose size must be at least
573026a558ab0d9e710f385ea658687f385312b970eRomain Guy     *                  {@link #getComponentCount()}, can be null
574026a558ab0d9e710f385ea658687f385312b970eRomain Guy     * @return The array passed as a parameter if not null, or a new array of length
575026a558ab0d9e710f385ea658687f385312b970eRomain Guy     *         {@link #getComponentCount()}
576026a558ab0d9e710f385ea658687f385312b970eRomain Guy     *
577026a558ab0d9e710f385ea658687f385312b970eRomain Guy     * @see #getComponent(int)
578026a558ab0d9e710f385ea658687f385312b970eRomain Guy     *
579026a558ab0d9e710f385ea658687f385312b970eRomain Guy     * @throws IllegalArgumentException If the specified array's length is less than
580026a558ab0d9e710f385ea658687f385312b970eRomain Guy     * {@link #getComponentCount()}
581026a558ab0d9e710f385ea658687f385312b970eRomain Guy     */
582026a558ab0d9e710f385ea658687f385312b970eRomain Guy    @NonNull
583026a558ab0d9e710f385ea658687f385312b970eRomain Guy    @Size(min = 4)
584026a558ab0d9e710f385ea658687f385312b970eRomain Guy    public float[] getComponents(@Nullable @Size(min = 4) float[] components) {
585026a558ab0d9e710f385ea658687f385312b970eRomain Guy        if (components == null) {
586026a558ab0d9e710f385ea658687f385312b970eRomain Guy            return Arrays.copyOf(mComponents, mComponents.length);
587026a558ab0d9e710f385ea658687f385312b970eRomain Guy        }
588026a558ab0d9e710f385ea658687f385312b970eRomain Guy
589026a558ab0d9e710f385ea658687f385312b970eRomain Guy        if (components.length < mComponents.length) {
590026a558ab0d9e710f385ea658687f385312b970eRomain Guy            throw new IllegalArgumentException("The specified array's length must be at "
591026a558ab0d9e710f385ea658687f385312b970eRomain Guy                    + "least " + mComponents.length);
592026a558ab0d9e710f385ea658687f385312b970eRomain Guy        }
593026a558ab0d9e710f385ea658687f385312b970eRomain Guy
594026a558ab0d9e710f385ea658687f385312b970eRomain Guy        System.arraycopy(mComponents, 0, components, 0, mComponents.length);
595026a558ab0d9e710f385ea658687f385312b970eRomain Guy        return components;
59677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
59777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
59877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
59977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Returns the value of the specified component in the range defined by
60077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * this color's color space (see {@link ColorSpace#getMinValue(int)} and
60177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#getMaxValue(int)}).</p>
60277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
60377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>If the requested component index is {@link #getComponentCount()},
60477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * this method returns the alpha component, always in the range
605026a558ab0d9e710f385ea658687f385312b970eRomain Guy     * \([0..1]\).</p>
60677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
60777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #getComponents()
60877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
60977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @throws ArrayIndexOutOfBoundsException If the specified component index
61077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * is < 0 or >= {@link #getComponentCount()}
61177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
61277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public float getComponent(@IntRange(from = 0, to = 4) int component) {
61377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return mComponents[component];
61477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
61577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
61677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
61777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Returns the relative luminance of this color.</p>
61877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
61977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Based on the formula for relative luminance defined in WCAG 2.0,
62077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * W3C Recommendation 11 December 2008.</p>
62177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
62277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A value between 0 (darkest black) and 1 (lightest white)
62377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
62477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @throws IllegalArgumentException If the this color's color space
62577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * does not use the {@link ColorSpace.Model#RGB RGB} color model
62677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
62777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public float luminance() {
62877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (mColorSpace.getModel() != ColorSpace.Model.RGB) {
62977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            throw new IllegalArgumentException("The specified color must be encoded in an RGB " +
63077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    "color space. The supplied color space is " + mColorSpace.getModel());
63177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        }
63277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
63377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        DoubleUnaryOperator eotf = ((ColorSpace.Rgb) mColorSpace).getEotf();
63477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        double r = eotf.applyAsDouble(mComponents[0]);
63577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        double g = eotf.applyAsDouble(mComponents[1]);
63677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        double b = eotf.applyAsDouble(mComponents[2]);
63777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
63877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return saturate((float) ((0.2126 * r) + (0.7152 * g) + (0.0722 * b)));
63977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
64077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
64177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @Override
64277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public boolean equals(Object o) {
64377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (this == o) return true;
64477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (o == null || getClass() != o.getClass()) return false;
64577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
64677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        Color color = (Color) o;
64777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
64877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        //noinspection SimplifiableIfStatement
64977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (!Arrays.equals(mComponents, color.mComponents)) return false;
65077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return mColorSpace.equals(color.mColorSpace);
65177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
65277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
65377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @Override
65477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public int hashCode() {
65577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        int result = Arrays.hashCode(mComponents);
65677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        result = 31 * result + mColorSpace.hashCode();
65777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return result;
65877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
65977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
66077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
66177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Returns a string representation of the object. This method returns
66277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * a string equal to the value of:</p>
66377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
66477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <pre class="prettyprint">
66577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * "Color(" + r + ", " + g + ", " + b + ", " + a +
66677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *         ", " + getColorSpace().getName + ')'
66777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * </pre>
66877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
66977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>For instance, the string representation of opaque black in the sRGB
67077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space is equal to the following value:</p>
67177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
67277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <pre>
67377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Color(0.0, 0.0, 0.0, 1.0, sRGB IEC61966-2.1)
67477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * </pre>
67577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
67677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null string representation of the object
67777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
67877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @Override
67977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
68077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public String toString() {
68177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        StringBuilder b = new StringBuilder("Color(");
68277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        for (float c : mComponents) {
68377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            b.append(c).append(", ");
68477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        }
68577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        b.append(mColorSpace.getName());
68677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        b.append(')');
68777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return b.toString();
68877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
68977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
69077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
69177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns the color space encoded in the specified color long.
69277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
69377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color long whose color space to extract
69426ca96ecb82cdbc058a39cebbfb16b402bf0fe03Romain Guy     * @return A non-null color space instance
69526ca96ecb82cdbc058a39cebbfb16b402bf0fe03Romain Guy     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
69677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
69777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #red(long)
69877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #green(long)
69977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #blue(long)
70077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #alpha(long)
70177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
70277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
70377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static ColorSpace colorSpace(@ColorLong long color) {
70477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return ColorSpace.get((int) (color & 0x3fL));
70577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
70677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
70777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
70877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns the red component encoded in the specified color long.
70977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The range of the returned value depends on the color space
71077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * associated with the specified color. The color space can be
71177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * queried by calling {@link #colorSpace(long)}.
71277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
71377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color long whose red channel to extract
71477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A float value with a range defined by the specified color's
71577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space
71677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
71777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #colorSpace(long)
71877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #green(long)
71977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #blue(long)
72077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #alpha(long)
72177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
72277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static float red(@ColorLong long color) {
72377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if ((color & 0x3fL) == 0L) return ((color >> 48) & 0xff) / 255.0f;
72477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return Half.toFloat((short) ((color >> 48) & 0xffff));
72577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
72677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
72777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
72877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns the green component encoded in the specified color long.
72977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The range of the returned value depends on the color space
73077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * associated with the specified color. The color space can be
73177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * queried by calling {@link #colorSpace(long)}.
73277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
73377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color long whose green channel to extract
73477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A float value with a range defined by the specified color's
73577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space
73677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
73777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #colorSpace(long)
73877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #red(long)
73977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #blue(long)
74077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #alpha(long)
74177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
74277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static float green(@ColorLong long color) {
74377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if ((color & 0x3fL) == 0L) return ((color >> 40) & 0xff) / 255.0f;
74477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return Half.toFloat((short) ((color >> 32) & 0xffff));
74577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
74677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
74777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
74877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns the blue component encoded in the specified color long.
74977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The range of the returned value depends on the color space
75077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * associated with the specified color. The color space can be
75177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * queried by calling {@link #colorSpace(long)}.
75277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
75377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color long whose blue channel to extract
75477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A float value with a range defined by the specified color's
75577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space
75677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
75777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #colorSpace(long)
75877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #red(long)
75977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #green(long)
76077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #alpha(long)
76177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
76277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static float blue(@ColorLong long color) {
76377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if ((color & 0x3fL) == 0L) return ((color >> 32) & 0xff) / 255.0f;
76477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return Half.toFloat((short) ((color >> 16) & 0xffff));
76577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
76677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
76777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
76877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Returns the alpha component encoded in the specified color long.
76977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The returned value is always in the range \([0..1]\).
77077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
77177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color long whose blue channel to extract
77277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A float value in the range \([0..1]\)
77377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
77477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #colorSpace(long)
77577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #red(long)
77677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #green(long)
77777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #blue(long)
77877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
77977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static float alpha(@ColorLong long color) {
78077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if ((color & 0x3fL) == 0L) return ((color >> 56) & 0xff) / 255.0f;
78177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return ((color >> 6) & 0x3ff) / 1023.0f;
78277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
78377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
78477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
78577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Indicates whether the specified color is in the
78677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace.Named#SRGB sRGB} color space.
78777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
78877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color to test
78977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return True if the color is in the sRGB color space, false otherwise
79026ca96ecb82cdbc058a39cebbfb16b402bf0fe03Romain Guy     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
79177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
79277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #isInColorSpace(long, ColorSpace)
79377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #isWideGamut(long)
79477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
79577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static boolean isSrgb(@ColorLong long color) {
79677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return colorSpace(color).isSrgb();
79777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
79877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
79977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
80077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Indicates whether the specified color is in a wide-gamut color space.
80177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * See {@link ColorSpace#isWideGamut()} for a definition of a wide-gamut
80277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space.
80377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
80477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color to test
80577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return True if the color is in a wide-gamut color space, false otherwise
80626ca96ecb82cdbc058a39cebbfb16b402bf0fe03Romain Guy     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
80777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
80877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #isInColorSpace(long, ColorSpace)
80977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #isSrgb(long)
81077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see ColorSpace#isWideGamut()
81177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
81277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static boolean isWideGamut(@ColorLong long color) {
81377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return colorSpace(color).isWideGamut();
81477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
81577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
81677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
81777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Indicates whether the specified color is in the specified color space.
81877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
81977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color to test
82077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param colorSpace The color space to test against
82177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return True if the color is in the specified color space, false otherwise
82277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
82377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #isSrgb(long)
82477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #isWideGamut(long)
82577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
82677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static boolean isInColorSpace(@ColorLong long color, @NonNull ColorSpace colorSpace) {
82777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return (int) (color & 0x3fL) == colorSpace.getId();
82877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
82977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
83077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
83177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Converts the specified color long to an ARGB color int. A color int is
83277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * always in the {@link ColorSpace.Named#SRGB sRGB} color space. This implies
83377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * a color space conversion is applied if needed.
83477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
83577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return An ARGB color in the sRGB color space
83626ca96ecb82cdbc058a39cebbfb16b402bf0fe03Romain Guy     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
83777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
83877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorInt
83977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static int toArgb(@ColorLong long color) {
84077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if ((color & 0x3fL) == 0L) return (int) (color >> 32);
84177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
84277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float r = red(color);
84377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float g = green(color);
84477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float b = blue(color);
84577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float a = alpha(color);
84677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
84777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        // The transformation saturates the output
84877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float[] c = ColorSpace.connect(colorSpace(color)).transform(r, g, b);
84977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
85077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return ((int) (a    * 255.0f + 0.5f) << 24) |
85177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy               ((int) (c[0] * 255.0f + 0.5f) << 16) |
85277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy               ((int) (c[1] * 255.0f + 0.5f) <<  8) |
85377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                (int) (c[2] * 255.0f + 0.5f);
85477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
85577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
85677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
85777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Creates a new <code>Color</code> instance from an ARGB color int.
85877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The resulting color is in the {@link ColorSpace.Named#SRGB sRGB}
85977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space.
86077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
86177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The ARGB color int to create a <code>Color</code> from
86277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null instance of {@link Color}
86377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
86477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
86577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static Color valueOf(@ColorInt int color) {
86677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float r = ((color >> 16) & 0xff) / 255.0f;
86777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float g = ((color >>  8) & 0xff) / 255.0f;
86877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float b = ((color      ) & 0xff) / 255.0f;
86977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float a = ((color >> 24) & 0xff) / 255.0f;
87077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return new Color(r, g, b, a, ColorSpace.get(ColorSpace.Named.SRGB));
87177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
87277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
87377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
87477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Creates a new <code>Color</code> instance from a color long.
87577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The resulting color is in the same color space as the specified color long.
87677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
87777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color long to create a <code>Color</code> from
87877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null instance of {@link Color}
87926ca96ecb82cdbc058a39cebbfb16b402bf0fe03Romain Guy     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
88077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
88177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
88277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static Color valueOf(@ColorLong long color) {
88377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return new Color(red(color), green(color), blue(color), alpha(color), colorSpace(color));
88477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
88577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
88677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
88777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Creates a new opaque <code>Color</code> in the {@link ColorSpace.Named#SRGB sRGB}
88877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space with the specified red, green and blue component values. The component
88977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * values must be in the range \([0..1]\).
89077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
89177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param r The red component of the opaque sRGB color to create, in \([0..1]\)
89277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param g The green component of the opaque sRGB color to create, in \([0..1]\)
89377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param b The blue component of the opaque sRGB color to create, in \([0..1]\)
89477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null instance of {@link Color}
89577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
89677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
89777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static Color valueOf(float r, float g, float b) {
89877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return new Color(r, g, b, 1.0f);
89977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
90077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
90177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
90277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Creates a new <code>Color</code> in the {@link ColorSpace.Named#SRGB sRGB}
90377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space with the specified red, green, blue and alpha component values.
90477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The component values must be in the range \([0..1]\).
90577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
90677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param r The red component of the sRGB color to create, in \([0..1]\)
90777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param g The green component of the sRGB color to create, in \([0..1]\)
90877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param b The blue component of the sRGB color to create, in \([0..1]\)
90977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param a The alpha component of the sRGB color to create, in \([0..1]\)
91077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null instance of {@link Color}
91177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
91277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
91377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static Color valueOf(float r, float g, float b, float a) {
91477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return new Color(saturate(r), saturate(g), saturate(b), saturate(a));
91577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
91677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
91777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
91877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Creates a new <code>Color</code> in the specified color space with the
91977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * specified red, green, blue and alpha component values. The range of the
92077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * components is defined by {@link ColorSpace#getMinValue(int)} and
92177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#getMaxValue(int)}. The values passed to this method
92277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * must be in the proper range.
92377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
92477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param r The red component of the color to create
92577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param g The green component of the color to create
92677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param b The blue component of the color to create
92777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param a The alpha component of the color to create, in \([0..1]\)
92877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param colorSpace The color space of the color to create
92977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null instance of {@link Color}
93077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
93177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @throws IllegalArgumentException If the specified color space uses a
93277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color model with more than 3 components
93377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
93477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
93577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static Color valueOf(float r, float g, float b, float a, @NonNull ColorSpace colorSpace) {
93677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (colorSpace.getComponentCount() > 3) {
93777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            throw new IllegalArgumentException("The specified color space must use a color model " +
93877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    "with at most 3 color components");
93977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        }
94077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return new Color(r, g, b, a, colorSpace);
94177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
94277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
94377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
94477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Creates a new <code>Color</code> in the specified color space with the
94577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * specified component values. The range of the components is defined by
94677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#getMinValue(int)} and {@link ColorSpace#getMaxValue(int)}.
94777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The values passed to this method must be in the proper range. The alpha
94877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * component is always in the range \([0..1]\).</p>
94977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
95077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>The length of the array of components must be at least
95177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <code>{@link ColorSpace#getComponentCount()} + 1</code>. The component at index
95277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#getComponentCount()} is always alpha.</p>
95377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
95477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param components The components of the color to create, with alpha as the last component
95577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param colorSpace The color space of the color to create
95677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A non-null instance of {@link Color}
95777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
95877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @throws IllegalArgumentException If the array of components is smaller than
95977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * required by the color space
96077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
96177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @NonNull
96277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static Color valueOf(@NonNull @Size(min = 4, max = 5) float[] components,
96377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @NonNull ColorSpace colorSpace) {
96477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (components.length < colorSpace.getComponentCount() + 1) {
96577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            throw new IllegalArgumentException("Received a component array of length " +
96677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    components.length + " but the color model requires " +
96777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    (colorSpace.getComponentCount() + 1) + " (including alpha)");
96877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        }
96977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return new Color(Arrays.copyOf(components, colorSpace.getComponentCount() + 1), colorSpace);
97077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
97177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
97277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
97377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Converts the specified ARGB color int to an RGBA color long in the sRGB
97477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space. See the documentation of this class for a description of
97577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * the color long format.
97677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
97777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The ARGB color int to convert to an RGBA color long in sRGB
97877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
97977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long
98077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
98177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
98277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static long pack(@ColorInt int color) {
98377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return (color & 0xffffffffL) << 32;
98477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
98577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
98677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
98777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Packs the sRGB color defined by the specified red, green and blue component
98877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * values into an RGBA color long in the sRGB color space. The alpha component
98977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * is set to 1.0. See the documentation of this class for a description of the
99077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color long format.
99177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
99277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param red The red component of the sRGB color to create, in \([0..1]\)
99377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param green The green component of the sRGB color to create, in \([0..1]\)
99477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param blue The blue component of the sRGB color to create, in \([0..1]\)
99577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
99677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long
99777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
99877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
99977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static long pack(float red, float green, float blue) {
100077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return pack(red, green, blue, 1.0f, ColorSpace.get(ColorSpace.Named.SRGB));
100177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
100277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
100377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
100477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Packs the sRGB color defined by the specified red, green, blue and alpha
100577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * component values into an RGBA color long in the sRGB color space. See the
100677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * documentation of this class for a description of the color long format.
100777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
100877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param red The red component of the sRGB color to create, in \([0..1]\)
100977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param green The green component of the sRGB color to create, in \([0..1]\)
101077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param blue The blue component of the sRGB color to create, in \([0..1]\)
101177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param alpha The alpha component of the sRGB color to create, in \([0..1]\)
101277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
101377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long
101477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
101577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
101677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static long pack(float red, float green, float blue, float alpha) {
101777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return pack(red, green, blue, alpha, ColorSpace.get(ColorSpace.Named.SRGB));
101877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
101977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
102077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
102177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Packs the 3 component color defined by the specified red, green, blue and
102277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * alpha component values into a color long in the specified color space. See the
102377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * documentation of this class for a description of the color long format.</p>
102477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
102577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>The red, green and blue components must be in the range defined by the
102677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * specified color space. See {@link ColorSpace#getMinValue(int)} and
102777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#getMaxValue(int)}.</p>
102877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
102977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param red The red component of the color to create
103077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param green The green component of the color to create
103177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param blue The blue component of the color to create
103277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param alpha The alpha component of the color to create, in \([0..1]\)
103377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
103477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long
103577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
103677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @throws IllegalArgumentException If the color space's id is {@link ColorSpace#MIN_ID}
103777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * or if the color space's color model has more than 3 components
103877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
103977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
104077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static long pack(float red, float green, float blue, float alpha,
104177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @NonNull ColorSpace colorSpace) {
104277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (colorSpace.isSrgb()) {
104377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            int argb =
104477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    ((int) (alpha * 255.0f + 0.5f) << 24) |
104577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    ((int) (red   * 255.0f + 0.5f) << 16) |
104677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    ((int) (green * 255.0f + 0.5f) <<  8) |
104777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                     (int) (blue  * 255.0f + 0.5f);
104877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            return (argb & 0xffffffffL) << 32;
104977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        }
105077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
105177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        int id = colorSpace.getId();
105277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (id == ColorSpace.MIN_ID) {
105377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            throw new IllegalArgumentException(
105477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    "Unknown color space, please use a color space returned by ColorSpace.get()");
105577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        }
105677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (colorSpace.getComponentCount() > 3) {
105777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            throw new IllegalArgumentException(
105877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    "The color space must use a color model with at most 3 components");
105977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        }
106077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
106195b52fd187564cabceb3309daa4ee6ddf697de58Romain Guy        @HalfFloat short r = Half.toHalf(red);
106295b52fd187564cabceb3309daa4ee6ddf697de58Romain Guy        @HalfFloat short g = Half.toHalf(green);
106395b52fd187564cabceb3309daa4ee6ddf697de58Romain Guy        @HalfFloat short b = Half.toHalf(blue);
106477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
106577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        int a = (int) (Math.max(0.0f, Math.min(alpha, 1.0f)) * 1023.0f + 0.5f);
106677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
106777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        // Suppress sign extension
106877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return  (r & 0xffffL) << 48 |
106977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                (g & 0xffffL) << 32 |
107077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                (b & 0xffffL) << 16 |
107177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                (a & 0x3ffL ) <<  6 |
107277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                id & 0x3fL;
107377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
107477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
107577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
107677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Converts the specified ARGB color int from the {@link ColorSpace.Named#SRGB sRGB}
107777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space into the specified destination color space. The resulting color is
107877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * returned as a color long. See the documentation of this class for a description
107977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * of the color long format.
108077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
108177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The sRGB color int to convert
108277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param colorSpace The destination color space
108377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long in the destination color space
108477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
108577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
108677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static long convert(@ColorInt int color, @NonNull ColorSpace colorSpace) {
108777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float r = ((color >> 16) & 0xff) / 255.0f;
108877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float g = ((color >>  8) & 0xff) / 255.0f;
108977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float b = ((color      ) & 0xff) / 255.0f;
109077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float a = ((color >> 24) & 0xff) / 255.0f;
109177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        ColorSpace source = ColorSpace.get(ColorSpace.Named.SRGB);
109277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return convert(r, g, b, a, source, colorSpace);
109377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
109477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
109577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
109677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Converts the specified color long from its color space into the specified
109777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * destination color space. The resulting color is returned as a color long. See
109877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * the documentation of this class for a description of the color long format.</p>
109977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
110077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>When converting several colors in a row, it is recommended to use
110177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link #convert(long, ColorSpace.Connector)} instead to
110277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * avoid the creation of a {@link ColorSpace.Connector} on every invocation.</p>
110377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
110477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color long to convert
110577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param colorSpace The destination color space
110677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long in the destination color space
110726ca96ecb82cdbc058a39cebbfb16b402bf0fe03Romain Guy     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
110877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
110977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
111077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static long convert(@ColorLong long color, @NonNull ColorSpace colorSpace) {
111177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float r = red(color);
111277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float g = green(color);
111377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float b = blue(color);
111477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float a = alpha(color);
111577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        ColorSpace source = colorSpace(color);
111677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return convert(r, g, b, a, source, colorSpace);
111777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
111877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
111977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
112077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Converts the specified 3 component color from the source color space to the
112177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * destination color space. The resulting color is returned as a color long. See
112277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * the documentation of this class for a description of the color long format.</p>
112377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
112477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>When converting multiple colors in a row, it is recommended to use
112577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link #convert(float, float, float, float, ColorSpace.Connector)} instead to
112677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * avoid the creation of a {@link ColorSpace.Connector} on every invocation.</p>
112777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
112877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>The red, green and blue components must be in the range defined by the
112977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * specified color space. See {@link ColorSpace#getMinValue(int)} and
113077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link ColorSpace#getMaxValue(int)}.</p>
113177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
113277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param r The red component of the color to convert
113377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param g The green component of the color to convert
113477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param b The blue component of the color to convert
113577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param a The alpha component of the color to convert, in \([0..1]\)
113677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param source The source color space, cannot be null
113777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param destination The destination color space, cannot be null
113877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long in the destination color space
113977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
114077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #convert(float, float, float, float, ColorSpace.Connector)
114177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
114277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
114377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static long convert(float r, float g, float b, float a,
114477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @NonNull ColorSpace source, @NonNull ColorSpace destination) {
114577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float[] c = ColorSpace.connect(source, destination).transform(r, g, b);
114677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return pack(c[0], c[1], c[2], a, destination);
114777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
114877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
114977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
115077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Converts the specified color long from a color space to another using the
115177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * specified color space {@link ColorSpace.Connector connector}. The resulting
115277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color is returned as a color long. See the documentation of this class for a
115377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * description of the color long format.</p>
115477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
115577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>When converting several colors in a row, this method is preferable to
115677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link #convert(long, ColorSpace)} as it prevents a new connector from being
115777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * created on every invocation.</p>
115877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
115977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p class="note">The connector's source color space should match the color long's
116077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color space.</p>
116177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
116277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param color The color long to convert
116377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param connector A color space connector, cannot be null
116477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long in the destination color space of the connector
116577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
116677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
116777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static long convert(@ColorLong long color, @NonNull ColorSpace.Connector connector) {
116877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float r = red(color);
116977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float g = green(color);
117077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float b = blue(color);
117177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float a = alpha(color);
117277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return convert(r, g, b, a, connector);
117377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
117477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
117577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
117677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Converts the specified 3 component color from a color space to another using
117777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * the specified color space {@link ColorSpace.Connector connector}. The resulting
117877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * color is returned as a color long. See the documentation of this class for a
117977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * description of the color long format.</p>
118077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
118177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>When converting several colors in a row, this method is preferable to
118277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * {@link #convert(float, float, float, float, ColorSpace, ColorSpace)} as
118377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * it prevents a new connector from being created on every invocation.</p>
118477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
118577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>The red, green and blue components must be in the range defined by the
118677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * source color space of the connector. See {@link ColorSpace#getMinValue(int)}
118777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * and {@link ColorSpace#getMaxValue(int)}.</p>
118877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
118977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param r The red component of the color to convert
119077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param g The green component of the color to convert
119177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param b The blue component of the color to convert
119277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param a The alpha component of the color to convert, in \([0..1]\)
119377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param connector A color space connector, cannot be null
119477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A color long in the destination color space of the connector
119577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
119677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @see #convert(float, float, float, float, ColorSpace, ColorSpace)
119777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
119877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorLong
119977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static long convert(float r, float g, float b, float a,
120077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @NonNull ColorSpace.Connector connector) {
120177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        float[] c = connector.transform(r, g, b);
120277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return pack(c[0], c[1], c[2], a, connector.getDestination());
120377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
120477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
120577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
120677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Returns the relative luminance of a color.</p>
120777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
120877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>Based on the formula for relative luminance defined in WCAG 2.0,
120977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * W3C Recommendation 11 December 2008.</p>
121077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
121177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @return A value between 0 (darkest black) and 1 (lightest white)
121277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
121377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @throws IllegalArgumentException If the specified color's color space
121426ca96ecb82cdbc058a39cebbfb16b402bf0fe03Romain Guy     * is unknown or does not use the {@link ColorSpace.Model#RGB RGB} color model
121577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
121677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static float luminance(@ColorLong long color) {
121777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        ColorSpace colorSpace = colorSpace(color);
121877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        if (colorSpace.getModel() != ColorSpace.Model.RGB) {
121977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            throw new IllegalArgumentException("The specified color must be encoded in an RGB " +
122077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                    "color space. The supplied color space is " + colorSpace.getModel());
122177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        }
122277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
122377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        DoubleUnaryOperator eotf = ((ColorSpace.Rgb) colorSpace).getEotf();
122477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        double r = eotf.applyAsDouble(red(color));
122577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        double g = eotf.applyAsDouble(green(color));
122677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        double b = eotf.applyAsDouble(blue(color));
122777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
122877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return saturate((float) ((0.2126 * r) + (0.7152 * g) + (0.0722 * b)));
122977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
123077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
123177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    private static float saturate(float v) {
123277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return v <= 0.0f ? 0.0f : (v >= 1.0f ? 1.0f : v);
123377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
123477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the alpha component of a color int. This is the same as saying
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * color >>> 24
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
123977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @IntRange(from = 0, to = 255)
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static int alpha(int color) {
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return color >>> 24;
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the red component of a color int. This is the same as saying
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (color >> 16) & 0xFF
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
124877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @IntRange(from = 0, to = 255)
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static int red(int color) {
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (color >> 16) & 0xFF;
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the green component of a color int. This is the same as saying
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (color >> 8) & 0xFF
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
125777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @IntRange(from = 0, to = 255)
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static int green(int color) {
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (color >> 8) & 0xFF;
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the blue component of a color int. This is the same as saying
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * color & 0xFF
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
126677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @IntRange(from = 0, to = 255)
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static int blue(int color) {
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return color & 0xFF;
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a color-int from red, green, blue components.
127377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * The alpha component is implicitly 255 (fully opaque).
127477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * These component values should be \([0..255]\), but there is no
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * range check performed, so if they are out of range, the
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned color is undefined.
127777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
127877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param red  Red component \([0..255]\) of the color
127977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param green Green component \([0..255]\) of the color
128077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param blue  Blue component \([0..255]\) of the color
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
128280756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt
128377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static int rgb(
128477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int red,
128577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int green,
128677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int blue) {
128768bd5fdd1ad3cf0b74c225b31adf1f68393bfbb6Romain Guy        return 0xff000000 | (red << 16) | (green << 8) | blue;
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
129177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Return a color-int from red, green, blue float components
129277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * in the range \([0..1]\). The alpha component is implicitly
129377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * 1.0 (fully opaque). If the components are out of range, the
129477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * returned color is undefined.
129577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
129677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param red Red component \([0..1]\) of the color
129777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param green Green component \([0..1]\) of the color
129877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param blue Blue component \([0..1]\) of the color
129977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
130077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorInt
130177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static int rgb(float red, float green, float blue) {
130277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return 0xff000000 |
130377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy               ((int) (red   * 255.0f + 0.5f) << 16) |
130477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy               ((int) (green * 255.0f + 0.5f) <<  8) |
130577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                (int) (blue  * 255.0f + 0.5f);
130677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
130777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
130877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a color-int from alpha, red, green, blue components.
131077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * These component values should be \([0..255]\), but there is no
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * range check performed, so if they are out of range, the
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned color is undefined.
131377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param alpha Alpha component \([0..255]\) of the color
131477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param red Red component \([0..255]\) of the color
131577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param green Green component \([0..255]\) of the color
131677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param blue Blue component \([0..255]\) of the color
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
131880756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt
131977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static int argb(
132077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int alpha,
132177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int red,
132277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int green,
132377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int blue) {
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (alpha << 24) | (red << 16) | (green << 8) | blue;
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
132877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Return a color-int from alpha, red, green, blue float components
132977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * in the range \([0..1]\). If the components are out of range, the
133077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * returned color is undefined.
133177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
133277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param alpha Alpha component \([0..1]\) of the color
133377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param red Red component \([0..1]\) of the color
133477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param green Green component \([0..1]\) of the color
133577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param blue Blue component \([0..1]\) of the color
133677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
133777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorInt
133877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static int argb(float alpha, float red, float green, float blue) {
133977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return ((int) (alpha * 255.0f + 0.5f) << 24) |
134077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy               ((int) (red   * 255.0f + 0.5f) << 16) |
134177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy               ((int) (green * 255.0f + 0.5f) <<  8) |
134277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy                (int) (blue  * 255.0f + 0.5f);
134377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    }
134477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
134577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    /**
134681590a48a4bb0b6700e5535c5bce720ddfc76fa2Alan Viverette     * Returns the relative luminance of a color.
134781590a48a4bb0b6700e5535c5bce720ddfc76fa2Alan Viverette     * <p>
134881590a48a4bb0b6700e5535c5bce720ddfc76fa2Alan Viverette     * Assumes sRGB encoding. Based on the formula for relative luminance
134981590a48a4bb0b6700e5535c5bce720ddfc76fa2Alan Viverette     * defined in WCAG 2.0, W3C Recommendation 11 December 2008.
1350a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy     *
135181590a48a4bb0b6700e5535c5bce720ddfc76fa2Alan Viverette     * @return a value between 0 (darkest black) and 1 (lightest white)
1352a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy     */
135381590a48a4bb0b6700e5535c5bce720ddfc76fa2Alan Viverette    public static float luminance(@ColorInt int color) {
135468bd5fdd1ad3cf0b74c225b31adf1f68393bfbb6Romain Guy        ColorSpace.Rgb cs = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB);
135568bd5fdd1ad3cf0b74c225b31adf1f68393bfbb6Romain Guy        DoubleUnaryOperator eotf = cs.getEotf();
135677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
135777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        double r = eotf.applyAsDouble(red(color) / 255.0);
135877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        double g = eotf.applyAsDouble(green(color) / 255.0);
135977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        double b = eotf.applyAsDouble(blue(color) / 255.0);
136077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy
136177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy        return (float) ((0.2126 * r) + (0.7152 * g) + (0.0722 * b));
1362a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy    }
1363a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy
1364a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy    /**
136577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * </p>Parse the color string, and return the corresponding color-int.
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the string cannot be parsed, throws an IllegalArgumentException
136777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * exception. Supported formats are:</p>
136877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
136977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <ul>
137077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>#RRGGBB</code></li>
137177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>#AARRGGBB</code></li>
137277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * </ul>
137377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *
137477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <p>The following names are also accepted: <code>red</code>, <code>blue</code>,
137577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <code>green</code>, <code>black</code>, <code>white</code>, <code>gray</code>,
137677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <code>cyan</code>, <code>magenta</code>, <code>yellow</code>, <code>lightgray</code>,
137777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <code>darkgray</code>, <code>grey</code>, <code>lightgrey</code>, <code>darkgrey</code>,
137877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <code>aqua</code>, <code>fuchsia</code>, <code>lime</code>, <code>maroon</code>,
137977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <code>navy</code>, <code>olive</code>, <code>purple</code>, <code>silver</code>,
138077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * and <code>teal</code>.</p>
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
138280756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt
1383b3ec733bb830f2d4425825d93f9ed95f284e9145Tor Norbye    public static int parseColor(@Size(min=1) String colorString) {
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (colorString.charAt(0) == '#') {
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Use a long to avoid rollovers on #ffXXXXXX
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long color = Long.parseLong(colorString.substring(1), 16);
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (colorString.length() == 7) {
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Set the alpha value
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                color |= 0x00000000ff000000;
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (colorString.length() != 9) {
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Unknown color");
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return (int)color;
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1395aeb60fb86fc572500239c6f6684d1eb71e3ae35bElliott Hughes            Integer color = sColorNameMap.get(colorString.toLowerCase(Locale.ROOT));
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (color != null) {
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return color;
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw new IllegalArgumentException("Unknown color");
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convert RGB components to HSV.
140577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <ul>
140677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[0]</code> is Hue \([0..360[\)</li>
140777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[1]</code> is Saturation \([0...1]\)</li>
140877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[2]</code> is Value \([0...1]\)</li>
140977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * </ul>
141077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param red  red component value \([0..255]\)
141177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param green  green component value \([0..255]\)
141277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * @param blue  blue component value \([0..255]\)
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param hsv  3 element array which holds the resulting HSV components.
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
141577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static void RGBToHSV(
141677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int red,
141777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int green,
141877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy            @IntRange(from = 0, to = 255) int blue, @Size(3) float hsv[]) {
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hsv.length < 3) {
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("3 components required for hsv");
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativeRGBToHSV(red, green, blue, hsv);
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
142677b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * Convert the ARGB color to its HSV components.
142777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <ul>
142877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[0]</code> is Hue \([0..360[\)</li>
142977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[1]</code> is Saturation \([0...1]\)</li>
143077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[2]</code> is Value \([0...1]\)</li>
143177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * </ul>
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param color the argb color to convert. The alpha component is ignored.
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param hsv  3 element array which holds the resulting HSV components.
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1435b3ec733bb830f2d4425825d93f9ed95f284e9145Tor Norbye    public static void colorToHSV(@ColorInt int color, @Size(3) float hsv[]) {
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RGBToHSV((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, hsv);
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convert HSV components to an ARGB color. Alpha set to 0xFF.
144177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <ul>
144277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[0]</code> is Hue \([0..360[\)</li>
144377b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[1]</code> is Saturation \([0...1]\)</li>
144477b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[2]</code> is Value \([0...1]\)</li>
144577b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * </ul>
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If hsv values are out of range, they are pinned.
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param hsv  3 element array which holds the input HSV components.
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the resulting argb color
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    */
145077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorInt
1451b3ec733bb830f2d4425825d93f9ed95f284e9145Tor Norbye    public static int HSVToColor(@Size(3) float hsv[]) {
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return HSVToColor(0xFF, hsv);
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convert HSV components to an ARGB color. The alpha component is passed
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * through unchanged.
145877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * <ul>
145977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[0]</code> is Hue \([0..360[\)</li>
146077b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[1]</code> is Saturation \([0...1]\)</li>
146177b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     *   <li><code>hsv[2]</code> is Value \([0...1]\)</li>
146277b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     * </ul>
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If hsv values are out of range, they are pinned.
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param alpha the alpha component of the returned argb color.
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param hsv  3 element array which holds the input HSV components.
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the resulting argb color
146777b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy     */
146877b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    @ColorInt
146977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static int HSVToColor(@IntRange(from = 0, to = 255) int alpha, @Size(3) float hsv[]) {
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hsv.length < 3) {
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("3 components required for hsv");
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return nativeHSVToColor(alpha, hsv);
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1476a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy    private static native void nativeRGBToHSV(int red, int greed, int blue, float hsv[]);
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native int nativeHSVToColor(int alpha, float hsv[]);
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy    /**
1480a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy     * Converts an HTML color (named or numeric) to an integer RGB value.
1481a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy     *
1482a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy     * @param color Non-null color string.
1483a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy     *
1484a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy     * @return A color value, or {@code -1} if the color string could not be interpreted.
1485a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy     *
1486a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy     * @hide
1487a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy     */
148880756e38882720860db52f1fcc21fa1505a02abfTor Norbye    @ColorInt
148977b161e0b14372e3eb124ed19321a9639aeb4271Romain Guy    public static int getHtmlColor(@NonNull String color) {
1490aeb60fb86fc572500239c6f6684d1eb71e3ae35bElliott Hughes        Integer i = sColorNameMap.get(color.toLowerCase(Locale.ROOT));
1491a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy        if (i != null) {
1492a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy            return i;
1493a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy        } else {
1494a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy            try {
1495a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy                return XmlUtils.convertValueToInt(color, -1);
1496a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy            } catch (NumberFormatException nfe) {
1497a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy                return -1;
1498a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy            }
1499a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy        }
1500a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy    }
1501a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final HashMap<String, Integer> sColorNameMap;
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static {
150468bd5fdd1ad3cf0b74c225b31adf1f68393bfbb6Romain Guy        sColorNameMap = new HashMap<>();
1505a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("black", BLACK);
1506a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("darkgray", DKGRAY);
1507a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("gray", GRAY);
1508a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("lightgray", LTGRAY);
1509a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("white", WHITE);
1510a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("red", RED);
1511a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("green", GREEN);
1512a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("blue", BLUE);
1513a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("yellow", YELLOW);
1514a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("cyan", CYAN);
1515a32d100b34d048cf0c765d8f31d87b81ab88d1ebRomain Guy        sColorNameMap.put("magenta", MAGENTA);
151686d3e03d381bff8c107e3def31cf37f4851f827cRomain Guy        sColorNameMap.put("aqua", 0xFF00FFFF);
151786d3e03d381bff8c107e3def31cf37f4851f827cRomain Guy        sColorNameMap.put("fuchsia", 0xFFFF00FF);
1518a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy        sColorNameMap.put("darkgrey", DKGRAY);
1519a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy        sColorNameMap.put("grey", GRAY);
1520a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy        sColorNameMap.put("lightgrey", LTGRAY);
152186d3e03d381bff8c107e3def31cf37f4851f827cRomain Guy        sColorNameMap.put("lime", 0xFF00FF00);
152286d3e03d381bff8c107e3def31cf37f4851f827cRomain Guy        sColorNameMap.put("maroon", 0xFF800000);
152386d3e03d381bff8c107e3def31cf37f4851f827cRomain Guy        sColorNameMap.put("navy", 0xFF000080);
152486d3e03d381bff8c107e3def31cf37f4851f827cRomain Guy        sColorNameMap.put("olive", 0xFF808000);
152586d3e03d381bff8c107e3def31cf37f4851f827cRomain Guy        sColorNameMap.put("purple", 0xFF800080);
152686d3e03d381bff8c107e3def31cf37f4851f827cRomain Guy        sColorNameMap.put("silver", 0xFFC0C0C0);
152786d3e03d381bff8c107e3def31cf37f4851f827cRomain Guy        sColorNameMap.put("teal", 0xFF008080);
1528a8f6d5f0720f400b6f59b0809aaefea83c5f51d4Romain Guy
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1531