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