1 /*
2  * Copyright (C) 2019 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 #include "GraphicsJNI.h"
18 
19 #include "SkColor.h"
20 #include "SkColorSpace.h"
21 #include "SkHalf.h"
22 
23 using namespace android;
24 
getNativeXYZMatrix(JNIEnv * env,jfloatArray xyzD50)25 static skcms_Matrix3x3 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50) {
26     skcms_Matrix3x3 xyzMatrix;
27     jfloat* array = env->GetFloatArrayElements(xyzD50, NULL);
28     xyzMatrix.vals[0][0] = array[0];
29     xyzMatrix.vals[1][0] = array[1];
30     xyzMatrix.vals[2][0] = array[2];
31     xyzMatrix.vals[0][1] = array[3];
32     xyzMatrix.vals[1][1] = array[4];
33     xyzMatrix.vals[2][1] = array[5];
34     xyzMatrix.vals[0][2] = array[6];
35     xyzMatrix.vals[1][2] = array[7];
36     xyzMatrix.vals[2][2] = array[8];
37     env->ReleaseFloatArrayElements(xyzD50, array, 0);
38     return xyzMatrix;
39 }
40 
41 ///////////////////////////////////////////////////////////////////////////////
42 
halfToFloat(uint16_t bits)43 static float halfToFloat(uint16_t bits) {
44 #ifdef __ANDROID__ // __fp16 is not defined on non-Android builds
45     __fp16 h;
46     memcpy(&h, &bits, 2);
47     return (float)h;
48 #else
49     return SkHalfToFloat(bits);
50 #endif
51 }
52 
convertColorLong(jlong color)53 SkColor4f GraphicsJNI::convertColorLong(jlong color) {
54     if ((color & 0x3f) == 0) {
55         // This corresponds to sRGB, which is treated differently than the rest.
56         uint8_t a = color >> 56 & 0xff;
57         uint8_t r = color >> 48 & 0xff;
58         uint8_t g = color >> 40 & 0xff;
59         uint8_t b = color >> 32 & 0xff;
60         SkColor c = SkColorSetARGB(a, r, g, b);
61         return SkColor4f::FromColor(c);
62     }
63 
64     // These match the implementation of android.graphics.Color#red(long) etc.
65     float r = halfToFloat((uint16_t)(color >> 48 & 0xffff));
66     float g = halfToFloat((uint16_t)(color >> 32 & 0xffff));
67     float b = halfToFloat((uint16_t)(color >> 16 & 0xffff));
68     float a =                       (color >>  6 &  0x3ff) / 1023.0f;
69 
70     return SkColor4f{r, g, b, a};
71 }
72 
getNativeColorSpace(jlong colorSpaceHandle)73 sk_sp<SkColorSpace> GraphicsJNI::getNativeColorSpace(jlong colorSpaceHandle) {
74     if (colorSpaceHandle == 0) return nullptr;
75     return sk_ref_sp(reinterpret_cast<SkColorSpace*>(colorSpaceHandle));
76 }
77 
unref_colorSpace(SkColorSpace * cs)78 static void unref_colorSpace(SkColorSpace* cs) {
79     SkSafeUnref(cs);
80 }
81 
ColorSpace_getNativeFinalizer(JNIEnv *,jobject)82 static jlong ColorSpace_getNativeFinalizer(JNIEnv*, jobject) {
83     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&unref_colorSpace));
84 }
85 
ColorSpace_creator(JNIEnv * env,jobject,jfloat a,jfloat b,jfloat c,jfloat d,jfloat e,jfloat f,jfloat g,jfloatArray xyzD50)86 static jlong ColorSpace_creator(JNIEnv* env, jobject, jfloat a, jfloat b, jfloat c,
87         jfloat d, jfloat e, jfloat f, jfloat g, jfloatArray xyzD50) {
88     skcms_TransferFunction p;
89     p.a = a;
90     p.b = b;
91     p.c = c;
92     p.d = d;
93     p.e = e;
94     p.f = f;
95     p.g = g;
96     skcms_Matrix3x3 xyzMatrix = getNativeXYZMatrix(env, xyzD50);
97 
98     return reinterpret_cast<jlong>(SkColorSpace::MakeRGB(p, xyzMatrix).release());
99 }
100 
101 static const JNINativeMethod gColorSpaceRgbMethods[] = {
102     {   "nativeGetNativeFinalizer", "()J", (void*)ColorSpace_getNativeFinalizer },
103     {   "nativeCreate", "(FFFFFFF[F)J", (void*)ColorSpace_creator }
104 };
105 
106 namespace android {
107 
register_android_graphics_ColorSpace(JNIEnv * env)108 int register_android_graphics_ColorSpace(JNIEnv* env) {
109     return android::RegisterMethodsOrDie(env, "android/graphics/ColorSpace$Rgb",
110                                          gColorSpaceRgbMethods, NELEM(gColorSpaceRgbMethods));
111 }
112 
113 }; // namespace android
114