1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics;
18 
19 import android.annotation.ColorInt;
20 import android.annotation.ColorLong;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.compat.annotation.UnsupportedAppUsage;
24 
25 public class RadialGradient extends Shader {
26     @UnsupportedAppUsage
27     private float mX;
28     @UnsupportedAppUsage
29     private float mY;
30     @UnsupportedAppUsage
31     private float mRadius;
32     @UnsupportedAppUsage
33     private float[] mPositions;
34     @UnsupportedAppUsage
35     private TileMode mTileMode;
36 
37     // @ColorInts are replaced by @ColorLongs, but these remain due to @UnsupportedAppUsage.
38     @UnsupportedAppUsage
39     @ColorInt
40     private int[] mColors;
41     @UnsupportedAppUsage
42     @ColorInt
43     private int mCenterColor;
44     @UnsupportedAppUsage
45     @ColorInt
46     private int mEdgeColor;
47 
48     @ColorLong
49     private final long[] mColorLongs;
50 
51     /**
52      * Create a shader that draws a radial gradient given the center and radius.
53      *
54      * @param centerX  The x-coordinate of the center of the radius
55      * @param centerY  The y-coordinate of the center of the radius
56      * @param radius   Must be positive. The radius of the circle for this gradient.
57      * @param colors   The sRGB colors to be distributed between the center and edge of the circle
58      * @param stops    May be <code>null</code>. Valid values are between <code>0.0f</code> and
59      *                 <code>1.0f</code>. The relative position of each corresponding color in
60      *                 the colors array. If <code>null</code>, colors are distributed evenly
61      *                 between the center and edge of the circle.
62      * @param tileMode The Shader tiling mode
63      */
RadialGradient(float centerX, float centerY, float radius, @NonNull @ColorInt int[] colors, @Nullable float[] stops, @NonNull TileMode tileMode)64     public RadialGradient(float centerX, float centerY, float radius,
65             @NonNull @ColorInt int[] colors, @Nullable float[] stops,
66             @NonNull TileMode tileMode) {
67         this(centerX, centerY, radius, convertColors(colors), stops, tileMode,
68                 ColorSpace.get(ColorSpace.Named.SRGB));
69     }
70 
71     /**
72      * Create a shader that draws a radial gradient given the center and radius.
73      *
74      * @param centerX  The x-coordinate of the center of the radius
75      * @param centerY  The y-coordinate of the center of the radius
76      * @param radius   Must be positive. The radius of the circle for this gradient.
77      * @param colors   The colors to be distributed between the center and edge of the circle
78      * @param stops    May be <code>null</code>. Valid values are between <code>0.0f</code> and
79      *                 <code>1.0f</code>. The relative position of each corresponding color in
80      *                 the colors array. If <code>null</code>, colors are distributed evenly
81      *                 between the center and edge of the circle.
82      * @param tileMode The Shader tiling mode
83      *
84      * @throws IllegalArgumentException if there are less than two colors, the colors do
85      *      not share the same {@link ColorSpace} or do not use a valid one, or {@code stops}
86      *      is not {@code null} and has a different length from {@code colors}.
87      */
RadialGradient(float centerX, float centerY, float radius, @NonNull @ColorLong long[] colors, @Nullable float[] stops, @NonNull TileMode tileMode)88     public RadialGradient(float centerX, float centerY, float radius,
89             @NonNull @ColorLong long[] colors, @Nullable float[] stops,
90             @NonNull TileMode tileMode) {
91         this(centerX, centerY, radius, colors.clone(), stops, tileMode, detectColorSpace(colors));
92     }
93 
94     /**
95      * Base constructor. Assumes @param colors is a copy that this object can hold onto,
96      * and all colors share @param colorSpace.
97      */
RadialGradient(float centerX, float centerY, float radius, @NonNull @ColorLong long[] colors, @Nullable float[] stops, @NonNull TileMode tileMode, ColorSpace colorSpace)98     private RadialGradient(float centerX, float centerY, float radius,
99             @NonNull @ColorLong long[] colors, @Nullable float[] stops,
100             @NonNull TileMode tileMode, ColorSpace colorSpace) {
101         super(colorSpace);
102 
103         if (radius <= 0) {
104             throw new IllegalArgumentException("radius must be > 0");
105         }
106         if (stops != null && colors.length != stops.length) {
107             throw new IllegalArgumentException("color and position arrays must be of equal length");
108         }
109         mX = centerX;
110         mY = centerY;
111         mRadius = radius;
112         mColorLongs = colors;
113         mPositions = stops != null ? stops.clone() : null;
114         mTileMode = tileMode;
115     }
116 
117     /**
118      * Create a shader that draws a radial gradient given the center and radius.
119      *
120      * @param centerX     The x-coordinate of the center of the radius
121      * @param centerY     The y-coordinate of the center of the radius
122      * @param radius      Must be positive. The radius of the circle for this gradient
123      * @param centerColor The sRGB color at the center of the circle.
124      * @param edgeColor   The sRGB color at the edge of the circle.
125      * @param tileMode    The Shader tiling mode
126      */
RadialGradient(float centerX, float centerY, float radius, @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode)127     public RadialGradient(float centerX, float centerY, float radius,
128             @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) {
129         this(centerX, centerY, radius, Color.pack(centerColor), Color.pack(edgeColor), tileMode);
130     }
131 
132     /**
133      * Create a shader that draws a radial gradient given the center and radius.
134      *
135      * @param centerX     The x-coordinate of the center of the radius
136      * @param centerY     The y-coordinate of the center of the radius
137      * @param radius      Must be positive. The radius of the circle for this gradient
138      * @param centerColor The color at the center of the circle.
139      * @param edgeColor   The color at the edge of the circle.
140      * @param tileMode    The Shader tiling mode
141      *
142      * @throws IllegalArgumentException if the colors do
143      *      not share the same {@link ColorSpace} or do not use a valid one.
144      */
RadialGradient(float centerX, float centerY, float radius, @ColorLong long centerColor, @ColorLong long edgeColor, @NonNull TileMode tileMode)145     public RadialGradient(float centerX, float centerY, float radius,
146             @ColorLong long centerColor, @ColorLong long edgeColor, @NonNull TileMode tileMode) {
147         this(centerX, centerY, radius, new long[] {centerColor, edgeColor}, null, tileMode);
148     }
149 
150     @Override
createNativeInstance(long nativeMatrix)151     long createNativeInstance(long nativeMatrix) {
152         return nativeCreate(nativeMatrix, mX, mY, mRadius,
153                 mColorLongs, mPositions, mTileMode.nativeInt,
154                 colorSpace().getNativeInstance());
155     }
156 
nativeCreate(long matrix, float x, float y, float radius, @ColorLong long[] colors, float[] positions, int tileMode, long colorSpaceHandle)157     private static native long nativeCreate(long matrix, float x, float y, float radius,
158             @ColorLong long[] colors, float[] positions, int tileMode, long colorSpaceHandle);
159 }
160 
161