Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4209e156 authored by Nader Jawad's avatar Nader Jawad Committed by Android (Google) Code Review
Browse files

Merge "Added support for focal points in RadialGradient"

parents 03bc25f7 e7ab841f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -15457,6 +15457,7 @@ package android.graphics {
  public class RadialGradient extends android.graphics.Shader {
    ctor public RadialGradient(float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
    ctor public RadialGradient(float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
    ctor public RadialGradient(float, float, @FloatRange(from=0.0f) float, float, float, @FloatRange(from=0.0f, fromInclusive=false) float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
    ctor public RadialGradient(float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode);
    ctor public RadialGradient(float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode);
  }
+73 −16
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.graphics;

import android.annotation.ColorInt;
import android.annotation.ColorLong;
import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -34,6 +35,10 @@ public class RadialGradient extends Shader {
    @UnsupportedAppUsage
    private TileMode mTileMode;

    private final float mFocalX;
    private final float mFocalY;
    private final float mFocalRadius;

    // @ColorInts are replaced by @ColorLongs, but these remain due to @UnsupportedAppUsage.
    @UnsupportedAppUsage
    @ColorInt
@@ -64,8 +69,8 @@ public class RadialGradient extends Shader {
    public RadialGradient(float centerX, float centerY, float radius,
            @NonNull @ColorInt int[] colors, @Nullable float[] stops,
            @NonNull TileMode tileMode) {
        this(centerX, centerY, radius, convertColors(colors), stops, tileMode,
                ColorSpace.get(ColorSpace.Named.SRGB));
        this(centerX, centerY, 0f, centerX, centerY, radius, convertColors(colors),
                stops, tileMode, ColorSpace.get(ColorSpace.Named.SRGB));
    }

    /**
@@ -88,27 +93,79 @@ public class RadialGradient extends Shader {
    public RadialGradient(float centerX, float centerY, float radius,
            @NonNull @ColorLong long[] colors, @Nullable float[] stops,
            @NonNull TileMode tileMode) {
        this(centerX, centerY, radius, colors.clone(), stops, tileMode, detectColorSpace(colors));
        this(centerX, centerY, 0f, centerX, centerY, radius, colors.clone(), stops,
                tileMode, detectColorSpace(colors));
    }

    /**
     * Create a shader that draws a radial gradient given the start and end points as well as
     * starting and ending radii. The starting point is often referred to as the focal center and
     * represents the starting circle of the radial gradient.
     *
     * @param startX   The x-coordinate of the center of the starting circle of the radial gradient,
     *                often referred to as the focal point.
     * @param startY   The y-coordinate of the center of the starting circle of the radial gradient,
     *                 often referred to as the focal point.
     * @param startRadius The radius of the starting circle of the radial gradient, often referred
     *                    to as the focal radius. Must be greater than or equal to zero.
     * @param endX  The x-coordinate of the center of the radius for the end circle of the
     *                 radial gradient
     * @param endY  The y-coordinate of the center of the radius for the end circle of the
     *                 radial gradient
     * @param endRadius   The radius of the ending circle for this gradient. This must be strictly
     *                    greater than zero. A radius value equal to zero is not allowed.
     * @param colors   The colors to be distributed between the center and edge of the circle
     * @param stops    May be <code>null</code>. Valid values are between <code>0.0f</code> and
     *                 <code>1.0f</code>. The relative position of each corresponding color in
     *                 the colors array. If <code>null</code>, colors are distributed evenly
     *                 between the center and edge of the circle.
     * @param tileMode The Shader tiling mode
     *
     * @throws IllegalArgumentException If one of the following circumstances:
     *      - There are less than two colors
     *      - The colors do not share the same {@link ColorSpace}
     *      - The colors do not use a valid {@link ColorSpace}
     *      - The {@code stops} parameter is not {@code null} and has a different length
     *        from {@code colors}.
     *      - The {@param startRadius} is negative
     *      - The {@param endRadius} is less than or equal to zero
     */
    public RadialGradient(float startX, float startY, @FloatRange(from = 0.0f) float startRadius,
            float endX, float endY, @FloatRange(from = 0.0f, fromInclusive = false) float endRadius,
            @NonNull @ColorLong long[] colors, @Nullable float[] stops,
            @NonNull TileMode tileMode) {
        this(startX, startY, startRadius, endX, endY, endRadius, colors.clone(), stops, tileMode,
                detectColorSpace(colors));
    }

    /**
     * Base constructor. Assumes @param colors is a copy that this object can hold onto,
     * and all colors share @param colorSpace.
     */
    private RadialGradient(float centerX, float centerY, float radius,
            @NonNull @ColorLong long[] colors, @Nullable float[] stops,
            @NonNull TileMode tileMode, ColorSpace colorSpace) {
    private RadialGradient(float startX, float startY, float startRadius, float endX, float endY,
            float endRadius, @NonNull @ColorLong long[] colors, @Nullable float[] stops,
            @NonNull TileMode tileMode, ColorSpace colorSpace
    ) {
        super(colorSpace);
        // A focal or starting radius of zero with a focal point that matches the center is
        // identical to a regular radial gradient
        if (startRadius < 0) {
            throw new IllegalArgumentException("starting/focal radius must be >= 0");
        }

        if (radius <= 0) {
            throw new IllegalArgumentException("radius must be > 0");
        if (endRadius <= 0) {
            throw new IllegalArgumentException("ending radius must be > 0");
        }

        if (stops != null && colors.length != stops.length) {
            throw new IllegalArgumentException("color and position arrays must be of equal length");
        }
        mX = centerX;
        mY = centerY;
        mRadius = radius;
        mX = endX;
        mY = endY;
        mRadius = endRadius;
        mFocalX = startX;
        mFocalY = startY;
        mFocalRadius = startRadius;
        mColorLongs = colors;
        mPositions = stops != null ? stops.clone() : null;
        mTileMode = tileMode;
@@ -150,12 +207,12 @@ public class RadialGradient extends Shader {
    /** @hide */
    @Override
    protected long createNativeInstance(long nativeMatrix) {
        return nativeCreate(nativeMatrix, mX, mY, mRadius,
                mColorLongs, mPositions, mTileMode.nativeInt,
                colorSpace().getNativeInstance());
        return nativeCreate(nativeMatrix, mFocalX, mFocalY, mFocalRadius, mX, mY, mRadius,
                mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance());
    }

    private static native long nativeCreate(long matrix, float x, float y, float radius,
            @ColorLong long[] colors, float[] positions, int tileMode, long colorSpaceHandle);
    private static native long nativeCreate(long matrix, float startX, float startY,
            float startRadius, float endX, float endY, float endRadius, @ColorLong long[] colors,
            float[] positions, int tileMode, long colorSpaceHandle);
}
+28 −8
Original line number Diff line number Diff line
@@ -133,11 +133,25 @@ static jlong LinearGradient_create(JNIEnv* env, jobject, jlong matrixPtr,

///////////////////////////////////////////////////////////////////////////////////////////////

static jlong RadialGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y,
        jfloat radius, jlongArray colorArray, jfloatArray posArray, jint tileMode,
static jlong RadialGradient_create(JNIEnv* env,
        jobject,
        jlong matrixPtr,
        jfloat startX,
        jfloat startY,
        jfloat startRadius,
        jfloat endX,
        jfloat endY,
        jfloat endRadius,
        jlongArray colorArray,
        jfloatArray posArray,
        jint tileMode,
        jlong colorSpaceHandle) {
    SkPoint center;
    center.set(x, y);

    SkPoint start;
    start.set(startX, startY);

    SkPoint end;
    end.set(endX, endY);

    std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);

@@ -148,11 +162,17 @@ static jlong RadialGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat
    #error Need to convert float array to SkScalar array before calling the following function.
#endif

    sk_sp<SkShader> shader = SkGradientShader::MakeRadial(center, radius, &colors[0],
            GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
            static_cast<SkTileMode>(tileMode), sGradientShaderFlags, nullptr);
    auto colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
    auto skTileMode = static_cast<SkTileMode>(tileMode);
    sk_sp<SkShader> shader = SkGradientShader::MakeTwoPointConical(start, startRadius, end,
                    endRadius, &colors[0], std::move(colorSpace), pos, colors.size(), skTileMode,
                    sGradientShaderFlags, nullptr);
    ThrowIAE_IfNull(env, shader);

    // Explicitly create a new shader with the specified matrix to match existing behavior.
    // Passing in the matrix in the instantiation above can throw exceptions for non-invertible
    // matrices. However, makeWithLocalMatrix will still allow for the shader to be created
    // and skia handles null-shaders internally (i.e. is ignored)
    const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
    if (matrix) {
        shader = shader->makeWithLocalMatrix(*matrix);
@@ -279,7 +299,7 @@ static const JNINativeMethod gLinearGradientMethods[] = {
};

static const JNINativeMethod gRadialGradientMethods[] = {
    { "nativeCreate",     "(JFFF[J[FIJ)J",  (void*)RadialGradient_create     },
    { "nativeCreate",     "(JFFFFFF[J[FIJ)J",  (void*)RadialGradient_create     },
};

static const JNINativeMethod gSweepGradientMethods[] = {
+1 −0
Original line number Diff line number Diff line
@@ -15439,6 +15439,7 @@ package android.graphics {
  public class RadialGradient extends android.graphics.Shader {
    ctor public RadialGradient(float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
    ctor public RadialGradient(float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
    ctor public RadialGradient(float, float, @FloatRange(from=0.0f) float, float, float, @FloatRange(from=0.0f, fromInclusive=false) float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
    ctor public RadialGradient(float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode);
    ctor public RadialGradient(float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode);
  }