1 /*
<lambda>null2  * Copyright 2020 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 package androidx.compose.ui.graphics
18 
19 import android.graphics.ColorSpace.get
20 import android.os.Build
21 import androidx.annotation.RequiresApi
22 import androidx.compose.ui.graphics.ColorSpaceVerificationHelper.composeColorSpace
23 import androidx.compose.ui.graphics.colorspace.ColorSpace
24 import androidx.compose.ui.graphics.colorspace.ColorSpaces
25 import androidx.compose.ui.graphics.colorspace.Rgb
26 import androidx.compose.ui.graphics.colorspace.TransferParameters
27 import androidx.compose.ui.graphics.colorspace.WhitePoint
28 
29 /** Convert the Compose [ColorSpace] into an Android framework [android.graphics.ColorSpace] */
30 @RequiresApi(Build.VERSION_CODES.O)
31 fun ColorSpace.toAndroidColorSpace(): android.graphics.ColorSpace =
32     with(ColorSpaceVerificationHelper) { androidColorSpace() }
33 
34 /** Convert the [android.graphics.ColorSpace] into a Compose [ColorSpace] */
35 @RequiresApi(Build.VERSION_CODES.O)
toComposeColorSpacenull36 fun android.graphics.ColorSpace.toComposeColorSpace() =
37     with(ColorSpaceVerificationHelper) { composeColorSpace() }
38 
39 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
40 private object ColorSpaceVerificationHelperV34 {
41 
42     @JvmStatic
obtainAndroidColorSpacenull43     fun obtainAndroidColorSpace(colorSpace: ColorSpace): android.graphics.ColorSpace? =
44         when (colorSpace) {
45             ColorSpaces.Bt2020Hlg -> get(android.graphics.ColorSpace.Named.BT2020_HLG)
46             ColorSpaces.Bt2020Pq -> get(android.graphics.ColorSpace.Named.BT2020_PQ)
47             else -> null
48         }
49 
50     @JvmStatic
obtainComposeColorSpaceFromIdnull51     fun obtainComposeColorSpaceFromId(id: Int): ColorSpace =
52         when (id) {
53             android.graphics.ColorSpace.Named.BT2020_HLG.ordinal -> ColorSpaces.Bt2020Hlg
54             android.graphics.ColorSpace.Named.BT2020_PQ.ordinal -> ColorSpaces.Bt2020Pq
55             else -> ColorSpaces.Unspecified
56         }
57 }
58 
59 @RequiresApi(Build.VERSION_CODES.O)
60 private object ColorSpaceVerificationHelper {
61 
62     @JvmStatic
63     @RequiresApi(Build.VERSION_CODES.O)
ColorSpacenull64     fun ColorSpace.androidColorSpace(): android.graphics.ColorSpace {
65         return when (this) {
66             ColorSpaces.Srgb -> get(android.graphics.ColorSpace.Named.SRGB)
67             ColorSpaces.Aces -> get(android.graphics.ColorSpace.Named.ACES)
68             ColorSpaces.Acescg -> get(android.graphics.ColorSpace.Named.ACESCG)
69             ColorSpaces.AdobeRgb -> get(android.graphics.ColorSpace.Named.ADOBE_RGB)
70             ColorSpaces.Bt2020 -> get(android.graphics.ColorSpace.Named.BT2020)
71             ColorSpaces.Bt709 -> get(android.graphics.ColorSpace.Named.BT709)
72             ColorSpaces.CieLab -> get(android.graphics.ColorSpace.Named.CIE_LAB)
73             ColorSpaces.CieXyz -> get(android.graphics.ColorSpace.Named.CIE_XYZ)
74             ColorSpaces.DciP3 -> get(android.graphics.ColorSpace.Named.DCI_P3)
75             ColorSpaces.DisplayP3 -> get(android.graphics.ColorSpace.Named.DISPLAY_P3)
76             ColorSpaces.ExtendedSrgb -> get(android.graphics.ColorSpace.Named.EXTENDED_SRGB)
77             ColorSpaces.LinearExtendedSrgb ->
78                 get(android.graphics.ColorSpace.Named.LINEAR_EXTENDED_SRGB)
79             ColorSpaces.LinearSrgb -> get(android.graphics.ColorSpace.Named.LINEAR_SRGB)
80             ColorSpaces.Ntsc1953 -> get(android.graphics.ColorSpace.Named.NTSC_1953)
81             ColorSpaces.ProPhotoRgb -> get(android.graphics.ColorSpace.Named.PRO_PHOTO_RGB)
82             ColorSpaces.SmpteC -> get(android.graphics.ColorSpace.Named.SMPTE_C)
83             else -> {
84                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
85                     val v34ColorSpace =
86                         ColorSpaceVerificationHelperV34.obtainAndroidColorSpace(this)
87                     if (v34ColorSpace != null) {
88                         return v34ColorSpace
89                     }
90                 }
91                 if (this is Rgb) {
92                     val whitePointArray = this.whitePoint.toXyz()
93                     val transferParams = this.transferParameters
94                     val androidTransferParams =
95                         if (transferParams != null) {
96                             android.graphics.ColorSpace.Rgb.TransferParameters(
97                                 transferParams.a,
98                                 transferParams.b,
99                                 transferParams.c,
100                                 transferParams.d,
101                                 transferParams.e,
102                                 transferParams.f,
103                                 transferParams.gamma
104                             )
105                         } else {
106                             null
107                         }
108                     if (androidTransferParams != null) {
109                         android.graphics.ColorSpace.Rgb(
110                             this.name,
111                             this.primaries,
112                             whitePointArray,
113                             androidTransferParams
114                         )
115                     } else {
116                         android.graphics.ColorSpace.Rgb(
117                             this.name,
118                             this.primaries,
119                             whitePointArray,
120                             this.oetf,
121                             this.eotf,
122                             this.getMinValue(0),
123                             this.getMaxValue(0)
124                         )
125                     }
126                 } else {
127                     get(android.graphics.ColorSpace.Named.SRGB)
128                 }
129             }
130         }
131     }
132 
133     @JvmStatic
134     @RequiresApi(Build.VERSION_CODES.O)
composeColorSpacenull135     fun android.graphics.ColorSpace.composeColorSpace(): ColorSpace {
136         return when (this.id) {
137             android.graphics.ColorSpace.Named.SRGB.ordinal -> ColorSpaces.Srgb
138             android.graphics.ColorSpace.Named.ACES.ordinal -> ColorSpaces.Aces
139             android.graphics.ColorSpace.Named.ACESCG.ordinal -> ColorSpaces.Acescg
140             android.graphics.ColorSpace.Named.ADOBE_RGB.ordinal -> ColorSpaces.AdobeRgb
141             android.graphics.ColorSpace.Named.BT2020.ordinal -> ColorSpaces.Bt2020
142             android.graphics.ColorSpace.Named.BT709.ordinal -> ColorSpaces.Bt709
143             android.graphics.ColorSpace.Named.CIE_LAB.ordinal -> ColorSpaces.CieLab
144             android.graphics.ColorSpace.Named.CIE_XYZ.ordinal -> ColorSpaces.CieXyz
145             android.graphics.ColorSpace.Named.DCI_P3.ordinal -> ColorSpaces.DciP3
146             android.graphics.ColorSpace.Named.DISPLAY_P3.ordinal -> ColorSpaces.DisplayP3
147             android.graphics.ColorSpace.Named.EXTENDED_SRGB.ordinal -> ColorSpaces.ExtendedSrgb
148             android.graphics.ColorSpace.Named.LINEAR_EXTENDED_SRGB.ordinal ->
149                 ColorSpaces.LinearExtendedSrgb
150             android.graphics.ColorSpace.Named.LINEAR_SRGB.ordinal -> ColorSpaces.LinearSrgb
151             android.graphics.ColorSpace.Named.NTSC_1953.ordinal -> ColorSpaces.Ntsc1953
152             android.graphics.ColorSpace.Named.PRO_PHOTO_RGB.ordinal -> ColorSpaces.ProPhotoRgb
153             android.graphics.ColorSpace.Named.SMPTE_C.ordinal -> ColorSpaces.SmpteC
154             else -> {
155                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
156                     val v34ColorSpace =
157                         ColorSpaceVerificationHelperV34.obtainComposeColorSpaceFromId(this.id)
158                     if (v34ColorSpace != ColorSpaces.Unspecified) {
159                         return v34ColorSpace
160                     }
161                 }
162                 if (this is android.graphics.ColorSpace.Rgb) {
163                     val transferParams = this.transferParameters
164                     val whitePoint =
165                         if (this.whitePoint.size == 3) {
166                             WhitePoint(this.whitePoint[0], this.whitePoint[1], this.whitePoint[2])
167                         } else {
168                             WhitePoint(this.whitePoint[0], this.whitePoint[1])
169                         }
170 
171                     val composeTransferParams =
172                         if (transferParams != null) {
173                             TransferParameters(
174                                 gamma = transferParams.g,
175                                 a = transferParams.a,
176                                 b = transferParams.b,
177                                 c = transferParams.c,
178                                 d = transferParams.d,
179                                 e = transferParams.e,
180                                 f = transferParams.f
181                             )
182                         } else {
183                             null
184                         }
185                     Rgb(
186                         name = this.name,
187                         primaries = this.primaries,
188                         whitePoint = whitePoint,
189                         transform = this.transform,
190                         oetf = { x -> this.oetf.applyAsDouble(x) },
191                         eotf = { x -> this.eotf.applyAsDouble(x) },
192                         min = this.getMinValue(0),
193                         max = this.getMaxValue(0),
194                         transferParameters = composeTransferParams,
195                         id = this.id
196                     )
197                 } else {
198                     ColorSpaces.Srgb
199                 }
200             }
201         }
202     }
203 }
204