Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *       http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 @file:Suppress("NOTHING_TO_INLINE", "WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE")
     18 
     19 package androidx.core.graphics
     20 
     21 import android.graphics.Color
     22 import android.graphics.ColorSpace
     23 import androidx.annotation.ColorInt
     24 import androidx.annotation.ColorLong
     25 import androidx.annotation.RequiresApi
     26 
     27 /**
     28  * Returns the first component of the color. For instance, when the color model
     29  * of the color is [android.graphics.ColorSpace.Model.RGB], the first component
     30  * is "red".
     31  *
     32  * This method allows to use destructuring declarations when working with colors,
     33  * for example:
     34  * ```
     35  * val (red, green, blue) = myColor
     36  * ```
     37  */
     38 @RequiresApi(26)
     39 inline operator fun Color.component1() = getComponent(0)
     40 
     41 /**
     42  * Returns the second component of the color. For instance, when the color model
     43  * of the color is [android.graphics.ColorSpace.Model.RGB], the second component
     44  * is "green".
     45  *
     46  * This method allows to use destructuring declarations when working with colors,
     47  * for example:
     48  * ```
     49  * val (red, green, blue) = myColor
     50  * ```
     51  */
     52 @RequiresApi(26)
     53 inline operator fun Color.component2() = getComponent(1)
     54 
     55 /**
     56  * Returns the third component of the color. For instance, when the color model
     57  * of the color is [android.graphics.ColorSpace.Model.RGB], the third component
     58  * is "blue".
     59 = *
     60  * This method allows to use destructuring declarations when working with colors,
     61  * for example:
     62  * ```
     63  * val (red, green, blue) = myColor
     64  * ```
     65  */
     66 @RequiresApi(26)
     67 inline operator fun Color.component3() = getComponent(2)
     68 
     69 /**
     70  * Returns the fourth component of the color. For instance, when the color model
     71  * of the color is [android.graphics.ColorSpace.Model.RGB], the fourth component
     72  * is "alpha".
     73  *
     74  * This method allows to use destructuring declarations when working with colors,
     75  * for example:
     76  * ```
     77  * val (red, green, blue, alpha) = myColor
     78  * ```
     79  */
     80 @RequiresApi(26)
     81 inline operator fun Color.component4() = getComponent(3)
     82 
     83 /**
     84  * Composites two translucent colors together. More specifically, adds two colors using
     85  * the [source over][android.graphics.PorterDuff.Mode.SRC_OVER] blending mode. The colors
     86  * must not be pre-multiplied and the result is a non pre-multiplied color.
     87  *
     88  * If the two colors have different color spaces, the color in the right-hand part
     89  * of the expression is converted to the color space of the color in left-hand part
     90  * of the expression.
     91  *
     92  * The following example creates a purple color by blending opaque blue with
     93  * semi-translucent red:
     94  *
     95  * ```
     96  * val purple = Color.valueOf(0f, 0f, 1f) + Color.valueOf(1f, 0f, 0f, 0.5f)
     97  * ```
     98  *
     99  * @throws IllegalArgumentException if the [color models][android.graphics.Color.getModel]
    100  *                                  of the colors do not match
    101  */
    102 @RequiresApi(26)
    103 operator fun Color.plus(c: Color): Color = ColorUtils.compositeColors(c, this)
    104 
    105 /**
    106  * Return the alpha component of a color int. This is equivalent to calling:
    107  * ```
    108  * Color.alpha(myInt)
    109  * ```
    110  */
    111 inline val @receiver:ColorInt Int.alpha get() = (this shr 24) and 0xff
    112 
    113 /**
    114  * Return the red component of a color int. This is equivalent to calling:
    115  * ```
    116  * Color.red(myInt)
    117  * ```
    118  */
    119 inline val @receiver:ColorInt Int.red get() = (this shr 16) and 0xff
    120 
    121 /**
    122  * Return the green component of a color int. This is equivalent to calling:
    123  * ```
    124  * Color.green(myInt)
    125  * ```
    126  */
    127 inline val @receiver:ColorInt Int.green get() = (this shr 8) and 0xff
    128 
    129 /**
    130  * Return the blue component of a color int. This is equivalent to calling:
    131  * ```
    132  * Color.blue(myInt)
    133  * ```
    134  */
    135 inline val @receiver:ColorInt Int.blue get() = this and 0xff
    136 
    137 /**
    138  * Return the alpha component of a color int. This is equivalent to calling:
    139  * ```
    140  * Color.alpha(myInt)
    141  * ```
    142  *
    143  * This method allows to use destructuring declarations when working with colors,
    144  * for example:
    145  * ```
    146  * val (alpha, red, green, blue) = myColor
    147  * ```
    148  */
    149 inline operator fun @receiver:ColorInt Int.component1() = (this shr 24) and 0xff
    150 
    151 /**
    152  * Return the red component of a color int. This is equivalent to calling:
    153  * ```
    154  * Color.red(myInt)
    155  * ```
    156  *
    157  * This method allows to use destructuring declarations when working with colors,
    158  * for example:
    159  * ```
    160  * val (alpha, red, green, blue) = myColor
    161  * ```
    162  */
    163 inline operator fun @receiver:ColorInt Int.component2() = (this shr 16) and 0xff
    164 
    165 /**
    166  * Return the green component of a color int. This is equivalent to calling:
    167  * ```
    168  * Color.green(myInt)
    169  * ```
    170  *
    171  * This method allows to use destructuring declarations when working with colors,
    172  * for example:
    173  * ```
    174  * val (alpha, red, green, blue) = myColor
    175  * ```
    176  */
    177 inline operator fun @receiver:ColorInt Int.component3() = (this shr 8) and 0xff
    178 
    179 /**
    180  * Return the blue component of a color int. This is equivalent to calling:
    181  * ```
    182  * Color.blue(myInt)
    183  * ```
    184  *
    185  * This method allows to use destructuring declarations when working with colors,
    186  * for example:
    187  * ```
    188  * val (alpha, red, green, blue) = myColor
    189  * ```
    190  */
    191 inline operator fun @receiver:ColorInt Int.component4() = this and 0xff
    192 
    193 /**
    194  * Returns the relative luminance of a color int, assuming sRGB encoding.
    195  * Based on the formula for relative luminance defined in WCAG 2.0,
    196  * W3C Recommendation 11 December 2008.
    197  */
    198 @get:RequiresApi(26)
    199 inline val @receiver:ColorInt Int.luminance get() = Color.luminance(this)
    200 
    201 /**
    202  * Creates a new [Color] instance from a color int. The resulting color
    203  * is in the [sRGB][android.graphics.ColorSpace.Named.SRGB] color space.
    204  */
    205 @RequiresApi(26)
    206 inline fun @receiver:ColorInt Int.toColor(): Color = Color.valueOf(this)
    207 
    208 /**
    209  * Converts the specified ARGB [color int][Color] to an RGBA [color long][Color]
    210  * in the [sRGB][android.graphics.ColorSpace.Named.SRGB] color space.
    211  */
    212 @RequiresApi(26)
    213 @ColorLong
    214 inline fun @receiver:ColorInt Int.toColorLong() = Color.pack(this)
    215 
    216 /**
    217  * Returns the first component of the color. For instance, when the color model
    218  * of the color is [android.graphics.ColorSpace.Model.RGB], the first component
    219  * is "red".
    220  *
    221  * This method allows to use destructuring declarations when working with colors,
    222  * for example:
    223  * ```
    224  * val (red, green, blue, alpha) = myColorLong
    225  * ```
    226  */
    227 @RequiresApi(26)
    228 inline operator fun @receiver:ColorLong Long.component1() = Color.red(this)
    229 
    230 /**
    231  * Returns the second component of the color. For instance, when the color model
    232  * of the color is [android.graphics.ColorSpace.Model.RGB], the second component
    233  * is "green".
    234  *
    235  * This method allows to use destructuring declarations when working with colors,
    236  * for example:
    237  * ```
    238  * val (red, green, blue, alpha) = myColorLong
    239  * ```
    240  */
    241 @RequiresApi(26)
    242 inline operator fun @receiver:ColorLong Long.component2() = Color.green(this)
    243 
    244 /**
    245  * Returns the third component of the color. For instance, when the color model
    246  * of the color is [android.graphics.ColorSpace.Model.RGB], the third component
    247  * is "blue".
    248  *
    249  * This method allows to use destructuring declarations when working with colors,
    250  * for example:
    251  * ```
    252  * val (red, green, blue, alpha) = myColorLong
    253  * ```
    254  */
    255 @RequiresApi(26)
    256 inline operator fun @receiver:ColorLong Long.component3() = Color.blue(this)
    257 
    258 /**
    259  * Returns the fourth component of the color. For instance, when the color model
    260  * of the color is [android.graphics.ColorSpace.Model.RGB], the fourth component
    261  * is "alpha".
    262  *
    263  * This method allows to use destructuring declarations when working with colors,
    264  * for example:
    265  * ```
    266  * val (red, green, blue, alpha) = myColorLong
    267  * ```
    268  */
    269 @RequiresApi(26)
    270 inline operator fun @receiver:ColorLong Long.component4() = Color.alpha(this)
    271 
    272 /**
    273  * Return the alpha component of a color long. This is equivalent to calling:
    274  * ```
    275  * Color.alpha(myLong)
    276  * ```
    277  */
    278 @get:RequiresApi(26)
    279 inline val @receiver:ColorLong Long.alpha get() = Color.alpha(this)
    280 
    281 /**
    282  * Return the red component of a color long. This is equivalent to calling:
    283  * ```
    284  * Color.red(myLong)
    285  * ```
    286  */
    287 @get:RequiresApi(26)
    288 inline val @receiver:ColorLong Long.red get() = Color.red(this)
    289 
    290 /**
    291  * Return the green component of a color long. This is equivalent to calling:
    292  * ```
    293  * Color.green(myLong)
    294  * ```
    295  */
    296 @get:RequiresApi(26)
    297 inline val @receiver:ColorLong Long.green get() = Color.green(this)
    298 
    299 /**
    300  * Return the blue component of a color long. This is equivalent to calling:
    301  * ```
    302  * Color.blue(myLong)
    303  * ```
    304  */
    305 @get:RequiresApi(26)
    306 inline val @receiver:ColorLong Long.blue get() = Color.blue(this)
    307 
    308 /**
    309  * Returns the relative luminance of a color. Based on the formula for
    310  * relative luminance defined in WCAG 2.0, W3C Recommendation 11 December 2008.
    311  */
    312 @get:RequiresApi(26)
    313 inline val @receiver:ColorLong Long.luminance get() = Color.luminance(this)
    314 
    315 /**
    316  * Creates a new [Color] instance from a [color long][Color].
    317  */
    318 @RequiresApi(26)
    319 inline fun @receiver:ColorLong Long.toColor(): Color = Color.valueOf(this)
    320 
    321 /**
    322  * Converts the specified [color long][Color] to an ARGB [color int][Color].
    323  */
    324 @RequiresApi(26)
    325 @ColorInt
    326 inline fun @receiver:ColorLong Long.toColorInt() = Color.toArgb(this)
    327 
    328 /**
    329  * Indicates whether the color is in the [sRGB][android.graphics.ColorSpace.Named.SRGB]
    330  * color space.
    331  */
    332 @get:RequiresApi(26)
    333 inline val @receiver:ColorLong Long.isSrgb get() = Color.isSrgb(this)
    334 
    335 /**
    336  * Indicates whether the color is in a [wide-gamut][android.graphics.ColorSpace] color space.
    337  */
    338 @get:RequiresApi(26)
    339 inline val @receiver:ColorLong Long.isWideGamut get() = Color.isWideGamut(this)
    340 
    341 /**
    342  * Returns the color space encoded in the specified color long.
    343  */
    344 @get:RequiresApi(26)
    345 inline val @receiver:ColorLong Long.colorSpace: ColorSpace get() = Color.colorSpace(this)
    346 
    347 /**
    348  * Return a corresponding [Int] color of this [String].
    349  *
    350  * Supported formats are:
    351  * ```
    352  * #RRGGBB
    353  * #AARRGGBB
    354  * ```
    355  *
    356  * The following names are also accepted: "red", "blue", "green", "black", "white",
    357  * "gray", "cyan", "magenta", "yellow", "lightgray", "darkgray",
    358  * "grey", "lightgrey", "darkgrey", "aqua", "fuchsia", "lime",
    359  * "maroon", "navy", "olive", "purple", "silver", "teal".
    360  *
    361  * @throws IllegalArgumentException if this [String] cannot be parsed.
    362  */
    363 @ColorInt
    364 inline fun String.toColorInt(): Int = Color.parseColor(this)
    365