blob: 4f21fbb161dfa15330c870b8626ca04ddbeae97b [file] [log] [blame]
/*
* Copyright 2021 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <jni.h>
#include "include/core/SkColorSpace.h"
#include "include/core/SkM44.h"
#include "include/effects/SkGradientShader.h"
#include "modules/androidkit/src/Utils.h"
namespace {
// Helper for common gradient data access.
class GradientData {
public:
GradientData(JNIEnv* env, const jfloatArray& jcolors, const jfloatArray& jpos,
jint jtm, jlong native_lm)
: fEnv(env)
, fJColors(jcolors)
, fJPos(jpos)
, fColors(env->GetFloatArrayElements(jcolors, nullptr))
, fPos(env->GetFloatArrayElements(jpos, nullptr))
, fCount(env->GetArrayLength(jpos))
, fTileMode(androidkit::utils::TileMode(jtm))
, fLocalMatrix(native_lm ? reinterpret_cast<const SkM44*>(native_lm)->asM33() : SkMatrix())
{
SkASSERT(env->GetArrayLength(jcolors) == 4*fCount);
}
~GradientData() {
fEnv->ReleaseFloatArrayElements(fJPos, fPos, 0);
fEnv->ReleaseFloatArrayElements(fJColors, fColors, 0);
}
int count() const { return fCount; }
const SkColor4f* colors() const { return reinterpret_cast<const SkColor4f*>(fColors); }
const float* pos() const { return fPos; }
const SkTileMode& tileMode() const { return fTileMode; }
const SkMatrix& localMatrix() const { return fLocalMatrix; }
private:
JNIEnv* fEnv;
const jfloatArray& fJColors;
const jfloatArray& fJPos;
float* fColors;
float* fPos;
const int fCount;
const SkTileMode fTileMode;
const SkMatrix fLocalMatrix;
};
static jlong MakeLinear(JNIEnv* env, jobject, jfloat x0, jfloat y0, jfloat x1, jfloat y1,
jfloatArray jcolors, jfloatArray jpos, jint jtm, jlong native_lm) {
const GradientData gdata(env, jcolors, jpos, jtm, native_lm);
const SkPoint pts[] = {{x0, y0}, {x1, y1}};
auto shader = SkGradientShader::MakeLinear(pts,
gdata.colors(),
nullptr,
gdata.pos(),
gdata.count(),
gdata.tileMode(),
0,
&gdata.localMatrix());
return reinterpret_cast<jlong>(shader.release());
}
static jlong MakeRadial(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat r,
jfloatArray jcolors, jfloatArray jpos, jint jtm, jlong native_lm) {
const GradientData gdata(env, jcolors, jpos, jtm, native_lm);
auto shader = SkGradientShader::MakeRadial({x,y}, r,
gdata.colors(),
nullptr,
gdata.pos(),
gdata.count(),
gdata.tileMode(),
0,
&gdata.localMatrix());
return reinterpret_cast<jlong>(shader.release());
}
static jlong 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) {
const GradientData gdata(env, jcolors, jpos, jtm, native_lm);
auto shader = SkGradientShader::MakeTwoPointConical({x0,y0}, r0,
{x1,y1}, r1,
gdata.colors(),
nullptr,
gdata.pos(),
gdata.count(),
gdata.tileMode(),
0,
&gdata.localMatrix());
return reinterpret_cast<jlong>(shader.release());
}
static jlong MakeSweep(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat sa, jfloat ea,
jfloatArray jcolors, jfloatArray jpos, jint jtm, jlong native_lm) {
const GradientData gdata(env, jcolors, jpos, jtm, native_lm);
auto shader = SkGradientShader::MakeSweep(x, y,
gdata.colors(),
nullptr,
gdata.pos(),
gdata.count(),
gdata.tileMode(),
sa, ea,
0,
&gdata.localMatrix());
return reinterpret_cast<jlong>(shader.release());
}
} // namespace
int register_androidkit_LinearGradient(JNIEnv* env) {
static const JNINativeMethod methods[] = {
{"nMakeLinear", "(FFFF[F[FIJ)J", reinterpret_cast<void*>(MakeLinear)},
};
const auto clazz = env->FindClass("org/skia/androidkit/LinearGradient");
return clazz
? env->RegisterNatives(clazz, methods, std::size(methods))
: JNI_ERR;
}
int register_androidkit_RadialGradient(JNIEnv* env) {
static const JNINativeMethod methods[] = {
{"nMakeRadial", "(FFF[F[FIJ)J", reinterpret_cast<void*>(MakeRadial)},
};
const auto clazz = env->FindClass("org/skia/androidkit/RadialGradient");
return clazz
? env->RegisterNatives(clazz, methods, std::size(methods))
: JNI_ERR;
}
int register_androidkit_TwoPointConicalGradient(JNIEnv* env) {
static const JNINativeMethod methods[] = {
{"nMakeTwoPointConical", "(FFFFFF[F[FIJ)J", reinterpret_cast<void*>(MakeTwoPointConical)},
};
const auto clazz = env->FindClass("org/skia/androidkit/TwoPointConicalGradient");
return clazz
? env->RegisterNatives(clazz, methods, std::size(methods))
: JNI_ERR;
}
int register_androidkit_SweepGradient(JNIEnv* env) {
static const JNINativeMethod methods[] = {
{"nMakeSweep", "(FFFF[F[FIJ)J", reinterpret_cast<void*>(MakeSweep)},
};
const auto clazz = env->FindClass("org/skia/androidkit/SweepGradient");
return clazz
? env->RegisterNatives(clazz, methods, std::size(methods))
: JNI_ERR;
}