Loading api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -14249,7 +14249,9 @@ package android.graphics { public class LinearGradient extends android.graphics.Shader { ctor public LinearGradient(float, float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @NonNull @ColorLong long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode); } public class MaskFilter { Loading Loading @@ -14778,7 +14780,9 @@ package android.graphics { public class RadialGradient extends android.graphics.Shader { ctor public RadialGradient(float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public RadialGradient(float, float, float, @NonNull @ColorLong 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); } public final class RecordingCanvas extends android.graphics.Canvas { Loading Loading @@ -15038,7 +15042,9 @@ package android.graphics { public class SweepGradient extends android.graphics.Shader { ctor public SweepGradient(float, float, @NonNull @ColorInt int[], @Nullable float[]); ctor public SweepGradient(float, float, @NonNull @ColorLong long[], @Nullable float[]); ctor public SweepGradient(float, float, @ColorInt int, @ColorInt int); ctor public SweepGradient(float, float, @ColorLong long, @ColorLong long); } public class Typeface { core/jni/android/graphics/Shader.cpp +56 −128 Original line number Diff line number Diff line Loading @@ -8,6 +8,8 @@ #include <jni.h> #include <vector> using namespace android::uirenderer; /** Loading @@ -18,10 +20,10 @@ using namespace android::uirenderer; */ static const uint32_t sGradientShaderFlags = SkGradientShader::kInterpolateColorsInPremul_Flag; static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { if (NULL == ptr) { doThrowIAE(env); } #define ThrowIAE_IfNull(env, ptr) \ if (nullptr == ptr) { \ doThrowIAE(env); \ return 0; \ } static void Color_RGBToHSV(JNIEnv* env, jobject, jint red, jint green, jint blue, jfloatArray hsvArray) Loading Loading @@ -76,186 +78,115 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j } sk_sp<SkShader> shader = image->makeShader( (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY); ThrowIAE_IfNull(env, shader.get()); if (matrix) { shader = shader->makeWithLocalMatrix(*matrix); } ThrowIAE_IfNull(env, shader.get()); return reinterpret_cast<jlong>(shader.release()); } /////////////////////////////////////////////////////////////////////////////////////////////// static jlong LinearGradient_create1(JNIEnv* env, jobject o, jlong matrixPtr, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jintArray colorArray, jfloatArray posArray, jint tileMode) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); static std::vector<SkColor4f> convertColorLongs(JNIEnv* env, jlongArray colorArray) { const size_t count = env->GetArrayLength(colorArray); const jlong* colorValues = env->GetLongArrayElements(colorArray, nullptr); std::vector<SkColor4f> colors(count); for (size_t i = 0; i < count; ++i) { colors[i] = GraphicsJNI::convertColorLong(colorValues[i]); } env->ReleaseLongArrayElements(colorArray, const_cast<jlong*>(colorValues), JNI_ABORT); return colors; } /////////////////////////////////////////////////////////////////////////////////////////////// static jlong LinearGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jlongArray colorArray, jfloatArray posArray, jint tileMode, long colorSpaceHandle) { SkPoint pts[2]; pts[0].set(x0, y0); pts[1].set(x1, y1); size_t count = env->GetArrayLength(colorArray); const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); std::vector<SkColor4f> colors = convertColorLongs(env, colorArray); AutoJavaFloatArray autoPos(env, posArray, count); AutoJavaFloatArray autoPos(env, posArray, colors.size()); #ifdef SK_SCALAR_IS_FLOAT SkScalar* pos = autoPos.ptr(); #else #error Need to convert float array to SkScalar array before calling the following function. #endif sk_sp<SkShader> baseShader(SkGradientShader::MakeLinear(pts, reinterpret_cast<const SkColor*>(colorValues), pos, count, static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL)); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); } env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); sk_sp<SkShader> shader(SkGradientShader::MakeLinear(pts, &colors[0], GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(), static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, nullptr)); ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); } static jlong LinearGradient_create2(JNIEnv* env, jobject o, jlong matrixPtr, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jint color0, jint color1, jint tileMode) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); SkPoint pts[2]; pts[0].set(x0, y0); pts[1].set(x1, y1); SkColor colors[2]; colors[0] = color0; colors[1] = color1; sk_sp<SkShader> baseShader(SkGradientShader::MakeLinear(pts, colors, NULL, 2, static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL)); SkShader* s; if (matrix) { s = baseShader->makeWithLocalMatrix(*matrix).release(); } else { s = baseShader.release(); shader = shader->makeWithLocalMatrix(*matrix); } ThrowIAE_IfNull(env, s); return reinterpret_cast<jlong>(s); return reinterpret_cast<jlong>(shader.release()); } /////////////////////////////////////////////////////////////////////////////////////////////// static jlong RadialGradient_create1(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jfloat radius, jintArray colorArray, jfloatArray posArray, jint tileMode) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); static jlong RadialGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jfloat radius, jlongArray colorArray, jfloatArray posArray, jint tileMode, jlong colorSpaceHandle) { SkPoint center; center.set(x, y); size_t count = env->GetArrayLength(colorArray); const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); std::vector<SkColor4f> colors = convertColorLongs(env, colorArray); AutoJavaFloatArray autoPos(env, posArray, count); AutoJavaFloatArray autoPos(env, posArray, colors.size()); #ifdef SK_SCALAR_IS_FLOAT SkScalar* pos = autoPos.ptr(); #else #error Need to convert float array to SkScalar array before calling the following function. #endif sk_sp<SkShader> baseShader = SkGradientShader::MakeRadial(center, radius, reinterpret_cast<const SkColor*>(colorValues), pos, count, static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); } env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); sk_sp<SkShader> shader = SkGradientShader::MakeRadial(center, radius, &colors[0], GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(), static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, nullptr); ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); } static jlong RadialGradient_create2(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jfloat radius, jint color0, jint color1, jint tileMode) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); SkPoint center; center.set(x, y); SkColor colors[2]; colors[0] = color0; colors[1] = color1; sk_sp<SkShader> baseShader = SkGradientShader::MakeRadial(center, radius, colors, NULL, 2, static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); shader = shader->makeWithLocalMatrix(*matrix); } ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); return reinterpret_cast<jlong>(shader.release()); } /////////////////////////////////////////////////////////////////////////////// static jlong SweepGradient_create1(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jintArray jcolors, jfloatArray jpositions) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); size_t count = env->GetArrayLength(jcolors); const jint* colors = env->GetIntArrayElements(jcolors, NULL); static jlong SweepGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jlongArray colorArray, jfloatArray jpositions, jlong colorSpaceHandle) { std::vector<SkColor4f> colors = convertColorLongs(env, colorArray); AutoJavaFloatArray autoPos(env, jpositions, count); AutoJavaFloatArray autoPos(env, jpositions, colors.size()); #ifdef SK_SCALAR_IS_FLOAT SkScalar* pos = autoPos.ptr(); #else #error Need to convert float array to SkScalar array before calling the following function. #endif sk_sp<SkShader> baseShader = SkGradientShader::MakeSweep(x, y, reinterpret_cast<const SkColor*>(colors), pos, count, sGradientShaderFlags, NULL); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); } env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors), JNI_ABORT); sk_sp<SkShader> shader = SkGradientShader::MakeSweep(x, y, &colors[0], GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(), sGradientShaderFlags, nullptr); ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); } static jlong SweepGradient_create2(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, int color0, int color1) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); SkColor colors[2]; colors[0] = color0; colors[1] = color1; sk_sp<SkShader> baseShader = SkGradientShader::MakeSweep(x, y, colors, NULL, 2, sGradientShaderFlags, NULL); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); shader = shader->makeWithLocalMatrix(*matrix); } ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); return reinterpret_cast<jlong>(shader.release()); } /////////////////////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -295,18 +226,15 @@ static const JNINativeMethod gBitmapShaderMethods[] = { }; static const JNINativeMethod gLinearGradientMethods[] = { { "nativeCreate1", "(JFFFF[I[FI)J", (void*)LinearGradient_create1 }, { "nativeCreate2", "(JFFFFIII)J", (void*)LinearGradient_create2 }, { "nativeCreate", "(JFFFF[J[FIJ)J", (void*)LinearGradient_create }, }; static const JNINativeMethod gRadialGradientMethods[] = { { "nativeCreate1", "(JFFF[I[FI)J", (void*)RadialGradient_create1 }, { "nativeCreate2", "(JFFFIII)J", (void*)RadialGradient_create2 }, { "nativeCreate", "(JFFF[J[FIJ)J", (void*)RadialGradient_create }, }; static const JNINativeMethod gSweepGradientMethods[] = { { "nativeCreate1", "(JFF[I[F)J", (void*)SweepGradient_create1 }, { "nativeCreate2", "(JFFII)J", (void*)SweepGradient_create2 }, { "nativeCreate", "(JFF[J[FJ)J", (void*)SweepGradient_create }, }; static const JNINativeMethod gComposeShaderMethods[] = { Loading graphics/java/android/graphics/LinearGradient.java +83 −52 Original line number Diff line number Diff line Loading @@ -17,21 +17,13 @@ package android.graphics; import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; public class LinearGradient extends Shader { private static final int TYPE_COLORS_AND_POSITIONS = 1; private static final int TYPE_COLOR_START_AND_COLOR_END = 2; /** * Type of the LinearGradient: can be either TYPE_COLORS_AND_POSITIONS or * TYPE_COLOR_START_AND_COLOR_END. */ private int mType; public class LinearGradient extends Shader { @UnsupportedAppUsage private float mX0; @UnsupportedAppUsage Loading @@ -41,16 +33,43 @@ public class LinearGradient extends Shader { @UnsupportedAppUsage private float mY1; @UnsupportedAppUsage private int[] mColors; @UnsupportedAppUsage private float[] mPositions; @UnsupportedAppUsage private TileMode mTileMode; // @ColorInts are replaced by @ColorLongs, but these remain due to @UnsupportedAppUsage. @UnsupportedAppUsage @ColorInt private int[] mColors; @UnsupportedAppUsage @ColorInt private int mColor0; @UnsupportedAppUsage @ColorInt private int mColor1; @UnsupportedAppUsage private TileMode mTileMode; @ColorLong private final long[] mColorLongs; /** * Create a shader that draws a linear gradient along a line. * * @param x0 The x-coordinate for the start of the gradient line * @param y0 The y-coordinate for the start of the gradient line * @param x1 The x-coordinate for the end of the gradient line * @param y1 The y-coordinate for the end of the gradient line * @param colors The sRGB colors to be distributed along the gradient line * @param positions May be null. The relative positions [0..1] of * each corresponding color in the colors array. If this is null, * the the colors are distributed evenly along the gradient line. * @param tile The Shader tiling mode */ public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int[] colors, @Nullable float[] positions, @NonNull TileMode tile) { this(x0, y0, x1, y1, convertColors(colors), positions, tile, ColorSpace.get(ColorSpace.Named.SRGB)); } /** * Create a shader that draws a linear gradient along a line. Loading @@ -64,25 +83,54 @@ public class LinearGradient extends Shader { * each corresponding color in the colors array. If this is null, * the the colors are distributed evenly along the gradient line. * @param tile The Shader tiling mode * * @throws IllegalArgumentException if there are less than two colors, the colors do * not share the same {@link ColorSpace} or do not use a valid one, or {@code positions} * is not {@code null} and has a different length from {@code colors}. */ public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile) { if (colors.length < 2) { throw new IllegalArgumentException("needs >= 2 number of colors"); public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorLong long[] colors, @Nullable float[] positions, @NonNull TileMode tile) { this(x0, y0, x1, y1, colors.clone(), positions, tile, detectColorSpace(colors)); } /** * Base constructor. Assumes @param colors is a copy that this object can hold onto, * and all colors share @param colorSpace. */ private LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorLong long[] colors, @Nullable float[] positions, @NonNull TileMode tile, @NonNull ColorSpace colorSpace) { super(colorSpace); if (positions != null && colors.length != positions.length) { throw new IllegalArgumentException("color and position arrays must be of equal length"); } mType = TYPE_COLORS_AND_POSITIONS; mX0 = x0; mY0 = y0; mX1 = x1; mY1 = y1; mColors = colors.clone(); mColorLongs = colors; mPositions = positions != null ? positions.clone() : null; mTileMode = tile; } /** * Create a shader that draws a linear gradient along a line. * * @param x0 The x-coordinate for the start of the gradient line * @param y0 The y-coordinate for the start of the gradient line * @param x1 The x-coordinate for the end of the gradient line * @param y1 The y-coordinate for the end of the gradient line * @param color0 The sRGB color at the start of the gradient line. * @param color1 The sRGB color at the end of the gradient line. * @param tile The Shader tiling mode */ public LinearGradient(float x0, float y0, float x1, float y1, @ColorInt int color0, @ColorInt int color1, @NonNull TileMode tile) { this(x0, y0, x1, y1, Color.pack(color0), Color.pack(color1), tile); } /** * Create a shader that draws a linear gradient along a line. * Loading @@ -93,31 +141,21 @@ public class LinearGradient extends Shader { * @param color0 The color at the start of the gradient line. * @param color1 The color at the end of the gradient line. * @param tile The Shader tiling mode * * @throws IllegalArgumentException if the colors do * not share the same {@link ColorSpace} or do not use a valid one. */ public LinearGradient(float x0, float y0, float x1, float y1, @ColorInt int color0, @ColorInt int color1, @ColorLong long color0, @ColorLong long color1, @NonNull TileMode tile) { mType = TYPE_COLOR_START_AND_COLOR_END; mX0 = x0; mY0 = y0; mX1 = x1; mY1 = y1; mColor0 = color0; mColor1 = color1; mColors = null; mPositions = null; mTileMode = tile; this(x0, y0, x1, y1, new long[] {color0, color1}, null, tile); } @Override long createNativeInstance(long nativeMatrix) { if (mType == TYPE_COLORS_AND_POSITIONS) { return nativeCreate1(nativeMatrix, mX0, mY0, mX1, mY1, mColors, mPositions, mTileMode.nativeInt); } else { // TYPE_COLOR_START_AND_COLOR_END return nativeCreate2(nativeMatrix, mX0, mY0, mX1, mY1, mColor0, mColor1, mTileMode.nativeInt); } return nativeCreate(nativeMatrix, mX0, mY0, mX1, mY1, mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance()); } /** Loading @@ -125,19 +163,12 @@ public class LinearGradient extends Shader { */ @Override protected Shader copy() { final LinearGradient copy; if (mType == TYPE_COLORS_AND_POSITIONS) { copy = new LinearGradient(mX0, mY0, mX1, mY1, mColors.clone(), mPositions != null ? mPositions.clone() : null, mTileMode); } else { // TYPE_COLOR_START_AND_COLOR_END copy = new LinearGradient(mX0, mY0, mX1, mY1, mColor0, mColor1, mTileMode); } final LinearGradient copy = new LinearGradient(mX0, mY0, mX1, mY1, mColorLongs, mPositions, mTileMode, colorSpace()); copyLocalMatrix(copy); return copy; } private native long nativeCreate1(long matrix, float x0, float y0, float x1, float y1, int colors[], float positions[], int tileMode); private native long nativeCreate2(long matrix, float x0, float y0, float x1, float y1, int color0, int color1, int tileMode); private native long nativeCreate(long matrix, float x0, float y0, float x1, float y1, long[] colors, float[] positions, int tileMode, long colorSpaceHandle); } graphics/java/android/graphics/RadialGradient.java +78 −50 File changed.Preview size limit exceeded, changes collapsed. Show changes graphics/java/android/graphics/Shader.java +65 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.graphics; import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; Loading @@ -39,7 +41,32 @@ public class Shader { * @deprecated Use subclass constructors directly instead. */ @Deprecated public Shader() {} public Shader() { mColorSpace = null; } /** * @hide */ public Shader(ColorSpace colorSpace) { mColorSpace = colorSpace; if (colorSpace == null) { throw new IllegalArgumentException( "Use Shader() to create a Shader with no ColorSpace"); } // This just ensures that if the ColorSpace is invalid, the Exception will be thrown now. mColorSpace.getNativeInstance(); } private final ColorSpace mColorSpace; /** * @hide */ protected ColorSpace colorSpace() { return mColorSpace; } /** * Current native shader instance. Created and updated lazily when {@link #getNativeInstance()} Loading Loading @@ -169,6 +196,43 @@ public class Shader { return mNativeInstance; } /** * @hide */ public static @ColorLong long[] convertColors(@NonNull @ColorInt int[] colors) { if (colors.length < 2) { throw new IllegalArgumentException("needs >= 2 number of colors"); } long[] colorLongs = new long[colors.length]; for (int i = 0; i < colors.length; ++i) { colorLongs[i] = Color.pack(colors[i]); } return colorLongs; } /** * Detect the ColorSpace that the {@code colors} share. * * @throws IllegalArgumentException if the colors do not all share the same, * valid ColorSpace, or if there are less than 2 colors. * * @hide */ public static ColorSpace detectColorSpace(@NonNull @ColorLong long[] colors) { if (colors.length < 2) { throw new IllegalArgumentException("needs >= 2 number of colors"); } final ColorSpace colorSpace = Color.colorSpace(colors[0]); for (int i = 1; i < colors.length; ++i) { if (Color.colorSpace(colors[i]) != colorSpace) { throw new IllegalArgumentException("All colors must be in the same ColorSpace!"); } } return colorSpace; } private static native long nativeGetFinalizer(); } Loading Loading
api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -14249,7 +14249,9 @@ package android.graphics { public class LinearGradient extends android.graphics.Shader { ctor public LinearGradient(float, float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @NonNull @ColorLong long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode); ctor public LinearGradient(float, float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode); } public class MaskFilter { Loading Loading @@ -14778,7 +14780,9 @@ package android.graphics { public class RadialGradient extends android.graphics.Shader { ctor public RadialGradient(float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode); ctor public RadialGradient(float, float, float, @NonNull @ColorLong 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); } public final class RecordingCanvas extends android.graphics.Canvas { Loading Loading @@ -15038,7 +15042,9 @@ package android.graphics { public class SweepGradient extends android.graphics.Shader { ctor public SweepGradient(float, float, @NonNull @ColorInt int[], @Nullable float[]); ctor public SweepGradient(float, float, @NonNull @ColorLong long[], @Nullable float[]); ctor public SweepGradient(float, float, @ColorInt int, @ColorInt int); ctor public SweepGradient(float, float, @ColorLong long, @ColorLong long); } public class Typeface {
core/jni/android/graphics/Shader.cpp +56 −128 Original line number Diff line number Diff line Loading @@ -8,6 +8,8 @@ #include <jni.h> #include <vector> using namespace android::uirenderer; /** Loading @@ -18,10 +20,10 @@ using namespace android::uirenderer; */ static const uint32_t sGradientShaderFlags = SkGradientShader::kInterpolateColorsInPremul_Flag; static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) { if (NULL == ptr) { doThrowIAE(env); } #define ThrowIAE_IfNull(env, ptr) \ if (nullptr == ptr) { \ doThrowIAE(env); \ return 0; \ } static void Color_RGBToHSV(JNIEnv* env, jobject, jint red, jint green, jint blue, jfloatArray hsvArray) Loading Loading @@ -76,186 +78,115 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j } sk_sp<SkShader> shader = image->makeShader( (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY); ThrowIAE_IfNull(env, shader.get()); if (matrix) { shader = shader->makeWithLocalMatrix(*matrix); } ThrowIAE_IfNull(env, shader.get()); return reinterpret_cast<jlong>(shader.release()); } /////////////////////////////////////////////////////////////////////////////////////////////// static jlong LinearGradient_create1(JNIEnv* env, jobject o, jlong matrixPtr, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jintArray colorArray, jfloatArray posArray, jint tileMode) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); static std::vector<SkColor4f> convertColorLongs(JNIEnv* env, jlongArray colorArray) { const size_t count = env->GetArrayLength(colorArray); const jlong* colorValues = env->GetLongArrayElements(colorArray, nullptr); std::vector<SkColor4f> colors(count); for (size_t i = 0; i < count; ++i) { colors[i] = GraphicsJNI::convertColorLong(colorValues[i]); } env->ReleaseLongArrayElements(colorArray, const_cast<jlong*>(colorValues), JNI_ABORT); return colors; } /////////////////////////////////////////////////////////////////////////////////////////////// static jlong LinearGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jlongArray colorArray, jfloatArray posArray, jint tileMode, long colorSpaceHandle) { SkPoint pts[2]; pts[0].set(x0, y0); pts[1].set(x1, y1); size_t count = env->GetArrayLength(colorArray); const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); std::vector<SkColor4f> colors = convertColorLongs(env, colorArray); AutoJavaFloatArray autoPos(env, posArray, count); AutoJavaFloatArray autoPos(env, posArray, colors.size()); #ifdef SK_SCALAR_IS_FLOAT SkScalar* pos = autoPos.ptr(); #else #error Need to convert float array to SkScalar array before calling the following function. #endif sk_sp<SkShader> baseShader(SkGradientShader::MakeLinear(pts, reinterpret_cast<const SkColor*>(colorValues), pos, count, static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL)); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); } env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); sk_sp<SkShader> shader(SkGradientShader::MakeLinear(pts, &colors[0], GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(), static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, nullptr)); ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); } static jlong LinearGradient_create2(JNIEnv* env, jobject o, jlong matrixPtr, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jint color0, jint color1, jint tileMode) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); SkPoint pts[2]; pts[0].set(x0, y0); pts[1].set(x1, y1); SkColor colors[2]; colors[0] = color0; colors[1] = color1; sk_sp<SkShader> baseShader(SkGradientShader::MakeLinear(pts, colors, NULL, 2, static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL)); SkShader* s; if (matrix) { s = baseShader->makeWithLocalMatrix(*matrix).release(); } else { s = baseShader.release(); shader = shader->makeWithLocalMatrix(*matrix); } ThrowIAE_IfNull(env, s); return reinterpret_cast<jlong>(s); return reinterpret_cast<jlong>(shader.release()); } /////////////////////////////////////////////////////////////////////////////////////////////// static jlong RadialGradient_create1(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jfloat radius, jintArray colorArray, jfloatArray posArray, jint tileMode) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); static jlong RadialGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jfloat radius, jlongArray colorArray, jfloatArray posArray, jint tileMode, jlong colorSpaceHandle) { SkPoint center; center.set(x, y); size_t count = env->GetArrayLength(colorArray); const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); std::vector<SkColor4f> colors = convertColorLongs(env, colorArray); AutoJavaFloatArray autoPos(env, posArray, count); AutoJavaFloatArray autoPos(env, posArray, colors.size()); #ifdef SK_SCALAR_IS_FLOAT SkScalar* pos = autoPos.ptr(); #else #error Need to convert float array to SkScalar array before calling the following function. #endif sk_sp<SkShader> baseShader = SkGradientShader::MakeRadial(center, radius, reinterpret_cast<const SkColor*>(colorValues), pos, count, static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); } env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT); sk_sp<SkShader> shader = SkGradientShader::MakeRadial(center, radius, &colors[0], GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(), static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, nullptr); ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); } static jlong RadialGradient_create2(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jfloat radius, jint color0, jint color1, jint tileMode) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); SkPoint center; center.set(x, y); SkColor colors[2]; colors[0] = color0; colors[1] = color1; sk_sp<SkShader> baseShader = SkGradientShader::MakeRadial(center, radius, colors, NULL, 2, static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, NULL); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); shader = shader->makeWithLocalMatrix(*matrix); } ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); return reinterpret_cast<jlong>(shader.release()); } /////////////////////////////////////////////////////////////////////////////// static jlong SweepGradient_create1(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jintArray jcolors, jfloatArray jpositions) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); size_t count = env->GetArrayLength(jcolors); const jint* colors = env->GetIntArrayElements(jcolors, NULL); static jlong SweepGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, jlongArray colorArray, jfloatArray jpositions, jlong colorSpaceHandle) { std::vector<SkColor4f> colors = convertColorLongs(env, colorArray); AutoJavaFloatArray autoPos(env, jpositions, count); AutoJavaFloatArray autoPos(env, jpositions, colors.size()); #ifdef SK_SCALAR_IS_FLOAT SkScalar* pos = autoPos.ptr(); #else #error Need to convert float array to SkScalar array before calling the following function. #endif sk_sp<SkShader> baseShader = SkGradientShader::MakeSweep(x, y, reinterpret_cast<const SkColor*>(colors), pos, count, sGradientShaderFlags, NULL); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); } env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors), JNI_ABORT); sk_sp<SkShader> shader = SkGradientShader::MakeSweep(x, y, &colors[0], GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(), sGradientShaderFlags, nullptr); ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); } static jlong SweepGradient_create2(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y, int color0, int color1) { const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); SkColor colors[2]; colors[0] = color0; colors[1] = color1; sk_sp<SkShader> baseShader = SkGradientShader::MakeSweep(x, y, colors, NULL, 2, sGradientShaderFlags, NULL); SkShader* shader; if (matrix) { shader = baseShader->makeWithLocalMatrix(*matrix).release(); } else { shader = baseShader.release(); shader = shader->makeWithLocalMatrix(*matrix); } ThrowIAE_IfNull(env, shader); return reinterpret_cast<jlong>(shader); return reinterpret_cast<jlong>(shader.release()); } /////////////////////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -295,18 +226,15 @@ static const JNINativeMethod gBitmapShaderMethods[] = { }; static const JNINativeMethod gLinearGradientMethods[] = { { "nativeCreate1", "(JFFFF[I[FI)J", (void*)LinearGradient_create1 }, { "nativeCreate2", "(JFFFFIII)J", (void*)LinearGradient_create2 }, { "nativeCreate", "(JFFFF[J[FIJ)J", (void*)LinearGradient_create }, }; static const JNINativeMethod gRadialGradientMethods[] = { { "nativeCreate1", "(JFFF[I[FI)J", (void*)RadialGradient_create1 }, { "nativeCreate2", "(JFFFIII)J", (void*)RadialGradient_create2 }, { "nativeCreate", "(JFFF[J[FIJ)J", (void*)RadialGradient_create }, }; static const JNINativeMethod gSweepGradientMethods[] = { { "nativeCreate1", "(JFF[I[F)J", (void*)SweepGradient_create1 }, { "nativeCreate2", "(JFFII)J", (void*)SweepGradient_create2 }, { "nativeCreate", "(JFF[J[FJ)J", (void*)SweepGradient_create }, }; static const JNINativeMethod gComposeShaderMethods[] = { Loading
graphics/java/android/graphics/LinearGradient.java +83 −52 Original line number Diff line number Diff line Loading @@ -17,21 +17,13 @@ package android.graphics; import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; public class LinearGradient extends Shader { private static final int TYPE_COLORS_AND_POSITIONS = 1; private static final int TYPE_COLOR_START_AND_COLOR_END = 2; /** * Type of the LinearGradient: can be either TYPE_COLORS_AND_POSITIONS or * TYPE_COLOR_START_AND_COLOR_END. */ private int mType; public class LinearGradient extends Shader { @UnsupportedAppUsage private float mX0; @UnsupportedAppUsage Loading @@ -41,16 +33,43 @@ public class LinearGradient extends Shader { @UnsupportedAppUsage private float mY1; @UnsupportedAppUsage private int[] mColors; @UnsupportedAppUsage private float[] mPositions; @UnsupportedAppUsage private TileMode mTileMode; // @ColorInts are replaced by @ColorLongs, but these remain due to @UnsupportedAppUsage. @UnsupportedAppUsage @ColorInt private int[] mColors; @UnsupportedAppUsage @ColorInt private int mColor0; @UnsupportedAppUsage @ColorInt private int mColor1; @UnsupportedAppUsage private TileMode mTileMode; @ColorLong private final long[] mColorLongs; /** * Create a shader that draws a linear gradient along a line. * * @param x0 The x-coordinate for the start of the gradient line * @param y0 The y-coordinate for the start of the gradient line * @param x1 The x-coordinate for the end of the gradient line * @param y1 The y-coordinate for the end of the gradient line * @param colors The sRGB colors to be distributed along the gradient line * @param positions May be null. The relative positions [0..1] of * each corresponding color in the colors array. If this is null, * the the colors are distributed evenly along the gradient line. * @param tile The Shader tiling mode */ public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int[] colors, @Nullable float[] positions, @NonNull TileMode tile) { this(x0, y0, x1, y1, convertColors(colors), positions, tile, ColorSpace.get(ColorSpace.Named.SRGB)); } /** * Create a shader that draws a linear gradient along a line. Loading @@ -64,25 +83,54 @@ public class LinearGradient extends Shader { * each corresponding color in the colors array. If this is null, * the the colors are distributed evenly along the gradient line. * @param tile The Shader tiling mode * * @throws IllegalArgumentException if there are less than two colors, the colors do * not share the same {@link ColorSpace} or do not use a valid one, or {@code positions} * is not {@code null} and has a different length from {@code colors}. */ public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile) { if (colors.length < 2) { throw new IllegalArgumentException("needs >= 2 number of colors"); public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorLong long[] colors, @Nullable float[] positions, @NonNull TileMode tile) { this(x0, y0, x1, y1, colors.clone(), positions, tile, detectColorSpace(colors)); } /** * Base constructor. Assumes @param colors is a copy that this object can hold onto, * and all colors share @param colorSpace. */ private LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorLong long[] colors, @Nullable float[] positions, @NonNull TileMode tile, @NonNull ColorSpace colorSpace) { super(colorSpace); if (positions != null && colors.length != positions.length) { throw new IllegalArgumentException("color and position arrays must be of equal length"); } mType = TYPE_COLORS_AND_POSITIONS; mX0 = x0; mY0 = y0; mX1 = x1; mY1 = y1; mColors = colors.clone(); mColorLongs = colors; mPositions = positions != null ? positions.clone() : null; mTileMode = tile; } /** * Create a shader that draws a linear gradient along a line. * * @param x0 The x-coordinate for the start of the gradient line * @param y0 The y-coordinate for the start of the gradient line * @param x1 The x-coordinate for the end of the gradient line * @param y1 The y-coordinate for the end of the gradient line * @param color0 The sRGB color at the start of the gradient line. * @param color1 The sRGB color at the end of the gradient line. * @param tile The Shader tiling mode */ public LinearGradient(float x0, float y0, float x1, float y1, @ColorInt int color0, @ColorInt int color1, @NonNull TileMode tile) { this(x0, y0, x1, y1, Color.pack(color0), Color.pack(color1), tile); } /** * Create a shader that draws a linear gradient along a line. * Loading @@ -93,31 +141,21 @@ public class LinearGradient extends Shader { * @param color0 The color at the start of the gradient line. * @param color1 The color at the end of the gradient line. * @param tile The Shader tiling mode * * @throws IllegalArgumentException if the colors do * not share the same {@link ColorSpace} or do not use a valid one. */ public LinearGradient(float x0, float y0, float x1, float y1, @ColorInt int color0, @ColorInt int color1, @ColorLong long color0, @ColorLong long color1, @NonNull TileMode tile) { mType = TYPE_COLOR_START_AND_COLOR_END; mX0 = x0; mY0 = y0; mX1 = x1; mY1 = y1; mColor0 = color0; mColor1 = color1; mColors = null; mPositions = null; mTileMode = tile; this(x0, y0, x1, y1, new long[] {color0, color1}, null, tile); } @Override long createNativeInstance(long nativeMatrix) { if (mType == TYPE_COLORS_AND_POSITIONS) { return nativeCreate1(nativeMatrix, mX0, mY0, mX1, mY1, mColors, mPositions, mTileMode.nativeInt); } else { // TYPE_COLOR_START_AND_COLOR_END return nativeCreate2(nativeMatrix, mX0, mY0, mX1, mY1, mColor0, mColor1, mTileMode.nativeInt); } return nativeCreate(nativeMatrix, mX0, mY0, mX1, mY1, mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance()); } /** Loading @@ -125,19 +163,12 @@ public class LinearGradient extends Shader { */ @Override protected Shader copy() { final LinearGradient copy; if (mType == TYPE_COLORS_AND_POSITIONS) { copy = new LinearGradient(mX0, mY0, mX1, mY1, mColors.clone(), mPositions != null ? mPositions.clone() : null, mTileMode); } else { // TYPE_COLOR_START_AND_COLOR_END copy = new LinearGradient(mX0, mY0, mX1, mY1, mColor0, mColor1, mTileMode); } final LinearGradient copy = new LinearGradient(mX0, mY0, mX1, mY1, mColorLongs, mPositions, mTileMode, colorSpace()); copyLocalMatrix(copy); return copy; } private native long nativeCreate1(long matrix, float x0, float y0, float x1, float y1, int colors[], float positions[], int tileMode); private native long nativeCreate2(long matrix, float x0, float y0, float x1, float y1, int color0, int color1, int tileMode); private native long nativeCreate(long matrix, float x0, float y0, float x1, float y1, long[] colors, float[] positions, int tileMode, long colorSpaceHandle); }
graphics/java/android/graphics/RadialGradient.java +78 −50 File changed.Preview size limit exceeded, changes collapsed. Show changes
graphics/java/android/graphics/Shader.java +65 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.graphics; import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; Loading @@ -39,7 +41,32 @@ public class Shader { * @deprecated Use subclass constructors directly instead. */ @Deprecated public Shader() {} public Shader() { mColorSpace = null; } /** * @hide */ public Shader(ColorSpace colorSpace) { mColorSpace = colorSpace; if (colorSpace == null) { throw new IllegalArgumentException( "Use Shader() to create a Shader with no ColorSpace"); } // This just ensures that if the ColorSpace is invalid, the Exception will be thrown now. mColorSpace.getNativeInstance(); } private final ColorSpace mColorSpace; /** * @hide */ protected ColorSpace colorSpace() { return mColorSpace; } /** * Current native shader instance. Created and updated lazily when {@link #getNativeInstance()} Loading Loading @@ -169,6 +196,43 @@ public class Shader { return mNativeInstance; } /** * @hide */ public static @ColorLong long[] convertColors(@NonNull @ColorInt int[] colors) { if (colors.length < 2) { throw new IllegalArgumentException("needs >= 2 number of colors"); } long[] colorLongs = new long[colors.length]; for (int i = 0; i < colors.length; ++i) { colorLongs[i] = Color.pack(colors[i]); } return colorLongs; } /** * Detect the ColorSpace that the {@code colors} share. * * @throws IllegalArgumentException if the colors do not all share the same, * valid ColorSpace, or if there are less than 2 colors. * * @hide */ public static ColorSpace detectColorSpace(@NonNull @ColorLong long[] colors) { if (colors.length < 2) { throw new IllegalArgumentException("needs >= 2 number of colors"); } final ColorSpace colorSpace = Color.colorSpace(colors[0]); for (int i = 1; i < colors.length; ++i) { if (Color.colorSpace(colors[i]) != colorSpace) { throw new IllegalArgumentException("All colors must be in the same ColorSpace!"); } } return colorSpace; } private static native long nativeGetFinalizer(); } Loading