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.FloatRange; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.compat.annotation.UnsupportedAppUsage; 25 import android.os.Build; 26 27 @android.ravenwood.annotation.RavenwoodKeepWholeClass 28 public class RadialGradient extends Shader { 29 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 30 private float mX; 31 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 32 private float mY; 33 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 34 private float mRadius; 35 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 36 private float[] mPositions; 37 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 38 private TileMode mTileMode; 39 40 private final float mFocalX; 41 private final float mFocalY; 42 private final float mFocalRadius; 43 44 // @ColorInts are replaced by @ColorLongs, but these remain due to @UnsupportedAppUsage. 45 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 46 @ColorInt 47 private int[] mColors; 48 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 49 @ColorInt 50 private int mCenterColor; 51 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 52 @ColorInt 53 private int mEdgeColor; 54 55 @ColorLong 56 private final long[] mColorLongs; 57 58 /** 59 * Create a shader that draws a radial gradient given the center and radius. 60 * 61 * @param centerX The x-coordinate of the center of the radius 62 * @param centerY The y-coordinate of the center of the radius 63 * @param radius Must be positive. The radius of the circle for this gradient. 64 * @param colors The sRGB colors to be distributed between the center and edge of the circle 65 * @param stops May be <code>null</code>. Valid values are between <code>0.0f</code> and 66 * <code>1.0f</code>. The relative position of each corresponding color in 67 * the colors array. If <code>null</code>, colors are distributed evenly 68 * between the center and edge of the circle. 69 * @param tileMode The Shader tiling mode 70 */ RadialGradient(float centerX, float centerY, float radius, @NonNull @ColorInt int[] colors, @Nullable float[] stops, @NonNull TileMode tileMode)71 public RadialGradient(float centerX, float centerY, float radius, 72 @NonNull @ColorInt int[] colors, @Nullable float[] stops, 73 @NonNull TileMode tileMode) { 74 this(centerX, centerY, 0f, centerX, centerY, radius, convertColors(colors), 75 stops, tileMode, ColorSpace.get(ColorSpace.Named.SRGB)); 76 } 77 78 /** 79 * Create a shader that draws a radial gradient given the center and radius. 80 * 81 * @param centerX The x-coordinate of the center of the radius 82 * @param centerY The y-coordinate of the center of the radius 83 * @param radius Must be positive. The radius of the circle for this gradient. 84 * @param colors The colors to be distributed between the center and edge of the circle 85 * @param stops May be <code>null</code>. Valid values are between <code>0.0f</code> and 86 * <code>1.0f</code>. The relative position of each corresponding color in 87 * the colors array. If <code>null</code>, colors are distributed evenly 88 * between the center and edge of the circle. 89 * @param tileMode The Shader tiling mode 90 * 91 * @throws IllegalArgumentException if there are less than two colors, the colors do 92 * not share the same {@link ColorSpace} or do not use a valid one, or {@code stops} 93 * is not {@code null} and has a different length from {@code colors}. 94 */ RadialGradient(float centerX, float centerY, float radius, @NonNull @ColorLong long[] colors, @Nullable float[] stops, @NonNull TileMode tileMode)95 public RadialGradient(float centerX, float centerY, float radius, 96 @NonNull @ColorLong long[] colors, @Nullable float[] stops, 97 @NonNull TileMode tileMode) { 98 this(centerX, centerY, 0f, centerX, centerY, radius, colors.clone(), stops, 99 tileMode, detectColorSpace(colors)); 100 } 101 102 /** 103 * Create a shader that draws a radial gradient given the start and end points as well as 104 * starting and ending radii. The starting point is often referred to as the focal center and 105 * represents the starting circle of the radial gradient. 106 * 107 * @param startX The x-coordinate of the center of the starting circle of the radial gradient, 108 * often referred to as the focal point. 109 * @param startY The y-coordinate of the center of the starting circle of the radial gradient, 110 * often referred to as the focal point. 111 * @param startRadius The radius of the starting circle of the radial gradient, often referred 112 * to as the focal radius. Must be greater than or equal to zero. 113 * @param endX The x-coordinate of the center of the radius for the end circle of the 114 * radial gradient 115 * @param endY The y-coordinate of the center of the radius for the end circle of the 116 * radial gradient 117 * @param endRadius The radius of the ending circle for this gradient. This must be strictly 118 * greater than zero. A radius value equal to zero is not allowed. 119 * @param colors The colors to be distributed between the center and edge of the circle 120 * @param stops May be <code>null</code>. Valid values are between <code>0.0f</code> and 121 * <code>1.0f</code>. The relative position of each corresponding color in 122 * the colors array. If <code>null</code>, colors are distributed evenly 123 * between the center and edge of the circle. 124 * @param tileMode The Shader tiling mode 125 * 126 * @throws IllegalArgumentException In one of the following circumstances: 127 * <ul> 128 * <li>There are less than two colors</li> 129 * <li>The colors do not share the same {@link ColorSpace}</li> 130 * <li>The colors do not use a valid {@link ColorSpace}</li> 131 * <li> 132 * The {@code stops} parameter is not {@code null} and has a different length from 133 * {@code colors}. 134 * </li> 135 * <li>The {@code startRadius} is negative</li> 136 * <li>The {@code endRadius} is less than or equal to zero</li> 137 * </ul> 138 */ 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)139 public RadialGradient(float startX, float startY, @FloatRange(from = 0.0f) float startRadius, 140 float endX, float endY, @FloatRange(from = 0.0f, fromInclusive = false) float endRadius, 141 @NonNull @ColorLong long[] colors, @Nullable float[] stops, 142 @NonNull TileMode tileMode) { 143 this(startX, startY, startRadius, endX, endY, endRadius, colors.clone(), stops, tileMode, 144 detectColorSpace(colors)); 145 } 146 147 /** 148 * Base constructor. Assumes @param colors is a copy that this object can hold onto, 149 * and all colors share @param colorSpace. 150 */ 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 )151 private RadialGradient(float startX, float startY, float startRadius, float endX, float endY, 152 float endRadius, @NonNull @ColorLong long[] colors, @Nullable float[] stops, 153 @NonNull TileMode tileMode, ColorSpace colorSpace 154 ) { 155 super(colorSpace); 156 // A focal or starting radius of zero with a focal point that matches the center is 157 // identical to a regular radial gradient 158 if (startRadius < 0) { 159 throw new IllegalArgumentException("starting/focal radius must be >= 0"); 160 } 161 162 if (endRadius <= 0) { 163 throw new IllegalArgumentException("ending radius must be > 0"); 164 } 165 166 if (stops != null && colors.length != stops.length) { 167 throw new IllegalArgumentException("color and position arrays must be of equal length"); 168 } 169 mX = endX; 170 mY = endY; 171 mRadius = endRadius; 172 mFocalX = startX; 173 mFocalY = startY; 174 mFocalRadius = startRadius; 175 mColorLongs = colors; 176 mPositions = stops != null ? stops.clone() : null; 177 mTileMode = tileMode; 178 } 179 180 /** 181 * Create a shader that draws a radial gradient given the center and radius. 182 * 183 * @param centerX The x-coordinate of the center of the radius 184 * @param centerY The y-coordinate of the center of the radius 185 * @param radius Must be positive. The radius of the circle for this gradient 186 * @param centerColor The sRGB color at the center of the circle. 187 * @param edgeColor The sRGB color at the edge of the circle. 188 * @param tileMode The Shader tiling mode 189 */ RadialGradient(float centerX, float centerY, float radius, @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode)190 public RadialGradient(float centerX, float centerY, float radius, 191 @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) { 192 this(centerX, centerY, radius, Color.pack(centerColor), Color.pack(edgeColor), tileMode); 193 } 194 195 /** 196 * Create a shader that draws a radial gradient given the center and radius. 197 * 198 * @param centerX The x-coordinate of the center of the radius 199 * @param centerY The y-coordinate of the center of the radius 200 * @param radius Must be positive. The radius of the circle for this gradient 201 * @param centerColor The color at the center of the circle. 202 * @param edgeColor The color at the edge of the circle. 203 * @param tileMode The Shader tiling mode 204 * 205 * @throws IllegalArgumentException if the colors do 206 * not share the same {@link ColorSpace} or do not use a valid one. 207 */ RadialGradient(float centerX, float centerY, float radius, @ColorLong long centerColor, @ColorLong long edgeColor, @NonNull TileMode tileMode)208 public RadialGradient(float centerX, float centerY, float radius, 209 @ColorLong long centerColor, @ColorLong long edgeColor, @NonNull TileMode tileMode) { 210 this(centerX, centerY, radius, new long[] {centerColor, edgeColor}, null, tileMode); 211 } 212 213 /** @hide */ 214 @Override createNativeInstance(long nativeMatrix, boolean filterFromPaint)215 protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) { 216 return nativeCreate(nativeMatrix, mFocalX, mFocalY, mFocalRadius, mX, mY, mRadius, 217 mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance()); 218 } 219 nativeCreate(long matrix, float startX, float startY, float startRadius, float endX, float endY, float endRadius, @ColorLong long[] colors, float[] positions, int tileMode, long colorSpaceHandle)220 private static native long nativeCreate(long matrix, float startX, float startY, 221 float startRadius, float endX, float endY, float endRadius, @ColorLong long[] colors, 222 float[] positions, int tileMode, long colorSpaceHandle); 223 } 224 225