1 /*
2 * Copyright 2021 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include <jni.h>
9
10 #include "include/core/SkColorSpace.h"
11 #include "include/core/SkM44.h"
12 #include "include/effects/SkGradientShader.h"
13 #include "modules/jetski/src/Utils.h"
14
15 namespace {
16
17 // Helper for common gradient data access.
18 class GradientData {
19 public:
GradientData(JNIEnv * env,const jfloatArray & jcolors,const jfloatArray & jpos,jint jtm,jlong native_lm)20 GradientData(JNIEnv* env, const jfloatArray& jcolors, const jfloatArray& jpos,
21 jint jtm, jlong native_lm)
22 : fEnv(env)
23 , fJColors(jcolors)
24 , fJPos(jpos)
25 , fColors(env->GetFloatArrayElements(jcolors, nullptr))
26 , fPos(env->GetFloatArrayElements(jpos, nullptr))
27 , fCount(env->GetArrayLength(jpos))
28 , fTileMode(jetski::utils::TileMode(jtm))
29 , fLocalMatrix(native_lm ? reinterpret_cast<const SkM44*>(native_lm)->asM33() : SkMatrix())
30 {
31 SkASSERT(env->GetArrayLength(jcolors) == 4*fCount);
32 }
33
~GradientData()34 ~GradientData() {
35 fEnv->ReleaseFloatArrayElements(fJPos, fPos, 0);
36 fEnv->ReleaseFloatArrayElements(fJColors, fColors, 0);
37 }
38
count() const39 int count() const { return fCount; }
40
colors() const41 const SkColor4f* colors() const { return reinterpret_cast<const SkColor4f*>(fColors); }
pos() const42 const float* pos() const { return fPos; }
tileMode() const43 const SkTileMode& tileMode() const { return fTileMode; }
localMatrix() const44 const SkMatrix& localMatrix() const { return fLocalMatrix; }
45
46 private:
47 JNIEnv* fEnv;
48 const jfloatArray& fJColors;
49 const jfloatArray& fJPos;
50 float* fColors;
51 float* fPos;
52 const int fCount;
53 const SkTileMode fTileMode;
54 const SkMatrix fLocalMatrix;
55 };
56
MakeLinear(JNIEnv * env,jobject,jfloat x0,jfloat y0,jfloat x1,jfloat y1,jfloatArray jcolors,jfloatArray jpos,jint jtm,jlong native_lm)57 static jlong MakeLinear(JNIEnv* env, jobject, jfloat x0, jfloat y0, jfloat x1, jfloat y1,
58 jfloatArray jcolors, jfloatArray jpos, jint jtm, jlong native_lm) {
59 const GradientData gdata(env, jcolors, jpos, jtm, native_lm);
60 const SkPoint pts[] = {{x0, y0}, {x1, y1}};
61
62 auto shader = SkGradientShader::MakeLinear(pts,
63 gdata.colors(),
64 nullptr,
65 gdata.pos(),
66 gdata.count(),
67 gdata.tileMode(),
68 0,
69 &gdata.localMatrix());
70
71 return reinterpret_cast<jlong>(shader.release());
72 }
73
MakeRadial(JNIEnv * env,jobject,jfloat x,jfloat y,jfloat r,jfloatArray jcolors,jfloatArray jpos,jint jtm,jlong native_lm)74 static jlong MakeRadial(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat r,
75 jfloatArray jcolors, jfloatArray jpos, jint jtm, jlong native_lm) {
76 const GradientData gdata(env, jcolors, jpos, jtm, native_lm);
77
78 auto shader = SkGradientShader::MakeRadial({x,y}, r,
79 gdata.colors(),
80 nullptr,
81 gdata.pos(),
82 gdata.count(),
83 gdata.tileMode(),
84 0,
85 &gdata.localMatrix());
86
87 return reinterpret_cast<jlong>(shader.release());
88 }
89
MakeTwoPointConical(JNIEnv * env,jobject,jfloat x0,jfloat y0,jfloat r0,jfloat x1,jfloat y1,jfloat r1,jfloatArray jcolors,jfloatArray jpos,jint jtm,jlong native_lm)90 static jlong MakeTwoPointConical(JNIEnv* env, jobject,
91 jfloat x0, jfloat y0, jfloat r0,
92 jfloat x1, jfloat y1, jfloat r1,
93 jfloatArray jcolors, jfloatArray jpos, jint jtm, jlong native_lm) {
94 const GradientData gdata(env, jcolors, jpos, jtm, native_lm);
95
96 auto shader = SkGradientShader::MakeTwoPointConical({x0,y0}, r0,
97 {x1,y1}, r1,
98 gdata.colors(),
99 nullptr,
100 gdata.pos(),
101 gdata.count(),
102 gdata.tileMode(),
103 0,
104 &gdata.localMatrix());
105
106 return reinterpret_cast<jlong>(shader.release());
107 }
108
MakeSweep(JNIEnv * env,jobject,jfloat x,jfloat y,jfloat sa,jfloat ea,jfloatArray jcolors,jfloatArray jpos,jint jtm,jlong native_lm)109 static jlong MakeSweep(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat sa, jfloat ea,
110 jfloatArray jcolors, jfloatArray jpos, jint jtm, jlong native_lm) {
111 const GradientData gdata(env, jcolors, jpos, jtm, native_lm);
112
113 auto shader = SkGradientShader::MakeSweep(x, y,
114 gdata.colors(),
115 nullptr,
116 gdata.pos(),
117 gdata.count(),
118 gdata.tileMode(),
119 sa, ea,
120 0,
121 &gdata.localMatrix());
122
123 return reinterpret_cast<jlong>(shader.release());
124 }
125
126 } // namespace
127
register_jetski_LinearGradient(JNIEnv * env)128 int register_jetski_LinearGradient(JNIEnv* env) {
129 static const JNINativeMethod methods[] = {
130 {"nMakeLinear", "(FFFF[F[FIJ)J", reinterpret_cast<void*>(MakeLinear)},
131 };
132
133 const auto clazz = env->FindClass("org/skia/jetski/LinearGradient");
134 return clazz
135 ? env->RegisterNatives(clazz, methods, std::size(methods))
136 : JNI_ERR;
137 }
138
register_jetski_RadialGradient(JNIEnv * env)139 int register_jetski_RadialGradient(JNIEnv* env) {
140 static const JNINativeMethod methods[] = {
141 {"nMakeRadial", "(FFF[F[FIJ)J", reinterpret_cast<void*>(MakeRadial)},
142 };
143
144 const auto clazz = env->FindClass("org/skia/jetski/RadialGradient");
145 return clazz
146 ? env->RegisterNatives(clazz, methods, std::size(methods))
147 : JNI_ERR;
148 }
149
register_jetski_TwoPointConicalGradient(JNIEnv * env)150 int register_jetski_TwoPointConicalGradient(JNIEnv* env) {
151 static const JNINativeMethod methods[] = {
152 {"nMakeTwoPointConical", "(FFFFFF[F[FIJ)J", reinterpret_cast<void*>(MakeTwoPointConical)},
153 };
154
155 const auto clazz = env->FindClass("org/skia/jetski/TwoPointConicalGradient");
156 return clazz
157 ? env->RegisterNatives(clazz, methods, std::size(methods))
158 : JNI_ERR;
159 }
160
register_jetski_SweepGradient(JNIEnv * env)161 int register_jetski_SweepGradient(JNIEnv* env) {
162 static const JNINativeMethod methods[] = {
163 {"nMakeSweep", "(FFFF[F[FIJ)J", reinterpret_cast<void*>(MakeSweep)},
164 };
165
166 const auto clazz = env->FindClass("org/skia/jetski/SweepGradient");
167 return clazz
168 ? env->RegisterNatives(clazz, methods, std::size(methods))
169 : JNI_ERR;
170 }
171