diff --git a/BUILD.gn b/BUILD.gn index a6fe5f693b..89d105b834 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -2522,6 +2522,7 @@ if (skia_enable_tools) { sources = [ "modules/androidkit/src/AndroidKit.cpp", "modules/androidkit/src/Canvas.cpp", + "modules/androidkit/src/Gradients.cpp", "modules/androidkit/src/Image.cpp", "modules/androidkit/src/ImageFilter.cpp", "modules/androidkit/src/Matrix.cpp", diff --git a/modules/androidkit/src/AndroidKit.cpp b/modules/androidkit/src/AndroidKit.cpp index 855b03d390..427e719d17 100644 --- a/modules/androidkit/src/AndroidKit.cpp +++ b/modules/androidkit/src/AndroidKit.cpp @@ -26,6 +26,7 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { REGISTER_NATIVES(Canvas) REGISTER_NATIVES(Image) REGISTER_NATIVES(ImageFilter) + REGISTER_NATIVES(LinearGradient) REGISTER_NATIVES(Matrix) REGISTER_NATIVES(Paint) REGISTER_NATIVES(Path) diff --git a/modules/androidkit/src/Gradients.cpp b/modules/androidkit/src/Gradients.cpp new file mode 100644 index 0000000000..f72259c4ae --- /dev/null +++ b/modules/androidkit/src/Gradients.cpp @@ -0,0 +1,53 @@ +/* + * 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 + +#include "include/core/SkM44.h" +#include "include/effects/SkGradientShader.h" +#include "modules/androidkit/src/Utils.h" + +namespace { + +static jlong MakeLinear(JNIEnv* env, jobject, jfloat x0, jfloat y0, jfloat x1, jfloat y1, + jfloatArray jcolors, jfloatArray jpos, jint jtm, jlong native_lm) { + const auto count = env->GetArrayLength(jpos); + SkASSERT(env->GetArrayLength(jcolors) == 4*count); + + auto* colors = env->GetFloatArrayElements(jcolors, nullptr); + auto* pos = env->GetFloatArrayElements(jpos, nullptr); + + const SkPoint pts[] = {{x0, y0}, {x1, y1}}; + + const auto tm = androidkit::utils::TileMode(jtm); + + SkMatrix lm; + if (const auto* lm44 = reinterpret_cast(native_lm)) { + lm = lm44->asM33(); + } + + auto shader = SkGradientShader::MakeLinear(pts, reinterpret_cast(colors), + nullptr, pos, count, tm, 0, &lm); + + env->ReleaseFloatArrayElements(jpos, pos, 0); + env->ReleaseFloatArrayElements(jcolors, colors, 0); + + return reinterpret_cast(shader.release()); +} + +} // namespace + +int register_androidkit_LinearGradient(JNIEnv* env) { + static const JNINativeMethod methods[] = { + {"nMakeLinear", "(FFFF[F[FIJ)J", reinterpret_cast(MakeLinear)}, + }; + + const auto clazz = env->FindClass("org/skia/androidkit/LinearGradient"); + return clazz + ? env->RegisterNatives(clazz, methods, SK_ARRAY_COUNT(methods)) + : JNI_ERR; +} diff --git a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/LinearGradient.java b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/LinearGradient.java new file mode 100644 index 0000000000..50c627140a --- /dev/null +++ b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/LinearGradient.java @@ -0,0 +1,48 @@ +/* + * Copyright 2021 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +package org.skia.androidkit; + +import android.support.annotation.Nullable; +import java.lang.IllegalArgumentException; + +public class LinearGradient extends Shader { + public LinearGradient(float x0, float y0, float x1, float y1, Color[] colors, + float[] pos, TileMode tm, + @Nullable Matrix localMatrix) throws IllegalArgumentException { + super(makeNative(x0, y0, x1, y1, colors, pos, tm, localMatrix)); + } + + public LinearGradient(float x0, float y0, float x1, float y1, Color[] colors, + float[] pos, TileMode tm) throws IllegalArgumentException { + this(x0, y0, x1, y1, colors, pos, tm, null); + } + + private static long makeNative(float x0, float y0, float x1, float y1, Color[] colors, + float[] pos, TileMode tm, + @Nullable Matrix localMatrix) throws IllegalArgumentException { + if (colors.length != pos.length) { + throw new IllegalArgumentException("Expecting equal-length colors and positions."); + } + + float[] fcolors = new float[colors.length * 4]; + for (int i = 0; i < colors.length; ++i) { + fcolors[4*i + 0] = colors[i].r(); + fcolors[4*i + 1] = colors[i].g(); + fcolors[4*i + 2] = colors[i].b(); + fcolors[4*i + 3] = colors[i].a(); + } + + long nativeLocalMatrix = localMatrix != null ? localMatrix.getNativeInstance() : 0; + + return nMakeLinear(x0, y0, x1, y1, fcolors, pos, tm.ordinal(), nativeLocalMatrix); + } + + private static native long nMakeLinear(float x0, float y0, float x1, float y1, + float[] colors, float[] pos, int tilemode, + long nativeLocalMatrix); +} diff --git a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Shader.java b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Shader.java index 20235a33d3..d11c0baa0f 100644 --- a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Shader.java +++ b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Shader.java @@ -10,10 +10,6 @@ package org.skia.androidkit; public class Shader { private long mNativeInstance; - protected Shader(long native_instance) { - mNativeInstance = native_instance; - } - /** * Releases any resources associated with this Shader. */ @@ -28,6 +24,10 @@ public class Shader { } // package private + Shader(long native_instance) { + mNativeInstance = native_instance; + } + long getNativeInstance() { return mNativeInstance; } private static native void nRelease(long nativeInstance); diff --git a/platform_tools/android/apps/androidkitdemo/src/main/java/org/skia/androidkitdemo1/AnimationActivity.java b/platform_tools/android/apps/androidkitdemo/src/main/java/org/skia/androidkitdemo1/AnimationActivity.java index 31c62be101..9b3ec176fe 100644 --- a/platform_tools/android/apps/androidkitdemo/src/main/java/org/skia/androidkitdemo1/AnimationActivity.java +++ b/platform_tools/android/apps/androidkitdemo/src/main/java/org/skia/androidkitdemo1/AnimationActivity.java @@ -26,8 +26,14 @@ class AnimationRenderer extends SurfaceRenderer { canvas.drawColor(0xffffffe0); - Paint p = new Paint(); - p.setColor(new Color(0, 1, 0, 1)); + Color[] colors = { new Color(1,0,0,1), + new Color(0,1,0,1), + new Color(0,0,1,1)}; + float[] pos = {0, 0.5f, 1}; + Shader gradient = new LinearGradient(0, 0, canvas.getWidth(), 0, + colors, pos, TileMode.CLAMP); + + Paint p = new Paint().setShader(gradient); float x = (float)(java.lang.Math.cos(ms * kSpeed / 1000) + 1) * canvas.getWidth()/2; canvas.drawRect(x - kWidth/2, (canvas.getHeight() - kHeight)/2,